@prbe.ai/electron-sdk 0.1.17 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../package.json","../src/agent.ts","../src/models.ts","../src/connection.ts","../src/state.ts","../src/tools/index.ts","../src/interactions.ts","../src/tools/filesystem.ts","../src/tools/logs.ts","../src/tools/interactive.ts","../src/tools/bash.ts","../src/tools/safe-commands.ts","../src/history.ts","../src/serialization.ts","../src/assets/index.ts"],"sourcesContent":["/**\n * index.ts — Public API exports for @prbe/electron-sdk\n */\n\n// Version\nexport { version as SDK_VERSION } from \"../package.json\";\n\n// Agent\nexport { PRBEAgent } from \"./agent\";\n\n// State\nexport { PRBEAgentState, PRBEStateEvent } from \"./state\";\n\n// Models\nexport {\n WSMessageType,\n WSMessage,\n ToolParamType,\n ToolName,\n UserIdentifierType,\n PRBEToolParameter,\n PRBEToolDeclaration,\n PRBEAgentConfigKey,\n PRBEAgentConfig,\n PRBEAgentStatus,\n PRBEAgentStatusType,\n PRBEAgentError,\n PRBEAgentErrorType,\n PRBEStatusEvent,\n PRBECRInvestigation,\n PRBECompletedInvestigation,\n FlaggedFileIn,\n InvestigationResult,\n PollRequest,\n PollResponse,\n ContextRequestOut,\n TicketStatusOut,\n TicketInfoRequest,\n TicketInfoOut,\n TicketInfoResponse,\n ResolveSessionsRequest,\n ResolvedTicketOut,\n ResolveSessionsResponse,\n ConversationRole,\n ConversationEntry,\n redactPII,\n API_URL,\n MIDDLEWARE_URL,\n} from \"./models\";\n\n// Interactions\nexport {\n InteractionType,\n InvestigationSource,\n AskQuestionPayload,\n RequestPermissionPayload,\n RequestPathAccessPayload,\n InteractionPayload,\n AskQuestionResponse,\n RequestPermissionResponse,\n RequestPathAccessResponse,\n InteractionResponse,\n ResolvedInteraction,\n PRBEInteractionRequester,\n PRBEInteractionHandler,\n} from \"./interactions\";\n\n// Serialization\nexport {\n PRBESerializedCR,\n PRBESerializedTicket,\n PRBESerializedCompletedInvestigation,\n PRBESerializedState,\n DEFAULT_PRBE_STATE,\n serializePRBEState,\n} from \"./serialization\";\n\n// Tools\nexport { PRBETool, PRBEToolRegistry, PRBEClosureTool } from \"./tools/index\";\nexport { resolveAndValidate, resolveWithAccessRequest, humanReadableSize } from \"./tools/index\";\nexport {\n ListDirectoryTool,\n ReadFileTool,\n SearchContentTool,\n FindFilesTool,\n FlagFileTool,\n} from \"./tools/filesystem\";\nexport {\n PRBELogCapture,\n LogEntry,\n ReadAppLogsTool,\n SearchAppLogsTool,\n ClearAppLogsTool,\n FlagAppLogsTool,\n} from \"./tools/logs\";\n\n// Interactive tools\nexport { AskUserTool } from \"./tools/interactive\";\nexport { BashExecuteTool } from \"./tools/bash\";\n\n// Assets\nexport { PROBE_MARK_SVG } from \"./assets/index\";\n","{\n \"name\": \"@prbe.ai/electron-sdk\",\n \"version\": \"0.1.17\",\n \"description\": \"PRBE debug agent SDK for Electron apps\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"./types\": {\n \"import\": {\n \"types\": \"./dist/types.d.mts\",\n \"default\": \"./dist/types.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/types.d.ts\",\n \"default\": \"./dist/types.js\"\n }\n },\n \"./assets/*\": \"./src/assets/*\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"clean\": \"rm -rf dist\"\n },\n \"files\": [\n \"dist\",\n \"src/assets/*.svg\"\n ],\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.0.0\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.7.0\"\n }\n}\n","/**\n * agent.ts — PRBEAgent class\n *\n * Main entry point for the PRBE debug agent SDK.\n * Handles WebSocket connection to middleware, investigation lifecycle,\n * background polling for context requests, file uploads, and persistence.\n *\n * Mirrors PRBEAgent.swift behavior.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { randomUUID } from \"crypto\";\nimport {\n WSMessageType,\n PRBEAgentConfigKey,\n ToolParamType,\n UserIdentifierType,\n API_URL,\n MIDDLEWARE_URL,\n redactPII,\n} from \"./models\";\nimport { version as SDK_VERSION } from \"../package.json\";\nimport type {\n WSMessage,\n PRBEAgentConfig,\n PRBEAgentStatus,\n PRBEToolParameter,\n InvestigationResult,\n FlaggedFileIn,\n PollRequest,\n PollResponse,\n ResolveSessionsRequest,\n ResolveSessionsResponse,\n TicketInfoRequest,\n TicketInfoResponse,\n TicketInfoOut,\n ContextRequestOut,\n ConversationEntry,\n} from \"./models\";\nimport { InvestigationConnection } from \"./connection\";\nimport {\n PRBEAgentStatusType,\n PRBEAgentError,\n PRBEAgentErrorType,\n} from \"./models\";\nimport { PRBEAgentState, PRBEStateEvent } from \"./state\";\nimport { PRBEToolRegistry, PRBEClosureTool } from \"./tools/index\";\nimport {\n ListDirectoryTool,\n ReadFileTool,\n SearchContentTool,\n FindFilesTool,\n FlagFileTool,\n} from \"./tools/filesystem\";\nimport {\n PRBELogCapture,\n ReadAppLogsTool,\n SearchAppLogsTool,\n ClearAppLogsTool,\n FlagAppLogsTool,\n} from \"./tools/logs\";\nimport { AskUserTool } from \"./tools/interactive\";\nimport { BashExecuteTool } from \"./tools/bash\";\nimport { InteractionType, InvestigationSource } from \"./interactions\";\nimport type {\n PRBEInteractionHandler,\n PRBEInteractionRequester,\n InteractionPayload,\n InteractionResponse,\n RequestPermissionResponse,\n RequestPathAccessResponse,\n} from \"./interactions\";\nimport { HistoryStore } from \"./history\";\n\n// ---------------------------------------------------------------------------\n// Persistence\n// ---------------------------------------------------------------------------\n\ninterface PersistedData {\n agentId?: string;\n sessionIds?: string[];\n respondedCRIds?: string[];\n}\n\nfunction getPersistencePath(): string {\n // Use platform-appropriate app data directory\n const appData =\n process.env[\"APPDATA\"] ||\n (process.platform === \"darwin\"\n ? path.join(os.homedir(), \"Library\", \"Application Support\")\n : path.join(os.homedir(), \".local\", \"share\"));\n const dir = path.join(appData, \"prbe-agent\");\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return path.join(dir, \"agent-state.json\");\n}\n\nfunction loadPersistedData(): PersistedData {\n try {\n const filePath = getPersistencePath();\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as PersistedData;\n }\n } catch {\n // Ignore read errors, return defaults\n }\n return {};\n}\n\nfunction savePersistedData(data: PersistedData): void {\n try {\n const filePath = getPersistencePath();\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), \"utf-8\");\n } catch {\n console.error(\"[PRBEAgent] Failed to save persisted data\");\n }\n}\n\n// ---------------------------------------------------------------------------\n// PRBEAgent\n// ---------------------------------------------------------------------------\n\nexport class PRBEAgent implements PRBEInteractionRequester {\n public readonly state: PRBEAgentState;\n public readonly logCapture: PRBELogCapture;\n\n private readonly config: Required<Pick<PRBEAgentConfig,\n | PRBEAgentConfigKey.API_KEY\n | PRBEAgentConfigKey.AUTO_APPROVED_DIRS\n | PRBEAgentConfigKey.POLLING_INTERVAL\n | PRBEAgentConfigKey.MAX_LOG_ENTRIES\n | PRBEAgentConfigKey.CAPTURE_CONSOLE\n | PRBEAgentConfigKey.BACKGROUND_POLLING\n >>;\n private readonly appDataPath?: string;\n private sessionMetadata: Record<string, unknown>;\n private readonly interactionHandler?: PRBEInteractionHandler;\n private readonly registry = new PRBEToolRegistry();\n private readonly grantedPaths = new Set<string>();\n private userCancelled = false;\n private activeConnection: InvestigationConnection | null = null;\n private pollingTimer: ReturnType<typeof setInterval> | null = null;\n private persistedData: PersistedData;\n private fetchAbortController: AbortController | null = null;\n private currentInvestigationSource: InvestigationSource = InvestigationSource.USER;\n private currentCRId: string | null = null;\n\n private readonly historyStore: HistoryStore;\n\n /** Files flagged during the current tool call — uploaded immediately after the tool returns. */\n private pendingFlaggedFiles: FlaggedFileIn[] = [];\n\n // ---------- User Identifier ----------\n\n private userEmail?: string;\n private userId?: string;\n\n // ---------- Persistence ----------\n\n private get agentID(): string {\n if (this.persistedData.agentId) {\n return this.persistedData.agentId;\n }\n const newID = randomUUID();\n this.persistedData.agentId = newID;\n savePersistedData(this.persistedData);\n return newID;\n }\n\n private get trackedSessionIDs(): string[] {\n return this.persistedData.sessionIds ?? [];\n }\n\n private set trackedSessionIDs(ids: string[]) {\n this.persistedData.sessionIds = ids;\n savePersistedData(this.persistedData);\n this.state.updateTrackedSessionIDs(ids);\n this.syncPolling(ids.length > 0);\n }\n\n private syncPolling(hasSessions: boolean): void {\n if (this.config.backgroundPolling && hasSessions) {\n if (this.pollingTimer === null) {\n this.startPolling();\n }\n } else if (!hasSessions) {\n this.stopPolling();\n }\n }\n\n private addTrackedSession(id: string): void {\n const ids = this.trackedSessionIDs;\n if (!ids.includes(id)) {\n this.trackedSessionIDs = [...ids, id];\n }\n }\n\n // ---------- Constructor ----------\n\n constructor(config: PRBEAgentConfig) {\n this.config = {\n apiKey: config.apiKey,\n autoApprovedDirs: config.autoApprovedDirs,\n pollingInterval: config.pollingInterval ?? 600_000,\n maxLogEntries: config.maxLogEntries ?? 10_000,\n captureConsole: config.captureConsole ?? true,\n backgroundPolling: config.backgroundPolling ?? true,\n };\n this.interactionHandler = config.interactionHandler;\n this.appDataPath = config.appDataPath;\n this.sessionMetadata = { sdk_version: SDK_VERSION, ...config.sessionMetadata };\n\n // Auto-add appDataPath to autoApprovedDirs if not already present\n if (this.appDataPath && !this.config.autoApprovedDirs.includes(this.appDataPath)) {\n this.config.autoApprovedDirs.push(this.appDataPath);\n }\n\n this.state = new PRBEAgentState();\n this.logCapture = new PRBELogCapture(this.config.maxLogEntries);\n this.persistedData = loadPersistedData();\n this.historyStore = new HistoryStore(this.config.apiKey);\n\n // Eagerly generate agent ID so it's available for setUserIdentifier() immediately\n void this.agentID;\n const history = this.historyStore.load();\n this.state.completedInvestigations = history.investigations;\n this.state.completedCRs = history.crs;\n\n const roots = this.config.autoApprovedDirs;\n const requester: PRBEInteractionRequester | undefined = this.interactionHandler ? this : undefined;\n const grantedPaths = this.grantedPaths;\n\n // Register built-in filesystem tools\n this.registry.register(new ListDirectoryTool(roots, requester, grantedPaths));\n this.registry.register(new ReadFileTool(roots, requester, grantedPaths));\n this.registry.register(new SearchContentTool(roots, requester, grantedPaths));\n this.registry.register(new FindFilesTool(roots, requester, grantedPaths));\n this.registry.register(\n new FlagFileTool(roots, (file) => {\n this.pendingFlaggedFiles.push(file);\n }, requester, grantedPaths),\n );\n\n // Register built-in log tools\n this.registry.register(new ReadAppLogsTool(this.logCapture));\n this.registry.register(new SearchAppLogsTool(this.logCapture));\n this.registry.register(new ClearAppLogsTool(this.logCapture));\n this.registry.register(\n new FlagAppLogsTool(this.logCapture, (file) => {\n this.pendingFlaggedFiles.push(file);\n }),\n );\n\n // Register interactive tools (only when handler is available)\n if (requester) {\n this.registry.register(new AskUserTool(requester));\n this.registry.register(new BashExecuteTool(requester, roots, grantedPaths));\n }\n\n // Register message_user tool — surfaces agent messages to the UI\n this.registry.register(\n new PRBEClosureTool(\n \"client_message_user\",\n \"Send a message to the user.\",\n [{ name: \"message\", type: ToolParamType.STRING, description: \"Message for the user\", required: true }],\n async (args) => {\n const message = (args[\"message\"] as string) ?? \"\";\n if (this.currentInvestigationSource === InvestigationSource.CONTEXT_REQUEST && this.currentCRId) {\n this.state.setCRAgentMessage(this.currentCRId, message);\n } else {\n this.state.setAgentMessage(message);\n }\n return \"Message delivered.\";\n },\n ),\n );\n\n // Start console capture if configured\n if (this.config.captureConsole) {\n this.logCapture.startCapturing();\n }\n\n // Hook electron-log if provided\n if (config.electronLog) {\n this.hookElectronLog(config.electronLog);\n }\n\n // Listen for renderer log forwarding via IPC if provided\n if (config.ipcMain) {\n this.hookRendererLogs(config.ipcMain, config.rendererLogChannel ?? \"prbe-renderer-log\");\n }\n\n // Bootstrap: trigger syncPolling + state update for existing sessions\n const existingSessions = this.trackedSessionIDs;\n if (existingSessions.length > 0) {\n this.trackedSessionIDs = existingSessions;\n }\n }\n\n\n // ---------- Log integration ----------\n\n private hookElectronLog(electronLog: NonNullable<PRBEAgentConfig[PRBEAgentConfigKey.ELECTRON_LOG]>): void {\n try {\n electronLog.hooks.push(\n (message: { level: string; data: any[] }, _transportFn: any, transportName: string) => {\n if (transportName !== \"file\") return message;\n try {\n const text = message.data\n .map((d: any) => (typeof d === \"string\" ? d : JSON.stringify(d)))\n .join(\" \");\n const level = PRBEAgent.mapElectronLogLevel(message.level);\n this.logCapture.log(text, level, `electron-log.${message.level}`);\n } catch {\n // ignore serialization errors\n }\n return message;\n },\n );\n } catch {\n // electron-log not available or incompatible\n }\n }\n\n private hookRendererLogs(\n ipcMain: NonNullable<PRBEAgentConfig[PRBEAgentConfigKey.IPC_MAIN]>,\n channel: string,\n ): void {\n ipcMain.on(channel, (_event: any, entry: { message: string; level: string; category: string }) => {\n this.logCapture.log(entry.message, entry.level, `renderer.${entry.category}`);\n });\n }\n\n private static mapElectronLogLevel(level: string): string {\n switch (level) {\n case \"error\": return \"ERROR\";\n case \"warn\": return \"WARNING\";\n case \"debug\":\n case \"verbose\":\n case \"silly\": return \"DEBUG\";\n default: return \"INFO\";\n }\n }\n\n // ---------- PRBEInteractionRequester implementation ----------\n\n get investigationSource(): InvestigationSource {\n return this.currentInvestigationSource;\n }\n\n sendConversationMessage(content: string): void {\n this.activeConnection?.sendConversationMessage(content);\n }\n\n async requestUserInteraction(payload: InteractionPayload): Promise<InteractionResponse> {\n if (!this.interactionHandler) {\n throw new PRBEAgentError(\n PRBEAgentErrorType.SERVER_ERROR,\n \"No interaction handler configured\",\n );\n }\n\n // Update state to show pending interaction\n if (this.currentInvestigationSource === InvestigationSource.CONTEXT_REQUEST && this.currentCRId) {\n this.state.setCRPendingInteraction(this.currentCRId, payload);\n } else {\n this.state.setPendingInteraction(payload);\n }\n\n try {\n const response = await this.interactionHandler.handleInteraction(payload);\n if (this.currentInvestigationSource === InvestigationSource.CONTEXT_REQUEST && this.currentCRId) {\n this.state.resolveCRInteraction(this.currentCRId, response);\n } else {\n this.state.resolveInteraction(response);\n }\n\n // Send permission decisions to conversation history\n if (response.type === InteractionType.REQUEST_PERMISSION) {\n const approved = (response as RequestPermissionResponse).approved;\n this.sendConversationMessage(approved ? \"Approved\" : \"Denied\");\n } else if (response.type === InteractionType.REQUEST_PATH_ACCESS) {\n const granted = (response as RequestPathAccessResponse).granted;\n this.sendConversationMessage(granted ? \"Allowed\" : \"Denied\");\n }\n\n return response;\n } catch (err) {\n if (this.currentInvestigationSource === InvestigationSource.CONTEXT_REQUEST && this.currentCRId) {\n this.state.clearCRPendingInteraction(this.currentCRId);\n } else {\n this.state.clearPendingInteraction();\n }\n throw err;\n }\n }\n\n /**\n * Add an additional root directory to the runtime allowed roots.\n */\n addAutoApprovedDir(rootPath: string): void {\n if (!this.config.autoApprovedDirs.includes(rootPath)) {\n this.config.autoApprovedDirs.push(rootPath);\n }\n }\n\n // ---------- Public API ----------\n\n /**\n * Update session metadata. Merged with existing metadata.\n * Call this to add user profile data, app version, etc. after async initialization.\n */\n updateSessionMetadata(metadata: Record<string, unknown>): void {\n this.sessionMetadata = { ...this.sessionMetadata, ...metadata };\n }\n\n /**\n * Set a user identifier for this agent. Persists to the backend agents table.\n * Can be called multiple times with different types to set both email and ID.\n * Also auto-injects user_email and/or user_id into session metadata for investigations.\n */\n setUserIdentifier(type: UserIdentifierType, value: string): void {\n if (type === UserIdentifierType.EMAIL) {\n this.userEmail = value;\n } else {\n this.userId = value;\n }\n this.syncUserIdentifierToBackend(type, value);\n }\n\n /**\n * Clear user identifier(s) for this agent.\n * Pass a specific type to clear only that identifier, or omit to clear both email and ID.\n */\n clearUserIdentifier(type?: UserIdentifierType): void {\n if (type) {\n if (type === UserIdentifierType.EMAIL) {\n this.userEmail = undefined;\n } else {\n this.userId = undefined;\n }\n this.syncUserIdentifierToBackend(type, null);\n } else {\n this.userEmail = undefined;\n this.userId = undefined;\n this.syncUserIdentifierToBackend(UserIdentifierType.EMAIL, null);\n this.syncUserIdentifierToBackend(UserIdentifierType.ID, null);\n }\n }\n\n private syncUserIdentifierToBackend(type: UserIdentifierType, value: string | null): void {\n void this.post(\"/api/agent/update-user\", {\n agent_id: this.agentID,\n identifier_type: type,\n identifier_value: value,\n }).catch((err) => {\n console.error(`[PRBEAgent] Failed to sync user identifier: ${err}`);\n });\n }\n\n /**\n * Register a custom tool that the middleware can invoke during investigations.\n */\n registerTool(\n name: string,\n description: string,\n parameters: PRBEToolParameter[],\n handler: (args: Record<string, unknown>) => Promise<string>,\n options?: { interactive?: boolean },\n ): void {\n this.registry.register(\n new PRBEClosureTool(name, description, parameters, handler, options),\n );\n }\n\n /**\n * User-initiated investigation. Updates `state` events/report directly.\n */\n async investigate(query: string, contextRequestID?: string): Promise<void> {\n this.userCancelled = false;\n this.currentInvestigationSource = InvestigationSource.USER;\n this.currentCRId = null;\n\n this.state.beginInvestigation(query);\n\n const emitter = (status: PRBEAgentStatus): void => {\n // Update state based on status\n switch (status.type) {\n case PRBEAgentStatusType.STARTED:\n this.state.appendEvent(\"Starting investigation...\");\n break;\n case PRBEAgentStatusType.THINKING:\n break;\n case PRBEAgentStatusType.TOOL_CALL:\n this.state.appendEvent(status.label);\n break;\n case PRBEAgentStatusType.OBSERVATION:\n this.state.attachObservation(status.text);\n break;\n case PRBEAgentStatusType.THOUGHT:\n this.state.appendEvent(\"Thinking\", status.text);\n break;\n case PRBEAgentStatusType.COMPLETED:\n this.state.completeInvestigation(status.report, status.ticketId);\n this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);\n break;\n case PRBEAgentStatusType.ERROR:\n this.state.failInvestigation(status.message);\n break;\n }\n };\n\n const result = await this.connectToProxy(\n query,\n contextRequestID,\n emitter,\n () => this.userCancelled,\n );\n\n this.currentInvestigationSource = InvestigationSource.USER;\n this.currentCRId = null;\n\n if (result?.sessionId) {\n this.addTrackedSession(result.sessionId);\n } else if (!result) {\n // No result — either cancelled or errored\n if (this.state.isInvestigating) {\n const message = this.userCancelled\n ? \"Investigation cancelled\"\n : \"Investigation ended unexpectedly\";\n this.state.failInvestigation(message);\n }\n }\n }\n\n /**\n * Cancel user-initiated investigation only (does not cancel background CRs).\n */\n cancelInvestigation(): void {\n this.userCancelled = true;\n if (this.activeConnection) {\n this.activeConnection.close(1000, \"User cancelled\");\n this.activeConnection = null;\n }\n }\n\n /**\n * Cancel everything — user investigation and polling.\n */\n cancel(): void {\n this.userCancelled = true;\n if (this.activeConnection) {\n this.activeConnection.close(1000, \"User cancelled\");\n this.activeConnection = null;\n }\n this.abortInFlightRequests();\n this.stopPolling();\n }\n\n /**\n * Poll the backend for context requests on tracked tickets.\n * Resolves session IDs → ticket IDs first, then polls with ticket IDs.\n */\n async poll(): Promise<PollResponse | null> {\n const sessionIDs = this.trackedSessionIDs;\n if (sessionIDs.length === 0) return null;\n\n try {\n // Step 1: Resolve sessions → tickets\n const resolved = await this.resolveSessions(sessionIDs);\n\n // Step 2+3: Prune in one pass — remove deleted sessions and resolved tickets' sessions\n const returnedSessionIDs = new Set(\n resolved.tickets.flatMap((t) => t.session_ids),\n );\n const resolvedSessionIDs = new Set(\n resolved.tickets\n .filter((t) => t.status === \"resolved\")\n .flatMap((t) => t.session_ids),\n );\n const survivingSessions = sessionIDs.filter(\n (id) => returnedSessionIDs.has(id) && !resolvedSessionIDs.has(id),\n );\n if (survivingSessions.length !== sessionIDs.length) {\n this.trackedSessionIDs = survivingSessions;\n }\n\n // Step 4: Poll with resolved ticket IDs\n const ticketIDs = resolved.tickets\n .filter((t) => t.status !== \"resolved\")\n .map((t) => t.ticket_id);\n\n if (ticketIDs.length === 0) return { tickets: [] };\n\n const request: PollRequest = {\n agent_id: this.agentID,\n ticket_ids: ticketIDs,\n };\n\n const response = await this.post<PollResponse>(\n \"/api/agent/poll\",\n request,\n );\n\n // Backend already filters out CRs this agent has responded to,\n // so every CR in the response is one we need to investigate.\n for (const ticket of response.tickets) {\n for (const cr of ticket.context_requests) {\n if (!cr.is_active) continue;\n await this.investigateForCR(cr, ticket.ticket_id);\n }\n }\n\n return response;\n } catch {\n return null;\n }\n }\n\n /**\n * Fetch ticket display info for all tracked sessions.\n * Resolves session IDs → ticket IDs first, then fetches ticket info.\n */\n async fetchTicketInfo(): Promise<TicketInfoOut[]> {\n const sessionIDs = this.trackedSessionIDs;\n if (sessionIDs.length === 0) return [];\n\n try {\n const resolved = await this.resolveSessions(sessionIDs);\n const ticketIDs = resolved.tickets.map((t) => t.ticket_id);\n if (ticketIDs.length === 0) return [];\n\n const request: TicketInfoRequest = { ticket_ids: ticketIDs };\n const response = await this.post<TicketInfoResponse>(\n \"/api/agent/tickets\",\n request,\n );\n this.state.updateTicketInfo(response.tickets);\n return response.tickets;\n } catch {\n return [];\n }\n }\n\n stopPolling(): void {\n if (this.pollingTimer !== null) {\n clearInterval(this.pollingTimer);\n this.pollingTimer = null;\n }\n }\n\n resumePolling(): void {\n if (this.trackedSessionIDs.length === 0) return;\n this.startPolling();\n }\n\n /**\n * Destroy the agent — stops polling, stops console capture, closes WS.\n */\n destroy(): void {\n this.cancel();\n this.logCapture.stopCapturing();\n }\n\n /**\n * Reset all persisted data (agent ID, tracked tickets, responded CRs).\n * Also clears in-memory state.\n */\n resetPersistedData(): void {\n this.stopPolling();\n this.persistedData = {};\n savePersistedData(this.persistedData);\n HistoryStore.clear();\n this.state.resetInvestigation();\n this.state.completedInvestigations = [];\n this.state.activeCRs.clear();\n this.state.completedCRs = [];\n this.state.trackedSessionIDs = [];\n this.state.ticketInfo = [];\n this.state.emit(PRBEStateEvent.STATUS);\n }\n\n /**\n * Delete the persisted data file. Can be called without an agent instance.\n */\n static clearPersistedData(): void {\n try {\n const filePath = getPersistencePath();\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n HistoryStore.clear();\n } catch {\n // Ignore\n }\n }\n\n // ---------- CR Investigation ----------\n\n private async investigateForCR(\n cr: ContextRequestOut,\n ticketId: string,\n ): Promise<void> {\n const crID = cr.id;\n this.currentInvestigationSource = InvestigationSource.CONTEXT_REQUEST;\n this.currentCRId = crID;\n\n this.state.beginCR(crID, cr.query, cr.slug ?? undefined, ticketId);\n\n const emitter = (status: PRBEAgentStatus): void => {\n switch (status.type) {\n case PRBEAgentStatusType.STARTED:\n this.state.appendCREvent(crID, \"Starting investigation...\");\n break;\n case PRBEAgentStatusType.THINKING:\n break;\n case PRBEAgentStatusType.TOOL_CALL:\n this.state.appendCREvent(crID, status.label);\n break;\n case PRBEAgentStatusType.OBSERVATION:\n this.state.attachCRObservation(crID, status.text);\n break;\n case PRBEAgentStatusType.THOUGHT:\n this.state.appendCREvent(crID, \"Thinking\", status.text);\n break;\n case PRBEAgentStatusType.COMPLETED:\n this.state.completeCR(crID, status.report);\n this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);\n break;\n case PRBEAgentStatusType.ERROR:\n this.state.failCR(crID, status.message);\n this.historyStore.save(this.state.completedInvestigations, this.state.completedCRs);\n break;\n }\n };\n\n const result = await this.connectToProxy(\n cr.query,\n crID,\n emitter,\n () => false, // CRs are not user-cancellable\n ticketId,\n );\n\n this.currentInvestigationSource = InvestigationSource.USER;\n this.currentCRId = null;\n\n if (result?.sessionId) {\n this.addTrackedSession(result.sessionId);\n }\n }\n\n // ---------- WebSocket Investigation ----------\n\n private connectToProxy(\n query: string,\n contextRequestID: string | undefined,\n emit: (status: PRBEAgentStatus) => void,\n isCancelled: () => boolean,\n ticketId?: string,\n ): Promise<InvestigationResult | null> {\n return new Promise<InvestigationResult | null>((resolve) => {\n const wsUrl = `${MIDDLEWARE_URL}/api/agent/client/ws`;\n let uploadBaseUrl: string | undefined;\n let resolved = false;\n\n const finish = (result: InvestigationResult | null) => {\n if (resolved) return;\n resolved = true;\n this.activeConnection = null;\n resolve(result);\n };\n\n let conn: InvestigationConnection;\n try {\n conn = new InvestigationConnection(\n wsUrl,\n this.config.apiKey,\n (msg) => this.handleMessage(msg, conn, emit, isCancelled, finish, () => uploadBaseUrl, (url) => { uploadBaseUrl = url; }),\n (message) => {\n if (!isCancelled()) emit({ type: PRBEAgentStatusType.ERROR, message });\n finish(null);\n },\n () => {\n if (!resolved) {\n if (isCancelled()) {\n finish(null);\n } else {\n emit({ type: PRBEAgentStatusType.ERROR, message: \"WebSocket connection closed unexpectedly\" });\n finish(null);\n }\n }\n },\n );\n } catch (err) {\n emit({ type: PRBEAgentStatusType.ERROR, message: `Failed to create WebSocket: ${err}` });\n resolve(null);\n return;\n }\n\n this.activeConnection = conn;\n\n conn.onopen = () => {\n const toolDeclarations = this.registry\n .allDeclarations()\n .map((decl) => ({\n name: decl.name,\n description: decl.description,\n parameters: decl.parameters.map((param) => ({\n name: param.name,\n type: param.type,\n description: param.description,\n required: param.required,\n })),\n ...(decl.interactive ? { interactive: true } : {}),\n }));\n\n const startMetadata: Record<string, unknown> = {\n agent_id: this.agentID,\n custom_tools: toolDeclarations,\n platform: os.platform(),\n os_version: os.release(),\n arch: os.arch(),\n };\n if (contextRequestID) startMetadata[\"context_request_id\"] = contextRequestID;\n if (ticketId) startMetadata[\"ticket_id\"] = ticketId;\n if (this.appDataPath) startMetadata[\"app_data_path\"] = this.appDataPath;\n // Auto-inject user identifiers into session metadata\n const enrichedMetadata = { ...this.sessionMetadata };\n if (this.userEmail) {\n enrichedMetadata[\"user_email\"] = this.userEmail;\n }\n if (this.userId) {\n enrichedMetadata[\"user_id\"] = this.userId;\n }\n if (Object.keys(enrichedMetadata).length > 0) {\n startMetadata[\"session_metadata\"] = enrichedMetadata;\n }\n\n if (!conn.send({ type: WSMessageType.START, content: query, metadata: startMetadata })) {\n emit({ type: PRBEAgentStatusType.ERROR, message: \"Failed to send start message\" });\n finish(null);\n return;\n }\n\n emit({ type: PRBEAgentStatusType.STARTED });\n this.pendingFlaggedFiles = [];\n };\n });\n }\n\n private async handleMessage(\n msg: WSMessage,\n conn: InvestigationConnection,\n emit: (status: PRBEAgentStatus) => void,\n isCancelled: () => boolean,\n finish: (result: InvestigationResult | null) => void,\n getUploadBaseUrl: () => string | undefined,\n setUploadBaseUrl: (url: string | undefined) => void,\n ): Promise<void> {\n if (isCancelled()) {\n conn.sendCancel();\n conn.close(1000, \"Cancelled\");\n finish(null);\n return;\n }\n\n switch (msg.type) {\n case WSMessageType.THOUGHT:\n emit({ type: PRBEAgentStatusType.THOUGHT, text: msg.content ?? \"\" });\n break;\n\n case WSMessageType.TOOL_CALL: {\n const toolName = msg.name ?? \"\";\n const callId = msg.id ?? \"\";\n const args = this.extractArgs(msg.metadata);\n\n emit({ type: PRBEAgentStatusType.TOOL_CALL, name: toolName, label: msg.content ?? `Running ${toolName}` });\n\n this.pendingFlaggedFiles = [];\n const toolResult = redactPII(await this.registry.execute(toolName, args));\n emit({ type: PRBEAgentStatusType.OBSERVATION, text: toolResult.substring(0, 200) });\n\n // Build refs for any files flagged during this tool call\n let resultMetadata: Record<string, unknown> | undefined;\n const uploadBaseUrl = getUploadBaseUrl();\n if (this.pendingFlaggedFiles.length > 0 && uploadBaseUrl) {\n const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);\n const uploadedRefs: Array<Record<string, unknown>> = [];\n\n for (const file of this.pendingFlaggedFiles) {\n const filename = path.basename(file.originalPath);\n const safeName = encodeURIComponent(filename);\n const storagePath = `${uploadPrefix}/${safeName}`;\n uploadedRefs.push({\n original_path: file.originalPath,\n reason: file.reason ?? \"\",\n storage_path: storagePath,\n file_size_bytes: file.data.length,\n });\n\n const uploadUrl = `${uploadBaseUrl}/${safeName}`;\n const contentType = file.isText ? \"text/plain\" : \"application/octet-stream\";\n void PRBEAgent.backgroundUpload(file.data, uploadUrl, this.config.apiKey, contentType, this.getFetchSignal());\n }\n resultMetadata = { flagged_files: uploadedRefs };\n this.pendingFlaggedFiles = [];\n }\n\n conn.sendToolResult(callId, toolName, toolResult, resultMetadata);\n break;\n }\n\n case WSMessageType.SERVER_TOOL_CALL:\n emit({ type: PRBEAgentStatusType.TOOL_CALL, name: msg.name ?? \"\", label: msg.content ?? \"\" });\n break;\n\n case WSMessageType.SERVER_OBSERVATION:\n emit({ type: PRBEAgentStatusType.OBSERVATION, text: (msg.content ?? \"\").substring(0, 200) });\n break;\n\n case WSMessageType.COMPLETE: {\n const report = msg.content ?? \"\";\n const completedTicketId = msg.metadata?.[\"ticket_id\"] as string | undefined;\n const sessionId = msg.metadata?.[\"session_id\"] as string | undefined;\n emit({ type: PRBEAgentStatusType.COMPLETED, report, ticketId: completedTicketId });\n conn.close(1000, \"Complete\");\n finish({ report, ticketId: completedTicketId, sessionId });\n break;\n }\n\n case WSMessageType.ERROR:\n emit({ type: PRBEAgentStatusType.ERROR, message: msg.content || \"Unknown error\" });\n conn.close(1000, \"Error received\");\n finish(null);\n break;\n\n case WSMessageType.SESSION_CONFIG:\n setUploadBaseUrl(msg.metadata?.[\"upload_url\"] as string | undefined);\n break;\n\n case WSMessageType.CONVERSATION_UPDATE: {\n try {\n const entry = JSON.parse(msg.content ?? \"{}\") as ConversationEntry;\n this.state.appendConversation(entry);\n } catch { /* ignore malformed entries */ }\n break;\n }\n\n case WSMessageType.PING:\n conn.sendPong();\n break;\n\n default:\n break;\n }\n }\n\n private extractArgs(\n metadata: Record<string, unknown> | undefined,\n ): Record<string, unknown> {\n if (!metadata) return {};\n const argsVal = metadata[\"args\"];\n if (argsVal && typeof argsVal === \"object\" && !Array.isArray(argsVal)) {\n return argsVal as Record<string, unknown>;\n }\n return {};\n }\n\n private extractUploadPrefix(baseUrl: string): string {\n try {\n const url = new URL(baseUrl);\n const urlPath = url.pathname; // \"/api/agent/upload/{tenant}/{uuid}/files\"\n const marker = \"/api/agent/upload/\";\n const idx = urlPath.indexOf(marker);\n if (idx !== -1) {\n return urlPath.substring(idx + marker.length);\n }\n } catch {\n // Ignore URL parse errors\n }\n return \"\";\n }\n\n // ---------- File Upload ----------\n\n private static async backgroundUpload(\n data: Buffer,\n uploadUrl: string,\n apiKey: string,\n contentType: string,\n signal?: AbortSignal,\n ): Promise<void> {\n try {\n const response = await fetch(uploadUrl, {\n method: \"PUT\",\n headers: {\n \"Content-Type\": contentType,\n \"X-API-Key\": apiKey,\n },\n body: data,\n signal,\n });\n\n if (!response.ok) {\n console.error(\n `[PRBEAgent] file upload failed: HTTP ${response.status} for ${uploadUrl}`,\n );\n }\n } catch (err) {\n console.error(`[PRBEAgent] file upload error: ${err} for ${uploadUrl}`);\n }\n }\n\n // ---------- Polling ----------\n\n private startPolling(): void {\n this.stopPolling();\n this.pollingTimer = setInterval(() => {\n void this.poll().then(() => {\n if (this.trackedSessionIDs.length === 0) {\n this.stopPolling();\n }\n });\n }, this.config.pollingInterval);\n }\n\n // ---------- Session Resolution ----------\n\n private async resolveSessions(sessionIDs: string[]): Promise<ResolveSessionsResponse> {\n const request: ResolveSessionsRequest = {\n agent_id: this.agentID,\n session_ids: sessionIDs,\n };\n return this.post<ResolveSessionsResponse>(\n \"/api/agent/resolve-sessions\",\n request,\n );\n }\n\n // ---------- Networking ----------\n\n /**\n * Abort all in-flight fetch requests to prevent orphaned DNS lookups\n * that can crash the c-ares resolver during process shutdown.\n */\n private abortInFlightRequests(): void {\n if (this.fetchAbortController) {\n this.fetchAbortController.abort();\n this.fetchAbortController = null;\n }\n }\n\n /**\n * Get an AbortSignal for fetch requests. Creates a new controller if needed.\n */\n private getFetchSignal(): AbortSignal {\n if (!this.fetchAbortController) {\n this.fetchAbortController = new AbortController();\n }\n return this.fetchAbortController.signal;\n }\n\n private async post<Res>(urlPath: string, body: unknown): Promise<Res> {\n const url = `${API_URL}${urlPath}`;\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.config.apiKey,\n },\n body: JSON.stringify(body),\n signal: this.getFetchSignal(),\n });\n\n if (!response.ok) {\n const message = await response.text().catch(() => \"Unknown error\");\n throw new PRBEAgentError(\n PRBEAgentErrorType.SERVER_ERROR,\n `Server error ${response.status}: ${message}`,\n response.status,\n );\n }\n\n return (await response.json()) as Res;\n }\n}\n","/**\n * models.ts — WSMessage, WSMessageType, tool types, config, errors\n *\n * All types must match the Swift SDK + middleware protocol exactly.\n */\n\n// ---------------------------------------------------------------------------\n// WebSocket Message Types\n// ---------------------------------------------------------------------------\n\nexport enum WSMessageType {\n // SDK -> Middleware\n START = \"start\",\n TOOL_RESULT = \"tool_result\",\n UPLOAD_REQUEST = \"upload_request\",\n CONVERSATION_MESSAGE = \"conversation_message\",\n CANCEL = \"cancel\",\n PONG = \"pong\",\n // Middleware -> SDK\n THOUGHT = \"thought\",\n TOOL_CALL = \"tool_call\",\n SERVER_TOOL_CALL = \"server_tool_call\",\n SERVER_OBSERVATION = \"server_observation\",\n UPLOAD_URL = \"upload_url\",\n SESSION_CONFIG = \"session_config\",\n CONVERSATION_UPDATE = \"conversation_update\",\n COMPLETE = \"complete\",\n ERROR = \"error\",\n PING = \"ping\",\n}\n\n// ---------------------------------------------------------------------------\n// Conversation\n// ---------------------------------------------------------------------------\n\nexport enum ConversationRole {\n User = \"user\",\n Agent = \"agent\",\n}\n\nexport interface ConversationEntry {\n role: ConversationRole;\n content: string;\n label?: string;\n ts: string;\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket Message\n// ---------------------------------------------------------------------------\n\nexport interface WSMessage {\n type: WSMessageType;\n id?: string;\n name?: string;\n content?: string;\n metadata?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Tool System\n// ---------------------------------------------------------------------------\n\nexport enum ToolParamType {\n STRING = \"STRING\",\n BOOLEAN = \"BOOLEAN\",\n INTEGER = \"INTEGER\",\n}\n\nexport interface PRBEToolParameter {\n name: string;\n type: ToolParamType;\n description: string;\n required: boolean;\n}\n\nexport interface PRBEToolDeclaration {\n name: string;\n description: string;\n parameters: PRBEToolParameter[];\n /** When true, the middleware uses a longer timeout for this tool (user interaction required). */\n interactive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Tool Names (must match middleware exactly)\n// ---------------------------------------------------------------------------\n\nexport enum ToolName {\n CLIENT_LIST_DIRECTORY = \"client_list_directory\",\n CLIENT_READ_FILE = \"client_read_file\",\n CLIENT_SEARCH_CONTENT = \"client_search_content\",\n CLIENT_FIND_FILES = \"client_find_files\",\n CLIENT_FLAG_FILE = \"client_flag_file\",\n CLIENT_READ_APP_LOGS = \"client_read_app_logs\",\n CLIENT_SEARCH_APP_LOGS = \"client_search_app_logs\",\n CLIENT_CLEAR_APP_LOGS = \"client_clear_app_logs\",\n CLIENT_FLAG_APP_LOGS = \"client_flag_app_logs\",\n CLIENT_ASK_USER = \"client_ask_user\",\n CLIENT_BASH_EXECUTE = \"client_bash_execute\",\n CLIENT_MESSAGE_USER = \"client_message_user\",\n}\n\n// ---------------------------------------------------------------------------\n// User Identifier\n// ---------------------------------------------------------------------------\n\nexport enum UserIdentifierType {\n EMAIL = \"email\",\n ID = \"id\",\n}\n\n// ---------------------------------------------------------------------------\n// Agent Configuration\n// ---------------------------------------------------------------------------\n\nexport enum PRBEAgentConfigKey {\n API_KEY = \"apiKey\",\n AUTO_APPROVED_DIRS = \"autoApprovedDirs\",\n POLLING_INTERVAL = \"pollingInterval\",\n MAX_LOG_ENTRIES = \"maxLogEntries\",\n CAPTURE_CONSOLE = \"captureConsole\",\n BACKGROUND_POLLING = \"backgroundPolling\",\n INTERACTION_HANDLER = \"interactionHandler\",\n ELECTRON_LOG = \"electronLog\",\n IPC_MAIN = \"ipcMain\",\n RENDERER_LOG_CHANNEL = \"rendererLogChannel\",\n APP_DATA_PATH = \"appDataPath\",\n SESSION_METADATA = \"sessionMetadata\",\n}\n\nexport interface PRBEAgentConfig {\n [PRBEAgentConfigKey.API_KEY]: string;\n [PRBEAgentConfigKey.AUTO_APPROVED_DIRS]: string[];\n [PRBEAgentConfigKey.POLLING_INTERVAL]?: number; // ms, default 600_000 (10 min)\n [PRBEAgentConfigKey.MAX_LOG_ENTRIES]?: number; // default 10_000\n [PRBEAgentConfigKey.CAPTURE_CONSOLE]?: boolean; // default true\n [PRBEAgentConfigKey.BACKGROUND_POLLING]?: boolean; // default true\n [PRBEAgentConfigKey.INTERACTION_HANDLER]?: import(\"./interactions\").PRBEInteractionHandler;\n /** electron-log instance (v5) — SDK hooks into its transports to capture main-process logs */\n [PRBEAgentConfigKey.ELECTRON_LOG]?: { hooks: { push: (hook: (...args: any[]) => any) => void } };\n /** Electron ipcMain instance — SDK listens for renderer log forwarding */\n [PRBEAgentConfigKey.IPC_MAIN]?: { on: (channel: string, listener: (event: any, ...args: any[]) => void) => void };\n /** IPC channel name for renderer log forwarding (default: \"prbe-renderer-log\") */\n [PRBEAgentConfigKey.RENDERER_LOG_CHANNEL]?: string;\n /** Path to the application's data directory (e.g. Electron userData). Sent to the agent so it explores this directory first. */\n [PRBEAgentConfigKey.APP_DATA_PATH]?: string;\n /** Custom metadata included in every session submission (e.g. user profile, app version). */\n [PRBEAgentConfigKey.SESSION_METADATA]?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Agent Status\n// ---------------------------------------------------------------------------\n\nexport enum PRBEAgentStatusType {\n STARTED = \"started\",\n THINKING = \"thinking\",\n TOOL_CALL = \"tool_call\",\n THOUGHT = \"thought\",\n OBSERVATION = \"observation\",\n COMPLETED = \"completed\",\n ERROR = \"error\",\n AWAITING_INTERACTION = \"awaiting_interaction\",\n}\n\nexport type PRBEAgentStatus =\n | { type: PRBEAgentStatusType.STARTED }\n | { type: PRBEAgentStatusType.THINKING }\n | { type: PRBEAgentStatusType.TOOL_CALL; name: string; label: string }\n | { type: PRBEAgentStatusType.THOUGHT; text: string }\n | { type: PRBEAgentStatusType.OBSERVATION; text: string }\n | { type: PRBEAgentStatusType.COMPLETED; report: string; ticketId?: string }\n | { type: PRBEAgentStatusType.ERROR; message: string }\n | { type: PRBEAgentStatusType.AWAITING_INTERACTION; interactionPayload: import(\"./interactions\").InteractionPayload };\n\n// ---------------------------------------------------------------------------\n// Investigation Result (internal)\n// ---------------------------------------------------------------------------\n\nexport interface InvestigationResult {\n report: string;\n ticketId?: string;\n sessionId?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Flagged File (internal)\n// ---------------------------------------------------------------------------\n\nexport interface FlaggedFileIn {\n originalPath: string;\n reason?: string;\n data: Buffer;\n isText: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Poll Endpoint\n// ---------------------------------------------------------------------------\n\nexport interface PollRequest {\n agent_id: string;\n ticket_ids: string[];\n}\n\nexport interface ContextRequestOut {\n id: string;\n query: string;\n slug?: string;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface TicketStatusOut {\n ticket_id: string;\n status: string;\n context_requests: ContextRequestOut[];\n}\n\nexport interface PollResponse {\n tickets: TicketStatusOut[];\n}\n\n// ---------------------------------------------------------------------------\n// Ticket Info\n// ---------------------------------------------------------------------------\n\nexport interface TicketInfoRequest {\n ticket_ids: string[];\n}\n\nexport interface TicketInfoOut {\n ticket_id: string;\n title: string;\n status: string;\n priority?: string;\n description?: string;\n session_count: number;\n}\n\nexport interface TicketInfoResponse {\n tickets: TicketInfoOut[];\n}\n\n// ---------------------------------------------------------------------------\n// Status Events (for state tracking)\n// ---------------------------------------------------------------------------\n\nexport interface PRBEStatusEvent {\n id: string;\n label: string;\n detail?: string;\n isCompleted: boolean;\n isExpanded: boolean;\n}\n\nexport interface PRBECRInvestigation {\n id: string;\n query: string;\n slug?: string;\n ticketId?: string;\n events: PRBEStatusEvent[];\n isRunning: boolean;\n isCompleted: boolean;\n isFailed: boolean;\n report: string;\n summary?: string;\n errorMessage?: string;\n agentMessage?: string;\n startedAt: Date;\n pendingInteraction?: import(\"./interactions\").InteractionPayload;\n resolvedInteractions?: import(\"./interactions\").ResolvedInteraction[];\n}\n\n// ---------------------------------------------------------------------------\n// Completed Investigation (persisted in state for history)\n// ---------------------------------------------------------------------------\n\nexport interface PRBECompletedInvestigation {\n id: string;\n query: string;\n report: string;\n summary?: string;\n ticketId?: string;\n events: PRBEStatusEvent[];\n resolvedInteractions: import(\"./interactions\").ResolvedInteraction[];\n conversationHistory?: ConversationEntry[];\n completedAt: Date;\n}\n\n// ---------------------------------------------------------------------------\n// Resolve Sessions\n// ---------------------------------------------------------------------------\n\nexport interface ResolveSessionsRequest {\n agent_id: string;\n session_ids: string[];\n}\n\nexport interface ResolvedTicketOut {\n ticket_id: string;\n status: string;\n session_ids: string[];\n}\n\nexport interface ResolveSessionsResponse {\n tickets: ResolvedTicketOut[];\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport enum PRBEAgentErrorType {\n SERVER_ERROR = \"server_error\",\n NETWORK_ERROR = \"network_error\",\n CANCELLED = \"cancelled\",\n MAX_ITERATIONS = \"max_iterations\",\n}\n\nexport class PRBEAgentError extends Error {\n public readonly errorType: PRBEAgentErrorType;\n public readonly statusCode?: number;\n\n constructor(errorType: PRBEAgentErrorType, message: string, statusCode?: number) {\n super(message);\n this.name = \"PRBEAgentError\";\n this.errorType = errorType;\n this.statusCode = statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// PII Redactor (pass-through stub, matches Swift SDK)\n// ---------------------------------------------------------------------------\n\nexport function redactPII(text: string): string {\n return text;\n}\n\n// ---------------------------------------------------------------------------\n// Static URLs\n// ---------------------------------------------------------------------------\n\nexport const API_URL = \"https://api.prbe.ai\";\nexport const MIDDLEWARE_URL = \"wss://middleware.prbe.ai\";\n","/**\n * connection.ts — InvestigationConnection\n *\n * Encapsulates the WebSocket connection to the middleware for a single investigation.\n * Handles message parsing, sending, and provides a clean interface for the agent.\n */\n\nimport { WSMessageType, ConversationRole } from \"./models\";\nimport type { WSMessage, ConversationEntry } from \"./models\";\n\nexport class InvestigationConnection {\n private ws: WebSocket;\n private closed = false;\n\n constructor(\n url: string,\n apiKey: string,\n private readonly onMessage: (msg: WSMessage) => void,\n private readonly onError: (message: string) => void,\n private readonly onClose: () => void,\n ) {\n this.ws = new WebSocket(url, {\n headers: { \"X-API-Key\": apiKey },\n } as unknown as string[]);\n\n this.ws.onmessage = (event: MessageEvent) => {\n const raw = typeof event.data === \"string\"\n ? event.data\n : event.data instanceof Buffer\n ? event.data.toString(\"utf-8\")\n : null;\n if (!raw) return;\n\n try {\n const msg = JSON.parse(raw) as WSMessage;\n this.onMessage(msg);\n } catch { /* ignore malformed messages */ }\n };\n\n this.ws.onerror = (event: unknown) => {\n const errorEvent = event as { message?: string };\n this.onError(errorEvent.message || \"WebSocket connection error\");\n };\n\n this.ws.onclose = () => {\n this.onClose();\n };\n }\n\n get isOpen(): boolean {\n return !this.closed && this.ws.readyState === WebSocket.OPEN;\n }\n\n send(msg: WSMessage): boolean {\n if (!this.isOpen) return false;\n try {\n this.ws.send(JSON.stringify(msg));\n return true;\n } catch {\n return false;\n }\n }\n\n sendConversationMessage(content: string): void {\n this.send({\n type: WSMessageType.CONVERSATION_MESSAGE,\n content,\n });\n }\n\n sendToolResult(callId: string, toolName: string, result: string, metadata?: Record<string, unknown>): void {\n this.send({\n type: WSMessageType.TOOL_RESULT,\n id: callId,\n name: toolName,\n content: result,\n metadata,\n });\n }\n\n sendCancel(): void {\n this.send({ type: WSMessageType.CANCEL });\n }\n\n sendPong(): void {\n this.send({ type: WSMessageType.PONG });\n }\n\n close(code = 1000, reason?: string): void {\n if (this.closed) return;\n this.closed = true;\n try {\n this.ws.close(code, reason);\n } catch { /* ignore */ }\n }\n\n /**\n * Set the onopen handler. Called when the connection is ready to send messages.\n */\n set onopen(handler: () => void) {\n this.ws.onopen = handler;\n }\n}\n","/**\n * state.ts — PRBEAgentState: EventEmitter-based observable investigation state\n *\n * Mirrors PRBEAgentState.swift but uses Node.js EventEmitter instead of Combine/@Published.\n * Host apps subscribe to events for UI updates.\n */\n\nimport { EventEmitter } from \"events\";\nimport { randomUUID } from \"crypto\";\nimport type {\n PRBEStatusEvent,\n PRBECRInvestigation,\n PRBECompletedInvestigation,\n TicketInfoOut,\n ConversationEntry,\n} from \"./models\";\nimport type { InteractionPayload, InteractionResponse, ResolvedInteraction } from \"./interactions\";\n\n// ---------------------------------------------------------------------------\n// Event types emitted by PRBEAgentState\n// ---------------------------------------------------------------------------\n\nexport enum PRBEStateEvent {\n /** Emitted on any state change. Payload: void */\n STATUS = \"status\",\n /** Emitted when a new event is appended. Payload: PRBEStatusEvent */\n EVENT = \"event\",\n /** Emitted when investigation completes. Payload: { report: string } */\n COMPLETE = \"complete\",\n /** Emitted on error. Payload: { message: string } */\n ERROR = \"error\",\n /** Emitted when a background CR starts. Payload: PRBECRInvestigation */\n CR_START = \"cr-start\",\n /** Emitted when a background CR completes/fails. Payload: PRBECRInvestigation */\n CR_COMPLETE = \"cr-complete\",\n /** Emitted when tracked ticket IDs change. Payload: string[] */\n TICKETS_CHANGED = \"tickets-changed\",\n /** Emitted when ticket info is updated. Payload: TicketInfoOut[] */\n TICKET_INFO = \"ticket-info\",\n /** Emitted when an interaction is requested. Payload: InteractionPayload */\n INTERACTION_REQUESTED = \"interaction-requested\",\n /** Emitted when an interaction is resolved. Payload: void */\n INTERACTION_RESOLVED = \"interaction-resolved\",\n /** Emitted when the agent sends a message to the user. Payload: { message: string } */\n AGENT_MESSAGE = \"agent-message\",\n}\n\n// ---------------------------------------------------------------------------\n// PRBEAgentState\n// ---------------------------------------------------------------------------\n\nexport class PRBEAgentState extends EventEmitter {\n // User-initiated investigation\n public isInvestigating = false;\n public events: PRBEStatusEvent[] = [];\n public report = \"\";\n public summary = \"\";\n public currentQuery = \"\";\n public investigationError?: string;\n public pendingInteraction?: InteractionPayload;\n public resolvedInteractions: ResolvedInteraction[] = [];\n public agentMessage?: string;\n public conversationHistory: ConversationEntry[] = [];\n\n // Completed user investigations (history)\n public completedInvestigations: PRBECompletedInvestigation[] = [];\n\n // Background context requests\n public activeCRs: Map<string, PRBECRInvestigation> = new Map();\n public completedCRs: PRBECRInvestigation[] = [];\n\n // Tracked tickets\n public trackedSessionIDs: string[] = [];\n public ticketInfo: TicketInfoOut[] = [];\n\n // Computed\n get hasActiveWork(): boolean {\n return this.isInvestigating || this.activeCRs.size > 0;\n }\n\n get activeCRCount(): number {\n return this.activeCRs.size;\n }\n\n get isActive(): boolean {\n return this.isInvestigating || this.report.length > 0 || this.investigationError != null;\n }\n\n // ---------- User investigation mutations ----------\n\n beginInvestigation(query: string): void {\n this.isInvestigating = true;\n this.events = [];\n this.resolvedInteractions = [];\n this.conversationHistory = [];\n this.report = \"\";\n this.summary = \"\";\n this.currentQuery = query;\n this.investigationError = undefined;\n this.agentMessage = undefined;\n this.emit(PRBEStateEvent.STATUS);\n }\n\n appendConversation(entry: ConversationEntry): void {\n this.conversationHistory.push(entry);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n resetInvestigation(): void {\n this.isInvestigating = false;\n this.events = [];\n this.resolvedInteractions = [];\n this.conversationHistory = [];\n this.report = \"\";\n this.summary = \"\";\n this.currentQuery = \"\";\n this.investigationError = undefined;\n this.pendingInteraction = undefined;\n this.agentMessage = undefined;\n this.emit(PRBEStateEvent.STATUS);\n }\n\n appendEvent(label: string, detail?: string, completed = false): void {\n // Mark previous event as completed before adding new one\n if (this.events.length > 0) {\n const last = this.events[this.events.length - 1];\n if (!last.isCompleted && !completed) {\n last.isCompleted = true;\n }\n }\n const event: PRBEStatusEvent = {\n id: randomUUID(),\n label,\n detail,\n isCompleted: completed,\n isExpanded: false,\n };\n this.events.push(event);\n this.emit(PRBEStateEvent.EVENT, event);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n attachObservation(text: string): void {\n if (this.events.length > 0) {\n this.events[this.events.length - 1].detail = text;\n this.emit(PRBEStateEvent.STATUS);\n }\n }\n\n completeInvestigation(report: string, ticketId?: string): void {\n if (this.events.length > 0) {\n this.events[this.events.length - 1].isCompleted = true;\n }\n this.appendEvent(\"Done\", undefined, true);\n\n // Save to history (snapshot events + interactions before reset)\n this.completedInvestigations.unshift({\n id: randomUUID(),\n query: this.currentQuery,\n report,\n ticketId,\n events: [...this.events],\n resolvedInteractions: [...this.resolvedInteractions],\n conversationHistory: [...this.conversationHistory],\n completedAt: new Date(),\n });\n\n this.report = report;\n this.isInvestigating = false;\n this.emit(PRBEStateEvent.COMPLETE, { report });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n failInvestigation(message: string): void {\n this.appendEvent(`Error: ${message}`);\n this.investigationError = message;\n this.isInvestigating = false;\n this.emit(PRBEStateEvent.ERROR, { message });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n // ---------- Interaction state mutations ----------\n\n setPendingInteraction(payload: InteractionPayload): void {\n this.pendingInteraction = payload;\n this.emit(PRBEStateEvent.INTERACTION_REQUESTED, payload);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n clearPendingInteraction(): void {\n this.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n setCRPendingInteraction(crID: string, payload: InteractionPayload): void {\n const cr = this.activeCRs.get(crID);\n if (!cr) return;\n cr.pendingInteraction = payload;\n this.emit(PRBEStateEvent.INTERACTION_REQUESTED, payload);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n clearCRPendingInteraction(crID: string): void {\n const cr = this.activeCRs.get(crID);\n if (!cr) return;\n cr.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n resolveInteraction(response: InteractionResponse): void {\n if (!this.pendingInteraction) return;\n this.resolvedInteractions.push({\n interactionId: this.pendingInteraction.interactionId,\n payload: this.pendingInteraction,\n response,\n eventIndex: this.events.length,\n });\n this.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n resolveCRInteraction(crID: string, response: InteractionResponse): void {\n const cr = this.activeCRs.get(crID);\n if (!cr || !cr.pendingInteraction) return;\n const resolved = cr.resolvedInteractions ?? [];\n resolved.push({\n interactionId: cr.pendingInteraction.interactionId,\n payload: cr.pendingInteraction,\n response,\n eventIndex: cr.events.length,\n });\n cr.resolvedInteractions = resolved;\n cr.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n setAgentMessage(message: string): void {\n this.agentMessage = message;\n this.emit(PRBEStateEvent.AGENT_MESSAGE, { message });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n setCRAgentMessage(crID: string, message: string): void {\n const cr = this.activeCRs.get(crID);\n if (!cr) return;\n cr.agentMessage = message;\n this.emit(PRBEStateEvent.AGENT_MESSAGE, { message });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n toggleExpansion(eventId: string): void {\n const event = this.events.find((e) => e.id === eventId);\n if (event) {\n event.isExpanded = !event.isExpanded;\n this.emit(PRBEStateEvent.STATUS);\n }\n }\n\n // ---------- CR state mutations ----------\n\n beginCR(id: string, query: string, slug?: string, ticketId?: string): void {\n const cr: PRBECRInvestigation = {\n id,\n query,\n slug,\n ticketId,\n events: [],\n resolvedInteractions: [],\n isRunning: true,\n isCompleted: false,\n isFailed: false,\n report: \"\",\n summary: \"\",\n startedAt: new Date(),\n };\n this.activeCRs.set(id, cr);\n this.emit(PRBEStateEvent.CR_START, cr);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n appendCREvent(crID: string, label: string, detail?: string, completed = false): void {\n const cr = this.activeCRs.get(crID);\n if (!cr) return;\n\n if (cr.events.length > 0) {\n const last = cr.events[cr.events.length - 1];\n if (!last.isCompleted && !completed) {\n last.isCompleted = true;\n }\n }\n cr.events.push({\n id: randomUUID(),\n label,\n detail,\n isCompleted: completed,\n isExpanded: false,\n });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n attachCRObservation(crID: string, text: string): void {\n const cr = this.activeCRs.get(crID);\n if (!cr || cr.events.length === 0) return;\n cr.events[cr.events.length - 1].detail = text;\n this.emit(PRBEStateEvent.STATUS);\n }\n\n completeCR(id: string, report: string): void {\n const cr = this.activeCRs.get(id);\n if (!cr) return;\n\n this.activeCRs.delete(id);\n if (cr.events.length > 0) {\n cr.events[cr.events.length - 1].isCompleted = true;\n }\n cr.events.push({\n id: randomUUID(),\n label: \"Done\",\n isCompleted: true,\n isExpanded: false,\n });\n cr.isRunning = false;\n cr.isCompleted = true;\n cr.report = report;\n this.completedCRs.unshift(cr);\n this.emit(PRBEStateEvent.CR_COMPLETE, cr);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n failCR(id: string, message: string): void {\n const cr = this.activeCRs.get(id);\n if (!cr) return;\n\n this.activeCRs.delete(id);\n cr.events.push({\n id: randomUUID(),\n label: `Error: ${message}`,\n isCompleted: false,\n isExpanded: false,\n });\n cr.isRunning = false;\n cr.isFailed = true;\n cr.errorMessage = message;\n this.completedCRs.unshift(cr);\n this.emit(PRBEStateEvent.CR_COMPLETE, cr);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n // ---------- Tickets ----------\n\n updateTrackedSessionIDs(ids: string[]): void {\n this.trackedSessionIDs = ids;\n this.emit(PRBEStateEvent.TICKETS_CHANGED, ids);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n updateTicketInfo(info: TicketInfoOut[]): void {\n this.ticketInfo = info;\n this.emit(PRBEStateEvent.TICKET_INFO, info);\n this.emit(PRBEStateEvent.STATUS);\n }\n}\n","/**\n * tools/index.ts — Tool interface, registry, and closure tool\n *\n * Mirrors PRBEAgentTools.swift tool protocol + registry pattern.\n */\n\nimport type { PRBEToolDeclaration, PRBEToolParameter } from \"../models\";\nimport { randomUUID } from \"crypto\";\nimport { InteractionType } from \"../interactions\";\nimport type { PRBEInteractionRequester, RequestPathAccessResponse } from \"../interactions\";\n\n// ---------------------------------------------------------------------------\n// Tool Interface\n// ---------------------------------------------------------------------------\n\nexport interface PRBETool {\n readonly declaration: PRBEToolDeclaration;\n execute(args: Record<string, unknown>): Promise<string>;\n}\n\n// ---------------------------------------------------------------------------\n// Tool Registry\n// ---------------------------------------------------------------------------\n\nexport class PRBEToolRegistry {\n private tools: Map<string, PRBETool> = new Map();\n\n register(tool: PRBETool): void {\n this.tools.set(tool.declaration.name, tool);\n }\n\n allDeclarations(): PRBEToolDeclaration[] {\n return Array.from(this.tools.values()).map((t) => t.declaration);\n }\n\n async execute(name: string, args: Record<string, unknown>): Promise<string> {\n const tool = this.tools.get(name);\n if (!tool) {\n return `Error: unknown tool '${name}'`;\n }\n return tool.execute(args);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Closure Tool (for user-registered custom tools)\n// ---------------------------------------------------------------------------\n\nexport class PRBEClosureTool implements PRBETool {\n public readonly declaration: PRBEToolDeclaration;\n private readonly handler: (args: Record<string, unknown>) => Promise<string>;\n\n constructor(\n name: string,\n description: string,\n parameters: PRBEToolParameter[],\n handler: (args: Record<string, unknown>) => Promise<string>,\n options?: { interactive?: boolean },\n ) {\n this.declaration = {\n name,\n description,\n parameters,\n ...(options?.interactive ? { interactive: true } : {}),\n };\n this.handler = handler;\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n return this.handler(args);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Path Validation (shared by filesystem + flag tools)\n// ---------------------------------------------------------------------------\n\nimport * as path from \"path\";\nimport * as fs from \"fs\";\n\n/**\n * Resolve a path string and validate it against auto-approved directories.\n * Returns the resolved absolute path or null if outside auto-approved directories.\n */\nexport function resolveAndValidate(pathStr: string, autoApprovedDirs: string[]): string | null {\n let resolved: string;\n if (path.isAbsolute(pathStr)) {\n resolved = path.resolve(pathStr);\n } else if (autoApprovedDirs.length > 0) {\n resolved = path.resolve(autoApprovedDirs[0], pathStr);\n } else {\n return null;\n }\n\n // Normalize to remove trailing slashes for comparison\n const normalizedResolved = path.resolve(resolved);\n\n for (const root of autoApprovedDirs) {\n const normalizedRoot = path.resolve(root);\n if (normalizedResolved === normalizedRoot || normalizedResolved.startsWith(normalizedRoot + path.sep)) {\n return normalizedResolved;\n }\n }\n\n return null;\n}\n\n/** Result of resolveWithAccessRequest — resolved path, null (silently denied), or error string for the agent */\nexport type PathResolution = { path: string } | { error: string } | null;\n\n/**\n * Resolve a path, requesting user access if outside auto-approved directories.\n * When a requester is available and the path fails validation, prompts\n * the user for permission and caches the grant in `grantedPaths`.\n *\n * Returns { path } on success, { error } with a message for the agent, or null.\n */\nexport async function resolveWithAccessRequest(\n pathStr: string,\n autoApprovedDirs: string[],\n grantedPaths: Set<string>,\n requester?: PRBEInteractionRequester,\n): Promise<PathResolution> {\n // First try against auto-approved directories + already-granted paths\n const allRoots = [...autoApprovedDirs, ...grantedPaths];\n const resolved = resolveAndValidate(pathStr, allRoots);\n if (resolved) return { path: resolved };\n\n // No requester — can't ask for access\n if (!requester) return null;\n\n // Resolve the absolute path even though it's outside roots\n let absolute: string;\n if (path.isAbsolute(pathStr)) {\n absolute = path.resolve(pathStr);\n } else if (autoApprovedDirs.length > 0) {\n absolute = path.resolve(autoApprovedDirs[0], pathStr);\n } else {\n return null;\n }\n\n // Reject overly broad paths — tell the agent to be more specific\n const depth = absolute.split(path.sep).filter(Boolean).length;\n if (depth < 3) {\n return { error: `Path '${pathStr}' is too broad. Use a more specific path (e.g. a subdirectory at least 3 levels deep).` };\n }\n\n // Request path access from the user\n const response = await requester.requestUserInteraction({\n type: InteractionType.REQUEST_PATH_ACCESS,\n interactionId: randomUUID(),\n path: absolute,\n reason: `The agent needs access to '${pathStr}' which is outside the allowed directories.`,\n });\n\n const pathResponse = response as RequestPathAccessResponse;\n if (!pathResponse.granted) return { error: \"Path access denied by user.\" };\n\n // Grant the exact resolved path (not parent — avoid overly broad grants)\n grantedPaths.add(absolute);\n\n return { path: absolute };\n}\n\n/**\n * Format byte sizes for human-readable output.\n */\nexport function humanReadableSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${kb.toFixed(1)} KB`;\n const mb = kb / 1024;\n if (mb < 1024) return `${mb.toFixed(1)} MB`;\n const gb = mb / 1024;\n return `${gb.toFixed(1)} GB`;\n}\n","/**\n * interactions.ts — Types for user interaction during investigations\n *\n * Defines the contract between tools (which request interactions) and\n * host apps (which present UI and collect responses).\n */\n\n// ---------------------------------------------------------------------------\n// Interaction Types\n// ---------------------------------------------------------------------------\n\nexport enum InteractionType {\n ASK_QUESTION = \"ask_question\",\n REQUEST_PERMISSION = \"request_permission\",\n REQUEST_PATH_ACCESS = \"request_path_access\",\n}\n\n// ---------------------------------------------------------------------------\n// Payloads (tool → host)\n// ---------------------------------------------------------------------------\n\nexport interface AskQuestionPayload {\n type: InteractionType.ASK_QUESTION;\n interactionId: string;\n question: string;\n context?: string;\n}\n\nexport interface RequestPermissionPayload {\n type: InteractionType.REQUEST_PERMISSION;\n interactionId: string;\n action: string;\n command: string;\n reason?: string;\n}\n\nexport interface RequestPathAccessPayload {\n type: InteractionType.REQUEST_PATH_ACCESS;\n interactionId: string;\n path: string;\n reason: string;\n}\n\nexport type InteractionPayload =\n | AskQuestionPayload\n | RequestPermissionPayload\n | RequestPathAccessPayload;\n\n// ---------------------------------------------------------------------------\n// Responses (host → tool)\n// ---------------------------------------------------------------------------\n\nexport interface AskQuestionResponse {\n type: InteractionType.ASK_QUESTION;\n answer: string;\n}\n\nexport interface RequestPermissionResponse {\n type: InteractionType.REQUEST_PERMISSION;\n approved: boolean;\n}\n\nexport interface RequestPathAccessResponse {\n type: InteractionType.REQUEST_PATH_ACCESS;\n granted: boolean;\n}\n\nexport type InteractionResponse =\n | AskQuestionResponse\n | RequestPermissionResponse\n | RequestPathAccessResponse;\n\n// ---------------------------------------------------------------------------\n// Investigation source\n// ---------------------------------------------------------------------------\n\nexport enum InvestigationSource {\n USER = \"user\",\n CONTEXT_REQUEST = \"context_request\",\n}\n\n// ---------------------------------------------------------------------------\n// Minimal requester interface (tools depend on this, not on PRBEAgent)\n// ---------------------------------------------------------------------------\n\nexport interface PRBEInteractionRequester {\n requestUserInteraction(payload: InteractionPayload): Promise<InteractionResponse>;\n sendConversationMessage(content: string): void;\n readonly investigationSource: InvestigationSource;\n}\n\n// ---------------------------------------------------------------------------\n// Handler interface (host app implements this)\n// ---------------------------------------------------------------------------\n\nexport interface PRBEInteractionHandler {\n handleInteraction(payload: InteractionPayload): Promise<InteractionResponse>;\n}\n\n// ---------------------------------------------------------------------------\n// Resolved interaction (question + response, for persistence)\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedInteraction {\n interactionId: string;\n payload: InteractionPayload;\n response: InteractionResponse;\n /** Number of events at time of resolution — used to split thinking bubbles */\n eventIndex: number;\n}\n","/**\n * tools/filesystem.ts — Built-in filesystem tools\n *\n * Implements: client_list_directory, client_read_file, client_search_content,\n * client_find_files, client_flag_file\n *\n * Mirrors PRBEAgentTools.swift filesystem tool implementations.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { PRBEToolDeclaration, FlaggedFileIn } from \"../models\";\nimport { ToolName, ToolParamType, redactPII } from \"../models\";\nimport type { PRBEInteractionRequester } from \"../interactions\";\nimport type { PRBETool } from \"./index\";\nimport { resolveAndValidate, resolveWithAccessRequest, humanReadableSize, type PathResolution } from \"./index\";\n\n/** Resolve a path using access request if available, else basic validation. Returns [resolved, error]. */\nasync function resolvePath(\n pathStr: string,\n autoApprovedDirs: string[],\n requester?: PRBEInteractionRequester,\n grantedPaths?: Set<string>,\n): Promise<[string | null, string | null]> {\n if (requester && grantedPaths) {\n const result = await resolveWithAccessRequest(pathStr, autoApprovedDirs, grantedPaths, requester);\n if (result && \"error\" in result) return [null, result.error];\n if (result && \"path\" in result) return [result.path, null];\n }\n const resolved = resolveAndValidate(pathStr, autoApprovedDirs);\n return [resolved, resolved ? null : \"path is outside auto-approved directories\"];\n}\n\n// ---------------------------------------------------------------------------\n// ListDirectoryTool\n// ---------------------------------------------------------------------------\n\nexport class ListDirectoryTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_LIST_DIRECTORY,\n description: \"List directory contents\",\n parameters: [\n { name: \"path\", type: ToolParamType.STRING, description: \"Directory path\", required: true },\n { name: \"recursive\", type: ToolParamType.BOOLEAN, description: \"List recursively\", required: false },\n { name: \"max_depth\", type: ToolParamType.INTEGER, description: \"Max depth (default 3)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n try {\n const stat = fs.statSync(resolved);\n if (!stat.isDirectory()) return `Error: '${pathStr}' is not a directory`;\n } catch {\n return `Error: '${pathStr}' does not exist or is not accessible`;\n }\n\n const recursive = args[\"recursive\"] === true;\n const maxDepth = typeof args[\"max_depth\"] === \"number\" ? args[\"max_depth\"] : 3;\n\n const lines: string[] = [];\n this.listDir(resolved, 0, recursive ? maxDepth : 1, lines);\n if (lines.length >= ListDirectoryTool.MAX_ENTRIES) {\n lines.push(`\\n(truncated at ${ListDirectoryTool.MAX_ENTRIES} entries — use a more specific path)`);\n }\n return lines.join(\"\\n\") || \"(empty directory)\";\n }\n\n private static readonly MAX_ENTRIES = 1000;\n\n private listDir(dirPath: string, depth: number, maxDepth: number, lines: string[]): void {\n if (depth >= maxDepth) return;\n if (lines.length >= ListDirectoryTool.MAX_ENTRIES) return;\n const indent = \" \".repeat(depth);\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n lines.push(`${indent}(access denied)`);\n return;\n }\n\n // Sort entries alphabetically, skip hidden files\n const sorted = entries\n .filter((e) => !e.name.startsWith(\".\"))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n for (const entry of sorted) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n lines.push(`${indent}${entry.name}/`);\n this.listDir(fullPath, depth + 1, maxDepth, lines);\n } else {\n try {\n const stat = fs.statSync(fullPath);\n lines.push(`${indent}${entry.name} (${humanReadableSize(stat.size)})`);\n } catch {\n lines.push(`${indent}${entry.name} (unknown size)`);\n }\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// ReadFileTool\n// ---------------------------------------------------------------------------\n\nexport class ReadFileTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_READ_FILE,\n description: \"Read file contents\",\n parameters: [\n { name: \"path\", type: ToolParamType.STRING, description: \"File path\", required: true },\n { name: \"offset\", type: ToolParamType.INTEGER, description: \"Line offset\", required: false },\n { name: \"limit\", type: ToolParamType.INTEGER, description: \"Max lines (default 200)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n let content: string;\n try {\n content = fs.readFileSync(resolved, \"utf-8\");\n } catch {\n return `Error: could not read file at '${pathStr}'`;\n }\n\n const allLines = content.split(/\\r?\\n/);\n const totalLines = allLines.length;\n const limit = typeof args[\"limit\"] === \"number\" ? args[\"limit\"] : 200;\n const rawOffset = typeof args[\"offset\"] === \"number\" ? args[\"offset\"] : 0;\n\n let startIndex: number;\n if (rawOffset < 0) {\n startIndex = Math.max(0, totalLines + rawOffset);\n } else {\n startIndex = rawOffset;\n }\n\n const endIndex = Math.min(startIndex + limit, totalLines);\n if (startIndex >= totalLines) {\n return `File has ${totalLines} lines; offset ${rawOffset} is out of range.`;\n }\n\n let stat: fs.Stats;\n try {\n stat = fs.statSync(resolved);\n } catch {\n stat = { size: 0 } as fs.Stats;\n }\n const sizeStr = humanReadableSize(stat.size);\n\n let result = `File: ${pathStr} (${totalLines} lines, ${sizeStr}, showing ${startIndex + 1}-${endIndex})\\n`;\n for (let i = startIndex; i < endIndex; i++) {\n const lineNum = String(i + 1).padStart(4, \" \");\n result += `${lineNum} | ${allLines[i]}\\n`;\n }\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SearchContentTool\n// ---------------------------------------------------------------------------\n\nexport class SearchContentTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_SEARCH_CONTENT,\n description: \"Search file contents\",\n parameters: [\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Regex pattern\", required: true },\n { name: \"path\", type: ToolParamType.STRING, description: \"File or directory to search\", required: true },\n { name: \"context_lines\", type: ToolParamType.INTEGER, description: \"Context lines (default 2)\", required: false },\n { name: \"max_results\", type: ToolParamType.INTEGER, description: \"Max results (default 50)\", required: false },\n { name: \"case_sensitive\", type: ToolParamType.BOOLEAN, description: \"Case-sensitive search (default false)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pattern = args[\"pattern\"] as string | undefined;\n if (!pattern) return \"Error: 'pattern' parameter is required\";\n\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n const contextLines = typeof args[\"context_lines\"] === \"number\" ? args[\"context_lines\"] : 2;\n const maxResults = typeof args[\"max_results\"] === \"number\" ? args[\"max_results\"] : 50;\n\n const caseSensitive = args[\"case_sensitive\"] === true;\n let regex: RegExp;\n try {\n regex = new RegExp(pattern, caseSensitive ? \"\" : \"i\");\n } catch {\n return `Error: invalid regex pattern '${pattern}'`;\n }\n\n // Collect file paths to search\n const fileURLs: string[] = [];\n let isDirectory = false;\n try {\n const stat = fs.statSync(resolved);\n if (stat.isDirectory()) {\n isDirectory = true;\n this.collectFiles(resolved, fileURLs);\n } else {\n fileURLs.push(resolved);\n }\n } catch {\n return `Error: could not access '${pathStr}'`;\n }\n\n const results: string[] = [];\n\n for (const filePath of fileURLs) {\n if (results.length >= maxResults) break;\n\n let content: string;\n try {\n content = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n continue;\n }\n\n const lines = content.split(/\\r?\\n/);\n const relativePath = isDirectory\n ? path.relative(resolved, filePath)\n : path.basename(filePath);\n\n for (let idx = 0; idx < lines.length; idx++) {\n if (results.length >= maxResults) break;\n if (!regex.test(lines[idx])) continue;\n\n let snippet: string;\n if (contextLines > 0) {\n const start = Math.max(0, idx - contextLines);\n const end = Math.min(lines.length - 1, idx + contextLines);\n snippet = \"\";\n for (let ci = start; ci <= end; ci++) {\n const marker = ci === idx ? \">\" : \" \";\n snippet += `${relativePath}:${ci + 1}:${marker} ${lines[ci]}\\n`;\n }\n } else {\n snippet = `${relativePath}:${idx + 1}: ${lines[idx]}`;\n }\n results.push(snippet);\n }\n }\n\n if (results.length === 0) {\n return `No matches found for '${pattern}' in '${pathStr}'`;\n }\n return `Found ${results.length} match(es):\\n\\n${results.join(\"\\n---\\n\")}`;\n }\n\n private collectFiles(dirPath: string, fileURLs: string[]): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n const fullPath = path.join(dirPath, entry.name);\n if (entry.isDirectory()) {\n this.collectFiles(fullPath, fileURLs);\n } else if (entry.isFile()) {\n fileURLs.push(fullPath);\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// FindFilesTool\n// ---------------------------------------------------------------------------\n\nexport class FindFilesTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_FIND_FILES,\n description: \"Find files by name\",\n parameters: [\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Glob pattern\", required: true },\n { name: \"path\", type: ToolParamType.STRING, description: \"Directory to search\", required: true },\n { name: \"max_results\", type: ToolParamType.INTEGER, description: \"Max results (default 50)\", required: false },\n { name: \"case_sensitive\", type: ToolParamType.BOOLEAN, description: \"Case-sensitive matching (default false)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pattern = args[\"pattern\"] as string | undefined;\n if (!pattern) return \"Error: 'pattern' parameter is required\";\n\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n const maxResults = typeof args[\"max_results\"] === \"number\" ? args[\"max_results\"] : 50;\n const caseSensitive = args[\"case_sensitive\"] === true;\n\n interface FileMatch {\n path: string;\n size: number;\n modified: Date;\n }\n\n const matches: FileMatch[] = [];\n this.walkAndMatch(resolved, pattern, matches, caseSensitive);\n\n // Sort newest-first\n matches.sort((a, b) => b.modified.getTime() - a.modified.getTime());\n const limited = matches.slice(0, maxResults);\n\n if (limited.length === 0) {\n return `No files matching '${pattern}' found in '${pathStr}'`;\n }\n\n let result = `Found ${matches.length} file(s) matching '${pattern}':\\n\\n`;\n for (const m of limited) {\n const sizeStr = humanReadableSize(m.size);\n const dateStr = m.modified.toISOString();\n result += `${m.path} (${sizeStr}, ${dateStr})\\n`;\n }\n return result;\n }\n\n private walkAndMatch(dirPath: string, pattern: string, matches: Array<{ path: string; size: number; modified: Date }>, caseSensitive: boolean): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n this.walkAndMatch(fullPath, pattern, matches, caseSensitive);\n } else if (entry.isFile()) {\n if (this.globMatch(entry.name, pattern, caseSensitive)) {\n try {\n const stat = fs.statSync(fullPath);\n matches.push({\n path: fullPath,\n size: stat.size,\n modified: stat.mtime,\n });\n } catch {\n // Skip files we can't stat\n }\n }\n }\n }\n }\n\n /**\n * Simple glob matching: supports *, ?, and character classes [...].\n * Converts glob to regex and tests against the filename.\n */\n private globMatch(filename: string, pattern: string, caseSensitive: boolean): boolean {\n // Convert glob pattern to regex\n let regexStr = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i];\n switch (c) {\n case \"*\":\n regexStr += \".*\";\n break;\n case \"?\":\n regexStr += \".\";\n break;\n case \"[\":\n // Find closing bracket\n const closeBracket = pattern.indexOf(\"]\", i + 1);\n if (closeBracket === -1) {\n regexStr += \"\\\\[\";\n } else {\n regexStr += pattern.substring(i, closeBracket + 1);\n i = closeBracket;\n }\n break;\n case \".\":\n case \"(\":\n case \")\":\n case \"+\":\n case \"^\":\n case \"$\":\n case \"|\":\n case \"{\":\n case \"}\":\n case \"\\\\\":\n regexStr += `\\\\${c}`;\n break;\n default:\n regexStr += c;\n }\n }\n regexStr += \"$\";\n\n try {\n return new RegExp(regexStr, caseSensitive ? \"\" : \"i\").test(filename);\n } catch {\n return false;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// FlagFileTool\n// ---------------------------------------------------------------------------\n\nexport class FlagFileTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly onFlag: (file: FlaggedFileIn) => void;\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n private static readonly MAX_BINARY_SIZE = 100 * 1024 * 1024; // 100MB\n\n constructor(\n autoApprovedDirs: string[],\n onFlag: (file: FlaggedFileIn) => void,\n requester?: PRBEInteractionRequester,\n grantedPaths?: Set<string>,\n ) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.onFlag = onFlag;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_FLAG_FILE,\n description:\n \"Flag a file (or part of a text file) as evidence. For large text files, use offset and limit to flag only the relevant section. Binary files are flagged in full (up to 100MB).\",\n parameters: [\n { name: \"path\", type: ToolParamType.STRING, description: \"File path\", required: true },\n { name: \"reason\", type: ToolParamType.STRING, description: \"Reason for flagging\", required: true },\n { name: \"offset\", type: ToolParamType.INTEGER, description: \"Starting line number (1-based, text files only). Negative = from end.\", required: false },\n { name: \"limit\", type: ToolParamType.INTEGER, description: \"Max number of lines to include (text files only).\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const reason = args[\"reason\"] as string | undefined;\n if (!reason) return \"Error: 'reason' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n if (!fs.existsSync(resolved)) {\n return `Error: file does not exist at '${pathStr}'`;\n }\n\n const offset = typeof args[\"offset\"] === \"number\" ? args[\"offset\"] : undefined;\n const limit = typeof args[\"limit\"] === \"number\" ? args[\"limit\"] : undefined;\n\n // Try reading as text first\n let textContent: string | null = null;\n try {\n textContent = fs.readFileSync(resolved, \"utf-8\");\n } catch {\n // Not readable as text\n }\n\n if (textContent !== null) {\n let content = textContent;\n\n if (offset !== undefined || limit !== undefined) {\n let lines = content.split(/\\r?\\n/);\n const totalLines = lines.length;\n\n let startIdx = 0;\n if (offset !== undefined) {\n startIdx = offset < 0 ? Math.max(0, totalLines + offset) : Math.max(0, offset - 1);\n }\n\n lines = lines.slice(startIdx);\n if (limit !== undefined && limit > 0) {\n lines = lines.slice(0, limit);\n }\n\n const rangeDesc = `lines ${startIdx + 1}-${startIdx + lines.length} of ${totalLines}`;\n content = `[${rangeDesc}]\\n${lines.join(\"\\n\")}`;\n }\n\n const redacted = redactPII(content);\n this.onFlag({\n originalPath: resolved,\n reason,\n data: Buffer.from(redacted, \"utf-8\"),\n isText: true,\n });\n const sizeDesc = offset !== undefined || limit !== undefined ? \" (partial)\" : \"\";\n return `Flagged '${pathStr}'${sizeDesc} — reason: ${reason}`;\n }\n\n // Binary file — flag in full, no partial support\n if (offset !== undefined || limit !== undefined) {\n return \"Error: offset/limit not supported for binary files. Flag the full file instead.\";\n }\n\n let data: Buffer;\n try {\n data = fs.readFileSync(resolved);\n } catch {\n return `Error: could not read file at '${pathStr}'`;\n }\n\n if (data.length > FlagFileTool.MAX_BINARY_SIZE) {\n const sizeMB = Math.floor(data.length / (1024 * 1024));\n return `Error: file is ${sizeMB}MB — exceeds 100MB limit`;\n }\n\n this.onFlag({\n originalPath: resolved,\n reason,\n data,\n isText: false,\n });\n return `Flagged '${pathStr}' (binary, ${data.length} bytes) — reason: ${reason}`;\n }\n}\n","/**\n * tools/logs.ts — Log capture + built-in log tools\n *\n * Implements: client_read_app_logs, client_search_app_logs,\n * client_clear_app_logs, client_flag_app_logs\n *\n * Mirrors PRBELogCapture.swift + log tool implementations from PRBEAgentTools.swift.\n * Log capture works by monkey-patching console.log/warn/error in the Electron main process.\n */\n\nimport type { PRBEToolDeclaration, FlaggedFileIn } from \"../models\";\nimport { ToolName, ToolParamType, redactPII } from \"../models\";\nimport type { PRBETool } from \"./index\";\n\n// ---------------------------------------------------------------------------\n// Log Entry\n// ---------------------------------------------------------------------------\n\nexport interface LogEntry {\n timestamp: Date;\n level: string;\n category: string;\n message: string;\n}\n\n// ---------------------------------------------------------------------------\n// PRBELogCapture\n// ---------------------------------------------------------------------------\n\nexport class PRBELogCapture {\n private entries: LogEntry[] = [];\n private readonly maxEntries: number;\n private isCapturing = false;\n\n // Original console methods, saved for restoration\n private originalLog?: typeof console.log;\n private originalWarn?: typeof console.warn;\n private originalError?: typeof console.error;\n private originalDebug?: typeof console.debug;\n private originalInfo?: typeof console.info;\n\n constructor(maxEntries: number = 10_000) {\n this.maxEntries = maxEntries;\n }\n\n // ---------- Structured Logging ----------\n\n log(message: string, level = \"PRINT\", category = \"print\"): void {\n this.append({\n timestamp: new Date(),\n level,\n category,\n message,\n });\n }\n\n // ---------- Query ----------\n\n get count(): number {\n return this.entries.length;\n }\n\n getEntries(options: {\n offset?: number;\n limit?: number;\n level?: string;\n from?: Date;\n to?: Date;\n } = {}): LogEntry[] {\n const { offset = 0, limit = 100, level, from, to } = options;\n\n let filtered = this.entries;\n if (level) {\n filtered = filtered.filter((e) => e.level === level);\n }\n if (from) {\n filtered = filtered.filter((e) => e.timestamp >= from);\n }\n if (to) {\n filtered = filtered.filter((e) => e.timestamp <= to);\n }\n\n if (offset >= filtered.length) return [];\n const end = Math.min(offset + limit, filtered.length);\n return filtered.slice(offset, end);\n }\n\n search(\n pattern: string,\n contextLines = 2,\n maxResults = 50,\n ): Array<{ index: number; entry: LogEntry }> {\n let regex: RegExp;\n try {\n regex = new RegExp(pattern, \"i\");\n } catch {\n return [];\n }\n\n const results: Array<{ index: number; entry: LogEntry }> = [];\n for (let i = 0; i < this.entries.length; i++) {\n if (results.length >= maxResults) break;\n if (regex.test(this.entries[i].message)) {\n results.push({ index: i, entry: this.entries[i] });\n }\n }\n return results;\n }\n\n // ---------- Clear ----------\n\n clearLogs(): number {\n const count = this.entries.length;\n this.entries = [];\n return count;\n }\n\n // ---------- Console Capture ----------\n\n startCapturing(): void {\n if (this.isCapturing) return;\n this.isCapturing = true;\n\n // Save originals\n this.originalLog = console.log;\n this.originalWarn = console.warn;\n this.originalError = console.error;\n this.originalDebug = console.debug;\n this.originalInfo = console.info;\n\n const self = this;\n\n console.log = (...args: unknown[]) => {\n self.originalLog?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"PRINT\", \"console.log\");\n };\n\n console.warn = (...args: unknown[]) => {\n self.originalWarn?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"WARNING\", \"console.warn\");\n };\n\n console.error = (...args: unknown[]) => {\n self.originalError?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"ERROR\", \"console.error\");\n };\n\n console.debug = (...args: unknown[]) => {\n self.originalDebug?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"DEBUG\", \"console.debug\");\n };\n\n console.info = (...args: unknown[]) => {\n self.originalInfo?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"INFO\", \"console.info\");\n };\n }\n\n stopCapturing(): void {\n if (!this.isCapturing) return;\n this.isCapturing = false;\n\n if (this.originalLog) console.log = this.originalLog;\n if (this.originalWarn) console.warn = this.originalWarn;\n if (this.originalError) console.error = this.originalError;\n if (this.originalDebug) console.debug = this.originalDebug;\n if (this.originalInfo) console.info = this.originalInfo;\n\n this.originalLog = undefined;\n this.originalWarn = undefined;\n this.originalError = undefined;\n this.originalDebug = undefined;\n this.originalInfo = undefined;\n }\n\n // ---------- Raw access to all entries (for tools) ----------\n\n getAllEntries(): LogEntry[] {\n return this.entries;\n }\n\n // ---------- Private ----------\n\n private append(entry: LogEntry): void {\n this.entries.push(entry);\n if (this.entries.length > this.maxEntries) {\n this.entries.splice(0, this.entries.length - this.maxEntries);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// ReadAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class ReadAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n\n constructor(logCapture: PRBELogCapture) {\n this.logCapture = logCapture;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_READ_APP_LOGS,\n description: \"Read application log entries captured from stdout and structured logging\",\n parameters: [\n { name: \"position\", type: ToolParamType.STRING, description: '\"top\" (oldest first) or \"bottom\" (newest first). Default: \"bottom\"', required: false },\n { name: \"count\", type: ToolParamType.INTEGER, description: \"Number of entries to return. Default: 100\", required: false },\n { name: \"level\", type: ToolParamType.STRING, description: 'Filter by log level (e.g. \"ERROR\", \"INFO\", \"PRINT\")', required: false },\n { name: \"from\", type: ToolParamType.STRING, description: \"ISO8601 start timestamp filter\", required: false },\n { name: \"to\", type: ToolParamType.STRING, description: \"ISO8601 end timestamp filter\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const position = (args[\"position\"] as string) ?? \"bottom\";\n const count = typeof args[\"count\"] === \"number\" ? args[\"count\"] : 100;\n const level = args[\"level\"] as string | undefined;\n\n const fromDate = args[\"from\"] ? new Date(args[\"from\"] as string) : undefined;\n const toDate = args[\"to\"] ? new Date(args[\"to\"] as string) : undefined;\n\n const totalCount = this.logCapture.count;\n const allEntries = this.logCapture.getEntries({\n offset: 0,\n limit: totalCount,\n level,\n from: fromDate,\n to: toDate,\n });\n\n if (allEntries.length === 0) {\n return \"No log entries found matching the specified filters.\";\n }\n\n let selected: LogEntry[];\n if (position === \"top\") {\n selected = allEntries.slice(0, count);\n } else {\n selected = allEntries.slice(-count);\n }\n\n let result = `Log entries (${selected.length} of ${allEntries.length} total):\\n\\n`;\n for (const entry of selected) {\n result += `[${entry.timestamp.toISOString()}] [${entry.level}] [${entry.category}] ${entry.message}\\n`;\n }\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SearchAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class SearchAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n\n constructor(logCapture: PRBELogCapture) {\n this.logCapture = logCapture;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_SEARCH_APP_LOGS,\n description: \"Search application logs by regex pattern with surrounding context\",\n parameters: [\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Regex pattern to search for\", required: true },\n { name: \"context_lines\", type: ToolParamType.INTEGER, description: \"Number of surrounding log entries for context. Default: 2\", required: false },\n { name: \"max_results\", type: ToolParamType.INTEGER, description: \"Maximum matches to return. Default: 50\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pattern = args[\"pattern\"] as string | undefined;\n if (!pattern) return \"Error: 'pattern' parameter is required\";\n\n const contextLines = typeof args[\"context_lines\"] === \"number\" ? args[\"context_lines\"] : 2;\n const maxResults = typeof args[\"max_results\"] === \"number\" ? args[\"max_results\"] : 50;\n\n const matches = this.logCapture.search(pattern, contextLines, maxResults);\n\n if (matches.length === 0) {\n return `No log entries matching '${pattern}' found.`;\n }\n\n const allEntries = this.logCapture.getAllEntries();\n\n let result = `Found ${matches.length} match(es) for '${pattern}':\\n\\n`;\n for (const match of matches) {\n const startIdx = Math.max(0, match.index - contextLines);\n const endIdx = Math.min(allEntries.length - 1, match.index + contextLines);\n for (let i = startIdx; i <= endIdx; i++) {\n const entry = allEntries[i];\n const marker = i === match.index ? \">\" : \" \";\n result += `${marker} [${entry.timestamp.toISOString()}] [${entry.level}] [${entry.category}] ${entry.message}\\n`;\n }\n result += \"---\\n\";\n }\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// ClearAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class ClearAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n\n constructor(logCapture: PRBELogCapture) {\n this.logCapture = logCapture;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_CLEAR_APP_LOGS,\n description: \"Clear all captured application logs\",\n parameters: [],\n };\n }\n\n async execute(_args: Record<string, unknown>): Promise<string> {\n const cleared = this.logCapture.clearLogs();\n return `Cleared ${cleared} log entries.`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// FlagAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class FlagAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n private readonly onFlag: (file: FlaggedFileIn) => void;\n\n constructor(logCapture: PRBELogCapture, onFlag: (file: FlaggedFileIn) => void) {\n this.logCapture = logCapture;\n this.onFlag = onFlag;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_FLAG_APP_LOGS,\n description:\n \"Flag application log entries as evidence for the debug report. Snapshots matching log entries and includes them in the output package. Call with no filters to flag all logs, or use pattern to filter by message content. Note: 'level' filters by the log level metadata (e.g. PRINT, ERROR), NOT by message content — use 'pattern' to match words in log messages.\",\n parameters: [\n { name: \"reason\", type: ToolParamType.STRING, description: \"Why these logs are relevant\", required: true },\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Regex pattern to filter log messages by content\", required: false },\n { name: \"level\", type: ToolParamType.STRING, description: \"Filter by log level metadata (PRINT, DEBUG, INFO, ERROR, etc.) — this is NOT a content search\", required: false },\n { name: \"from\", type: ToolParamType.STRING, description: \"ISO8601 start timestamp filter\", required: false },\n { name: \"to\", type: ToolParamType.STRING, description: \"ISO8601 end timestamp filter\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const reason = args[\"reason\"] as string | undefined;\n if (!reason) return \"Error: 'reason' parameter is required\";\n\n const level = args[\"level\"] as string | undefined;\n const fromDate = args[\"from\"] ? new Date(args[\"from\"] as string) : undefined;\n const toDate = args[\"to\"] ? new Date(args[\"to\"] as string) : undefined;\n\n // Get filtered entries\n const totalCount = this.logCapture.count;\n let entries = this.logCapture.getEntries({\n offset: 0,\n limit: totalCount,\n level,\n from: fromDate,\n to: toDate,\n });\n\n // Apply regex pattern filter if provided\n const patternStr = args[\"pattern\"] as string | undefined;\n if (patternStr) {\n let regex: RegExp;\n try {\n regex = new RegExp(patternStr, \"i\");\n } catch {\n return `Error: invalid regex pattern '${patternStr}'`;\n }\n entries = entries.filter((entry) => regex.test(entry.message));\n }\n\n if (entries.length === 0) {\n const filters: string[] = [];\n if (level) filters.push(`level=${level}`);\n if (patternStr) filters.push(`pattern=${patternStr}`);\n if (fromDate) filters.push(`from=${args[\"from\"]}`);\n if (toDate) filters.push(`to=${args[\"to\"]}`);\n\n const hint = filters.length === 0\n ? `The log buffer is empty (${totalCount} entries).`\n : `No entries matched filters: ${filters.join(\", \")}. Total log entries: ${totalCount}. Try calling with no filters, or use 'pattern' instead of 'level' to match message content.`;\n return hint;\n }\n\n // Format entries into file-like content\n let content = \"\";\n for (const entry of entries) {\n content += `[${entry.timestamp.toISOString()}] [${entry.level}] [${entry.category}] ${entry.message}\\n`;\n }\n\n // Build a descriptive filename: app_logs_<filter_summary>_<timestamp>.txt\n const nameParts = [\"app_logs\"];\n if (level) nameParts.push(level.toLowerCase());\n if (patternStr) {\n const safe = patternStr.replace(/[^a-zA-Z0-9]/g, \"_\");\n const trimmed = safe.substring(0, 30).replace(/^_+|_+$/g, \"\");\n if (trimmed.length > 0) nameParts.push(trimmed);\n }\n const ts = new Date()\n .toISOString()\n .replace(/[:\\-]/g, \"\")\n .substring(0, 15); // e.g. \"20260316T212158\"\n nameParts.push(ts);\n const filename = nameParts.join(\"_\") + \".txt\";\n\n this.onFlag({\n originalPath: filename,\n reason,\n data: Buffer.from(redactPII(content), \"utf-8\"),\n isText: true,\n });\n\n return `Flagged ${entries.length} log entries as '${filename}' — reason: ${reason}`;\n }\n}\n","/**\n * tools/interactive.ts — AskUserTool\n *\n * Allows the agent to ask the user a question during an investigation.\n * The question text is displayed via conversation history (middleware handles this).\n * This tool only prompts the user for input with an optional reason hint.\n */\n\nimport { randomUUID } from \"crypto\";\nimport type { PRBEToolDeclaration } from \"../models\";\nimport { ToolName, ToolParamType } from \"../models\";\nimport { InteractionType, InvestigationSource } from \"../interactions\";\nimport type { PRBEInteractionRequester } from \"../interactions\";\nimport type { AskQuestionResponse } from \"../interactions\";\nimport type { PRBETool } from \"./index\";\n\nexport class AskUserTool implements PRBETool {\n private readonly requester: PRBEInteractionRequester;\n\n constructor(requester: PRBEInteractionRequester) {\n this.requester = requester;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_ASK_USER,\n description:\n \"Ask the user a question and wait for their response. Use this when you need clarification or additional information from the user to continue the investigation.\",\n interactive: true,\n parameters: [\n {\n name: \"question\",\n type: ToolParamType.STRING,\n description: \"The question to ask the user\",\n required: true,\n },\n {\n name: \"reason\",\n type: ToolParamType.STRING,\n description: \"Short reason displayed alongside the input prompt explaining why you need this information\",\n required: false,\n },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const question = args[\"question\"] as string | undefined;\n if (!question) return \"Error: 'question' parameter is required\";\n\n // CRs are autonomous — don't prompt the user, tell the agent to proceed\n if (this.requester.investigationSource !== InvestigationSource.USER) {\n return \"This is a context request investigation — you cannot ask the user questions. Use the available tools to answer the query autonomously.\";\n }\n\n const reason = (args[\"reason\"] as string | undefined) ?? \"Waiting for your response\";\n\n const response = await this.requester.requestUserInteraction({\n type: InteractionType.ASK_QUESTION,\n interactionId: randomUUID(),\n question: reason,\n });\n\n const askResponse = response as AskQuestionResponse;\n return askResponse.answer;\n }\n}\n","/**\n * tools/bash.ts — BashExecuteTool\n *\n * Allows the agent to execute shell commands during investigations.\n * Uses a whitelist-only safety model: commands on the whitelist run without\n * permission; everything else requires user approval.\n *\n * Platform-aware: uses separate whitelists for Unix and Windows, and\n * runs commands via PowerShell on Windows for consistent behavior.\n */\n\nimport { exec } from \"child_process\";\nimport { randomUUID } from \"crypto\";\nimport * as path from \"path\";\nimport type { PRBEToolDeclaration } from \"../models\";\nimport { ToolName, ToolParamType } from \"../models\";\nimport { InteractionType } from \"../interactions\";\nimport type { PRBEInteractionRequester, RequestPermissionResponse } from \"../interactions\";\nimport type { PRBETool } from \"./index\";\nimport { resolveAndValidate } from \"./index\";\nimport { SAFE_COMMANDS, SAFE_COMMAND_PREFIXES } from \"./safe-commands\";\n\n// ---------------------------------------------------------------------------\n// Platform detection\n// ---------------------------------------------------------------------------\n\nconst IS_WINDOWS = process.platform === \"win32\";\n\nconst MAX_OUTPUT_BYTES = 100 * 1024; // 100KB\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst MAX_TIMEOUT_MS = 120_000;\n\n// ---------------------------------------------------------------------------\n// BashExecuteTool\n// ---------------------------------------------------------------------------\n\nexport class BashExecuteTool implements PRBETool {\n private readonly requester: PRBEInteractionRequester;\n private readonly autoApprovedDirs: string[];\n private readonly grantedPaths: Set<string>;\n\n constructor(\n requester: PRBEInteractionRequester,\n autoApprovedDirs: string[],\n grantedPaths: Set<string>,\n ) {\n this.requester = requester;\n this.autoApprovedDirs = autoApprovedDirs;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_BASH_EXECUTE,\n description:\n \"Execute a shell command on the user's machine. Safe read-only commands run immediately; potentially destructive commands require user approval first.\",\n interactive: true,\n parameters: [\n {\n name: \"command\",\n type: ToolParamType.STRING,\n description: \"The shell command to execute\",\n required: true,\n },\n {\n name: \"cwd\",\n type: ToolParamType.STRING,\n description: \"Working directory for the command (must be within auto-approved directories)\",\n required: false,\n },\n {\n name: \"timeout\",\n type: ToolParamType.INTEGER,\n description: \"Timeout in seconds (default 30, max 120)\",\n required: false,\n },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const command = args[\"command\"] as string | undefined;\n if (!command) return \"Error: 'command' parameter is required\";\n\n const cwdArg = args[\"cwd\"] as string | undefined;\n const timeoutSec = typeof args[\"timeout\"] === \"number\" ? args[\"timeout\"] : DEFAULT_TIMEOUT_MS / 1000;\n const timeoutMs = Math.min(timeoutSec * 1000, MAX_TIMEOUT_MS);\n\n // Validate cwd if provided\n let cwd: string | undefined;\n if (cwdArg) {\n const allRoots = [...this.autoApprovedDirs, ...this.grantedPaths];\n const resolved = resolveAndValidate(cwdArg, allRoots);\n if (!resolved) {\n return `Error: working directory '${cwdArg}' is outside auto-approved directories`;\n }\n cwd = resolved;\n }\n\n // Check if command is safe (whitelist-only)\n const isSafe = this.isCommandSafe(command);\n\n if (!isSafe) {\n const response = await this.requester.requestUserInteraction({\n type: InteractionType.REQUEST_PERMISSION,\n interactionId: randomUUID(),\n action: \"Execute shell command\",\n command,\n reason: `The agent wants to run this command${cwd ? ` in ${cwd}` : \"\"}.`,\n });\n\n const permResponse = response as RequestPermissionResponse;\n if (!permResponse.approved) {\n return \"Command execution denied by user.\";\n }\n }\n\n // Execute the command\n return new Promise<string>((resolve) => {\n exec(\n command,\n {\n cwd,\n timeout: timeoutMs,\n maxBuffer: MAX_OUTPUT_BYTES,\n env: process.env,\n // On Windows, use PowerShell for more consistent behavior\n ...(IS_WINDOWS ? { shell: \"powershell.exe\" } : {}),\n },\n (error, stdout, stderr) => {\n let output = \"\";\n\n if (stdout) {\n output += stdout;\n }\n if (stderr) {\n if (output) output += \"\\n--- stderr ---\\n\";\n output += stderr;\n }\n\n if (error) {\n if (error.killed) {\n output += `\\n[Command timed out after ${timeoutSec}s]`;\n } else if (!stdout && !stderr) {\n output = `Error: ${error.message}`;\n }\n }\n\n // Truncate if too large\n if (Buffer.byteLength(output, \"utf-8\") > MAX_OUTPUT_BYTES) {\n output = output.slice(0, MAX_OUTPUT_BYTES) + \"\\n[Output truncated at 100KB]\";\n }\n\n resolve(output || \"(no output)\");\n },\n );\n });\n }\n\n /**\n * Check if a command is on the safe whitelist.\n */\n private isCommandSafe(command: string): boolean {\n const trimmed = command.trim();\n\n // Check two-word prefixes first (e.g. \"git status\")\n for (const prefix of SAFE_COMMAND_PREFIXES) {\n if (trimmed === prefix || trimmed.startsWith(prefix + \" \")) {\n return true;\n }\n }\n\n // Extract base command\n const firstCommand = IS_WINDOWS\n ? trimmed.split(/[|;]/, 1)[0].trim() // PowerShell uses | and ;\n : trimmed.split(/[|;&]/, 1)[0].trim(); // bash uses |, ;, &\n const baseCommand = firstCommand.split(/\\s+/, 1)[0];\n\n const commandName = IS_WINDOWS\n ? baseCommand.toLowerCase() // Windows commands are case-insensitive\n : path.basename(baseCommand);\n\n if (SAFE_COMMANDS.has(commandName)) {\n return this.areAllPipeSegmentsSafe(trimmed);\n }\n\n return false;\n }\n\n /**\n * For piped commands, check that every segment uses a safe command.\n */\n private areAllPipeSegmentsSafe(command: string): boolean {\n // Chained commands (;, &&, ||) require permission\n if (IS_WINDOWS) {\n if (/;/.test(command) && command.split(\"|\").length <= 1) return false;\n } else {\n if (/[;&]|&&|\\|\\|/.test(command)) return false;\n }\n\n const segments = command.split(\"|\").map((s) => s.trim());\n for (const segment of segments) {\n const baseCommand = segment.split(/\\s+/, 1)[0];\n const commandName = IS_WINDOWS\n ? baseCommand.toLowerCase()\n : path.basename(baseCommand);\n if (!SAFE_COMMANDS.has(commandName)) {\n return false;\n }\n }\n return true;\n }\n}\n","/**\n * safe-commands.ts — Whitelisted read-only shell commands\n *\n * Commands on these lists run without user approval.\n * Only strictly read-only / informational commands belong here.\n * If a command has ANY flags that can modify system state, it does NOT belong.\n */\n\n// ---------------------------------------------------------------------------\n// Unix (macOS + Linux)\n// ---------------------------------------------------------------------------\n\nconst UNIX_SAFE_COMMANDS = new Set([\n // Filesystem (read-only)\n \"ls\", \"cat\", \"head\", \"tail\", \"find\", \"file\", \"stat\",\n \"du\", \"df\", \"wc\", \"sort\", \"uniq\", \"diff\", \"tree\",\n\n // Search\n \"grep\", \"rg\", \"which\",\n\n // Text\n \"echo\", \"printf\",\n\n // Identity / environment\n \"whoami\", \"pwd\", \"id\", \"hostname\", \"uname\",\n \"env\", \"printenv\", \"locale\",\n\n // System info (read-only reporters)\n \"date\", \"uptime\", \"free\",\n \"ps\", \"top\",\n\n // macOS-specific (read-only only)\n \"sw_vers\", // macOS version\n \"system_profiler\", // hardware/software info\n \"mdls\", // Spotlight metadata for a file\n \"mdfind\", // Spotlight search\n \"lsof\", // list open files\n \"ioreg\", // I/O registry (hardware tree)\n \"log\", // macOS unified log (show, stream — read-only)\n\n // Linux-specific (read-only reporters)\n \"lsb_release\", // distro info\n \"lscpu\", // CPU info\n \"lsblk\", // block devices\n \"lspci\", // PCI devices\n \"lsusb\", // USB devices\n \"lsmem\", // memory ranges\n \"dmidecode\", // BIOS/hardware info\n \"ss\", // socket statistics\n \"journalctl\", // systemd logs (read-only)\n]);\n\n// ---------------------------------------------------------------------------\n// Windows (CMD + PowerShell)\n// ---------------------------------------------------------------------------\n\nconst WINDOWS_SAFE_COMMANDS = new Set([\n // CMD — filesystem (read-only)\n \"dir\", \"type\", \"tree\", \"more\",\n \"findstr\", \"where\",\n\n // CMD — system info (read-only reporters)\n \"systeminfo\", \"hostname\", \"ver\", \"vol\",\n \"date\", \"set\", \"path\", \"chcp\",\n \"whoami\", \"echo\", \"sort\", \"fc\",\n\n // CMD — processes\n \"tasklist\", \"driverquery\",\n\n // CMD — network (read-only)\n \"netstat\",\n\n // CMD — policy (read-only)\n \"gpresult\",\n\n // PowerShell — Get-* cmdlets (strictly read-only by convention)\n \"get-childitem\", \"get-content\", \"get-item\",\n \"test-path\", \"resolve-path\",\n \"get-itemproperty\",\n \"select-string\", \"measure-object\",\n \"get-host\", \"get-computerinfo\", \"get-date\",\n \"get-volume\", \"get-disk\", \"get-partition\",\n \"get-process\", \"get-service\",\n \"get-netadapter\", \"get-nettcpconnection\",\n \"get-netipaddress\", \"get-netroute\",\n \"get-hotfix\", \"get-eventlog\", \"get-winevent\",\n \"get-wmiobject\", \"get-ciminstance\",\n]);\n\n// ---------------------------------------------------------------------------\n// Cross-platform safe command prefixes (two-word commands)\n// ---------------------------------------------------------------------------\n\nconst SAFE_COMMAND_PREFIXES = new Set([\n \"git status\",\n \"git log\",\n \"git diff\",\n \"git show\",\n \"git branch\",\n \"node --version\",\n \"npm --version\",\n \"npm list\",\n \"npm ls\",\n]);\n\n// ---------------------------------------------------------------------------\n// Exports\n// ---------------------------------------------------------------------------\n\nconst IS_WINDOWS = process.platform === \"win32\";\n\nexport const SAFE_COMMANDS = IS_WINDOWS ? WINDOWS_SAFE_COMMANDS : UNIX_SAFE_COMMANDS;\nexport { SAFE_COMMAND_PREFIXES };\n","/**\n * history.ts — Encrypted per-session investigation history persistence\n *\n * Stores each completed investigation and context request as an individually\n * encrypted file under a `history/` directory. Uses AES-256-GCM with a key\n * derived from the API key via HKDF-SHA256 — no key material stored on disk.\n *\n * Wire format per file: [IV (12 bytes)][authTag (16 bytes)][ciphertext]\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport * as crypto from \"crypto\";\nimport type { PRBESerializedCompletedInvestigation, PRBESerializedCR } from \"./serialization\";\nimport type { PRBECompletedInvestigation, PRBECRInvestigation } from \"./models\";\n\n// ---------------------------------------------------------------------------\n// Encryption constants\n// ---------------------------------------------------------------------------\n\nenum EncryptionConfig {\n ALGORITHM = \"aes-256-gcm\",\n IV_LENGTH = 12,\n AUTH_TAG_LENGTH = 16,\n KEY_LENGTH = 32,\n HISTORY_DIR = \"history\",\n}\n\nconst HKDF_SALT = Buffer.from(\"prbe-history-encryption-salt\", \"utf-8\");\nconst HKDF_INFO = Buffer.from(\"prbe-history-v1\", \"utf-8\");\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction getAppDataDir(): string {\n const appData =\n process.env[\"APPDATA\"] ||\n (process.platform === \"darwin\"\n ? path.join(os.homedir(), \"Library\", \"Application Support\")\n : path.join(os.homedir(), \".local\", \"share\"));\n return path.join(appData, \"prbe-agent\");\n}\n\nfunction getHistoryDir(): string {\n const dir = path.join(getAppDataDir(), EncryptionConfig.HISTORY_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\n\nfunction deriveKey(apiKey: string): Buffer {\n return Buffer.from(\n crypto.hkdfSync(\n \"sha256\",\n Buffer.from(apiKey, \"utf-8\"),\n HKDF_SALT,\n HKDF_INFO,\n EncryptionConfig.KEY_LENGTH,\n ),\n );\n}\n\nfunction encrypt(plaintext: string, key: Buffer): Buffer {\n const iv = crypto.randomBytes(EncryptionConfig.IV_LENGTH);\n const cipher = crypto.createCipheriv(\n EncryptionConfig.ALGORITHM,\n key,\n iv,\n { authTagLength: EncryptionConfig.AUTH_TAG_LENGTH } as crypto.CipherGCMOptions,\n );\n const encrypted = Buffer.concat([cipher.update(plaintext, \"utf-8\"), cipher.final()]);\n const authTag = cipher.getAuthTag();\n // Wire format: [IV][authTag][ciphertext]\n return Buffer.concat([iv, authTag, encrypted]);\n}\n\nfunction decrypt(data: Buffer, key: Buffer): string {\n const iv = data.subarray(0, EncryptionConfig.IV_LENGTH);\n const authTag = data.subarray(\n EncryptionConfig.IV_LENGTH,\n EncryptionConfig.IV_LENGTH + EncryptionConfig.AUTH_TAG_LENGTH,\n );\n const ciphertext = data.subarray(\n EncryptionConfig.IV_LENGTH + EncryptionConfig.AUTH_TAG_LENGTH,\n );\n const decipher = crypto.createDecipheriv(\n EncryptionConfig.ALGORITHM,\n key,\n iv,\n { authTagLength: EncryptionConfig.AUTH_TAG_LENGTH } as crypto.CipherGCMOptions,\n );\n decipher.setAuthTag(authTag);\n return decipher.update(ciphertext) + decipher.final(\"utf-8\");\n}\n\n// ---------------------------------------------------------------------------\n// HistoryStore\n// ---------------------------------------------------------------------------\n\nexport class HistoryStore {\n private readonly key: Buffer;\n\n constructor(apiKey: string) {\n this.key = deriveKey(apiKey);\n }\n\n load(): {\n investigations: PRBECompletedInvestigation[];\n crs: PRBECRInvestigation[];\n } {\n const investigations: PRBECompletedInvestigation[] = [];\n const crs: PRBECRInvestigation[] = [];\n\n try {\n const dir = getHistoryDir();\n\n let files: string[];\n try {\n files = fs.readdirSync(dir);\n } catch {\n return { investigations, crs };\n }\n\n for (const filename of files) {\n try {\n const filePath = path.join(dir, filename);\n const raw = fs.readFileSync(filePath);\n const json = decrypt(raw, this.key);\n\n if (filename.startsWith(\"inv-\") && filename.endsWith(\".json\")) {\n const item = JSON.parse(json) as PRBESerializedCompletedInvestigation;\n investigations.push({\n ...item,\n completedAt: new Date(item.completedAt),\n });\n } else if (filename.startsWith(\"cr-\") && filename.endsWith(\".json\")) {\n const item = JSON.parse(json) as PRBESerializedCR;\n crs.push({\n ...item,\n startedAt: new Date(item.startedAt),\n resolvedInteractions: item.resolvedInteractions ?? [],\n });\n }\n } catch {\n // Corrupted or unreadable file (e.g. key changed) — skip\n console.warn(`[PRBEAgent] Skipping unreadable history file: ${filename}`);\n }\n }\n } catch {\n // Top-level failure — return empty\n }\n\n // Sort newest-first (matching prior unshift behavior)\n investigations.sort(\n (a, b) => b.completedAt.getTime() - a.completedAt.getTime(),\n );\n crs.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());\n\n return { investigations, crs };\n }\n\n save(\n investigations: PRBECompletedInvestigation[],\n crs: PRBECRInvestigation[],\n ): void {\n try {\n const dir = getHistoryDir();\n\n // Build set of desired filenames\n const desiredFiles = new Set<string>();\n\n for (const inv of investigations) {\n const filename = `inv-${inv.id}.json`;\n desiredFiles.add(filename);\n const data: PRBESerializedCompletedInvestigation = {\n id: inv.id,\n query: inv.query,\n report: inv.report,\n summary: inv.summary,\n ticketId: inv.ticketId,\n events: inv.events,\n resolvedInteractions: inv.resolvedInteractions,\n conversationHistory: inv.conversationHistory,\n completedAt: inv.completedAt.toISOString(),\n };\n fs.writeFileSync(\n path.join(dir, filename),\n encrypt(JSON.stringify(data), this.key),\n );\n }\n\n for (const cr of crs) {\n const filename = `cr-${cr.id}.json`;\n desiredFiles.add(filename);\n const data: PRBESerializedCR = {\n id: cr.id,\n query: cr.query,\n slug: cr.slug,\n ticketId: cr.ticketId,\n events: cr.events,\n isRunning: cr.isRunning,\n isCompleted: cr.isCompleted,\n isFailed: cr.isFailed,\n report: cr.report,\n summary: cr.summary,\n errorMessage: cr.errorMessage,\n startedAt: cr.startedAt.toISOString(),\n pendingInteraction: cr.pendingInteraction,\n resolvedInteractions: cr.resolvedInteractions ?? [],\n };\n fs.writeFileSync(\n path.join(dir, filename),\n encrypt(JSON.stringify(data), this.key),\n );\n }\n\n // Remove files that are no longer in the current state\n try {\n const existing = fs.readdirSync(dir);\n for (const filename of existing) {\n if (!desiredFiles.has(filename)) {\n fs.unlinkSync(path.join(dir, filename));\n }\n }\n } catch {\n // Ignore cleanup errors\n }\n } catch {\n console.error(\"[PRBEAgent] Failed to save investigation history\");\n }\n }\n\n static clear(): void {\n try {\n const dir = path.join(getAppDataDir(), EncryptionConfig.HISTORY_DIR);\n if (fs.existsSync(dir)) {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n } catch {\n // Ignore\n }\n }\n}\n","/**\n * serialization.ts — IPC-safe serialization of agent state\n *\n * Converts live PRBEAgentState (with Map, Date, EventEmitter) into\n * plain JSON-safe objects suitable for IPC or structured clone.\n */\n\nimport type { PRBEAgentState } from \"./state\";\nimport type {\n PRBEStatusEvent,\n PRBECRInvestigation,\n TicketInfoOut,\n ConversationEntry,\n} from \"./models\";\nimport type { InteractionPayload, ResolvedInteraction } from \"./interactions\";\n\n// ---------------------------------------------------------------------------\n// Serialized CR (Date → ISO string, safe for IPC)\n// ---------------------------------------------------------------------------\n\nexport interface PRBESerializedCR {\n id: string;\n query: string;\n slug?: string;\n ticketId?: string;\n events: PRBEStatusEvent[];\n isRunning: boolean;\n isCompleted: boolean;\n isFailed: boolean;\n report: string;\n summary?: string;\n errorMessage?: string;\n agentMessage?: string;\n startedAt: string; // ISO string\n pendingInteraction?: InteractionPayload;\n resolvedInteractions?: ResolvedInteraction[];\n}\n\n// ---------------------------------------------------------------------------\n// Serialized Ticket (pass-through — already plain)\n// ---------------------------------------------------------------------------\n\nexport type PRBESerializedTicket = TicketInfoOut;\n\n// ---------------------------------------------------------------------------\n// Serialized Completed Investigation (Date → ISO string)\n// ---------------------------------------------------------------------------\n\nexport interface PRBESerializedCompletedInvestigation {\n id: string;\n query: string;\n report: string;\n summary?: string;\n ticketId?: string;\n events: PRBEStatusEvent[];\n resolvedInteractions: ResolvedInteraction[];\n conversationHistory?: ConversationEntry[];\n completedAt: string; // ISO string\n}\n\n// ---------------------------------------------------------------------------\n// Full serialized state (no Map, Date, or EventEmitter)\n// ---------------------------------------------------------------------------\n\nexport interface PRBESerializedState {\n isInvestigating: boolean;\n events: PRBEStatusEvent[];\n report: string;\n summary?: string;\n currentQuery: string;\n investigationError?: string;\n pendingInteraction?: InteractionPayload;\n resolvedInteractions: ResolvedInteraction[];\n agentMessage?: string;\n conversationHistory: ConversationEntry[];\n completedInvestigations: PRBESerializedCompletedInvestigation[];\n activeCRs: PRBESerializedCR[];\n completedCRs: PRBESerializedCR[];\n trackedSessionIDs: string[];\n ticketInfo: PRBESerializedTicket[];\n hasActiveWork: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Default state (used before agent initializes)\n// ---------------------------------------------------------------------------\n\nexport const DEFAULT_PRBE_STATE: PRBESerializedState = {\n isInvestigating: false,\n events: [],\n report: \"\",\n summary: \"\",\n currentQuery: \"\",\n resolvedInteractions: [],\n conversationHistory: [],\n completedInvestigations: [],\n activeCRs: [],\n completedCRs: [],\n trackedSessionIDs: [],\n ticketInfo: [],\n hasActiveWork: false,\n};\n\n// ---------------------------------------------------------------------------\n// Converter: live state → IPC-safe plain object\n// ---------------------------------------------------------------------------\n\nfunction serializeCR(cr: PRBECRInvestigation): PRBESerializedCR {\n return {\n id: cr.id,\n query: cr.query,\n slug: cr.slug,\n ticketId: cr.ticketId,\n events: cr.events,\n isRunning: cr.isRunning,\n isCompleted: cr.isCompleted,\n isFailed: cr.isFailed,\n report: cr.report,\n summary: cr.summary,\n errorMessage: cr.errorMessage,\n agentMessage: cr.agentMessage,\n startedAt: cr.startedAt.toISOString(),\n pendingInteraction: cr.pendingInteraction,\n resolvedInteractions: cr.resolvedInteractions ?? [],\n };\n}\n\nexport function serializePRBEState(state: PRBEAgentState): PRBESerializedState {\n return {\n isInvestigating: state.isInvestigating,\n events: state.events,\n report: state.report,\n summary: state.summary,\n currentQuery: state.currentQuery,\n investigationError: state.investigationError,\n pendingInteraction: state.pendingInteraction,\n resolvedInteractions: state.resolvedInteractions,\n agentMessage: state.agentMessage,\n conversationHistory: state.conversationHistory,\n completedInvestigations: state.completedInvestigations.map((inv) => ({\n id: inv.id,\n query: inv.query,\n report: inv.report,\n summary: inv.summary,\n ticketId: inv.ticketId,\n events: inv.events,\n resolvedInteractions: inv.resolvedInteractions,\n conversationHistory: inv.conversationHistory,\n completedAt: inv.completedAt.toISOString(),\n })),\n activeCRs: Array.from(state.activeCRs.values()).map(serializeCR),\n completedCRs: state.completedCRs.map(serializeCR),\n trackedSessionIDs: state.trackedSessionIDs,\n ticketInfo: state.ticketInfo,\n hasActiveWork: state.hasActiveWork,\n };\n}\n","/**\n * Probe brand mark SVG (transparent background, dark mark).\n * Exported as a string so host apps can use it inline without bundler plugins.\n */\nexport const PROBE_MARK_SVG = `<svg width=\"256\" height=\"256\" viewBox=\"0 0 256 256\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M50 112 L114 148 L50 184 Z\" fill=\"#111111\" opacity=\"0.07\"/>\n <path d=\"M70 86 L148 134 L70 182 Z\" fill=\"#111111\" opacity=\"0.18\"/>\n <path d=\"M92 56 L192 118 L92 180 Z\" fill=\"#111111\"/>\n</svg>`;\n"],"mappings":"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","names":["fs","path","os","import_crypto","WSMessageType","ConversationRole","ToolParamType","ToolName","UserIdentifierType","PRBEAgentConfigKey","PRBEAgentStatusType","PRBEAgentErrorType","PRBEStateEvent","import_crypto","InteractionType","InvestigationSource","path","import_crypto","import_crypto","path","IS_WINDOWS","resolve","fs","path","resolve"]}
1
+ {"version":3,"sources":["../src/index.ts","../package.json","../src/agent.ts","../src/models.ts","../src/connection.ts","../src/state.ts","../src/tools/index.ts","../src/interactions.ts","../src/tools/filesystem.ts","../src/tools/logs.ts","../src/tools/interactive.ts","../src/tools/bash.ts","../src/tools/safe-commands.ts","../src/serialization.ts","../src/assets/index.ts"],"sourcesContent":["/**\n * index.ts — Public API exports for @prbe/electron-sdk\n */\n\n// Version\nexport { version as SDK_VERSION } from \"../package.json\";\n\n// Agent\nexport { PRBEAgent } from \"./agent\";\n\n// State\nexport { PRBEAgentState, PRBEStateEvent } from \"./state\";\n\n// Models\nexport {\n WSMessageType,\n WSMessage,\n ToolParamType,\n ToolName,\n UserIdentifierType,\n PRBEToolParameter,\n PRBEToolDeclaration,\n PRBEAgentConfigKey,\n PRBEAgentConfig,\n PRBEAgentStatus,\n PRBEAgentStatusType,\n PRBEAgentError,\n PRBEAgentErrorType,\n PRBEStatusEvent,\n PRBEBackgroundInvestigation,\n PRBECompletedInvestigation,\n FlaggedFileIn,\n InvestigationResult,\n PollRequest,\n PollResponse,\n ContextRequestOut,\n ExternalRequestOut,\n TicketInfoOut,\n AgentHistoryRequest,\n AgentSessionOut,\n AgentTicketOut,\n AgentHistoryResponse,\n ConversationRole,\n ConversationEntry,\n redactPII,\n API_URL,\n MIDDLEWARE_URL,\n} from \"./models\";\n\n// Interactions\nexport {\n InteractionType,\n InvestigationSource,\n AskQuestionPayload,\n RequestPermissionPayload,\n RequestPathAccessPayload,\n InteractionPayload,\n AskQuestionResponse,\n RequestPermissionResponse,\n RequestPathAccessResponse,\n InteractionResponse,\n ResolvedInteraction,\n PRBEInteractionRequester,\n PRBEInteractionHandler,\n} from \"./interactions\";\n\n// Serialization\nexport {\n PRBESerializedBackgroundInvestigation,\n PRBESerializedTicket,\n PRBESerializedCompletedInvestigation,\n PRBESerializedState,\n DEFAULT_PRBE_STATE,\n serializePRBEState,\n} from \"./serialization\";\n\n// Tools\nexport { PRBETool, PRBEToolRegistry, PRBEClosureTool } from \"./tools/index\";\nexport { resolveAndValidate, resolveWithAccessRequest, humanReadableSize } from \"./tools/index\";\nexport {\n ListDirectoryTool,\n ReadFileTool,\n SearchContentTool,\n FindFilesTool,\n FlagFileTool,\n} from \"./tools/filesystem\";\nexport {\n PRBELogCapture,\n LogEntry,\n ReadAppLogsTool,\n SearchAppLogsTool,\n ClearAppLogsTool,\n FlagAppLogsTool,\n} from \"./tools/logs\";\n\n// Interactive tools\nexport { AskUserTool } from \"./tools/interactive\";\nexport { BashExecuteTool } from \"./tools/bash\";\n\n// Assets\nexport { PROBE_MARK_SVG } from \"./assets/index\";\n","{\n \"name\": \"@prbe.ai/electron-sdk\",\n \"version\": \"0.1.18\",\n \"description\": \"PRBE debug agent SDK for Electron apps\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"./types\": {\n \"import\": {\n \"types\": \"./dist/types.d.mts\",\n \"default\": \"./dist/types.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/types.d.ts\",\n \"default\": \"./dist/types.js\"\n }\n },\n \"./assets/*\": \"./src/assets/*\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"clean\": \"rm -rf dist\"\n },\n \"files\": [\n \"dist\",\n \"src/assets/*.svg\"\n ],\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.0.0\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.7.0\"\n }\n}\n","/**\n * agent.ts — PRBEAgent class\n *\n * Main entry point for the PRBE debug agent SDK.\n * Handles WebSocket connection to middleware, investigation lifecycle,\n * background polling for context requests, file uploads, and persistence.\n *\n * Mirrors PRBEAgent.swift behavior.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { randomUUID } from \"crypto\";\nimport {\n WSMessageType,\n PRBEAgentConfigKey,\n ToolParamType,\n UserIdentifierType,\n API_URL,\n MIDDLEWARE_URL,\n redactPII,\n} from \"./models\";\nimport { version as SDK_VERSION } from \"../package.json\";\nimport type {\n WSMessage,\n PRBEAgentConfig,\n PRBEAgentStatus,\n PRBEToolParameter,\n InvestigationResult,\n FlaggedFileIn,\n PollRequest,\n PollResponse,\n ContextRequestOut,\n ExternalRequestOut,\n AgentHistoryResponse,\n ConversationEntry,\n} from \"./models\";\nimport { InvestigationConnection } from \"./connection\";\nimport {\n PRBEAgentStatusType,\n PRBEAgentError,\n PRBEAgentErrorType,\n} from \"./models\";\nimport { PRBEAgentState, PRBEStateEvent } from \"./state\";\nimport { PRBEToolRegistry, PRBEClosureTool } from \"./tools/index\";\nimport {\n ListDirectoryTool,\n ReadFileTool,\n SearchContentTool,\n FindFilesTool,\n FlagFileTool,\n} from \"./tools/filesystem\";\nimport {\n PRBELogCapture,\n ReadAppLogsTool,\n SearchAppLogsTool,\n ClearAppLogsTool,\n FlagAppLogsTool,\n} from \"./tools/logs\";\nimport { AskUserTool } from \"./tools/interactive\";\nimport { BashExecuteTool } from \"./tools/bash\";\nimport { InteractionType, InvestigationSource } from \"./interactions\";\nimport type {\n PRBEInteractionHandler,\n PRBEInteractionRequester,\n InteractionPayload,\n InteractionResponse,\n RequestPermissionResponse,\n RequestPathAccessResponse,\n} from \"./interactions\";\n\n// ---------------------------------------------------------------------------\n// Persistence\n// ---------------------------------------------------------------------------\n\ninterface PersistedData {\n agentId?: string;\n}\n\nfunction getPersistencePath(): string {\n // Use platform-appropriate app data directory\n const appData =\n process.env[\"APPDATA\"] ||\n (process.platform === \"darwin\"\n ? path.join(os.homedir(), \"Library\", \"Application Support\")\n : path.join(os.homedir(), \".local\", \"share\"));\n const dir = path.join(appData, \"prbe-agent\");\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return path.join(dir, \"agent-state.json\");\n}\n\nfunction loadPersistedData(): PersistedData {\n try {\n const filePath = getPersistencePath();\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as PersistedData;\n }\n } catch {\n // Ignore read errors, return defaults\n }\n return {};\n}\n\nfunction savePersistedData(data: PersistedData): void {\n try {\n const filePath = getPersistencePath();\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), \"utf-8\");\n } catch {\n console.error(\"[PRBEAgent] Failed to save persisted data\");\n }\n}\n\n// ---------------------------------------------------------------------------\n// PRBEAgent\n// ---------------------------------------------------------------------------\n\nexport class PRBEAgent implements PRBEInteractionRequester {\n public readonly state: PRBEAgentState;\n public readonly logCapture: PRBELogCapture;\n\n private readonly config: Required<Pick<PRBEAgentConfig,\n | PRBEAgentConfigKey.API_KEY\n | PRBEAgentConfigKey.AUTO_APPROVED_DIRS\n | PRBEAgentConfigKey.POLLING_INTERVAL\n | PRBEAgentConfigKey.MAX_LOG_ENTRIES\n | PRBEAgentConfigKey.CAPTURE_CONSOLE\n | PRBEAgentConfigKey.BACKGROUND_POLLING\n >>;\n private readonly appDataPath?: string;\n private sessionMetadata: Record<string, unknown>;\n private readonly interactionHandler?: PRBEInteractionHandler;\n private readonly registry = new PRBEToolRegistry();\n private readonly grantedPaths = new Set<string>();\n private userCancelled = false;\n private activeConnection: InvestigationConnection | null = null;\n private pollingTimer: ReturnType<typeof setInterval> | null = null;\n private persistedData: PersistedData;\n private fetchAbortController: AbortController | null = null;\n private currentInvestigationSource: InvestigationSource = InvestigationSource.USER;\n private currentBackgroundId: string | null = null;\n\n /** Files flagged during the current tool call — uploaded immediately after the tool returns. */\n private pendingFlaggedFiles: FlaggedFileIn[] = [];\n\n // ---------- User Identifier ----------\n\n private userEmail?: string;\n private userId?: string;\n\n // ---------- Persistence ----------\n\n private get agentID(): string {\n if (this.persistedData.agentId) {\n return this.persistedData.agentId;\n }\n const newID = randomUUID();\n this.persistedData.agentId = newID;\n savePersistedData(this.persistedData);\n return newID;\n }\n\n // ---------- Constructor ----------\n\n constructor(config: PRBEAgentConfig) {\n this.config = {\n apiKey: config.apiKey,\n autoApprovedDirs: config.autoApprovedDirs,\n pollingInterval: config.pollingInterval ?? 600_000,\n maxLogEntries: config.maxLogEntries ?? 10_000,\n captureConsole: config.captureConsole ?? true,\n backgroundPolling: config.backgroundPolling ?? true,\n };\n this.interactionHandler = config.interactionHandler;\n this.appDataPath = config.appDataPath;\n this.sessionMetadata = { sdk_version: SDK_VERSION, ...config.sessionMetadata };\n\n // Auto-add appDataPath to autoApprovedDirs if not already present\n if (this.appDataPath && !this.config.autoApprovedDirs.includes(this.appDataPath)) {\n this.config.autoApprovedDirs.push(this.appDataPath);\n }\n\n this.state = new PRBEAgentState();\n this.logCapture = new PRBELogCapture(this.config.maxLogEntries);\n this.persistedData = loadPersistedData();\n\n // Eagerly generate agent ID so it's available for setUserIdentifier() immediately\n void this.agentID;\n\n const roots = this.config.autoApprovedDirs;\n const requester: PRBEInteractionRequester | undefined = this.interactionHandler ? this : undefined;\n const grantedPaths = this.grantedPaths;\n\n // Register built-in filesystem tools\n this.registry.register(new ListDirectoryTool(roots, requester, grantedPaths));\n this.registry.register(new ReadFileTool(roots, requester, grantedPaths));\n this.registry.register(new SearchContentTool(roots, requester, grantedPaths));\n this.registry.register(new FindFilesTool(roots, requester, grantedPaths));\n this.registry.register(\n new FlagFileTool(roots, (file) => {\n this.pendingFlaggedFiles.push(file);\n }, requester, grantedPaths),\n );\n\n // Register built-in log tools\n this.registry.register(new ReadAppLogsTool(this.logCapture));\n this.registry.register(new SearchAppLogsTool(this.logCapture));\n this.registry.register(new ClearAppLogsTool(this.logCapture));\n this.registry.register(\n new FlagAppLogsTool(this.logCapture, (file) => {\n this.pendingFlaggedFiles.push(file);\n }),\n );\n\n // Register interactive tools (only when handler is available)\n if (requester) {\n this.registry.register(new AskUserTool(requester));\n this.registry.register(new BashExecuteTool(requester, roots, grantedPaths));\n }\n\n // Register message_user tool — surfaces agent messages to the UI\n this.registry.register(\n new PRBEClosureTool(\n \"client_message_user\",\n \"Send a message to the user.\",\n [{ name: \"message\", type: ToolParamType.STRING, description: \"Message for the user\", required: true }],\n async (args) => {\n const message = (args[\"message\"] as string) ?? \"\";\n if (this.currentInvestigationSource !== InvestigationSource.USER && this.currentBackgroundId) {\n this.state.setBackgroundAgentMessage(this.currentBackgroundId, message);\n } else {\n this.state.setAgentMessage(message);\n }\n return \"Message delivered.\";\n },\n ),\n );\n\n // Start console capture if configured\n if (this.config.captureConsole) {\n this.logCapture.startCapturing();\n }\n\n // Hook electron-log if provided\n if (config.electronLog) {\n this.hookElectronLog(config.electronLog);\n }\n\n // Listen for renderer log forwarding via IPC if provided\n if (config.ipcMain) {\n this.hookRendererLogs(config.ipcMain, config.rendererLogChannel ?? \"prbe-renderer-log\");\n }\n\n // Start background polling immediately if enabled\n if (this.config.backgroundPolling) {\n this.startPolling();\n }\n }\n\n\n // ---------- Log integration ----------\n\n private hookElectronLog(electronLog: NonNullable<PRBEAgentConfig[PRBEAgentConfigKey.ELECTRON_LOG]>): void {\n try {\n electronLog.hooks.push(\n (message: { level: string; data: any[] }, _transportFn: any, transportName: string) => {\n if (transportName !== \"file\") return message;\n try {\n const text = message.data\n .map((d: any) => (typeof d === \"string\" ? d : JSON.stringify(d)))\n .join(\" \");\n const level = PRBEAgent.mapElectronLogLevel(message.level);\n this.logCapture.log(text, level, `electron-log.${message.level}`);\n } catch {\n // ignore serialization errors\n }\n return message;\n },\n );\n } catch {\n // electron-log not available or incompatible\n }\n }\n\n private hookRendererLogs(\n ipcMain: NonNullable<PRBEAgentConfig[PRBEAgentConfigKey.IPC_MAIN]>,\n channel: string,\n ): void {\n ipcMain.on(channel, (_event: any, entry: { message: string; level: string; category: string }) => {\n this.logCapture.log(entry.message, entry.level, `renderer.${entry.category}`);\n });\n }\n\n private static mapElectronLogLevel(level: string): string {\n switch (level) {\n case \"error\": return \"ERROR\";\n case \"warn\": return \"WARNING\";\n case \"debug\":\n case \"verbose\":\n case \"silly\": return \"DEBUG\";\n default: return \"INFO\";\n }\n }\n\n // ---------- PRBEInteractionRequester implementation ----------\n\n get investigationSource(): InvestigationSource {\n return this.currentInvestigationSource;\n }\n\n sendConversationMessage(content: string): void {\n this.activeConnection?.sendConversationMessage(content);\n }\n\n async requestUserInteraction(payload: InteractionPayload): Promise<InteractionResponse> {\n if (!this.interactionHandler) {\n throw new PRBEAgentError(\n PRBEAgentErrorType.SERVER_ERROR,\n \"No interaction handler configured\",\n );\n }\n\n // Update state to show pending interaction\n if (this.currentInvestigationSource !== InvestigationSource.USER && this.currentBackgroundId) {\n this.state.setBackgroundPendingInteraction(this.currentBackgroundId, payload);\n } else {\n this.state.setPendingInteraction(payload);\n }\n\n try {\n const response = await this.interactionHandler.handleInteraction(payload);\n if (this.currentInvestigationSource !== InvestigationSource.USER && this.currentBackgroundId) {\n this.state.resolveBackgroundInteraction(this.currentBackgroundId, response);\n } else {\n this.state.resolveInteraction(response);\n }\n\n // Send permission decisions to conversation history\n if (response.type === InteractionType.REQUEST_PERMISSION) {\n const approved = (response as RequestPermissionResponse).approved;\n this.sendConversationMessage(approved ? \"Approved\" : \"Denied\");\n } else if (response.type === InteractionType.REQUEST_PATH_ACCESS) {\n const granted = (response as RequestPathAccessResponse).granted;\n this.sendConversationMessage(granted ? \"Allowed\" : \"Denied\");\n }\n\n return response;\n } catch (err) {\n if (this.currentInvestigationSource !== InvestigationSource.USER && this.currentBackgroundId) {\n this.state.clearBackgroundPendingInteraction(this.currentBackgroundId);\n } else {\n this.state.clearPendingInteraction();\n }\n throw err;\n }\n }\n\n /**\n * Add an additional root directory to the runtime allowed roots.\n */\n addAutoApprovedDir(rootPath: string): void {\n if (!this.config.autoApprovedDirs.includes(rootPath)) {\n this.config.autoApprovedDirs.push(rootPath);\n }\n }\n\n // ---------- Public API ----------\n\n /**\n * Update session metadata. Merged with existing metadata.\n * Call this to add user profile data, app version, etc. after async initialization.\n */\n updateSessionMetadata(metadata: Record<string, unknown>): void {\n this.sessionMetadata = { ...this.sessionMetadata, ...metadata };\n }\n\n /**\n * Set a user identifier for this agent. Persists to the backend agents table.\n * Can be called multiple times with different types to set both email and ID.\n * Also auto-injects user_email and/or user_id into session metadata for investigations.\n */\n setUserIdentifier(type: UserIdentifierType, value: string): void {\n if (type === UserIdentifierType.EMAIL) {\n this.userEmail = value;\n } else {\n this.userId = value;\n }\n this.syncUserIdentifierToBackend(type, value);\n }\n\n /**\n * Clear user identifier(s) for this agent.\n * Pass a specific type to clear only that identifier, or omit to clear both email and ID.\n */\n clearUserIdentifier(type?: UserIdentifierType): void {\n if (type) {\n if (type === UserIdentifierType.EMAIL) {\n this.userEmail = undefined;\n } else {\n this.userId = undefined;\n }\n this.syncUserIdentifierToBackend(type, null);\n } else {\n this.userEmail = undefined;\n this.userId = undefined;\n this.syncUserIdentifierToBackend(UserIdentifierType.EMAIL, null);\n this.syncUserIdentifierToBackend(UserIdentifierType.ID, null);\n }\n }\n\n private syncUserIdentifierToBackend(type: UserIdentifierType, value: string | null): void {\n void this.post(\"/api/agent/update-user\", {\n agent_id: this.agentID,\n identifier_type: type,\n identifier_value: value,\n }).catch((err) => {\n console.error(`[PRBEAgent] Failed to sync user identifier: ${err}`);\n });\n }\n\n /**\n * Register a custom tool that the middleware can invoke during investigations.\n */\n registerTool(\n name: string,\n description: string,\n parameters: PRBEToolParameter[],\n handler: (args: Record<string, unknown>) => Promise<string>,\n options?: { interactive?: boolean },\n ): void {\n this.registry.register(\n new PRBEClosureTool(name, description, parameters, handler, options),\n );\n }\n\n // ---------- Unified Investigation ----------\n\n private async runInvestigation(opts: {\n query: string;\n source: InvestigationSource;\n sourceId?: string;\n contextRequestId?: string;\n externalRequestId?: string;\n externalRequestSource?: string;\n externalRequestSourceDetail?: string;\n ticketId?: string;\n cancellable: boolean;\n }): Promise<InvestigationResult | null> {\n this.currentInvestigationSource = opts.source;\n this.currentBackgroundId = opts.sourceId ?? null;\n\n const isBackground = opts.source !== InvestigationSource.USER;\n\n const emitter = (status: PRBEAgentStatus): void => {\n switch (status.type) {\n case PRBEAgentStatusType.STARTED:\n if (isBackground && opts.sourceId) {\n this.state.appendBackgroundEvent(opts.sourceId, \"Starting investigation...\");\n } else {\n this.state.appendEvent(\"Starting investigation...\");\n }\n break;\n case PRBEAgentStatusType.THINKING:\n break;\n case PRBEAgentStatusType.TOOL_CALL:\n if (isBackground && opts.sourceId) {\n this.state.appendBackgroundEvent(opts.sourceId, status.label);\n } else {\n this.state.appendEvent(status.label);\n }\n break;\n case PRBEAgentStatusType.OBSERVATION:\n if (isBackground && opts.sourceId) {\n this.state.attachBackgroundObservation(opts.sourceId, status.text);\n } else {\n this.state.attachObservation(status.text);\n }\n break;\n case PRBEAgentStatusType.THOUGHT:\n if (isBackground && opts.sourceId) {\n this.state.appendBackgroundEvent(opts.sourceId, \"Thinking\", status.text);\n } else {\n this.state.appendEvent(\"Thinking\", status.text);\n }\n break;\n case PRBEAgentStatusType.COMPLETED:\n if (isBackground && opts.sourceId) {\n this.state.completeBackgroundInvestigation(opts.sourceId, status.report);\n } else {\n this.state.completeInvestigation(status.report, status.ticketId);\n }\n break;\n case PRBEAgentStatusType.ERROR:\n if (isBackground && opts.sourceId) {\n this.state.failBackgroundInvestigation(opts.sourceId, status.message);\n } else {\n this.state.failInvestigation(status.message);\n }\n break;\n }\n };\n\n const result = await this.connectToProxy(\n opts.query,\n opts.contextRequestId,\n opts.externalRequestId,\n opts.externalRequestSource,\n opts.externalRequestSourceDetail,\n emitter,\n opts.cancellable ? () => this.userCancelled : () => false,\n opts.ticketId,\n );\n\n this.currentInvestigationSource = InvestigationSource.USER;\n this.currentBackgroundId = null;\n\n return result;\n }\n\n /**\n * User-initiated investigation. Updates `state` events/report directly.\n */\n async investigate(query: string, contextRequestID?: string): Promise<void> {\n this.userCancelled = false;\n this.state.beginInvestigation(query);\n\n const result = await this.runInvestigation({\n query,\n source: InvestigationSource.USER,\n contextRequestId: contextRequestID,\n cancellable: true,\n });\n\n if (!result && this.state.isInvestigating) {\n const message = this.userCancelled\n ? \"Investigation cancelled\"\n : \"Investigation ended unexpectedly\";\n this.state.failInvestigation(message);\n }\n }\n\n /**\n * Cancel user-initiated investigation only (does not cancel background investigations).\n */\n cancelInvestigation(): void {\n this.userCancelled = true;\n if (this.activeConnection) {\n this.activeConnection.close(1000, \"User cancelled\");\n this.activeConnection = null;\n }\n }\n\n /**\n * Cancel everything — user investigation and polling.\n */\n cancel(): void {\n this.userCancelled = true;\n if (this.activeConnection) {\n this.activeConnection.close(1000, \"User cancelled\");\n this.activeConnection = null;\n }\n this.abortInFlightRequests();\n this.stopPolling();\n }\n\n /**\n * Poll the backend for context requests and external requests.\n */\n async poll(): Promise<PollResponse | null> {\n try {\n const request: PollRequest = { agent_id: this.agentID };\n const response = await this.post<PollResponse>(\"/api/agent/poll\", request);\n\n for (const cr of response.context_requests) {\n if (!cr.is_active) continue;\n if (this.state.activeBackgroundInvestigations.has(cr.id)) continue;\n await this.investigateForCR(cr, cr.ticket_id);\n }\n\n for (const er of response.external_requests) {\n if (!er.is_active) continue;\n if (this.state.activeBackgroundInvestigations.has(er.id)) continue;\n await this.investigateForER(er);\n }\n\n return response;\n } catch {\n return null;\n }\n }\n\n /**\n * Fetch agent history (tickets + sessions) from the backend.\n */\n async fetchHistory(): Promise<AgentHistoryResponse | null> {\n try {\n const response = await this.post<AgentHistoryResponse>(\n \"/api/agent/history\",\n { agent_id: this.agentID },\n );\n this.state.updateAgentHistory(response.tickets);\n return response;\n } catch {\n return null;\n }\n }\n\n stopPolling(): void {\n if (this.pollingTimer !== null) {\n clearInterval(this.pollingTimer);\n this.pollingTimer = null;\n }\n }\n\n resumePolling(): void {\n if (!this.config.backgroundPolling) return;\n this.startPolling();\n }\n\n /**\n * Destroy the agent — stops polling, stops console capture, closes WS.\n */\n destroy(): void {\n this.cancel();\n this.logCapture.stopCapturing();\n }\n\n /**\n * Reset all persisted data (agent ID, tracked tickets, responded CRs).\n * Also clears in-memory state.\n */\n resetPersistedData(): void {\n this.stopPolling();\n this.persistedData = {};\n savePersistedData(this.persistedData);\n this.state.resetInvestigation();\n this.state.completedInvestigations = [];\n this.state.activeBackgroundInvestigations.clear();\n this.state.completedBackgroundInvestigations = [];\n this.state.agentHistory = [];\n this.state.emit(PRBEStateEvent.STATUS);\n }\n\n /**\n * Delete the persisted data file. Can be called without an agent instance.\n */\n static clearPersistedData(): void {\n try {\n const filePath = getPersistencePath();\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n } catch {\n // Ignore\n }\n }\n\n // ---------- Background Investigation ----------\n\n private async investigateForCR(\n cr: ContextRequestOut,\n ticketId: string,\n ): Promise<void> {\n this.state.beginBackgroundInvestigation(cr.id, cr.query, cr.slug ?? undefined, ticketId);\n\n await this.runInvestigation({\n query: cr.query,\n source: InvestigationSource.CONTEXT_REQUEST,\n sourceId: cr.id,\n contextRequestId: cr.id,\n ticketId,\n cancellable: false,\n });\n }\n\n private async investigateForER(\n er: ExternalRequestOut,\n ): Promise<void> {\n this.state.beginBackgroundInvestigation(er.id, er.query, undefined, undefined, er.source, er.source_detail);\n\n await this.runInvestigation({\n query: er.query,\n source: InvestigationSource.EXTERNAL_REQUEST,\n sourceId: er.id,\n externalRequestId: er.id,\n externalRequestSource: er.source,\n externalRequestSourceDetail: er.source_detail,\n cancellable: false,\n });\n }\n\n // ---------- WebSocket Investigation ----------\n\n private connectToProxy(\n query: string,\n contextRequestID: string | undefined,\n externalRequestId: string | undefined,\n externalRequestSource: string | undefined,\n externalRequestSourceDetail: string | undefined,\n emit: (status: PRBEAgentStatus) => void,\n isCancelled: () => boolean,\n ticketId?: string,\n ): Promise<InvestigationResult | null> {\n return new Promise<InvestigationResult | null>((resolve) => {\n const wsUrl = `${MIDDLEWARE_URL}/api/agent/client/ws`;\n let uploadBaseUrl: string | undefined;\n let resolved = false;\n\n const finish = (result: InvestigationResult | null) => {\n if (resolved) return;\n resolved = true;\n this.activeConnection = null;\n resolve(result);\n };\n\n let conn: InvestigationConnection;\n try {\n conn = new InvestigationConnection(\n wsUrl,\n this.config.apiKey,\n (msg) => this.handleMessage(msg, conn, emit, isCancelled, finish, () => uploadBaseUrl, (url) => { uploadBaseUrl = url; }),\n (message) => {\n if (!isCancelled()) emit({ type: PRBEAgentStatusType.ERROR, message });\n finish(null);\n },\n () => {\n if (!resolved) {\n if (isCancelled()) {\n finish(null);\n } else {\n emit({ type: PRBEAgentStatusType.ERROR, message: \"WebSocket connection closed unexpectedly\" });\n finish(null);\n }\n }\n },\n );\n } catch (err) {\n emit({ type: PRBEAgentStatusType.ERROR, message: `Failed to create WebSocket: ${err}` });\n resolve(null);\n return;\n }\n\n this.activeConnection = conn;\n\n conn.onopen = () => {\n const toolDeclarations = this.registry\n .allDeclarations()\n .map((decl) => ({\n name: decl.name,\n description: decl.description,\n parameters: decl.parameters.map((param) => ({\n name: param.name,\n type: param.type,\n description: param.description,\n required: param.required,\n })),\n ...(decl.interactive ? { interactive: true } : {}),\n }));\n\n const startMetadata: Record<string, unknown> = {\n agent_id: this.agentID,\n custom_tools: toolDeclarations,\n platform: os.platform(),\n os_version: os.release(),\n arch: os.arch(),\n };\n if (contextRequestID) startMetadata[\"context_request_id\"] = contextRequestID;\n if (externalRequestId) startMetadata[\"external_request_id\"] = externalRequestId;\n if (externalRequestSource) startMetadata[\"external_request_source\"] = externalRequestSource;\n if (externalRequestSourceDetail) startMetadata[\"external_request_source_detail\"] = externalRequestSourceDetail;\n if (ticketId) startMetadata[\"ticket_id\"] = ticketId;\n if (this.appDataPath) startMetadata[\"app_data_path\"] = this.appDataPath;\n // Auto-inject user identifiers into session metadata\n const enrichedMetadata = { ...this.sessionMetadata };\n if (this.userEmail) {\n enrichedMetadata[\"user_email\"] = this.userEmail;\n }\n if (this.userId) {\n enrichedMetadata[\"user_id\"] = this.userId;\n }\n if (Object.keys(enrichedMetadata).length > 0) {\n startMetadata[\"session_metadata\"] = enrichedMetadata;\n }\n\n if (!conn.send({ type: WSMessageType.START, content: query, metadata: startMetadata })) {\n emit({ type: PRBEAgentStatusType.ERROR, message: \"Failed to send start message\" });\n finish(null);\n return;\n }\n\n emit({ type: PRBEAgentStatusType.STARTED });\n this.pendingFlaggedFiles = [];\n };\n });\n }\n\n private async handleMessage(\n msg: WSMessage,\n conn: InvestigationConnection,\n emit: (status: PRBEAgentStatus) => void,\n isCancelled: () => boolean,\n finish: (result: InvestigationResult | null) => void,\n getUploadBaseUrl: () => string | undefined,\n setUploadBaseUrl: (url: string | undefined) => void,\n ): Promise<void> {\n if (isCancelled()) {\n conn.sendCancel();\n conn.close(1000, \"Cancelled\");\n finish(null);\n return;\n }\n\n switch (msg.type) {\n case WSMessageType.THOUGHT:\n emit({ type: PRBEAgentStatusType.THOUGHT, text: msg.content ?? \"\" });\n break;\n\n case WSMessageType.TOOL_CALL: {\n const toolName = msg.name ?? \"\";\n const callId = msg.id ?? \"\";\n const args = this.extractArgs(msg.metadata);\n\n emit({ type: PRBEAgentStatusType.TOOL_CALL, name: toolName, label: msg.content ?? `Running ${toolName}` });\n\n this.pendingFlaggedFiles = [];\n const toolResult = redactPII(await this.registry.execute(toolName, args));\n emit({ type: PRBEAgentStatusType.OBSERVATION, text: toolResult.substring(0, 200) });\n\n // Build refs for any files flagged during this tool call\n let resultMetadata: Record<string, unknown> | undefined;\n const uploadBaseUrl = getUploadBaseUrl();\n if (this.pendingFlaggedFiles.length > 0 && uploadBaseUrl) {\n const uploadPrefix = this.extractUploadPrefix(uploadBaseUrl);\n const uploadedRefs: Array<Record<string, unknown>> = [];\n\n for (const file of this.pendingFlaggedFiles) {\n const filename = path.basename(file.originalPath);\n const safeName = encodeURIComponent(filename);\n const storagePath = `${uploadPrefix}/${safeName}`;\n uploadedRefs.push({\n original_path: file.originalPath,\n reason: file.reason ?? \"\",\n storage_path: storagePath,\n file_size_bytes: file.data.length,\n });\n\n const uploadUrl = `${uploadBaseUrl}/${safeName}`;\n const contentType = file.isText ? \"text/plain\" : \"application/octet-stream\";\n void PRBEAgent.backgroundUpload(file.data, uploadUrl, this.config.apiKey, contentType, this.getFetchSignal());\n }\n resultMetadata = { flagged_files: uploadedRefs };\n this.pendingFlaggedFiles = [];\n }\n\n conn.sendToolResult(callId, toolName, toolResult, resultMetadata);\n break;\n }\n\n case WSMessageType.SERVER_TOOL_CALL:\n emit({ type: PRBEAgentStatusType.TOOL_CALL, name: msg.name ?? \"\", label: msg.content ?? \"\" });\n break;\n\n case WSMessageType.SERVER_OBSERVATION:\n emit({ type: PRBEAgentStatusType.OBSERVATION, text: (msg.content ?? \"\").substring(0, 200) });\n break;\n\n case WSMessageType.COMPLETE: {\n const report = msg.content ?? \"\";\n const completedTicketId = msg.metadata?.[\"ticket_id\"] as string | undefined;\n const sessionId = msg.metadata?.[\"session_id\"] as string | undefined;\n emit({ type: PRBEAgentStatusType.COMPLETED, report, ticketId: completedTicketId });\n conn.close(1000, \"Complete\");\n finish({ report, ticketId: completedTicketId, sessionId });\n break;\n }\n\n case WSMessageType.ERROR:\n emit({ type: PRBEAgentStatusType.ERROR, message: msg.content || \"Unknown error\" });\n conn.close(1000, \"Error received\");\n finish(null);\n break;\n\n case WSMessageType.SESSION_CONFIG:\n setUploadBaseUrl(msg.metadata?.[\"upload_url\"] as string | undefined);\n break;\n\n case WSMessageType.CONVERSATION_UPDATE: {\n try {\n const entry = JSON.parse(msg.content ?? \"{}\") as ConversationEntry;\n if (this.currentInvestigationSource !== InvestigationSource.USER && this.currentBackgroundId) {\n this.state.appendBackgroundConversation(this.currentBackgroundId, entry);\n } else {\n this.state.appendConversation(entry);\n }\n } catch { /* ignore malformed entries */ }\n break;\n }\n\n case WSMessageType.PING:\n conn.sendPong();\n break;\n\n default:\n break;\n }\n }\n\n private extractArgs(\n metadata: Record<string, unknown> | undefined,\n ): Record<string, unknown> {\n if (!metadata) return {};\n const argsVal = metadata[\"args\"];\n if (argsVal && typeof argsVal === \"object\" && !Array.isArray(argsVal)) {\n return argsVal as Record<string, unknown>;\n }\n return {};\n }\n\n private extractUploadPrefix(baseUrl: string): string {\n try {\n const url = new URL(baseUrl);\n const urlPath = url.pathname; // \"/api/agent/upload/{tenant}/{uuid}/files\"\n const marker = \"/api/agent/upload/\";\n const idx = urlPath.indexOf(marker);\n if (idx !== -1) {\n return urlPath.substring(idx + marker.length);\n }\n } catch {\n // Ignore URL parse errors\n }\n return \"\";\n }\n\n // ---------- File Upload ----------\n\n private static async backgroundUpload(\n data: Buffer,\n uploadUrl: string,\n apiKey: string,\n contentType: string,\n signal?: AbortSignal,\n ): Promise<void> {\n try {\n const response = await fetch(uploadUrl, {\n method: \"PUT\",\n headers: {\n \"Content-Type\": contentType,\n \"X-API-Key\": apiKey,\n },\n body: data,\n signal,\n });\n\n if (!response.ok) {\n console.error(\n `[PRBEAgent] file upload failed: HTTP ${response.status} for ${uploadUrl}`,\n );\n }\n } catch (err) {\n console.error(`[PRBEAgent] file upload error: ${err} for ${uploadUrl}`);\n }\n }\n\n // ---------- Polling ----------\n\n private startPolling(): void {\n this.stopPolling();\n this.pollingTimer = setInterval(() => {\n void this.poll();\n }, this.config.pollingInterval);\n }\n\n // ---------- Networking ----------\n\n /**\n * Abort all in-flight fetch requests to prevent orphaned DNS lookups\n * that can crash the c-ares resolver during process shutdown.\n */\n private abortInFlightRequests(): void {\n if (this.fetchAbortController) {\n this.fetchAbortController.abort();\n this.fetchAbortController = null;\n }\n }\n\n /**\n * Get an AbortSignal for fetch requests. Creates a new controller if needed.\n */\n private getFetchSignal(): AbortSignal {\n if (!this.fetchAbortController) {\n this.fetchAbortController = new AbortController();\n }\n return this.fetchAbortController.signal;\n }\n\n private async post<Res>(urlPath: string, body: unknown): Promise<Res> {\n const url = `${API_URL}${urlPath}`;\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.config.apiKey,\n },\n body: JSON.stringify(body),\n signal: this.getFetchSignal(),\n });\n\n if (!response.ok) {\n const message = await response.text().catch(() => \"Unknown error\");\n throw new PRBEAgentError(\n PRBEAgentErrorType.SERVER_ERROR,\n `Server error ${response.status}: ${message}`,\n response.status,\n );\n }\n\n return (await response.json()) as Res;\n }\n}\n","/**\n * models.ts — WSMessage, WSMessageType, tool types, config, errors\n *\n * All types must match the Swift SDK + middleware protocol exactly.\n */\n\n// ---------------------------------------------------------------------------\n// WebSocket Message Types\n// ---------------------------------------------------------------------------\n\nexport enum WSMessageType {\n // SDK -> Middleware\n START = \"start\",\n TOOL_RESULT = \"tool_result\",\n UPLOAD_REQUEST = \"upload_request\",\n CONVERSATION_MESSAGE = \"conversation_message\",\n CANCEL = \"cancel\",\n PONG = \"pong\",\n // Middleware -> SDK\n THOUGHT = \"thought\",\n TOOL_CALL = \"tool_call\",\n SERVER_TOOL_CALL = \"server_tool_call\",\n SERVER_OBSERVATION = \"server_observation\",\n UPLOAD_URL = \"upload_url\",\n SESSION_CONFIG = \"session_config\",\n CONVERSATION_UPDATE = \"conversation_update\",\n COMPLETE = \"complete\",\n ERROR = \"error\",\n PING = \"ping\",\n}\n\n// ---------------------------------------------------------------------------\n// Conversation\n// ---------------------------------------------------------------------------\n\nexport enum ConversationRole {\n User = \"user\",\n Agent = \"agent\",\n}\n\nexport interface ConversationEntry {\n role: ConversationRole;\n content: string;\n label?: string;\n ts: string;\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket Message\n// ---------------------------------------------------------------------------\n\nexport interface WSMessage {\n type: WSMessageType;\n id?: string;\n name?: string;\n content?: string;\n metadata?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Tool System\n// ---------------------------------------------------------------------------\n\nexport enum ToolParamType {\n STRING = \"STRING\",\n BOOLEAN = \"BOOLEAN\",\n INTEGER = \"INTEGER\",\n}\n\nexport interface PRBEToolParameter {\n name: string;\n type: ToolParamType;\n description: string;\n required: boolean;\n}\n\nexport interface PRBEToolDeclaration {\n name: string;\n description: string;\n parameters: PRBEToolParameter[];\n /** When true, the middleware uses a longer timeout for this tool (user interaction required). */\n interactive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Tool Names (must match middleware exactly)\n// ---------------------------------------------------------------------------\n\nexport enum ToolName {\n CLIENT_LIST_DIRECTORY = \"client_list_directory\",\n CLIENT_READ_FILE = \"client_read_file\",\n CLIENT_SEARCH_CONTENT = \"client_search_content\",\n CLIENT_FIND_FILES = \"client_find_files\",\n CLIENT_FLAG_FILE = \"client_flag_file\",\n CLIENT_READ_APP_LOGS = \"client_read_app_logs\",\n CLIENT_SEARCH_APP_LOGS = \"client_search_app_logs\",\n CLIENT_CLEAR_APP_LOGS = \"client_clear_app_logs\",\n CLIENT_FLAG_APP_LOGS = \"client_flag_app_logs\",\n CLIENT_ASK_USER = \"client_ask_user\",\n CLIENT_BASH_EXECUTE = \"client_bash_execute\",\n CLIENT_MESSAGE_USER = \"client_message_user\",\n}\n\n// ---------------------------------------------------------------------------\n// User Identifier\n// ---------------------------------------------------------------------------\n\nexport enum UserIdentifierType {\n EMAIL = \"email\",\n ID = \"id\",\n}\n\n// ---------------------------------------------------------------------------\n// Agent Configuration\n// ---------------------------------------------------------------------------\n\nexport enum PRBEAgentConfigKey {\n API_KEY = \"apiKey\",\n AUTO_APPROVED_DIRS = \"autoApprovedDirs\",\n POLLING_INTERVAL = \"pollingInterval\",\n MAX_LOG_ENTRIES = \"maxLogEntries\",\n CAPTURE_CONSOLE = \"captureConsole\",\n BACKGROUND_POLLING = \"backgroundPolling\",\n INTERACTION_HANDLER = \"interactionHandler\",\n ELECTRON_LOG = \"electronLog\",\n IPC_MAIN = \"ipcMain\",\n RENDERER_LOG_CHANNEL = \"rendererLogChannel\",\n APP_DATA_PATH = \"appDataPath\",\n SESSION_METADATA = \"sessionMetadata\",\n}\n\nexport interface PRBEAgentConfig {\n [PRBEAgentConfigKey.API_KEY]: string;\n [PRBEAgentConfigKey.AUTO_APPROVED_DIRS]: string[];\n [PRBEAgentConfigKey.POLLING_INTERVAL]?: number; // ms, default 600_000 (10 min)\n [PRBEAgentConfigKey.MAX_LOG_ENTRIES]?: number; // default 10_000\n [PRBEAgentConfigKey.CAPTURE_CONSOLE]?: boolean; // default true\n [PRBEAgentConfigKey.BACKGROUND_POLLING]?: boolean; // default true\n [PRBEAgentConfigKey.INTERACTION_HANDLER]?: import(\"./interactions\").PRBEInteractionHandler;\n /** electron-log instance (v5) — SDK hooks into its transports to capture main-process logs */\n [PRBEAgentConfigKey.ELECTRON_LOG]?: { hooks: { push: (hook: (...args: any[]) => any) => void } };\n /** Electron ipcMain instance — SDK listens for renderer log forwarding */\n [PRBEAgentConfigKey.IPC_MAIN]?: { on: (channel: string, listener: (event: any, ...args: any[]) => void) => void };\n /** IPC channel name for renderer log forwarding (default: \"prbe-renderer-log\") */\n [PRBEAgentConfigKey.RENDERER_LOG_CHANNEL]?: string;\n /** Path to the application's data directory (e.g. Electron userData). Sent to the agent so it explores this directory first. */\n [PRBEAgentConfigKey.APP_DATA_PATH]?: string;\n /** Custom metadata included in every session submission (e.g. user profile, app version). */\n [PRBEAgentConfigKey.SESSION_METADATA]?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Agent Status\n// ---------------------------------------------------------------------------\n\nexport enum PRBEAgentStatusType {\n STARTED = \"started\",\n THINKING = \"thinking\",\n TOOL_CALL = \"tool_call\",\n THOUGHT = \"thought\",\n OBSERVATION = \"observation\",\n COMPLETED = \"completed\",\n ERROR = \"error\",\n AWAITING_INTERACTION = \"awaiting_interaction\",\n}\n\nexport type PRBEAgentStatus =\n | { type: PRBEAgentStatusType.STARTED }\n | { type: PRBEAgentStatusType.THINKING }\n | { type: PRBEAgentStatusType.TOOL_CALL; name: string; label: string }\n | { type: PRBEAgentStatusType.THOUGHT; text: string }\n | { type: PRBEAgentStatusType.OBSERVATION; text: string }\n | { type: PRBEAgentStatusType.COMPLETED; report: string; ticketId?: string }\n | { type: PRBEAgentStatusType.ERROR; message: string }\n | { type: PRBEAgentStatusType.AWAITING_INTERACTION; interactionPayload: import(\"./interactions\").InteractionPayload };\n\n// ---------------------------------------------------------------------------\n// Investigation Result (internal)\n// ---------------------------------------------------------------------------\n\nexport interface InvestigationResult {\n report: string;\n ticketId?: string;\n sessionId?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Flagged File (internal)\n// ---------------------------------------------------------------------------\n\nexport interface FlaggedFileIn {\n originalPath: string;\n reason?: string;\n data: Buffer;\n isText: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Poll Endpoint\n// ---------------------------------------------------------------------------\n\nexport interface PollRequest {\n agent_id: string;\n}\n\nexport interface ContextRequestOut {\n id: string;\n query: string;\n slug?: string;\n ticket_id: string;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface ExternalRequestOut {\n id: string;\n query: string;\n source: string;\n source_detail?: string;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface PollResponse {\n context_requests: ContextRequestOut[];\n external_requests: ExternalRequestOut[];\n}\n\n// ---------------------------------------------------------------------------\n// Ticket Info (used by state for UI display)\n// ---------------------------------------------------------------------------\n\nexport interface TicketInfoOut {\n ticket_id: string;\n title: string;\n status: string;\n priority?: string;\n description?: string;\n session_count: number;\n}\n\n// ---------------------------------------------------------------------------\n// Agent History\n// ---------------------------------------------------------------------------\n\nexport interface AgentHistoryRequest {\n agent_id: string;\n}\n\nexport interface AgentSessionOut {\n session_id: string;\n title: string;\n status: string;\n context_summary?: string;\n created_at: string;\n}\n\nexport interface AgentTicketOut {\n ticket_id: string;\n title: string;\n status: string;\n priority?: string;\n sessions: AgentSessionOut[];\n}\n\nexport interface AgentHistoryResponse {\n tickets: AgentTicketOut[];\n}\n\n// ---------------------------------------------------------------------------\n// Status Events (for state tracking)\n// ---------------------------------------------------------------------------\n\nexport interface PRBEStatusEvent {\n id: string;\n label: string;\n detail?: string;\n isCompleted: boolean;\n isExpanded: boolean;\n}\n\nexport interface PRBEBackgroundInvestigation {\n id: string;\n query: string;\n slug?: string;\n ticketId?: string;\n source?: string;\n sourceDetail?: string;\n events: PRBEStatusEvent[];\n isRunning: boolean;\n isCompleted: boolean;\n isFailed: boolean;\n report: string;\n summary?: string;\n errorMessage?: string;\n agentMessage?: string;\n startedAt: Date;\n pendingInteraction?: import(\"./interactions\").InteractionPayload;\n resolvedInteractions?: import(\"./interactions\").ResolvedInteraction[];\n conversationHistory: ConversationEntry[];\n}\n\n// ---------------------------------------------------------------------------\n// Completed Investigation (persisted in state for history)\n// ---------------------------------------------------------------------------\n\nexport interface PRBECompletedInvestigation {\n id: string;\n query: string;\n report: string;\n summary?: string;\n ticketId?: string;\n events: PRBEStatusEvent[];\n resolvedInteractions: import(\"./interactions\").ResolvedInteraction[];\n conversationHistory?: ConversationEntry[];\n completedAt: Date;\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport enum PRBEAgentErrorType {\n SERVER_ERROR = \"server_error\",\n NETWORK_ERROR = \"network_error\",\n CANCELLED = \"cancelled\",\n MAX_ITERATIONS = \"max_iterations\",\n}\n\nexport class PRBEAgentError extends Error {\n public readonly errorType: PRBEAgentErrorType;\n public readonly statusCode?: number;\n\n constructor(errorType: PRBEAgentErrorType, message: string, statusCode?: number) {\n super(message);\n this.name = \"PRBEAgentError\";\n this.errorType = errorType;\n this.statusCode = statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// PII Redactor (pass-through stub, matches Swift SDK)\n// ---------------------------------------------------------------------------\n\nexport function redactPII(text: string): string {\n return text;\n}\n\n// ---------------------------------------------------------------------------\n// Static URLs\n// ---------------------------------------------------------------------------\n\nexport const API_URL = \"https://api.prbe.ai\";\nexport const MIDDLEWARE_URL = \"wss://middleware.prbe.ai\";\n","/**\n * connection.ts — InvestigationConnection\n *\n * Encapsulates the WebSocket connection to the middleware for a single investigation.\n * Handles message parsing, sending, and provides a clean interface for the agent.\n */\n\nimport { WSMessageType, ConversationRole } from \"./models\";\nimport type { WSMessage, ConversationEntry } from \"./models\";\n\nexport class InvestigationConnection {\n private ws: WebSocket;\n private closed = false;\n\n constructor(\n url: string,\n apiKey: string,\n private readonly onMessage: (msg: WSMessage) => void,\n private readonly onError: (message: string) => void,\n private readonly onClose: () => void,\n ) {\n this.ws = new WebSocket(url, {\n headers: { \"X-API-Key\": apiKey },\n } as unknown as string[]);\n\n this.ws.onmessage = (event: MessageEvent) => {\n const raw = typeof event.data === \"string\"\n ? event.data\n : event.data instanceof Buffer\n ? event.data.toString(\"utf-8\")\n : null;\n if (!raw) return;\n\n try {\n const msg = JSON.parse(raw) as WSMessage;\n this.onMessage(msg);\n } catch { /* ignore malformed messages */ }\n };\n\n this.ws.onerror = (event: unknown) => {\n const errorEvent = event as { message?: string };\n this.onError(errorEvent.message || \"WebSocket connection error\");\n };\n\n this.ws.onclose = () => {\n this.onClose();\n };\n }\n\n get isOpen(): boolean {\n return !this.closed && this.ws.readyState === WebSocket.OPEN;\n }\n\n send(msg: WSMessage): boolean {\n if (!this.isOpen) return false;\n try {\n this.ws.send(JSON.stringify(msg));\n return true;\n } catch {\n return false;\n }\n }\n\n sendConversationMessage(content: string): void {\n this.send({\n type: WSMessageType.CONVERSATION_MESSAGE,\n content,\n });\n }\n\n sendToolResult(callId: string, toolName: string, result: string, metadata?: Record<string, unknown>): void {\n this.send({\n type: WSMessageType.TOOL_RESULT,\n id: callId,\n name: toolName,\n content: result,\n metadata,\n });\n }\n\n sendCancel(): void {\n this.send({ type: WSMessageType.CANCEL });\n }\n\n sendPong(): void {\n this.send({ type: WSMessageType.PONG });\n }\n\n close(code = 1000, reason?: string): void {\n if (this.closed) return;\n this.closed = true;\n try {\n this.ws.close(code, reason);\n } catch { /* ignore */ }\n }\n\n /**\n * Set the onopen handler. Called when the connection is ready to send messages.\n */\n set onopen(handler: () => void) {\n this.ws.onopen = handler;\n }\n}\n","/**\n * state.ts — PRBEAgentState: EventEmitter-based observable investigation state\n *\n * Mirrors PRBEAgentState.swift but uses Node.js EventEmitter instead of Combine/@Published.\n * Host apps subscribe to events for UI updates.\n */\n\nimport { EventEmitter } from \"events\";\nimport { randomUUID } from \"crypto\";\nimport type {\n PRBEStatusEvent,\n PRBEBackgroundInvestigation,\n PRBECompletedInvestigation,\n TicketInfoOut,\n AgentTicketOut,\n ConversationEntry,\n} from \"./models\";\nimport type { InteractionPayload, InteractionResponse, ResolvedInteraction } from \"./interactions\";\n\n// ---------------------------------------------------------------------------\n// Event types emitted by PRBEAgentState\n// ---------------------------------------------------------------------------\n\nexport enum PRBEStateEvent {\n /** Emitted on any state change. Payload: void */\n STATUS = \"status\",\n /** Emitted when a new event is appended. Payload: PRBEStatusEvent */\n EVENT = \"event\",\n /** Emitted when investigation completes. Payload: { report: string } */\n COMPLETE = \"complete\",\n /** Emitted on error. Payload: { message: string } */\n ERROR = \"error\",\n /** Emitted when a background investigation starts. Payload: PRBEBackgroundInvestigation */\n BACKGROUND_START = \"background-start\",\n /** Emitted when a background investigation completes/fails. Payload: PRBEBackgroundInvestigation */\n BACKGROUND_COMPLETE = \"background-complete\",\n /** Emitted when tracked ticket IDs change. Payload: string[] */\n TICKETS_CHANGED = \"tickets-changed\",\n /** Emitted when ticket info is updated. Payload: TicketInfoOut[] */\n TICKET_INFO = \"ticket-info\",\n /** Emitted when an interaction is requested. Payload: InteractionPayload */\n INTERACTION_REQUESTED = \"interaction-requested\",\n /** Emitted when an interaction is resolved. Payload: void */\n INTERACTION_RESOLVED = \"interaction-resolved\",\n /** Emitted when the agent sends a message to the user. Payload: { message: string } */\n AGENT_MESSAGE = \"agent-message\",\n}\n\n// ---------------------------------------------------------------------------\n// PRBEAgentState\n// ---------------------------------------------------------------------------\n\nexport class PRBEAgentState extends EventEmitter {\n // User-initiated investigation\n public isInvestigating = false;\n public events: PRBEStatusEvent[] = [];\n public report = \"\";\n public summary = \"\";\n public currentQuery = \"\";\n public investigationError?: string;\n public pendingInteraction?: InteractionPayload;\n public resolvedInteractions: ResolvedInteraction[] = [];\n public agentMessage?: string;\n public conversationHistory: ConversationEntry[] = [];\n\n // Completed user investigations (history)\n public completedInvestigations: PRBECompletedInvestigation[] = [];\n\n // Background investigations (context requests, external requests, etc.)\n public activeBackgroundInvestigations: Map<string, PRBEBackgroundInvestigation> = new Map();\n public completedBackgroundInvestigations: PRBEBackgroundInvestigation[] = [];\n\n // Tracked tickets\n public trackedSessionIDs: string[] = [];\n public ticketInfo: TicketInfoOut[] = [];\n\n // Agent history\n public agentHistory: AgentTicketOut[] = [];\n\n // Computed\n get hasActiveWork(): boolean {\n return this.isInvestigating || this.activeBackgroundInvestigations.size > 0;\n }\n\n get activeBackgroundCount(): number {\n return this.activeBackgroundInvestigations.size;\n }\n\n get isActive(): boolean {\n return this.isInvestigating || this.report.length > 0 || this.investigationError != null;\n }\n\n // ---------- User investigation mutations ----------\n\n beginInvestigation(query: string): void {\n this.isInvestigating = true;\n this.events = [];\n this.resolvedInteractions = [];\n this.conversationHistory = [];\n this.report = \"\";\n this.summary = \"\";\n this.currentQuery = query;\n this.investigationError = undefined;\n this.agentMessage = undefined;\n this.emit(PRBEStateEvent.STATUS);\n }\n\n appendConversation(entry: ConversationEntry): void {\n this.conversationHistory.push(entry);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n appendBackgroundConversation(backgroundId: string, entry: ConversationEntry): void {\n const bg = this.activeBackgroundInvestigations.get(backgroundId);\n if (!bg) return;\n bg.conversationHistory.push(entry);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n resetInvestigation(): void {\n this.isInvestigating = false;\n this.events = [];\n this.resolvedInteractions = [];\n this.conversationHistory = [];\n this.report = \"\";\n this.summary = \"\";\n this.currentQuery = \"\";\n this.investigationError = undefined;\n this.pendingInteraction = undefined;\n this.agentMessage = undefined;\n this.emit(PRBEStateEvent.STATUS);\n }\n\n appendEvent(label: string, detail?: string, completed = false): void {\n // Mark previous event as completed before adding new one\n if (this.events.length > 0) {\n const last = this.events[this.events.length - 1];\n if (!last.isCompleted && !completed) {\n last.isCompleted = true;\n }\n }\n const event: PRBEStatusEvent = {\n id: randomUUID(),\n label,\n detail,\n isCompleted: completed,\n isExpanded: false,\n };\n this.events.push(event);\n this.emit(PRBEStateEvent.EVENT, event);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n attachObservation(text: string): void {\n if (this.events.length > 0) {\n this.events[this.events.length - 1].detail = text;\n this.emit(PRBEStateEvent.STATUS);\n }\n }\n\n completeInvestigation(report: string, ticketId?: string): void {\n if (this.events.length > 0) {\n this.events[this.events.length - 1].isCompleted = true;\n }\n this.appendEvent(\"Done\", undefined, true);\n\n // Save to history (snapshot events + interactions before reset)\n this.completedInvestigations.unshift({\n id: randomUUID(),\n query: this.currentQuery,\n report,\n ticketId,\n events: [...this.events],\n resolvedInteractions: [...this.resolvedInteractions],\n conversationHistory: [...this.conversationHistory],\n completedAt: new Date(),\n });\n\n this.report = report;\n this.isInvestigating = false;\n this.emit(PRBEStateEvent.COMPLETE, { report });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n failInvestigation(message: string): void {\n this.appendEvent(`Error: ${message}`);\n this.investigationError = message;\n this.isInvestigating = false;\n this.emit(PRBEStateEvent.ERROR, { message });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n // ---------- Interaction state mutations ----------\n\n setPendingInteraction(payload: InteractionPayload): void {\n this.pendingInteraction = payload;\n this.emit(PRBEStateEvent.INTERACTION_REQUESTED, payload);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n clearPendingInteraction(): void {\n this.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n setBackgroundPendingInteraction(backgroundId: string, payload: InteractionPayload): void {\n const bg = this.activeBackgroundInvestigations.get(backgroundId);\n if (!bg) return;\n bg.pendingInteraction = payload;\n this.emit(PRBEStateEvent.INTERACTION_REQUESTED, payload);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n clearBackgroundPendingInteraction(backgroundId: string): void {\n const bg = this.activeBackgroundInvestigations.get(backgroundId);\n if (!bg) return;\n bg.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n resolveInteraction(response: InteractionResponse): void {\n if (!this.pendingInteraction) return;\n this.resolvedInteractions.push({\n interactionId: this.pendingInteraction.interactionId,\n payload: this.pendingInteraction,\n response,\n eventIndex: this.events.length,\n });\n this.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n resolveBackgroundInteraction(backgroundId: string, response: InteractionResponse): void {\n const bg = this.activeBackgroundInvestigations.get(backgroundId);\n if (!bg || !bg.pendingInteraction) return;\n const resolved = bg.resolvedInteractions ?? [];\n resolved.push({\n interactionId: bg.pendingInteraction.interactionId,\n payload: bg.pendingInteraction,\n response,\n eventIndex: bg.events.length,\n });\n bg.resolvedInteractions = resolved;\n bg.pendingInteraction = undefined;\n this.emit(PRBEStateEvent.INTERACTION_RESOLVED);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n setAgentMessage(message: string): void {\n this.agentMessage = message;\n this.emit(PRBEStateEvent.AGENT_MESSAGE, { message });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n setBackgroundAgentMessage(backgroundId: string, message: string): void {\n const bg = this.activeBackgroundInvestigations.get(backgroundId);\n if (!bg) return;\n bg.agentMessage = message;\n this.emit(PRBEStateEvent.AGENT_MESSAGE, { message });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n toggleExpansion(eventId: string): void {\n const event = this.events.find((e) => e.id === eventId);\n if (event) {\n event.isExpanded = !event.isExpanded;\n this.emit(PRBEStateEvent.STATUS);\n }\n }\n\n // ---------- Background investigation state mutations ----------\n\n beginBackgroundInvestigation(id: string, query: string, slug?: string, ticketId?: string, source?: string, sourceDetail?: string): void {\n const bg: PRBEBackgroundInvestigation = {\n id,\n query,\n slug,\n ticketId,\n source,\n sourceDetail,\n events: [],\n conversationHistory: [],\n resolvedInteractions: [],\n isRunning: true,\n isCompleted: false,\n isFailed: false,\n report: \"\",\n summary: \"\",\n startedAt: new Date(),\n };\n this.activeBackgroundInvestigations.set(id, bg);\n this.emit(PRBEStateEvent.BACKGROUND_START, bg);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n appendBackgroundEvent(backgroundId: string, label: string, detail?: string, completed = false): void {\n const bg = this.activeBackgroundInvestigations.get(backgroundId);\n if (!bg) return;\n\n if (bg.events.length > 0) {\n const last = bg.events[bg.events.length - 1];\n if (!last.isCompleted && !completed) {\n last.isCompleted = true;\n }\n }\n bg.events.push({\n id: randomUUID(),\n label,\n detail,\n isCompleted: completed,\n isExpanded: false,\n });\n this.emit(PRBEStateEvent.STATUS);\n }\n\n attachBackgroundObservation(backgroundId: string, text: string): void {\n const bg = this.activeBackgroundInvestigations.get(backgroundId);\n if (!bg || bg.events.length === 0) return;\n bg.events[bg.events.length - 1].detail = text;\n this.emit(PRBEStateEvent.STATUS);\n }\n\n completeBackgroundInvestigation(id: string, report: string): void {\n const bg = this.activeBackgroundInvestigations.get(id);\n if (!bg) return;\n\n this.activeBackgroundInvestigations.delete(id);\n if (bg.events.length > 0) {\n bg.events[bg.events.length - 1].isCompleted = true;\n }\n bg.events.push({\n id: randomUUID(),\n label: \"Done\",\n isCompleted: true,\n isExpanded: false,\n });\n bg.isRunning = false;\n bg.isCompleted = true;\n bg.report = report;\n this.completedBackgroundInvestigations.unshift(bg);\n this.emit(PRBEStateEvent.BACKGROUND_COMPLETE, bg);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n failBackgroundInvestigation(id: string, message: string): void {\n const bg = this.activeBackgroundInvestigations.get(id);\n if (!bg) return;\n\n this.activeBackgroundInvestigations.delete(id);\n bg.events.push({\n id: randomUUID(),\n label: `Error: ${message}`,\n isCompleted: false,\n isExpanded: false,\n });\n bg.isRunning = false;\n bg.isFailed = true;\n bg.errorMessage = message;\n this.completedBackgroundInvestigations.unshift(bg);\n this.emit(PRBEStateEvent.BACKGROUND_COMPLETE, bg);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n // ---------- Tickets ----------\n\n updateTrackedSessionIDs(ids: string[]): void {\n this.trackedSessionIDs = ids;\n this.emit(PRBEStateEvent.TICKETS_CHANGED, ids);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n updateTicketInfo(info: TicketInfoOut[]): void {\n this.ticketInfo = info;\n this.emit(PRBEStateEvent.TICKET_INFO, info);\n this.emit(PRBEStateEvent.STATUS);\n }\n\n updateAgentHistory(tickets: AgentTicketOut[]): void {\n this.agentHistory = tickets;\n this.emit(PRBEStateEvent.STATUS);\n }\n}\n","/**\n * tools/index.ts — Tool interface, registry, and closure tool\n *\n * Mirrors PRBEAgentTools.swift tool protocol + registry pattern.\n */\n\nimport type { PRBEToolDeclaration, PRBEToolParameter } from \"../models\";\nimport { randomUUID } from \"crypto\";\nimport { InteractionType } from \"../interactions\";\nimport type { PRBEInteractionRequester, RequestPathAccessResponse } from \"../interactions\";\n\n// ---------------------------------------------------------------------------\n// Tool Interface\n// ---------------------------------------------------------------------------\n\nexport interface PRBETool {\n readonly declaration: PRBEToolDeclaration;\n execute(args: Record<string, unknown>): Promise<string>;\n}\n\n// ---------------------------------------------------------------------------\n// Tool Registry\n// ---------------------------------------------------------------------------\n\nexport class PRBEToolRegistry {\n private tools: Map<string, PRBETool> = new Map();\n\n register(tool: PRBETool): void {\n this.tools.set(tool.declaration.name, tool);\n }\n\n allDeclarations(): PRBEToolDeclaration[] {\n return Array.from(this.tools.values()).map((t) => t.declaration);\n }\n\n async execute(name: string, args: Record<string, unknown>): Promise<string> {\n const tool = this.tools.get(name);\n if (!tool) {\n return `Error: unknown tool '${name}'`;\n }\n return tool.execute(args);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Closure Tool (for user-registered custom tools)\n// ---------------------------------------------------------------------------\n\nexport class PRBEClosureTool implements PRBETool {\n public readonly declaration: PRBEToolDeclaration;\n private readonly handler: (args: Record<string, unknown>) => Promise<string>;\n\n constructor(\n name: string,\n description: string,\n parameters: PRBEToolParameter[],\n handler: (args: Record<string, unknown>) => Promise<string>,\n options?: { interactive?: boolean },\n ) {\n this.declaration = {\n name,\n description,\n parameters,\n ...(options?.interactive ? { interactive: true } : {}),\n };\n this.handler = handler;\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n return this.handler(args);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Path Validation (shared by filesystem + flag tools)\n// ---------------------------------------------------------------------------\n\nimport * as path from \"path\";\nimport * as fs from \"fs\";\n\n/**\n * Resolve a path string and validate it against auto-approved directories.\n * Returns the resolved absolute path or null if outside auto-approved directories.\n */\nexport function resolveAndValidate(pathStr: string, autoApprovedDirs: string[]): string | null {\n let resolved: string;\n if (path.isAbsolute(pathStr)) {\n resolved = path.resolve(pathStr);\n } else if (autoApprovedDirs.length > 0) {\n resolved = path.resolve(autoApprovedDirs[0], pathStr);\n } else {\n return null;\n }\n\n // Normalize to remove trailing slashes for comparison\n const normalizedResolved = path.resolve(resolved);\n\n for (const root of autoApprovedDirs) {\n const normalizedRoot = path.resolve(root);\n if (normalizedResolved === normalizedRoot || normalizedResolved.startsWith(normalizedRoot + path.sep)) {\n return normalizedResolved;\n }\n }\n\n return null;\n}\n\n/** Result of resolveWithAccessRequest — resolved path, null (silently denied), or error string for the agent */\nexport type PathResolution = { path: string } | { error: string } | null;\n\n/**\n * Resolve a path, requesting user access if outside auto-approved directories.\n * When a requester is available and the path fails validation, prompts\n * the user for permission and caches the grant in `grantedPaths`.\n *\n * Returns { path } on success, { error } with a message for the agent, or null.\n */\nexport async function resolveWithAccessRequest(\n pathStr: string,\n autoApprovedDirs: string[],\n grantedPaths: Set<string>,\n requester?: PRBEInteractionRequester,\n): Promise<PathResolution> {\n // First try against auto-approved directories + already-granted paths\n const allRoots = [...autoApprovedDirs, ...grantedPaths];\n const resolved = resolveAndValidate(pathStr, allRoots);\n if (resolved) return { path: resolved };\n\n // No requester — can't ask for access\n if (!requester) return null;\n\n // Resolve the absolute path even though it's outside roots\n let absolute: string;\n if (path.isAbsolute(pathStr)) {\n absolute = path.resolve(pathStr);\n } else if (autoApprovedDirs.length > 0) {\n absolute = path.resolve(autoApprovedDirs[0], pathStr);\n } else {\n return null;\n }\n\n // Reject overly broad paths — tell the agent to be more specific\n const depth = absolute.split(path.sep).filter(Boolean).length;\n if (depth < 3) {\n return { error: `Path '${pathStr}' is too broad. Use a more specific path (e.g. a subdirectory at least 3 levels deep).` };\n }\n\n // Request path access from the user\n const response = await requester.requestUserInteraction({\n type: InteractionType.REQUEST_PATH_ACCESS,\n interactionId: randomUUID(),\n path: absolute,\n reason: `The agent needs access to '${pathStr}' which is outside the allowed directories.`,\n });\n\n const pathResponse = response as RequestPathAccessResponse;\n if (!pathResponse.granted) return { error: \"Path access denied by user.\" };\n\n // Grant the exact resolved path (not parent — avoid overly broad grants)\n grantedPaths.add(absolute);\n\n return { path: absolute };\n}\n\n/**\n * Format byte sizes for human-readable output.\n */\nexport function humanReadableSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${kb.toFixed(1)} KB`;\n const mb = kb / 1024;\n if (mb < 1024) return `${mb.toFixed(1)} MB`;\n const gb = mb / 1024;\n return `${gb.toFixed(1)} GB`;\n}\n","/**\n * interactions.ts — Types for user interaction during investigations\n *\n * Defines the contract between tools (which request interactions) and\n * host apps (which present UI and collect responses).\n */\n\n// ---------------------------------------------------------------------------\n// Interaction Types\n// ---------------------------------------------------------------------------\n\nexport enum InteractionType {\n ASK_QUESTION = \"ask_question\",\n REQUEST_PERMISSION = \"request_permission\",\n REQUEST_PATH_ACCESS = \"request_path_access\",\n}\n\n// ---------------------------------------------------------------------------\n// Payloads (tool → host)\n// ---------------------------------------------------------------------------\n\nexport interface AskQuestionPayload {\n type: InteractionType.ASK_QUESTION;\n interactionId: string;\n question: string;\n context?: string;\n}\n\nexport interface RequestPermissionPayload {\n type: InteractionType.REQUEST_PERMISSION;\n interactionId: string;\n action: string;\n command: string;\n reason?: string;\n}\n\nexport interface RequestPathAccessPayload {\n type: InteractionType.REQUEST_PATH_ACCESS;\n interactionId: string;\n path: string;\n reason: string;\n}\n\nexport type InteractionPayload =\n | AskQuestionPayload\n | RequestPermissionPayload\n | RequestPathAccessPayload;\n\n// ---------------------------------------------------------------------------\n// Responses (host → tool)\n// ---------------------------------------------------------------------------\n\nexport interface AskQuestionResponse {\n type: InteractionType.ASK_QUESTION;\n answer: string;\n}\n\nexport interface RequestPermissionResponse {\n type: InteractionType.REQUEST_PERMISSION;\n approved: boolean;\n}\n\nexport interface RequestPathAccessResponse {\n type: InteractionType.REQUEST_PATH_ACCESS;\n granted: boolean;\n}\n\nexport type InteractionResponse =\n | AskQuestionResponse\n | RequestPermissionResponse\n | RequestPathAccessResponse;\n\n// ---------------------------------------------------------------------------\n// Investigation source\n// ---------------------------------------------------------------------------\n\nexport enum InvestigationSource {\n USER = \"user\",\n CONTEXT_REQUEST = \"context_request\",\n EXTERNAL_REQUEST = \"external_request\",\n}\n\n// ---------------------------------------------------------------------------\n// Minimal requester interface (tools depend on this, not on PRBEAgent)\n// ---------------------------------------------------------------------------\n\nexport interface PRBEInteractionRequester {\n requestUserInteraction(payload: InteractionPayload): Promise<InteractionResponse>;\n sendConversationMessage(content: string): void;\n readonly investigationSource: InvestigationSource;\n}\n\n// ---------------------------------------------------------------------------\n// Handler interface (host app implements this)\n// ---------------------------------------------------------------------------\n\nexport interface PRBEInteractionHandler {\n handleInteraction(payload: InteractionPayload): Promise<InteractionResponse>;\n}\n\n// ---------------------------------------------------------------------------\n// Resolved interaction (question + response, for persistence)\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedInteraction {\n interactionId: string;\n payload: InteractionPayload;\n response: InteractionResponse;\n /** Number of events at time of resolution — used to split thinking bubbles */\n eventIndex: number;\n}\n","/**\n * tools/filesystem.ts — Built-in filesystem tools\n *\n * Implements: client_list_directory, client_read_file, client_search_content,\n * client_find_files, client_flag_file\n *\n * Mirrors PRBEAgentTools.swift filesystem tool implementations.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { PRBEToolDeclaration, FlaggedFileIn } from \"../models\";\nimport { ToolName, ToolParamType, redactPII } from \"../models\";\nimport type { PRBEInteractionRequester } from \"../interactions\";\nimport type { PRBETool } from \"./index\";\nimport { resolveAndValidate, resolveWithAccessRequest, humanReadableSize, type PathResolution } from \"./index\";\n\n/** Resolve a path using access request if available, else basic validation. Returns [resolved, error]. */\nasync function resolvePath(\n pathStr: string,\n autoApprovedDirs: string[],\n requester?: PRBEInteractionRequester,\n grantedPaths?: Set<string>,\n): Promise<[string | null, string | null]> {\n if (requester && grantedPaths) {\n const result = await resolveWithAccessRequest(pathStr, autoApprovedDirs, grantedPaths, requester);\n if (result && \"error\" in result) return [null, result.error];\n if (result && \"path\" in result) return [result.path, null];\n }\n const resolved = resolveAndValidate(pathStr, autoApprovedDirs);\n return [resolved, resolved ? null : \"path is outside auto-approved directories\"];\n}\n\n// ---------------------------------------------------------------------------\n// ListDirectoryTool\n// ---------------------------------------------------------------------------\n\nexport class ListDirectoryTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_LIST_DIRECTORY,\n description: \"List directory contents\",\n parameters: [\n { name: \"path\", type: ToolParamType.STRING, description: \"Directory path\", required: true },\n { name: \"recursive\", type: ToolParamType.BOOLEAN, description: \"List recursively\", required: false },\n { name: \"max_depth\", type: ToolParamType.INTEGER, description: \"Max depth (default 3)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n try {\n const stat = fs.statSync(resolved);\n if (!stat.isDirectory()) return `Error: '${pathStr}' is not a directory`;\n } catch {\n return `Error: '${pathStr}' does not exist or is not accessible`;\n }\n\n const recursive = args[\"recursive\"] === true;\n const maxDepth = typeof args[\"max_depth\"] === \"number\" ? args[\"max_depth\"] : 3;\n\n const lines: string[] = [];\n this.listDir(resolved, 0, recursive ? maxDepth : 1, lines);\n if (lines.length >= ListDirectoryTool.MAX_ENTRIES) {\n lines.push(`\\n(truncated at ${ListDirectoryTool.MAX_ENTRIES} entries — use a more specific path)`);\n }\n return lines.join(\"\\n\") || \"(empty directory)\";\n }\n\n private static readonly MAX_ENTRIES = 1000;\n\n private listDir(dirPath: string, depth: number, maxDepth: number, lines: string[]): void {\n if (depth >= maxDepth) return;\n if (lines.length >= ListDirectoryTool.MAX_ENTRIES) return;\n const indent = \" \".repeat(depth);\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n lines.push(`${indent}(access denied)`);\n return;\n }\n\n // Sort entries alphabetically, skip hidden files\n const sorted = entries\n .filter((e) => !e.name.startsWith(\".\"))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n for (const entry of sorted) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n lines.push(`${indent}${entry.name}/`);\n this.listDir(fullPath, depth + 1, maxDepth, lines);\n } else {\n try {\n const stat = fs.statSync(fullPath);\n lines.push(`${indent}${entry.name} (${humanReadableSize(stat.size)})`);\n } catch {\n lines.push(`${indent}${entry.name} (unknown size)`);\n }\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// ReadFileTool\n// ---------------------------------------------------------------------------\n\nexport class ReadFileTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_READ_FILE,\n description: \"Read file contents\",\n parameters: [\n { name: \"path\", type: ToolParamType.STRING, description: \"File path\", required: true },\n { name: \"offset\", type: ToolParamType.INTEGER, description: \"Line offset\", required: false },\n { name: \"limit\", type: ToolParamType.INTEGER, description: \"Max lines (default 200)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n let content: string;\n try {\n content = fs.readFileSync(resolved, \"utf-8\");\n } catch {\n return `Error: could not read file at '${pathStr}'`;\n }\n\n const allLines = content.split(/\\r?\\n/);\n const totalLines = allLines.length;\n const limit = typeof args[\"limit\"] === \"number\" ? args[\"limit\"] : 200;\n const rawOffset = typeof args[\"offset\"] === \"number\" ? args[\"offset\"] : 0;\n\n let startIndex: number;\n if (rawOffset < 0) {\n startIndex = Math.max(0, totalLines + rawOffset);\n } else {\n startIndex = rawOffset;\n }\n\n const endIndex = Math.min(startIndex + limit, totalLines);\n if (startIndex >= totalLines) {\n return `File has ${totalLines} lines; offset ${rawOffset} is out of range.`;\n }\n\n let stat: fs.Stats;\n try {\n stat = fs.statSync(resolved);\n } catch {\n stat = { size: 0 } as fs.Stats;\n }\n const sizeStr = humanReadableSize(stat.size);\n\n let result = `File: ${pathStr} (${totalLines} lines, ${sizeStr}, showing ${startIndex + 1}-${endIndex})\\n`;\n for (let i = startIndex; i < endIndex; i++) {\n const lineNum = String(i + 1).padStart(4, \" \");\n result += `${lineNum} | ${allLines[i]}\\n`;\n }\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SearchContentTool\n// ---------------------------------------------------------------------------\n\nexport class SearchContentTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_SEARCH_CONTENT,\n description: \"Search file contents\",\n parameters: [\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Regex pattern\", required: true },\n { name: \"path\", type: ToolParamType.STRING, description: \"File or directory to search\", required: true },\n { name: \"context_lines\", type: ToolParamType.INTEGER, description: \"Context lines (default 2)\", required: false },\n { name: \"max_results\", type: ToolParamType.INTEGER, description: \"Max results (default 50)\", required: false },\n { name: \"case_sensitive\", type: ToolParamType.BOOLEAN, description: \"Case-sensitive search (default false)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pattern = args[\"pattern\"] as string | undefined;\n if (!pattern) return \"Error: 'pattern' parameter is required\";\n\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n const contextLines = typeof args[\"context_lines\"] === \"number\" ? args[\"context_lines\"] : 2;\n const maxResults = typeof args[\"max_results\"] === \"number\" ? args[\"max_results\"] : 50;\n\n const caseSensitive = args[\"case_sensitive\"] === true;\n let regex: RegExp;\n try {\n regex = new RegExp(pattern, caseSensitive ? \"\" : \"i\");\n } catch {\n return `Error: invalid regex pattern '${pattern}'`;\n }\n\n // Collect file paths to search\n const fileURLs: string[] = [];\n let isDirectory = false;\n try {\n const stat = fs.statSync(resolved);\n if (stat.isDirectory()) {\n isDirectory = true;\n this.collectFiles(resolved, fileURLs);\n } else {\n fileURLs.push(resolved);\n }\n } catch {\n return `Error: could not access '${pathStr}'`;\n }\n\n const results: string[] = [];\n\n for (const filePath of fileURLs) {\n if (results.length >= maxResults) break;\n\n let content: string;\n try {\n content = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n continue;\n }\n\n const lines = content.split(/\\r?\\n/);\n const relativePath = isDirectory\n ? path.relative(resolved, filePath)\n : path.basename(filePath);\n\n for (let idx = 0; idx < lines.length; idx++) {\n if (results.length >= maxResults) break;\n if (!regex.test(lines[idx])) continue;\n\n let snippet: string;\n if (contextLines > 0) {\n const start = Math.max(0, idx - contextLines);\n const end = Math.min(lines.length - 1, idx + contextLines);\n snippet = \"\";\n for (let ci = start; ci <= end; ci++) {\n const marker = ci === idx ? \">\" : \" \";\n snippet += `${relativePath}:${ci + 1}:${marker} ${lines[ci]}\\n`;\n }\n } else {\n snippet = `${relativePath}:${idx + 1}: ${lines[idx]}`;\n }\n results.push(snippet);\n }\n }\n\n if (results.length === 0) {\n return `No matches found for '${pattern}' in '${pathStr}'`;\n }\n return `Found ${results.length} match(es):\\n\\n${results.join(\"\\n---\\n\")}`;\n }\n\n private collectFiles(dirPath: string, fileURLs: string[]): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n const fullPath = path.join(dirPath, entry.name);\n if (entry.isDirectory()) {\n this.collectFiles(fullPath, fileURLs);\n } else if (entry.isFile()) {\n fileURLs.push(fullPath);\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// FindFilesTool\n// ---------------------------------------------------------------------------\n\nexport class FindFilesTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_FIND_FILES,\n description: \"Find files by name\",\n parameters: [\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Glob pattern\", required: true },\n { name: \"path\", type: ToolParamType.STRING, description: \"Directory to search\", required: true },\n { name: \"max_results\", type: ToolParamType.INTEGER, description: \"Max results (default 50)\", required: false },\n { name: \"case_sensitive\", type: ToolParamType.BOOLEAN, description: \"Case-sensitive matching (default false)\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pattern = args[\"pattern\"] as string | undefined;\n if (!pattern) return \"Error: 'pattern' parameter is required\";\n\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n const maxResults = typeof args[\"max_results\"] === \"number\" ? args[\"max_results\"] : 50;\n const caseSensitive = args[\"case_sensitive\"] === true;\n\n interface FileMatch {\n path: string;\n size: number;\n modified: Date;\n }\n\n const matches: FileMatch[] = [];\n this.walkAndMatch(resolved, pattern, matches, caseSensitive);\n\n // Sort newest-first\n matches.sort((a, b) => b.modified.getTime() - a.modified.getTime());\n const limited = matches.slice(0, maxResults);\n\n if (limited.length === 0) {\n return `No files matching '${pattern}' found in '${pathStr}'`;\n }\n\n let result = `Found ${matches.length} file(s) matching '${pattern}':\\n\\n`;\n for (const m of limited) {\n const sizeStr = humanReadableSize(m.size);\n const dateStr = m.modified.toISOString();\n result += `${m.path} (${sizeStr}, ${dateStr})\\n`;\n }\n return result;\n }\n\n private walkAndMatch(dirPath: string, pattern: string, matches: Array<{ path: string; size: number; modified: Date }>, caseSensitive: boolean): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n this.walkAndMatch(fullPath, pattern, matches, caseSensitive);\n } else if (entry.isFile()) {\n if (this.globMatch(entry.name, pattern, caseSensitive)) {\n try {\n const stat = fs.statSync(fullPath);\n matches.push({\n path: fullPath,\n size: stat.size,\n modified: stat.mtime,\n });\n } catch {\n // Skip files we can't stat\n }\n }\n }\n }\n }\n\n /**\n * Simple glob matching: supports *, ?, and character classes [...].\n * Converts glob to regex and tests against the filename.\n */\n private globMatch(filename: string, pattern: string, caseSensitive: boolean): boolean {\n // Convert glob pattern to regex\n let regexStr = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i];\n switch (c) {\n case \"*\":\n regexStr += \".*\";\n break;\n case \"?\":\n regexStr += \".\";\n break;\n case \"[\":\n // Find closing bracket\n const closeBracket = pattern.indexOf(\"]\", i + 1);\n if (closeBracket === -1) {\n regexStr += \"\\\\[\";\n } else {\n regexStr += pattern.substring(i, closeBracket + 1);\n i = closeBracket;\n }\n break;\n case \".\":\n case \"(\":\n case \")\":\n case \"+\":\n case \"^\":\n case \"$\":\n case \"|\":\n case \"{\":\n case \"}\":\n case \"\\\\\":\n regexStr += `\\\\${c}`;\n break;\n default:\n regexStr += c;\n }\n }\n regexStr += \"$\";\n\n try {\n return new RegExp(regexStr, caseSensitive ? \"\" : \"i\").test(filename);\n } catch {\n return false;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// FlagFileTool\n// ---------------------------------------------------------------------------\n\nexport class FlagFileTool implements PRBETool {\n private readonly autoApprovedDirs: string[];\n private readonly onFlag: (file: FlaggedFileIn) => void;\n private readonly requester?: PRBEInteractionRequester;\n private readonly grantedPaths?: Set<string>;\n\n private static readonly MAX_BINARY_SIZE = 100 * 1024 * 1024; // 100MB\n\n constructor(\n autoApprovedDirs: string[],\n onFlag: (file: FlaggedFileIn) => void,\n requester?: PRBEInteractionRequester,\n grantedPaths?: Set<string>,\n ) {\n this.autoApprovedDirs = autoApprovedDirs;\n this.onFlag = onFlag;\n this.requester = requester;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_FLAG_FILE,\n description:\n \"Flag a file (or part of a text file) as evidence. For large text files, use offset and limit to flag only the relevant section. Binary files are flagged in full (up to 100MB).\",\n parameters: [\n { name: \"path\", type: ToolParamType.STRING, description: \"File path\", required: true },\n { name: \"reason\", type: ToolParamType.STRING, description: \"Reason for flagging\", required: true },\n { name: \"offset\", type: ToolParamType.INTEGER, description: \"Starting line number (1-based, text files only). Negative = from end.\", required: false },\n { name: \"limit\", type: ToolParamType.INTEGER, description: \"Max number of lines to include (text files only).\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pathStr = args[\"path\"] as string | undefined;\n if (!pathStr) return \"Error: 'path' parameter is required\";\n\n const reason = args[\"reason\"] as string | undefined;\n if (!reason) return \"Error: 'reason' parameter is required\";\n\n const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);\n if (!resolved) return `Error: ${resolveErr}`;\n\n if (!fs.existsSync(resolved)) {\n return `Error: file does not exist at '${pathStr}'`;\n }\n\n const offset = typeof args[\"offset\"] === \"number\" ? args[\"offset\"] : undefined;\n const limit = typeof args[\"limit\"] === \"number\" ? args[\"limit\"] : undefined;\n\n // Try reading as text first\n let textContent: string | null = null;\n try {\n textContent = fs.readFileSync(resolved, \"utf-8\");\n } catch {\n // Not readable as text\n }\n\n if (textContent !== null) {\n let content = textContent;\n\n if (offset !== undefined || limit !== undefined) {\n let lines = content.split(/\\r?\\n/);\n const totalLines = lines.length;\n\n let startIdx = 0;\n if (offset !== undefined) {\n startIdx = offset < 0 ? Math.max(0, totalLines + offset) : Math.max(0, offset - 1);\n }\n\n lines = lines.slice(startIdx);\n if (limit !== undefined && limit > 0) {\n lines = lines.slice(0, limit);\n }\n\n const rangeDesc = `lines ${startIdx + 1}-${startIdx + lines.length} of ${totalLines}`;\n content = `[${rangeDesc}]\\n${lines.join(\"\\n\")}`;\n }\n\n const redacted = redactPII(content);\n this.onFlag({\n originalPath: resolved,\n reason,\n data: Buffer.from(redacted, \"utf-8\"),\n isText: true,\n });\n const sizeDesc = offset !== undefined || limit !== undefined ? \" (partial)\" : \"\";\n return `Flagged '${pathStr}'${sizeDesc} — reason: ${reason}`;\n }\n\n // Binary file — flag in full, no partial support\n if (offset !== undefined || limit !== undefined) {\n return \"Error: offset/limit not supported for binary files. Flag the full file instead.\";\n }\n\n let data: Buffer;\n try {\n data = fs.readFileSync(resolved);\n } catch {\n return `Error: could not read file at '${pathStr}'`;\n }\n\n if (data.length > FlagFileTool.MAX_BINARY_SIZE) {\n const sizeMB = Math.floor(data.length / (1024 * 1024));\n return `Error: file is ${sizeMB}MB — exceeds 100MB limit`;\n }\n\n this.onFlag({\n originalPath: resolved,\n reason,\n data,\n isText: false,\n });\n return `Flagged '${pathStr}' (binary, ${data.length} bytes) — reason: ${reason}`;\n }\n}\n","/**\n * tools/logs.ts — Log capture + built-in log tools\n *\n * Implements: client_read_app_logs, client_search_app_logs,\n * client_clear_app_logs, client_flag_app_logs\n *\n * Mirrors PRBELogCapture.swift + log tool implementations from PRBEAgentTools.swift.\n * Log capture works by monkey-patching console.log/warn/error in the Electron main process.\n */\n\nimport type { PRBEToolDeclaration, FlaggedFileIn } from \"../models\";\nimport { ToolName, ToolParamType, redactPII } from \"../models\";\nimport type { PRBETool } from \"./index\";\n\n// ---------------------------------------------------------------------------\n// Log Entry\n// ---------------------------------------------------------------------------\n\nexport interface LogEntry {\n timestamp: Date;\n level: string;\n category: string;\n message: string;\n}\n\n// ---------------------------------------------------------------------------\n// PRBELogCapture\n// ---------------------------------------------------------------------------\n\nexport class PRBELogCapture {\n private entries: LogEntry[] = [];\n private readonly maxEntries: number;\n private isCapturing = false;\n\n // Original console methods, saved for restoration\n private originalLog?: typeof console.log;\n private originalWarn?: typeof console.warn;\n private originalError?: typeof console.error;\n private originalDebug?: typeof console.debug;\n private originalInfo?: typeof console.info;\n\n constructor(maxEntries: number = 10_000) {\n this.maxEntries = maxEntries;\n }\n\n // ---------- Structured Logging ----------\n\n log(message: string, level = \"PRINT\", category = \"print\"): void {\n this.append({\n timestamp: new Date(),\n level,\n category,\n message,\n });\n }\n\n // ---------- Query ----------\n\n get count(): number {\n return this.entries.length;\n }\n\n getEntries(options: {\n offset?: number;\n limit?: number;\n level?: string;\n from?: Date;\n to?: Date;\n } = {}): LogEntry[] {\n const { offset = 0, limit = 100, level, from, to } = options;\n\n let filtered = this.entries;\n if (level) {\n filtered = filtered.filter((e) => e.level === level);\n }\n if (from) {\n filtered = filtered.filter((e) => e.timestamp >= from);\n }\n if (to) {\n filtered = filtered.filter((e) => e.timestamp <= to);\n }\n\n if (offset >= filtered.length) return [];\n const end = Math.min(offset + limit, filtered.length);\n return filtered.slice(offset, end);\n }\n\n search(\n pattern: string,\n contextLines = 2,\n maxResults = 50,\n ): Array<{ index: number; entry: LogEntry }> {\n let regex: RegExp;\n try {\n regex = new RegExp(pattern, \"i\");\n } catch {\n return [];\n }\n\n const results: Array<{ index: number; entry: LogEntry }> = [];\n for (let i = 0; i < this.entries.length; i++) {\n if (results.length >= maxResults) break;\n if (regex.test(this.entries[i].message)) {\n results.push({ index: i, entry: this.entries[i] });\n }\n }\n return results;\n }\n\n // ---------- Clear ----------\n\n clearLogs(): number {\n const count = this.entries.length;\n this.entries = [];\n return count;\n }\n\n // ---------- Console Capture ----------\n\n startCapturing(): void {\n if (this.isCapturing) return;\n this.isCapturing = true;\n\n // Save originals\n this.originalLog = console.log;\n this.originalWarn = console.warn;\n this.originalError = console.error;\n this.originalDebug = console.debug;\n this.originalInfo = console.info;\n\n const self = this;\n\n console.log = (...args: unknown[]) => {\n self.originalLog?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"PRINT\", \"console.log\");\n };\n\n console.warn = (...args: unknown[]) => {\n self.originalWarn?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"WARNING\", \"console.warn\");\n };\n\n console.error = (...args: unknown[]) => {\n self.originalError?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"ERROR\", \"console.error\");\n };\n\n console.debug = (...args: unknown[]) => {\n self.originalDebug?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"DEBUG\", \"console.debug\");\n };\n\n console.info = (...args: unknown[]) => {\n self.originalInfo?.apply(console, args);\n self.log(args.map(String).join(\" \"), \"INFO\", \"console.info\");\n };\n }\n\n stopCapturing(): void {\n if (!this.isCapturing) return;\n this.isCapturing = false;\n\n if (this.originalLog) console.log = this.originalLog;\n if (this.originalWarn) console.warn = this.originalWarn;\n if (this.originalError) console.error = this.originalError;\n if (this.originalDebug) console.debug = this.originalDebug;\n if (this.originalInfo) console.info = this.originalInfo;\n\n this.originalLog = undefined;\n this.originalWarn = undefined;\n this.originalError = undefined;\n this.originalDebug = undefined;\n this.originalInfo = undefined;\n }\n\n // ---------- Raw access to all entries (for tools) ----------\n\n getAllEntries(): LogEntry[] {\n return this.entries;\n }\n\n // ---------- Private ----------\n\n private append(entry: LogEntry): void {\n this.entries.push(entry);\n if (this.entries.length > this.maxEntries) {\n this.entries.splice(0, this.entries.length - this.maxEntries);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// ReadAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class ReadAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n\n constructor(logCapture: PRBELogCapture) {\n this.logCapture = logCapture;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_READ_APP_LOGS,\n description: \"Read application log entries captured from stdout and structured logging\",\n parameters: [\n { name: \"position\", type: ToolParamType.STRING, description: '\"top\" (oldest first) or \"bottom\" (newest first). Default: \"bottom\"', required: false },\n { name: \"count\", type: ToolParamType.INTEGER, description: \"Number of entries to return. Default: 100\", required: false },\n { name: \"level\", type: ToolParamType.STRING, description: 'Filter by log level (e.g. \"ERROR\", \"INFO\", \"PRINT\")', required: false },\n { name: \"from\", type: ToolParamType.STRING, description: \"ISO8601 start timestamp filter\", required: false },\n { name: \"to\", type: ToolParamType.STRING, description: \"ISO8601 end timestamp filter\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const position = (args[\"position\"] as string) ?? \"bottom\";\n const count = typeof args[\"count\"] === \"number\" ? args[\"count\"] : 100;\n const level = args[\"level\"] as string | undefined;\n\n const fromDate = args[\"from\"] ? new Date(args[\"from\"] as string) : undefined;\n const toDate = args[\"to\"] ? new Date(args[\"to\"] as string) : undefined;\n\n const totalCount = this.logCapture.count;\n const allEntries = this.logCapture.getEntries({\n offset: 0,\n limit: totalCount,\n level,\n from: fromDate,\n to: toDate,\n });\n\n if (allEntries.length === 0) {\n return \"No log entries found matching the specified filters.\";\n }\n\n let selected: LogEntry[];\n if (position === \"top\") {\n selected = allEntries.slice(0, count);\n } else {\n selected = allEntries.slice(-count);\n }\n\n let result = `Log entries (${selected.length} of ${allEntries.length} total):\\n\\n`;\n for (const entry of selected) {\n result += `[${entry.timestamp.toISOString()}] [${entry.level}] [${entry.category}] ${entry.message}\\n`;\n }\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SearchAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class SearchAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n\n constructor(logCapture: PRBELogCapture) {\n this.logCapture = logCapture;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_SEARCH_APP_LOGS,\n description: \"Search application logs by regex pattern with surrounding context\",\n parameters: [\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Regex pattern to search for\", required: true },\n { name: \"context_lines\", type: ToolParamType.INTEGER, description: \"Number of surrounding log entries for context. Default: 2\", required: false },\n { name: \"max_results\", type: ToolParamType.INTEGER, description: \"Maximum matches to return. Default: 50\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const pattern = args[\"pattern\"] as string | undefined;\n if (!pattern) return \"Error: 'pattern' parameter is required\";\n\n const contextLines = typeof args[\"context_lines\"] === \"number\" ? args[\"context_lines\"] : 2;\n const maxResults = typeof args[\"max_results\"] === \"number\" ? args[\"max_results\"] : 50;\n\n const matches = this.logCapture.search(pattern, contextLines, maxResults);\n\n if (matches.length === 0) {\n return `No log entries matching '${pattern}' found.`;\n }\n\n const allEntries = this.logCapture.getAllEntries();\n\n let result = `Found ${matches.length} match(es) for '${pattern}':\\n\\n`;\n for (const match of matches) {\n const startIdx = Math.max(0, match.index - contextLines);\n const endIdx = Math.min(allEntries.length - 1, match.index + contextLines);\n for (let i = startIdx; i <= endIdx; i++) {\n const entry = allEntries[i];\n const marker = i === match.index ? \">\" : \" \";\n result += `${marker} [${entry.timestamp.toISOString()}] [${entry.level}] [${entry.category}] ${entry.message}\\n`;\n }\n result += \"---\\n\";\n }\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// ClearAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class ClearAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n\n constructor(logCapture: PRBELogCapture) {\n this.logCapture = logCapture;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_CLEAR_APP_LOGS,\n description: \"Clear all captured application logs\",\n parameters: [],\n };\n }\n\n async execute(_args: Record<string, unknown>): Promise<string> {\n const cleared = this.logCapture.clearLogs();\n return `Cleared ${cleared} log entries.`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// FlagAppLogsTool\n// ---------------------------------------------------------------------------\n\nexport class FlagAppLogsTool implements PRBETool {\n private readonly logCapture: PRBELogCapture;\n private readonly onFlag: (file: FlaggedFileIn) => void;\n\n constructor(logCapture: PRBELogCapture, onFlag: (file: FlaggedFileIn) => void) {\n this.logCapture = logCapture;\n this.onFlag = onFlag;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_FLAG_APP_LOGS,\n description:\n \"Flag application log entries as evidence for the debug report. Snapshots matching log entries and includes them in the output package. Call with no filters to flag all logs, or use pattern to filter by message content. Note: 'level' filters by the log level metadata (e.g. PRINT, ERROR), NOT by message content — use 'pattern' to match words in log messages.\",\n parameters: [\n { name: \"reason\", type: ToolParamType.STRING, description: \"Why these logs are relevant\", required: true },\n { name: \"pattern\", type: ToolParamType.STRING, description: \"Regex pattern to filter log messages by content\", required: false },\n { name: \"level\", type: ToolParamType.STRING, description: \"Filter by log level metadata (PRINT, DEBUG, INFO, ERROR, etc.) — this is NOT a content search\", required: false },\n { name: \"from\", type: ToolParamType.STRING, description: \"ISO8601 start timestamp filter\", required: false },\n { name: \"to\", type: ToolParamType.STRING, description: \"ISO8601 end timestamp filter\", required: false },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const reason = args[\"reason\"] as string | undefined;\n if (!reason) return \"Error: 'reason' parameter is required\";\n\n const level = args[\"level\"] as string | undefined;\n const fromDate = args[\"from\"] ? new Date(args[\"from\"] as string) : undefined;\n const toDate = args[\"to\"] ? new Date(args[\"to\"] as string) : undefined;\n\n // Get filtered entries\n const totalCount = this.logCapture.count;\n let entries = this.logCapture.getEntries({\n offset: 0,\n limit: totalCount,\n level,\n from: fromDate,\n to: toDate,\n });\n\n // Apply regex pattern filter if provided\n const patternStr = args[\"pattern\"] as string | undefined;\n if (patternStr) {\n let regex: RegExp;\n try {\n regex = new RegExp(patternStr, \"i\");\n } catch {\n return `Error: invalid regex pattern '${patternStr}'`;\n }\n entries = entries.filter((entry) => regex.test(entry.message));\n }\n\n if (entries.length === 0) {\n const filters: string[] = [];\n if (level) filters.push(`level=${level}`);\n if (patternStr) filters.push(`pattern=${patternStr}`);\n if (fromDate) filters.push(`from=${args[\"from\"]}`);\n if (toDate) filters.push(`to=${args[\"to\"]}`);\n\n const hint = filters.length === 0\n ? `The log buffer is empty (${totalCount} entries).`\n : `No entries matched filters: ${filters.join(\", \")}. Total log entries: ${totalCount}. Try calling with no filters, or use 'pattern' instead of 'level' to match message content.`;\n return hint;\n }\n\n // Format entries into file-like content\n let content = \"\";\n for (const entry of entries) {\n content += `[${entry.timestamp.toISOString()}] [${entry.level}] [${entry.category}] ${entry.message}\\n`;\n }\n\n // Build a descriptive filename: app_logs_<filter_summary>_<timestamp>.txt\n const nameParts = [\"app_logs\"];\n if (level) nameParts.push(level.toLowerCase());\n if (patternStr) {\n const safe = patternStr.replace(/[^a-zA-Z0-9]/g, \"_\");\n const trimmed = safe.substring(0, 30).replace(/^_+|_+$/g, \"\");\n if (trimmed.length > 0) nameParts.push(trimmed);\n }\n const ts = new Date()\n .toISOString()\n .replace(/[:\\-]/g, \"\")\n .substring(0, 15); // e.g. \"20260316T212158\"\n nameParts.push(ts);\n const filename = nameParts.join(\"_\") + \".txt\";\n\n this.onFlag({\n originalPath: filename,\n reason,\n data: Buffer.from(redactPII(content), \"utf-8\"),\n isText: true,\n });\n\n return `Flagged ${entries.length} log entries as '${filename}' — reason: ${reason}`;\n }\n}\n","/**\n * tools/interactive.ts — AskUserTool\n *\n * Allows the agent to ask the user a question during an investigation.\n * The question text is displayed via conversation history (middleware handles this).\n * This tool only prompts the user for input with an optional reason hint.\n */\n\nimport { randomUUID } from \"crypto\";\nimport type { PRBEToolDeclaration } from \"../models\";\nimport { ToolName, ToolParamType } from \"../models\";\nimport { InteractionType, InvestigationSource } from \"../interactions\";\nimport type { PRBEInteractionRequester } from \"../interactions\";\nimport type { AskQuestionResponse } from \"../interactions\";\nimport type { PRBETool } from \"./index\";\n\nexport class AskUserTool implements PRBETool {\n private readonly requester: PRBEInteractionRequester;\n\n constructor(requester: PRBEInteractionRequester) {\n this.requester = requester;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_ASK_USER,\n description:\n \"Ask the user a question and wait for their response. Use this when you need clarification or additional information from the user to continue the investigation.\",\n interactive: true,\n parameters: [\n {\n name: \"question\",\n type: ToolParamType.STRING,\n description: \"The question to ask the user\",\n required: true,\n },\n {\n name: \"reason\",\n type: ToolParamType.STRING,\n description: \"Short reason displayed alongside the input prompt explaining why you need this information\",\n required: false,\n },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const question = args[\"question\"] as string | undefined;\n if (!question) return \"Error: 'question' parameter is required\";\n\n // CRs are autonomous — don't prompt the user, tell the agent to proceed\n if (this.requester.investigationSource !== InvestigationSource.USER) {\n return \"This is a context request investigation — you cannot ask the user questions. Use the available tools to answer the query autonomously.\";\n }\n\n const reason = (args[\"reason\"] as string | undefined) ?? \"Waiting for your response\";\n\n const response = await this.requester.requestUserInteraction({\n type: InteractionType.ASK_QUESTION,\n interactionId: randomUUID(),\n question: reason,\n });\n\n const askResponse = response as AskQuestionResponse;\n return askResponse.answer;\n }\n}\n","/**\n * tools/bash.ts — BashExecuteTool\n *\n * Allows the agent to execute shell commands during investigations.\n * Uses a whitelist-only safety model: commands on the whitelist run without\n * permission; everything else requires user approval.\n *\n * Platform-aware: uses separate whitelists for Unix and Windows, and\n * runs commands via PowerShell on Windows for consistent behavior.\n */\n\nimport { exec } from \"child_process\";\nimport { randomUUID } from \"crypto\";\nimport * as path from \"path\";\nimport type { PRBEToolDeclaration } from \"../models\";\nimport { ToolName, ToolParamType } from \"../models\";\nimport { InteractionType } from \"../interactions\";\nimport type { PRBEInteractionRequester, RequestPermissionResponse } from \"../interactions\";\nimport type { PRBETool } from \"./index\";\nimport { resolveAndValidate } from \"./index\";\nimport { SAFE_COMMANDS, SAFE_COMMAND_PREFIXES } from \"./safe-commands\";\n\n// ---------------------------------------------------------------------------\n// Platform detection\n// ---------------------------------------------------------------------------\n\nconst IS_WINDOWS = process.platform === \"win32\";\n\nconst MAX_OUTPUT_BYTES = 100 * 1024; // 100KB\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst MAX_TIMEOUT_MS = 120_000;\n\n// ---------------------------------------------------------------------------\n// BashExecuteTool\n// ---------------------------------------------------------------------------\n\nexport class BashExecuteTool implements PRBETool {\n private readonly requester: PRBEInteractionRequester;\n private readonly autoApprovedDirs: string[];\n private readonly grantedPaths: Set<string>;\n\n constructor(\n requester: PRBEInteractionRequester,\n autoApprovedDirs: string[],\n grantedPaths: Set<string>,\n ) {\n this.requester = requester;\n this.autoApprovedDirs = autoApprovedDirs;\n this.grantedPaths = grantedPaths;\n }\n\n get declaration(): PRBEToolDeclaration {\n return {\n name: ToolName.CLIENT_BASH_EXECUTE,\n description:\n \"Execute a shell command on the user's machine. Safe read-only commands run immediately; potentially destructive commands require user approval first.\",\n interactive: true,\n parameters: [\n {\n name: \"command\",\n type: ToolParamType.STRING,\n description: \"The shell command to execute\",\n required: true,\n },\n {\n name: \"cwd\",\n type: ToolParamType.STRING,\n description: \"Working directory for the command (must be within auto-approved directories)\",\n required: false,\n },\n {\n name: \"timeout\",\n type: ToolParamType.INTEGER,\n description: \"Timeout in seconds (default 30, max 120)\",\n required: false,\n },\n ],\n };\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const command = args[\"command\"] as string | undefined;\n if (!command) return \"Error: 'command' parameter is required\";\n\n const cwdArg = args[\"cwd\"] as string | undefined;\n const timeoutSec = typeof args[\"timeout\"] === \"number\" ? args[\"timeout\"] : DEFAULT_TIMEOUT_MS / 1000;\n const timeoutMs = Math.min(timeoutSec * 1000, MAX_TIMEOUT_MS);\n\n // Validate cwd if provided\n let cwd: string | undefined;\n if (cwdArg) {\n const allRoots = [...this.autoApprovedDirs, ...this.grantedPaths];\n const resolved = resolveAndValidate(cwdArg, allRoots);\n if (!resolved) {\n return `Error: working directory '${cwdArg}' is outside auto-approved directories`;\n }\n cwd = resolved;\n }\n\n // Check if command is safe (whitelist-only)\n const isSafe = this.isCommandSafe(command);\n\n if (!isSafe) {\n const response = await this.requester.requestUserInteraction({\n type: InteractionType.REQUEST_PERMISSION,\n interactionId: randomUUID(),\n action: \"Execute shell command\",\n command,\n reason: `The agent wants to run this command${cwd ? ` in ${cwd}` : \"\"}.`,\n });\n\n const permResponse = response as RequestPermissionResponse;\n if (!permResponse.approved) {\n return \"Command execution denied by user.\";\n }\n }\n\n // Execute the command\n return new Promise<string>((resolve) => {\n exec(\n command,\n {\n cwd,\n timeout: timeoutMs,\n maxBuffer: MAX_OUTPUT_BYTES,\n env: process.env,\n // On Windows, use PowerShell for more consistent behavior\n ...(IS_WINDOWS ? { shell: \"powershell.exe\" } : {}),\n },\n (error, stdout, stderr) => {\n let output = \"\";\n\n if (stdout) {\n output += stdout;\n }\n if (stderr) {\n if (output) output += \"\\n--- stderr ---\\n\";\n output += stderr;\n }\n\n if (error) {\n if (error.killed) {\n output += `\\n[Command timed out after ${timeoutSec}s]`;\n } else if (!stdout && !stderr) {\n output = `Error: ${error.message}`;\n }\n }\n\n // Truncate if too large\n if (Buffer.byteLength(output, \"utf-8\") > MAX_OUTPUT_BYTES) {\n output = output.slice(0, MAX_OUTPUT_BYTES) + \"\\n[Output truncated at 100KB]\";\n }\n\n resolve(output || \"(no output)\");\n },\n );\n });\n }\n\n /**\n * Check if a command is on the safe whitelist.\n */\n private isCommandSafe(command: string): boolean {\n const trimmed = command.trim();\n\n // Check two-word prefixes first (e.g. \"git status\")\n for (const prefix of SAFE_COMMAND_PREFIXES) {\n if (trimmed === prefix || trimmed.startsWith(prefix + \" \")) {\n return true;\n }\n }\n\n // Extract base command\n const firstCommand = IS_WINDOWS\n ? trimmed.split(/[|;]/, 1)[0].trim() // PowerShell uses | and ;\n : trimmed.split(/[|;&]/, 1)[0].trim(); // bash uses |, ;, &\n const baseCommand = firstCommand.split(/\\s+/, 1)[0];\n\n const commandName = IS_WINDOWS\n ? baseCommand.toLowerCase() // Windows commands are case-insensitive\n : path.basename(baseCommand);\n\n if (SAFE_COMMANDS.has(commandName)) {\n return this.areAllPipeSegmentsSafe(trimmed);\n }\n\n return false;\n }\n\n /**\n * For piped commands, check that every segment uses a safe command.\n */\n private areAllPipeSegmentsSafe(command: string): boolean {\n // Chained commands (;, &&, ||) require permission\n if (IS_WINDOWS) {\n if (/;/.test(command) && command.split(\"|\").length <= 1) return false;\n } else {\n if (/[;&]|&&|\\|\\|/.test(command)) return false;\n }\n\n const segments = command.split(\"|\").map((s) => s.trim());\n for (const segment of segments) {\n const baseCommand = segment.split(/\\s+/, 1)[0];\n const commandName = IS_WINDOWS\n ? baseCommand.toLowerCase()\n : path.basename(baseCommand);\n if (!SAFE_COMMANDS.has(commandName)) {\n return false;\n }\n }\n return true;\n }\n}\n","/**\n * safe-commands.ts — Whitelisted read-only shell commands\n *\n * Commands on these lists run without user approval.\n * Only strictly read-only / informational commands belong here.\n * If a command has ANY flags that can modify system state, it does NOT belong.\n */\n\n// ---------------------------------------------------------------------------\n// Unix (macOS + Linux)\n// ---------------------------------------------------------------------------\n\nconst UNIX_SAFE_COMMANDS = new Set([\n // Filesystem (read-only)\n \"ls\", \"cat\", \"head\", \"tail\", \"find\", \"file\", \"stat\",\n \"du\", \"df\", \"wc\", \"sort\", \"uniq\", \"diff\", \"tree\",\n\n // Search\n \"grep\", \"rg\", \"which\",\n\n // Text\n \"echo\", \"printf\",\n\n // Identity / environment\n \"whoami\", \"pwd\", \"id\", \"hostname\", \"uname\",\n \"env\", \"printenv\", \"locale\",\n\n // System info (read-only reporters)\n \"date\", \"uptime\", \"free\",\n \"ps\", \"top\",\n\n // macOS-specific (read-only only)\n \"sw_vers\", // macOS version\n \"system_profiler\", // hardware/software info\n \"mdls\", // Spotlight metadata for a file\n \"mdfind\", // Spotlight search\n \"lsof\", // list open files\n \"ioreg\", // I/O registry (hardware tree)\n \"log\", // macOS unified log (show, stream — read-only)\n\n // Linux-specific (read-only reporters)\n \"lsb_release\", // distro info\n \"lscpu\", // CPU info\n \"lsblk\", // block devices\n \"lspci\", // PCI devices\n \"lsusb\", // USB devices\n \"lsmem\", // memory ranges\n \"dmidecode\", // BIOS/hardware info\n \"ss\", // socket statistics\n \"journalctl\", // systemd logs (read-only)\n]);\n\n// ---------------------------------------------------------------------------\n// Windows (CMD + PowerShell)\n// ---------------------------------------------------------------------------\n\nconst WINDOWS_SAFE_COMMANDS = new Set([\n // CMD — filesystem (read-only)\n \"dir\", \"type\", \"tree\", \"more\",\n \"findstr\", \"where\",\n\n // CMD — system info (read-only reporters)\n \"systeminfo\", \"hostname\", \"ver\", \"vol\",\n \"date\", \"set\", \"path\", \"chcp\",\n \"whoami\", \"echo\", \"sort\", \"fc\",\n\n // CMD — processes\n \"tasklist\", \"driverquery\",\n\n // CMD — network (read-only)\n \"netstat\",\n\n // CMD — policy (read-only)\n \"gpresult\",\n\n // PowerShell — Get-* cmdlets (strictly read-only by convention)\n \"get-childitem\", \"get-content\", \"get-item\",\n \"test-path\", \"resolve-path\",\n \"get-itemproperty\",\n \"select-string\", \"measure-object\",\n \"get-host\", \"get-computerinfo\", \"get-date\",\n \"get-volume\", \"get-disk\", \"get-partition\",\n \"get-process\", \"get-service\",\n \"get-netadapter\", \"get-nettcpconnection\",\n \"get-netipaddress\", \"get-netroute\",\n \"get-hotfix\", \"get-eventlog\", \"get-winevent\",\n \"get-wmiobject\", \"get-ciminstance\",\n]);\n\n// ---------------------------------------------------------------------------\n// Cross-platform safe command prefixes (two-word commands)\n// ---------------------------------------------------------------------------\n\nconst SAFE_COMMAND_PREFIXES = new Set([\n \"git status\",\n \"git log\",\n \"git diff\",\n \"git show\",\n \"git branch\",\n \"node --version\",\n \"npm --version\",\n \"npm list\",\n \"npm ls\",\n]);\n\n// ---------------------------------------------------------------------------\n// Exports\n// ---------------------------------------------------------------------------\n\nconst IS_WINDOWS = process.platform === \"win32\";\n\nexport const SAFE_COMMANDS = IS_WINDOWS ? WINDOWS_SAFE_COMMANDS : UNIX_SAFE_COMMANDS;\nexport { SAFE_COMMAND_PREFIXES };\n","/**\n * serialization.ts — IPC-safe serialization of agent state\n *\n * Converts live PRBEAgentState (with Map, Date, EventEmitter) into\n * plain JSON-safe objects suitable for IPC or structured clone.\n */\n\nimport type { PRBEAgentState } from \"./state\";\nimport type {\n PRBEStatusEvent,\n PRBEBackgroundInvestigation,\n TicketInfoOut,\n AgentTicketOut,\n ConversationEntry,\n} from \"./models\";\nimport type { InteractionPayload, ResolvedInteraction } from \"./interactions\";\n\n// ---------------------------------------------------------------------------\n// Serialized Background Investigation (Date → ISO string, safe for IPC)\n// ---------------------------------------------------------------------------\n\nexport interface PRBESerializedBackgroundInvestigation {\n id: string;\n query: string;\n slug?: string;\n ticketId?: string;\n source?: string;\n sourceDetail?: string;\n events: PRBEStatusEvent[];\n isRunning: boolean;\n isCompleted: boolean;\n isFailed: boolean;\n report: string;\n summary?: string;\n errorMessage?: string;\n agentMessage?: string;\n startedAt: string; // ISO string\n pendingInteraction?: InteractionPayload;\n resolvedInteractions?: ResolvedInteraction[];\n conversationHistory: ConversationEntry[];\n}\n\n// ---------------------------------------------------------------------------\n// Serialized Ticket (pass-through — already plain)\n// ---------------------------------------------------------------------------\n\nexport type PRBESerializedTicket = TicketInfoOut;\n\n// ---------------------------------------------------------------------------\n// Serialized Completed Investigation (Date → ISO string)\n// ---------------------------------------------------------------------------\n\nexport interface PRBESerializedCompletedInvestigation {\n id: string;\n query: string;\n report: string;\n summary?: string;\n ticketId?: string;\n events: PRBEStatusEvent[];\n resolvedInteractions: ResolvedInteraction[];\n conversationHistory?: ConversationEntry[];\n completedAt: string; // ISO string\n}\n\n// ---------------------------------------------------------------------------\n// Full serialized state (no Map, Date, or EventEmitter)\n// ---------------------------------------------------------------------------\n\nexport interface PRBESerializedState {\n isInvestigating: boolean;\n events: PRBEStatusEvent[];\n report: string;\n summary?: string;\n currentQuery: string;\n investigationError?: string;\n pendingInteraction?: InteractionPayload;\n resolvedInteractions: ResolvedInteraction[];\n agentMessage?: string;\n conversationHistory: ConversationEntry[];\n completedInvestigations: PRBESerializedCompletedInvestigation[];\n activeBackgroundInvestigations: PRBESerializedBackgroundInvestigation[];\n completedBackgroundInvestigations: PRBESerializedBackgroundInvestigation[];\n ticketInfo: PRBESerializedTicket[];\n agentHistory: AgentTicketOut[];\n hasActiveWork: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Default state (used before agent initializes)\n// ---------------------------------------------------------------------------\n\nexport const DEFAULT_PRBE_STATE: PRBESerializedState = {\n isInvestigating: false,\n events: [],\n report: \"\",\n summary: \"\",\n currentQuery: \"\",\n resolvedInteractions: [],\n conversationHistory: [],\n completedInvestigations: [],\n activeBackgroundInvestigations: [],\n completedBackgroundInvestigations: [],\n ticketInfo: [],\n agentHistory: [],\n hasActiveWork: false,\n};\n\n// ---------------------------------------------------------------------------\n// Converter: live state → IPC-safe plain object\n// ---------------------------------------------------------------------------\n\nfunction serializeBackgroundInvestigation(bg: PRBEBackgroundInvestigation): PRBESerializedBackgroundInvestigation {\n return {\n id: bg.id,\n query: bg.query,\n slug: bg.slug,\n ticketId: bg.ticketId,\n source: bg.source,\n sourceDetail: bg.sourceDetail,\n events: bg.events,\n isRunning: bg.isRunning,\n isCompleted: bg.isCompleted,\n isFailed: bg.isFailed,\n report: bg.report,\n summary: bg.summary,\n errorMessage: bg.errorMessage,\n agentMessage: bg.agentMessage,\n startedAt: bg.startedAt.toISOString(),\n pendingInteraction: bg.pendingInteraction,\n resolvedInteractions: bg.resolvedInteractions ?? [],\n conversationHistory: bg.conversationHistory ?? [],\n };\n}\n\nexport function serializePRBEState(state: PRBEAgentState): PRBESerializedState {\n return {\n isInvestigating: state.isInvestigating,\n events: state.events,\n report: state.report,\n summary: state.summary,\n currentQuery: state.currentQuery,\n investigationError: state.investigationError,\n pendingInteraction: state.pendingInteraction,\n resolvedInteractions: state.resolvedInteractions,\n agentMessage: state.agentMessage,\n conversationHistory: state.conversationHistory,\n completedInvestigations: state.completedInvestigations.map((inv) => ({\n id: inv.id,\n query: inv.query,\n report: inv.report,\n summary: inv.summary,\n ticketId: inv.ticketId,\n events: inv.events,\n resolvedInteractions: inv.resolvedInteractions,\n conversationHistory: inv.conversationHistory,\n completedAt: inv.completedAt.toISOString(),\n })),\n activeBackgroundInvestigations: Array.from(state.activeBackgroundInvestigations.values()).map(serializeBackgroundInvestigation),\n completedBackgroundInvestigations: state.completedBackgroundInvestigations.map(serializeBackgroundInvestigation),\n ticketInfo: state.ticketInfo,\n agentHistory: state.agentHistory,\n hasActiveWork: state.hasActiveWork,\n };\n}\n","/**\n * Probe brand mark SVG (transparent background, dark mark).\n * Exported as a string so host apps can use it inline without bundler plugins.\n */\nexport const PROBE_MARK_SVG = `<svg width=\"256\" height=\"256\" viewBox=\"0 0 256 256\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M50 112 L114 148 L50 184 Z\" fill=\"#111111\" opacity=\"0.07\"/>\n <path d=\"M70 86 L148 134 L70 182 Z\" fill=\"#111111\" opacity=\"0.18\"/>\n <path d=\"M92 56 L192 118 L92 180 Z\" fill=\"#111111\"/>\n</svg>`;\n"],"mappings":"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","names":["fs","path","import_crypto","WSMessageType","ConversationRole","ToolParamType","ToolName","UserIdentifierType","PRBEAgentConfigKey","PRBEAgentStatusType","PRBEAgentErrorType","PRBEStateEvent","import_crypto","InteractionType","InvestigationSource","path","import_crypto","import_crypto","path","IS_WINDOWS","resolve","resolve"]}