Add observability for LLM topic context inclusion (#1038)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thomasnordquist <7721625+thomasnordquist@users.noreply.github.com>
Co-authored-by: Thomas Nordquist <thomasnordquist@users.noreply.github.com>
This commit is contained in:
Copilot
2026-01-30 20:53:29 +01:00
committed by GitHub
parent 080a773dbd
commit ed8a7f559e
194 changed files with 35234 additions and 4085 deletions

View File

@@ -43,11 +43,7 @@ export interface SaveDialogOptions {
nameFieldLabel?: string
showsTagField?: boolean
properties?: Array<
| 'showHiddenFiles'
| 'createDirectory'
| 'treatPackageAsDirectory'
| 'showOverwriteConfirmation'
| 'dontAddToRecent'
'showHiddenFiles' | 'createDirectory' | 'treatPackageAsDirectory' | 'showOverwriteConfirmation' | 'dontAddToRecent'
>
securityScopedBookmarks?: boolean
}

View File

@@ -7,6 +7,7 @@ interface CallbackStore {
export class EventDispatcher<Message> {
private emitter = new EventEmitter()
private callbacks: Array<CallbackStore> = []
public dispatch(msg: Message) {

View File

@@ -4,8 +4,11 @@ import { EventBusInterface } from './EventBusInterface'
export class IpcMainEventBus implements EventBusInterface {
private ipc: IpcMain
private clients: Map<number, WebContents> = new Map() // webContentsId -> WebContents
private connectionOwners: Map<string, number> = new Map() // connectionId -> webContentsId
private currentClient: WebContents | undefined
constructor(ipc: IpcMain) {
@@ -57,7 +60,7 @@ export class IpcMainEventBus implements EventBusInterface {
}
public emit<MessageType>(event: Event<MessageType>, msg: MessageType) {
const topic = event.topic
const { topic } = event
// RPC responses go only to the requesting client
if (topic.includes('/response/')) {

View File

@@ -1,10 +1,11 @@
import { IpcRenderer } from 'electron'
import { CallbackStore } from './CallbackStore'
import { EventBusInterface } from './EventBusInterface'
import { Event } from '../Events'
import { IpcRenderer } from 'electron'
export class IpcRendererEventBus implements EventBusInterface {
private ipc: IpcRenderer
private callbacks: Array<CallbackStore> = []
constructor(ipc: IpcRenderer) {

View File

@@ -1,6 +1,6 @@
import { v4 } from 'uuid'
import { Event } from '../Events'
import { EventBusInterface } from './EventBusInterface'
import { v4 } from 'uuid'
export type RpcEvent<RequestType, ResponseType> = {
topic: string
@@ -54,7 +54,7 @@ export class Rpc {
} catch (e) {
error = e
}
const id = (request as any).id
const { id } = request as any
console.log(`${event.topic}/response/${id}`, payload, error)
this.participant.emit({ topic: `${event.topic}/response/${id}` }, { id, payload, error })
})

View File

@@ -1,7 +1,7 @@
import { Server as SocketIOServer, Socket } from 'socket.io'
import Debug from 'debug'
import { Event } from '../Events'
import { EventBusInterface } from './EventBusInterface'
import Debug from 'debug'
const debug = Debug('mqtt-explorer:socketio')
const debugConnect = Debug('mqtt-explorer:socketio:connect')
@@ -17,6 +17,7 @@ interface SocketSubscription {
export class SocketIOServerEventBus implements EventBusInterface {
private io: SocketIOServer
private clients: Map<string, Socket> = new Map() // socketId -> Socket
// Global handlers that apply to ALL sockets (like RPC endpoints)
@@ -232,7 +233,7 @@ export class SocketIOServerEventBus implements EventBusInterface {
}
public emit<MessageType>(event: Event<MessageType>, msg: MessageType) {
const topic = event.topic
const { topic } = event
// Check if this is an RPC response (contains /response/ in topic)
if (topic.includes('/response/')) {

View File

@@ -1,6 +1,6 @@
import { UpdateInfo } from 'builder-util-runtime'
import { Base64MessageDTO } from '../backend/src/Model/Base64Message'
import { DataSourceState, MqttOptions } from '../backend/src/DataSource'
import { UpdateInfo } from 'builder-util-runtime'
import { RpcEvent } from './EventSystem/Rpc'
export type Event<MessageType> = {

View File

@@ -6,9 +6,9 @@
* you can now use: Events.connectionState(id)
*/
import { UpdateInfo } from 'builder-util-runtime'
import { Base64MessageDTO } from '../backend/src/Model/Base64Message'
import { DataSourceState, MqttOptions } from '../backend/src/DataSource'
import { UpdateInfo } from 'builder-util-runtime'
import { RpcEvent } from './EventSystem/Rpc'
export type EventV2<MessageType> = {
@@ -36,6 +36,7 @@ export const RpcEvents = {
openDialog: { topic: 'openDialog' } as RpcEvent<OpenDialogOptionsV2, OpenDialogReturnValueV2>,
saveDialog: { topic: 'saveDialog' } as RpcEvent<SaveDialogOptionsV2, SaveDialogReturnValueV2>,
uploadCertificate: { topic: 'uploadCertificate' } as RpcEvent<CertificateUploadRequest, CertificateUploadResponse>,
llmChat: { topic: 'llm/chat' } as RpcEvent<LlmChatRequest, LlmChatResponse>,
}
// Type definitions
@@ -62,6 +63,19 @@ export interface CertificateUploadResponse {
data: string // base64 encoded
}
// LLM Chat RPC types
export interface LlmChatRequest {
messages: Array<{
role: 'system' | 'user' | 'assistant'
content: string
}>
topicContext?: string
}
export interface LlmChatResponse {
response: string
}
// Dialog types (browser-compatible versions)
import type { OpenDialogOptions, OpenDialogReturnValue, SaveDialogOptions, SaveDialogReturnValue } from './DialogTypes'