aisnitch 0.1.0
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/LICENSE +190 -0
- package/README.md +296 -0
- package/dist/cli/index.cjs +12402 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +17 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.js +12370 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.cjs +9429 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2382 -0
- package/dist/index.d.ts +2382 -0
- package/dist/index.js +9298 -0
- package/dist/index.js.map +1 -0
- package/package.json +102 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/adapters/aider.ts","../src/core/engine/logger.ts","../src/core/session-identity.ts","../src/adapters/base.ts","../src/core/events/schema.ts","../src/core/events/factory.ts","../src/adapters/claude-code.ts","../src/adapters/copilot-cli.ts","../src/adapters/codex.ts","../src/adapters/gemini-cli.ts","../src/adapters/goose.ts","../src/adapters/openclaw.ts","../src/adapters/opencode.ts","../src/adapters/registry.ts","../src/adapters/generic-pty.ts","../src/core/engine/context-detector.ts","../src/adapters/index.ts","../src/core/config/schema.ts","../src/core/config/defaults.ts","../src/core/config/loader.ts","../src/core/engine/event-bus.ts","../src/core/engine/ring-buffer.ts","../src/core/engine/ws-server.ts","../src/core/engine/http-receiver.ts","../src/core/engine/uds-server.ts","../src/core/engine/pipeline.ts","../src/core/events/cesp.ts","../src/package-info.ts","../src/tui/index.tsx","../src/tui/App.tsx","../src/tui/components/EventInspector.tsx","../src/tui/event-details.ts","../src/tui/theme.ts","../src/tui/event-inspector.ts","../src/tui/components/EventStream.tsx","../src/tui/components/EventLine.tsx","../src/tui/components/FilterBar.tsx","../src/tui/filters.ts","../src/tui/components/Header.tsx","../src/tui/components/GlobalBadge.tsx","../src/tui/components/HelpOverlay.tsx","../src/tui/components/Layout.tsx","../src/tui/components/SessionPanel.tsx","../src/tui/components/StatusBar.tsx","../src/tui/hooks/useEventStream.ts","../src/tui/hooks/useKeyBinds.ts","../src/tui/hooks/useSessions.ts","../src/tui/types.ts","../src/tui/live-monitor.ts"],"sourcesContent":["/**\n * @file src/index.ts\n * @description Public entrypoint for the AISnitch package and its foundational modules.\n * @functions\n * โ none\n * @exports Public package modules and package metadata helpers\n * @see ./core/index.ts\n * @see ./cli/index.ts\n * @see ./package-info.ts\n */\n\nexport * from './adapters/index.js';\nexport * from './core/index.js';\nexport * from './package-info.js';\nexport * from './tui/index.js';\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { watch, type FSWatcher } from 'chokidar';\nimport pidCwd from 'pid-cwd';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type {\n AISnitchEventType,\n ErrorType,\n EventData,\n} from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/aider.ts\n * @description Aider adapter combining passive markdown history parsing, notifications-command hooks, and active process discovery.\n * @functions\n * โ parseAiderHistoryMarkdown\n * @exports AiderAdapter, AiderAdapterOptions, AiderHistoryObservation, AiderHistoryParseResult, parseAiderHistoryMarkdown\n * @see ./base.ts\n * @see ../cli/commands/setup.ts\n * @see ../../tasks/06-adapters-secondary/03_adapters-secondary_aider-pty_DONE.md\n */\n\nconst execFile = promisify(execFileCallback);\n\nconst DEFAULT_AIDER_HISTORY_FILE = '.aider.chat.history.md';\nconst AIDER_ERROR_HINT =\n /failed|error|exception|keyboardinterrupt|did not conform|traceback/iu;\nconst AIDER_ASKING_USER_HINT =\n /\\b\\(Y(?:es)?\\/N(?:o)?\\)|\\bPress Enter\\b|\\bcontinue\\?\\b|\\bcontinue to exit\\b/iu;\nconst AIDER_FILE_COMMAND_HINT = /^\\/(?:add|drop|read-only)\\b/iu;\nconst AIDER_STARTUP_STATUS_HINT =\n /^(?:\\/.+\\/aider|Aider v|Main model:|Model:|Weak model:|Git repo:|Repo-map:)/u;\n\nexport interface AiderAdapterOptions extends AdapterRuntimeOptions {\n readonly cwdResolver?: (pid: number) => Promise<string | undefined>;\n readonly historyFileName?: string;\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n readonly watcherFactory?: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n}\n\ninterface AiderProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\ninterface AiderSessionRuntime {\n readonly cwd: string;\n readonly historyPath: string;\n readonly pids: readonly number[];\n readonly sessionId: string;\n readonly model?: string;\n}\n\ninterface AiderHistoryWatcher {\n readonly fingerprints: Set<string>;\n readonly watcher: FSWatcher;\n}\n\ninterface AiderHistoryParseOptions {\n readonly cwd: string;\n readonly historyPath: string;\n readonly initialModel?: string;\n}\n\nexport interface AiderHistoryObservation {\n readonly fingerprint: string;\n readonly type: AISnitchEventType;\n readonly data: Omit<EventData, 'state'>;\n}\n\nexport interface AiderHistoryParseResult {\n readonly lastModel?: string;\n readonly observations: readonly AiderHistoryObservation[];\n}\n\n/**\n * ๐ Aider's transcript is markdown, not a stable machine API. The parser\n * therefore sticks to high-signal structures: prompts, quoted status lines,\n * assistant prose, and SEARCH/REPLACE file blocks.\n */\nexport class AiderAdapter extends BaseAdapter {\n public override readonly displayName = 'Aider';\n\n public override readonly name = 'aider' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'hooks',\n 'log-watch',\n 'process-detect',\n ];\n\n private readonly cwdResolver: (pid: number) => Promise<string | undefined>;\n\n private readonly historyFileName: string;\n\n private readonly historySessions = new Map<string, AiderSessionRuntime>();\n\n private readonly historyWatchers = new Map<string, AiderHistoryWatcher>();\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n private readonly watcherFactory: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n\n public constructor(options: AiderAdapterOptions) {\n super(options);\n this.cwdResolver =\n options.cwdResolver ??\n (async (pid) => {\n return await pidCwd(pid);\n });\n this.historyFileName = options.historyFileName ?? DEFAULT_AIDER_HISTORY_FILE;\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ??\n (async () =>\n await execFile('pgrep', ['-lf', '(^|[ /])aider([ ]|$)']).then(\n (result) => result.stdout,\n ));\n this.watcherFactory = options.watcherFactory ?? watch;\n }\n\n public override start(): Promise<void> {\n if (this.getStatus().running) {\n return Promise.resolve();\n }\n\n this.setRunning(true);\n this.startProcessPolling();\n\n return Promise.resolve();\n }\n\n public override async stop(): Promise<void> {\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n for (const watcherHandle of this.historyWatchers.values()) {\n await watcherHandle.watcher.close();\n }\n\n this.historySessions.clear();\n this.historyWatchers.clear();\n this.setRunning(false);\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload === null) {\n logger.debug({ payload }, 'Aider ignores non-normalized hook payloads');\n return;\n }\n\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n transcriptPath: normalizedPayload.transcriptPath,\n }),\n });\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs > 0) {\n this.processPoller = setInterval(() => {\n void this.pollAiderProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n }\n\n void this.pollAiderProcesses();\n }\n\n private async pollAiderProcesses(): Promise<void> {\n const processes = await listAiderProcesses(this.processListCommand);\n const nextSessions = new Map<string, AiderSessionRuntime>();\n\n for (const processInfo of processes) {\n const cwd = await this.cwdResolver(processInfo.pid);\n\n if (!cwd) {\n continue;\n }\n\n const historyPath = resolveAiderHistoryPath(\n cwd,\n processInfo.command,\n this.historyFileName,\n );\n const existingSession = nextSessions.get(historyPath);\n\n if (existingSession) {\n nextSessions.set(historyPath, {\n ...existingSession,\n pids: [...existingSession.pids, processInfo.pid],\n });\n continue;\n }\n\n const previousSession = this.historySessions.get(historyPath);\n const sessionId =\n previousSession?.sessionId ??\n resolveSessionId({\n cwd,\n tool: this.name,\n transcriptPath: historyPath,\n });\n\n nextSessions.set(historyPath, {\n cwd,\n historyPath,\n model: previousSession?.model,\n pids: [processInfo.pid],\n sessionId,\n });\n }\n\n for (const [historyPath, session] of nextSessions) {\n if (this.historySessions.has(historyPath)) {\n this.historySessions.set(historyPath, session);\n continue;\n }\n\n this.historySessions.set(historyPath, session);\n await this.ensureHistoryWatcher(session);\n await this.emitHistoryEvent(\n session,\n 'session.start',\n {\n project: basename(session.cwd) || session.cwd,\n projectPath: session.cwd,\n raw: {\n historyPath,\n pids: session.pids,\n source: 'process-detect',\n },\n },\n {\n pid: session.pids[0],\n source: 'aisnitch://adapters/aider/process-detect',\n },\n );\n await this.emitHistoryEvent(\n session,\n 'agent.idle',\n {\n model: session.model,\n project: basename(session.cwd) || session.cwd,\n projectPath: session.cwd,\n raw: {\n historyPath,\n source: 'process-detect',\n },\n },\n {\n pid: session.pids[0],\n source: 'aisnitch://adapters/aider/process-detect',\n },\n );\n }\n\n for (const [historyPath, previousSession] of this.historySessions) {\n if (nextSessions.has(historyPath)) {\n continue;\n }\n\n await this.emitHistoryEvent(\n previousSession,\n 'session.end',\n {\n model: previousSession.model,\n project: basename(previousSession.cwd) || previousSession.cwd,\n projectPath: previousSession.cwd,\n raw: {\n historyPath,\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n pid: previousSession.pids[0],\n source: 'aisnitch://adapters/aider/process-detect',\n },\n );\n await this.releaseHistoryWatcher(historyPath);\n this.historySessions.delete(historyPath);\n }\n }\n\n private async ensureHistoryWatcher(\n session: AiderSessionRuntime,\n ): Promise<void> {\n if (this.historyWatchers.has(session.historyPath)) {\n return;\n }\n\n const fingerprintSet = new Set<string>();\n const seedResult = await readOptionalAiderHistory(session);\n\n if (seedResult !== null) {\n for (const observation of seedResult.observations) {\n fingerprintSet.add(observation.fingerprint);\n }\n\n if (seedResult.lastModel) {\n this.historySessions.set(session.historyPath, {\n ...session,\n model: seedResult.lastModel,\n });\n }\n }\n\n const watcher = this.watcherFactory(session.historyPath, {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n });\n\n watcher.on('add', () => {\n void this.processHistoryUpdate(session.historyPath);\n });\n watcher.on('change', () => {\n void this.processHistoryUpdate(session.historyPath);\n });\n watcher.on('error', (error) => {\n logger.warn(\n {\n error,\n historyPath: session.historyPath,\n },\n 'Aider history watcher error',\n );\n });\n\n this.historyWatchers.set(session.historyPath, {\n fingerprints: fingerprintSet,\n watcher,\n });\n }\n\n private async processHistoryUpdate(historyPath: string): Promise<void> {\n const session = this.historySessions.get(historyPath);\n const watcherHandle = this.historyWatchers.get(historyPath);\n\n if (!session || !watcherHandle) {\n return;\n }\n\n const parseResult = await readOptionalAiderHistory(session);\n\n if (parseResult === null) {\n return;\n }\n\n if (parseResult.lastModel !== session.model) {\n this.historySessions.set(historyPath, {\n ...session,\n model: parseResult.lastModel,\n });\n }\n\n for (const observation of parseResult.observations) {\n if (watcherHandle.fingerprints.has(observation.fingerprint)) {\n continue;\n }\n\n watcherHandle.fingerprints.add(observation.fingerprint);\n await this.emitHistoryEvent(\n this.historySessions.get(historyPath) ?? session,\n observation.type,\n observation.data,\n {\n pid: session.pids[0],\n source: 'aisnitch://adapters/aider/history',\n },\n );\n }\n }\n\n private async emitHistoryEvent(\n session: AiderSessionRuntime,\n type: AISnitchEventType,\n data: Omit<EventData, 'state'>,\n context: Omit<AdapterPublishContext, 'sessionId' | 'cwd' | 'transcriptPath'>,\n ): Promise<void> {\n await this.emitStateChange(\n type,\n {\n cwd: session.cwd,\n model: data.model ?? session.model,\n project: data.project ?? (basename(session.cwd) || session.cwd),\n projectPath: data.projectPath ?? session.cwd,\n ...data,\n },\n {\n ...context,\n cwd: session.cwd,\n sessionId: session.sessionId,\n transcriptPath: session.historyPath,\n },\n );\n }\n\n private async releaseHistoryWatcher(historyPath: string): Promise<void> {\n const watcherHandle = this.historyWatchers.get(historyPath);\n\n if (!watcherHandle) {\n return;\n }\n\n await watcherHandle.watcher.close();\n this.historyWatchers.delete(historyPath);\n }\n}\n\n/**\n * Parses an aider markdown history file into normalized AISnitch observations.\n */\nexport function parseAiderHistoryMarkdown(\n markdown: string,\n options: AiderHistoryParseOptions,\n): AiderHistoryParseResult {\n const observations: AiderHistoryObservation[] = [];\n const lines = markdown.split(/\\r?\\n/u);\n let model = options.initialModel;\n\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index] ?? '';\n\n if (line.startsWith('# aider chat started at ')) {\n continue;\n }\n\n if (line.startsWith('#### ')) {\n const prompt = line.slice(5).trim();\n\n if (prompt.length === 0) {\n continue;\n }\n\n observations.push(createPromptObservation(prompt, index, {\n cwd: options.cwd,\n historyPath: options.historyPath,\n model,\n }));\n continue;\n }\n\n if (line.startsWith('>')) {\n const block = collectQuotedBlock(lines, index);\n const parsedBlock = parseQuotedOutputBlock(block.lines, {\n cwd: options.cwd,\n historyPath: options.historyPath,\n lineIndex: index,\n model,\n });\n\n observations.push(...parsedBlock.observations);\n model = parsedBlock.lastModel ?? model;\n index = block.nextIndex - 1;\n continue;\n }\n\n if (isAiderPatchBlockStart(lines, index)) {\n const patchBlock = collectPatchBlock(lines, index);\n observations.push(\n createCodingObservation(\n patchBlock.activeFile,\n patchBlock.body,\n index,\n {\n cwd: options.cwd,\n historyPath: options.historyPath,\n model,\n },\n ),\n );\n index = patchBlock.nextIndex - 1;\n continue;\n }\n\n if (line.trim().length === 0) {\n continue;\n }\n\n const proseBlock = collectProseBlock(lines, index);\n\n if (proseBlock.body.length > 0) {\n observations.push(\n createStreamingObservation(proseBlock.body, index, {\n cwd: options.cwd,\n historyPath: options.historyPath,\n model,\n }),\n );\n }\n\n index = proseBlock.nextIndex - 1;\n }\n\n return {\n lastModel: model,\n observations,\n };\n}\n\nasync function readOptionalAiderHistory(\n session: AiderSessionRuntime,\n): Promise<AiderHistoryParseResult | null> {\n try {\n const content = await readFile(session.historyPath, 'utf8');\n\n return parseAiderHistoryMarkdown(content, {\n cwd: session.cwd,\n historyPath: session.historyPath,\n initialModel: session.model,\n });\n } catch (error: unknown) {\n if (\n error instanceof Error &&\n 'code' in error &&\n error.code === 'ENOENT'\n ) {\n return null;\n }\n\n throw error;\n }\n}\n\nfunction createPromptObservation(\n prompt: string,\n lineIndex: number,\n context: {\n readonly cwd: string;\n readonly historyPath: string;\n readonly model?: string;\n },\n): AiderHistoryObservation {\n if (prompt.startsWith('/')) {\n const slashCommand = parseAiderSlashCommand(prompt);\n\n return {\n data: {\n activeFile: slashCommand.filePath,\n model: context.model,\n raw: {\n historyPath: context.historyPath,\n prompt,\n source: 'history-markdown',\n },\n toolInput: slashCommand.filePath\n ? {\n filePath: slashCommand.filePath,\n }\n : {\n command: prompt,\n },\n toolName: `aider:${slashCommand.name}`,\n },\n fingerprint: createHistoryFingerprint(\n 'agent.tool_call',\n lineIndex,\n prompt,\n slashCommand.filePath,\n ),\n type: 'agent.tool_call',\n };\n }\n\n return {\n data: {\n model: context.model,\n raw: {\n historyPath: context.historyPath,\n prompt,\n source: 'history-markdown',\n },\n },\n fingerprint: createHistoryFingerprint('task.start', lineIndex, prompt),\n type: 'task.start',\n };\n}\n\nfunction parseQuotedOutputBlock(\n quotedLines: readonly string[],\n context: {\n readonly cwd: string;\n readonly historyPath: string;\n readonly lineIndex: number;\n readonly model?: string;\n },\n): AiderHistoryParseResult {\n const observations: AiderHistoryObservation[] = [];\n let lastModel = context.model;\n const leftoverLines: string[] = [];\n\n for (let offset = 0; offset < quotedLines.length; offset += 1) {\n const rawLine = quotedLines[offset] ?? '';\n const line = rawLine.trim();\n\n if (line.length === 0) {\n continue;\n }\n\n const parsedModel = parseAiderModelLine(line);\n\n if (parsedModel) {\n lastModel = parsedModel;\n continue;\n }\n\n if (AIDER_STARTUP_STATUS_HINT.test(line)) {\n continue;\n }\n\n const tokenCount = parseAiderTokenUsage(line);\n\n if (tokenCount !== undefined) {\n observations.push({\n data: {\n model: lastModel,\n raw: {\n historyPath: context.historyPath,\n output: line,\n source: 'history-markdown',\n },\n tokensUsed: tokenCount,\n },\n fingerprint: createHistoryFingerprint(\n 'agent.thinking',\n context.lineIndex + offset,\n line,\n ),\n type: 'agent.thinking',\n });\n continue;\n }\n\n const addedFileMatch = line.match(/^Added\\s+(.+?)\\s+to the chat$/u);\n\n if (addedFileMatch) {\n const addedFile = addedFileMatch[1]?.trim();\n\n if (addedFile) {\n observations.push({\n data: {\n activeFile: addedFile,\n model: lastModel,\n raw: {\n historyPath: context.historyPath,\n output: line,\n source: 'history-markdown',\n },\n toolInput: {\n filePath: addedFile,\n },\n toolName: 'aider:/add',\n },\n fingerprint: createHistoryFingerprint(\n 'agent.tool_call',\n context.lineIndex + offset,\n line,\n addedFile,\n ),\n type: 'agent.tool_call',\n });\n continue;\n }\n }\n\n const appliedEditMatch = line.match(\n /^(?:Applied|Updated|Edited|Created|Wrote)\\s+(.+?)$/u,\n );\n\n if (appliedEditMatch) {\n const activeFile = appliedEditMatch[1]?.trim();\n\n if (activeFile) {\n observations.push(createCodingObservation(activeFile, line, context.lineIndex + offset, {\n cwd: context.cwd,\n historyPath: context.historyPath,\n model: lastModel,\n }));\n continue;\n }\n }\n\n if (AIDER_ASKING_USER_HINT.test(line)) {\n observations.push({\n data: {\n model: lastModel,\n raw: {\n historyPath: context.historyPath,\n output: line,\n source: 'history-markdown',\n },\n },\n fingerprint: createHistoryFingerprint(\n 'agent.asking_user',\n context.lineIndex + offset,\n line,\n ),\n type: 'agent.asking_user',\n });\n continue;\n }\n\n if (AIDER_ERROR_HINT.test(line)) {\n observations.push({\n data: {\n errorMessage: line,\n errorType: classifyAiderErrorType(line),\n model: lastModel,\n raw: {\n historyPath: context.historyPath,\n output: line,\n source: 'history-markdown',\n },\n },\n fingerprint: createHistoryFingerprint(\n 'agent.error',\n context.lineIndex + offset,\n line,\n ),\n type: 'agent.error',\n });\n continue;\n }\n\n leftoverLines.push(line);\n }\n\n if (leftoverLines.length > 0) {\n const body = leftoverLines.join('\\n').trim();\n\n observations.push({\n data: {\n model: lastModel,\n raw: {\n historyPath: context.historyPath,\n output: body,\n source: 'history-markdown',\n },\n },\n fingerprint: createHistoryFingerprint(\n 'agent.thinking',\n context.lineIndex,\n body,\n ),\n type: 'agent.thinking',\n });\n }\n\n return {\n lastModel,\n observations,\n };\n}\n\nfunction createStreamingObservation(\n body: string,\n lineIndex: number,\n context: {\n readonly cwd: string;\n readonly historyPath: string;\n readonly model?: string;\n },\n): AiderHistoryObservation {\n return {\n data: {\n model: context.model,\n raw: {\n historyPath: context.historyPath,\n output: body,\n source: 'history-markdown',\n },\n },\n fingerprint: createHistoryFingerprint('agent.streaming', lineIndex, body),\n type: 'agent.streaming',\n };\n}\n\nfunction createCodingObservation(\n activeFile: string,\n body: string,\n lineIndex: number,\n context: {\n readonly cwd: string;\n readonly historyPath: string;\n readonly model?: string;\n },\n): AiderHistoryObservation {\n return {\n data: {\n activeFile,\n model: context.model,\n raw: {\n historyPath: context.historyPath,\n output: body,\n source: 'history-markdown',\n },\n toolInput: {\n filePath: activeFile,\n },\n toolName: 'search-replace',\n },\n fingerprint: createHistoryFingerprint(\n 'agent.coding',\n lineIndex,\n body,\n activeFile,\n ),\n type: 'agent.coding',\n };\n}\n\nfunction collectQuotedBlock(\n lines: readonly string[],\n startIndex: number,\n): {\n readonly lines: readonly string[];\n readonly nextIndex: number;\n} {\n const blockLines: string[] = [];\n let index = startIndex;\n\n while (index < lines.length) {\n const currentLine = lines[index];\n\n if (!currentLine?.startsWith('>')) {\n break;\n }\n\n blockLines.push(currentLine.replace(/^>\\s?/u, ''));\n index += 1;\n }\n\n return {\n lines: blockLines,\n nextIndex: index,\n };\n}\n\nfunction collectProseBlock(\n lines: readonly string[],\n startIndex: number,\n): {\n readonly body: string;\n readonly nextIndex: number;\n} {\n const proseLines: string[] = [];\n let index = startIndex;\n\n while (index < lines.length) {\n const currentLine = lines[index] ?? '';\n\n if (\n currentLine.trim().length === 0 ||\n currentLine.startsWith('# aider chat started at ') ||\n currentLine.startsWith('#### ') ||\n currentLine.startsWith('>') ||\n isAiderPatchBlockStart(lines, index)\n ) {\n break;\n }\n\n proseLines.push(currentLine);\n index += 1;\n }\n\n return {\n body: proseLines.join('\\n').trim(),\n nextIndex: index,\n };\n}\n\nfunction collectPatchBlock(\n lines: readonly string[],\n startIndex: number,\n): {\n readonly activeFile: string;\n readonly body: string;\n readonly nextIndex: number;\n} {\n const activeFile = (lines[startIndex] ?? '').trim();\n const blockLines = [activeFile];\n let index = startIndex + 1;\n\n while (index < lines.length) {\n const currentLine = lines[index] ?? '';\n\n if (\n currentLine.startsWith('#### ') ||\n currentLine.startsWith('# aider chat started at ') ||\n currentLine.startsWith('> ')\n ) {\n break;\n }\n\n if (\n currentLine.trim().length === 0 &&\n !looksLikePatchMarker(lines[index + 1] ?? '')\n ) {\n blockLines.push(currentLine);\n index += 1;\n break;\n }\n\n blockLines.push(currentLine);\n index += 1;\n }\n\n return {\n activeFile,\n body: blockLines.join('\\n').trim(),\n nextIndex: index,\n };\n}\n\nfunction isAiderPatchBlockStart(\n lines: readonly string[],\n index: number,\n): boolean {\n const currentLine = (lines[index] ?? '').trim();\n const nextLine = lines[index + 1] ?? '';\n\n if (\n currentLine.length === 0 ||\n currentLine.startsWith('#') ||\n currentLine.startsWith('>') ||\n currentLine.startsWith('#### ')\n ) {\n return false;\n }\n\n return looksLikePatchMarker(nextLine);\n}\n\nfunction looksLikePatchMarker(line: string): boolean {\n const trimmedLine = line.trim();\n\n return (\n trimmedLine.startsWith('<<<<<<< ') ||\n trimmedLine.startsWith('=======') ||\n trimmedLine.startsWith('>>>>>>> ')\n );\n}\n\nfunction parseAiderModelLine(line: string): string | undefined {\n const modelMatch = line.match(/^(?:Main model|Model):\\s*(.+?)(?:\\s+with\\s+|$)/u);\n\n return modelMatch?.[1]?.trim() || undefined;\n}\n\nfunction parseAiderTokenUsage(line: string): number | undefined {\n const tokenMatch = line.match(\n /Tokens:\\s+([0-9.]+[kKmM]?)\\s+sent,\\s+([0-9.]+[kKmM]?)\\s+received/u,\n );\n\n if (!tokenMatch) {\n return undefined;\n }\n\n const sentTokens = parseHumanTokenCount(tokenMatch[1]);\n const receivedTokens = parseHumanTokenCount(tokenMatch[2]);\n\n if (sentTokens === undefined || receivedTokens === undefined) {\n return undefined;\n }\n\n return sentTokens + receivedTokens;\n}\n\nfunction parseHumanTokenCount(rawValue: string | undefined): number | undefined {\n if (!rawValue) {\n return undefined;\n }\n\n const match = rawValue.trim().match(/^([0-9]+(?:\\.[0-9]+)?)([kKmM])?$/u);\n\n if (!match) {\n return undefined;\n }\n\n const numericValue = Number.parseFloat(match[1] ?? '');\n\n if (!Number.isFinite(numericValue)) {\n return undefined;\n }\n\n const suffix = match[2]?.toLowerCase();\n\n if (suffix === 'k') {\n return Math.round(numericValue * 1_000);\n }\n\n if (suffix === 'm') {\n return Math.round(numericValue * 1_000_000);\n }\n\n return Math.round(numericValue);\n}\n\nfunction parseAiderSlashCommand(prompt: string): {\n readonly filePath?: string;\n readonly name: string;\n} {\n const normalizedPrompt = prompt.trim();\n const commandName = normalizedPrompt\n .slice(1)\n .split(/\\s+/u)[0]\n ?.toLowerCase();\n const filePath = AIDER_FILE_COMMAND_HINT.test(normalizedPrompt)\n ? normalizedPrompt.split(/\\s+/u).slice(1).join(' ').trim() || undefined\n : undefined;\n\n return {\n filePath,\n name: commandName ?? 'command',\n };\n}\n\nfunction createHistoryFingerprint(\n type: AISnitchEventType,\n lineIndex: number,\n text: string,\n activeFile?: string,\n): string {\n return [\n type,\n String(lineIndex),\n activeFile ?? '',\n text.trim().replace(/\\s+/gu, ' ').slice(0, 240),\n ].join('::');\n}\n\nfunction classifyAiderErrorType(message: string): ErrorType {\n if (/rate limit|quota|too many requests/iu.test(message)) {\n return 'rate_limit';\n }\n\n if (/context|token limit|context window/iu.test(message)) {\n return 'context_overflow';\n }\n\n if (/search\\/replace|edit format|apply|patch|write/iu.test(message)) {\n return 'tool_failure';\n }\n\n return 'api_error';\n}\n\nfunction resolveAiderHistoryPath(\n cwd: string,\n command: string,\n fallbackHistoryFileName: string,\n): string {\n const configuredHistoryPath =\n extractCommandOptionValue(command, 'chat-history-file') ??\n extractCommandOptionValue(command, 'chat_history_file');\n\n if (!configuredHistoryPath) {\n return join(cwd, fallbackHistoryFileName);\n }\n\n return configuredHistoryPath.startsWith('/')\n ? configuredHistoryPath\n : join(cwd, configuredHistoryPath);\n}\n\nfunction extractCommandOptionValue(\n command: string,\n optionName: string,\n): string | undefined {\n const matcher = new RegExp(\n `(?:^|\\\\s)--${escapeForRegExp(optionName)}(?:=|\\\\s+)(\"([^\"]+)\"|'([^']+)'|(\\\\S+))`,\n 'u',\n );\n const match = command.match(matcher);\n\n return match?.[2] ?? match?.[3] ?? match?.[4] ?? undefined;\n}\n\nfunction escapeForRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, '\\\\$&');\n}\n\nasync function listAiderProcesses(\n processListCommand: () => Promise<string>,\n): Promise<readonly AiderProcessInfo[]> {\n try {\n const output = await processListCommand();\n\n return output\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n const match = line.match(/^(\\d+)\\s+(.+)$/u);\n\n if (!match) {\n return null;\n }\n\n const pid = Number.parseInt(match[1] ?? '', 10);\n const command = match[2]?.trim();\n\n if (!Number.isInteger(pid) || pid <= 0 || !command) {\n return null;\n }\n\n return {\n command,\n pid,\n } satisfies AiderProcessInfo;\n })\n .filter((processInfo): processInfo is AiderProcessInfo => processInfo !== null);\n } catch (error: unknown) {\n logger.debug({ error }, 'Aider process discovery returned no matches');\n return [];\n }\n}\n","import pino from 'pino';\n\n/**\n * @file src/core/engine/logger.ts\n * @description Shared structured logger for the in-memory AISnitch runtime.\n * @functions\n * โ setLoggerLevel\n * @exports AISnitchLoggerLevel, logger, setLoggerLevel\n */\n\n/**\n * Supported logger levels for internal runtime usage.\n */\nexport type AISnitchLoggerLevel =\n | 'debug'\n | 'info'\n | 'warn'\n | 'error'\n | 'silent';\n\n/**\n * ๐ The logger writes to stdout only. The project is memory-only for runtime\n * data, so logging to files here would quietly violate that design.\n */\nexport const logger = pino({\n name: 'aisnitch',\n level: 'info',\n base: {\n service: 'aisnitch',\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n});\n\n/**\n * Updates the shared logger level at runtime.\n */\nexport function setLoggerLevel(level: AISnitchLoggerLevel): void {\n logger.level = level;\n}\n","import { basename, dirname, extname } from 'node:path';\n\nimport type { AISnitchEvent, ToolName } from './events/types.js';\n\n/**\n * @file src/core/session-identity.ts\n * @description Shared helpers for deriving stable session ids and readable session labels from partial runtime metadata.\n * @functions\n * โ isGenericSessionId\n * โ resolveSessionId\n * โ formatSessionLabel\n * โ formatSessionShortId\n * โ formatSessionLabelFromEvent\n * @exports SessionIdentityInput, isGenericSessionId, resolveSessionId, formatSessionLabel, formatSessionShortId, formatSessionLabelFromEvent\n * @see ./engine/pipeline.ts\n * @see ../adapters/base.ts\n * @see ../tui/components/SessionPanel.tsx\n */\n\n/**\n * Shared metadata used to derive or display one session identity.\n */\nexport interface SessionIdentityInput {\n readonly activeFile?: string;\n readonly cwd?: string;\n readonly instanceIndex?: number;\n readonly instanceTotal?: number;\n readonly pid?: number;\n readonly project?: string;\n readonly projectPath?: string;\n readonly sessionId?: string;\n readonly tool: ToolName;\n readonly transcriptPath?: string;\n}\n\nconst GENERIC_SESSION_SUFFIXES = new Set([\n 'default',\n 'hook',\n 'hook-session',\n 'process',\n 'session',\n 'unknown',\n]);\n\n/**\n * ๐ Some tool hooks only expose a placeholder session id such as\n * `opencode-session` or `codex:hook-session`. Treating those as canonical\n * collapses unrelated runs together, so AISnitch upgrades them when richer\n * metadata exists.\n */\nexport function isGenericSessionId(\n tool: ToolName,\n sessionId: string,\n): boolean {\n const normalizedSessionId = sessionId.trim().toLowerCase();\n const normalizedTool = tool.toLowerCase();\n\n if (normalizedSessionId.length === 0) {\n return true;\n }\n\n if (\n normalizedSessionId === 'hook-session' ||\n normalizedSessionId === 'session'\n ) {\n return true;\n }\n\n for (const suffix of GENERIC_SESSION_SUFFIXES) {\n if (\n normalizedSessionId === `${normalizedTool}:${suffix}` ||\n normalizedSessionId === `${normalizedTool}-${suffix}`\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Returns the best-effort stable session id for one event source.\n */\nexport function resolveSessionId(input: SessionIdentityInput): string {\n if (input.sessionId && !isGenericSessionId(input.tool, input.sessionId)) {\n return input.sessionId;\n }\n\n const scopeToken = sanitizeToken(\n input.project ??\n getPathTail(input.projectPath) ??\n getPathTail(input.cwd) ??\n getPathTail(input.activeFile) ??\n getPathTail(input.transcriptPath ? dirname(input.transcriptPath) : undefined),\n );\n const transcriptToken = sanitizeToken(\n input.transcriptPath\n ? basename(input.transcriptPath, extname(input.transcriptPath))\n : undefined,\n );\n const pidToken = input.pid ? `p${input.pid}` : undefined;\n const parts = [\n input.tool,\n scopeToken,\n transcriptToken && transcriptToken !== scopeToken ? transcriptToken : undefined,\n pidToken,\n ].filter((value): value is string => typeof value === 'string' && value.length > 0);\n\n if (parts.length > 1) {\n return parts.join(':');\n }\n\n return input.sessionId ?? `${input.tool}:session`;\n}\n\n/**\n * Formats a compact human-readable label for logs and the TUI.\n */\nexport function formatSessionLabel(input: SessionIdentityInput): string {\n const scopeLabel =\n input.project ??\n getPathTail(input.projectPath) ??\n getPathTail(input.cwd) ??\n getPathTail(input.activeFile);\n const parts = [\n scopeLabel,\n input.instanceTotal && input.instanceTotal > 1\n ? `#${input.instanceIndex ?? 1}/${input.instanceTotal}`\n : undefined,\n input.pid ? `pid ${input.pid}` : formatSessionShortId(input.tool, input.sessionId),\n ].filter((value): value is string => typeof value === 'string' && value.length > 0);\n\n return parts.length > 0 ? parts.join(' ยท ') : input.tool;\n}\n\n/**\n * Formats a short session-id fragment for UI display without losing all entropy.\n */\nexport function formatSessionShortId(\n tool: ToolName,\n sessionId: string | undefined,\n): string | undefined {\n if (!sessionId || isGenericSessionId(tool, sessionId)) {\n return undefined;\n }\n\n const withoutToolPrefix = sessionId.startsWith(`${tool}:`)\n ? sessionId.slice(tool.length + 1)\n : sessionId;\n\n if (withoutToolPrefix.length <= 16) {\n return withoutToolPrefix;\n }\n\n return `${withoutToolPrefix.slice(0, 6)}โฆ${withoutToolPrefix.slice(-4)}`;\n}\n\n/**\n * Builds a display label directly from a normalized AISnitch event.\n */\nexport function formatSessionLabelFromEvent(event: AISnitchEvent): string {\n return formatSessionLabel({\n activeFile: event.data.activeFile,\n cwd: event.data.cwd,\n instanceIndex: event.data.instanceIndex,\n instanceTotal: event.data.instanceTotal,\n pid: event.data.pid,\n project: event.data.project,\n projectPath: event.data.projectPath,\n sessionId: event['aisnitch.sessionid'],\n tool: event['aisnitch.tool'],\n });\n}\n\nfunction getPathTail(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n\n const pathParts = value.split(/[\\\\/]+/u).filter((part) => part.length > 0);\n\n return pathParts.at(-1);\n}\n\nfunction sanitizeToken(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n\n const normalizedToken = value\n .trim()\n .replace(/[\\\\/]+/gu, '-')\n .replace(/[^A-Za-z0-9._-]+/gu, '-')\n .replace(/-+/gu, '-')\n .replace(/^[-_.]+|[-_.]+$/gu, '');\n\n return normalizedToken.length > 0 ? normalizedToken : undefined;\n}\n","import { homedir } from 'node:os';\n\nimport { z } from 'zod';\n\nimport type { AISnitchConfig } from '../core/config/schema.js';\nimport { createEvent } from '../core/events/factory.js';\nimport { EventDataSchema, createUuidV7 } from '../core/events/schema.js';\nimport type {\n AISnitchEvent,\n AISnitchEventType,\n EventData,\n ToolName,\n} from '../core/events/types.js';\n\n/**\n * @file src/adapters/base.ts\n * @description Shared adapter primitives for lifecycle management, normalized event emission, and idle/session tracking.\n * @functions\n * โ none\n * @exports InterceptionStrategy, AdapterPublishContext, AdapterRuntimeOptions, AdapterStatus, NormalizedAdapterHookPayload, BaseAdapter\n * @see ./registry.ts\n * @see ./claude-code.ts\n * @see ./opencode.ts\n */\n\nconst NormalizedAdapterHookPayloadSchema = z.strictObject({\n type: z.string().min(1),\n source: z.string().min(1).optional(),\n sessionId: z.string().min(1).optional(),\n seqnum: z.number().int().min(1).optional(),\n data: EventDataSchema.partial().optional(),\n pid: z.number().int().positive().optional(),\n transcriptPath: z.string().min(1).optional(),\n cwd: z.string().min(1).optional(),\n env: z.record(z.string(), z.string()).optional(),\n hookPayload: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Capture strategies supported by built-in and future community adapters.\n */\nexport type InterceptionStrategy =\n | 'hooks'\n | 'jsonl-watch'\n | 'log-watch'\n | 'sqlite-watch'\n | 'stream-json'\n | 'process-detect'\n | 'pty-wrap'\n | 'api-client';\n\n/**\n * Extra context that adapters can provide alongside emitted events.\n */\nexport interface AdapterPublishContext {\n readonly cwd?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly hookPayload?: Record<string, unknown>;\n readonly pid?: number;\n readonly sessionId?: string;\n readonly source?: string;\n readonly transcriptPath?: string;\n}\n\n/**\n * Dependency injection contract shared by all adapters.\n */\nexport interface AdapterRuntimeOptions {\n readonly config: AISnitchConfig;\n readonly env?: NodeJS.ProcessEnv;\n readonly homeDirectory?: string;\n readonly publishEvent: (\n event: AISnitchEvent,\n context?: AdapterPublishContext,\n ) => Promise<boolean>;\n}\n\n/**\n * Observable adapter runtime state exposed to the registry and CLI.\n */\nexport interface AdapterStatus {\n readonly activeSessions: number;\n readonly displayName: string;\n readonly eventsEmitted: number;\n readonly name: ToolName;\n readonly running: boolean;\n readonly strategies: readonly InterceptionStrategy[];\n}\n\n/**\n * Best-effort normalized payload shape accepted from hook/plugin bridges.\n */\nexport type NormalizedAdapterHookPayload = z.infer<\n typeof NormalizedAdapterHookPayloadSchema\n>;\n\n/**\n * ๐ Every concrete adapter gets the same boring-but-essential plumbing here:\n * session ids, sequence numbers, idle timers, and validated event emission.\n */\nexport abstract class BaseAdapter {\n public abstract readonly displayName: string;\n\n public abstract readonly name: ToolName;\n\n public abstract readonly strategies: readonly InterceptionStrategy[];\n\n protected currentSessionId: string | null = null;\n\n protected readonly env: NodeJS.ProcessEnv | undefined;\n\n protected readonly homeDirectory: string;\n\n protected sequenceNumber = 0;\n\n private readonly activeSessions = new Set<string>();\n\n private eventsEmitted = 0;\n\n private idleTimer: NodeJS.Timeout | null = null;\n\n private readonly idleTimeoutMs: number;\n\n private readonly publishEventImplementation: AdapterRuntimeOptions['publishEvent'];\n\n private running = false;\n\n protected constructor(options: AdapterRuntimeOptions) {\n this.env = options.env;\n this.homeDirectory = options.homeDirectory ?? homedir();\n this.idleTimeoutMs = options.config.idleTimeoutMs;\n this.publishEventImplementation = options.publishEvent;\n }\n\n /**\n * Starts the adapter-specific watchers, pollers, or hook bridges.\n */\n public abstract start(): Promise<void>;\n\n /**\n * Stops adapter-specific resources and clears runtime state.\n */\n public abstract stop(): Promise<void>;\n\n /**\n * Hook-based adapters override this to transform tool-native payloads.\n */\n public handleHook(_payload: unknown): Promise<void> {\n return Promise.reject(\n new Error(`${this.name} does not support hook payloads.`),\n );\n }\n\n /**\n * Returns the current observable adapter status snapshot.\n */\n public getStatus(): AdapterStatus {\n return {\n activeSessions: this.activeSessions.size,\n displayName: this.displayName,\n eventsEmitted: this.eventsEmitted,\n name: this.name,\n running: this.running,\n strategies: this.strategies,\n };\n }\n\n /**\n * Accepts the normalized hook payload shape used by setup-installed bridges.\n */\n protected parseNormalizedHookPayload(\n payload: unknown,\n ): NormalizedAdapterHookPayload | null {\n const parsedPayload = NormalizedAdapterHookPayloadSchema.safeParse(payload);\n\n if (!parsedPayload.success) {\n return null;\n }\n\n return parsedPayload.data;\n }\n\n /**\n * Emits one already-normalized payload through the common adapter lifecycle.\n */\n protected async emitNormalizedPayload(\n payload: NormalizedAdapterHookPayload,\n ): Promise<boolean> {\n return await this.emit(payload.type as AISnitchEventType, payload.data, {\n cwd: payload.cwd,\n env: payload.env,\n hookPayload: payload.hookPayload,\n pid: payload.pid,\n sessionId: payload.sessionId,\n source: payload.source,\n transcriptPath: payload.transcriptPath,\n });\n }\n\n /**\n * Emits a fully normalized AISnitch event and updates idle/session tracking.\n */\n protected async emit(\n type: AISnitchEventType,\n data: Omit<EventData, 'state'> = {},\n context: AdapterPublishContext = {},\n ): Promise<boolean> {\n const sessionId = this.resolveSessionId(context.sessionId);\n\n this.sequenceNumber += 1;\n\n const event = createEvent({\n source: context.source ?? `aisnitch://adapters/${this.name}`,\n type,\n 'aisnitch.tool': this.name,\n 'aisnitch.sessionid': sessionId,\n 'aisnitch.seqnum': this.sequenceNumber,\n data: {\n ...data,\n cwd: data.cwd ?? context.cwd,\n },\n });\n\n const published = await this.publishEventImplementation(event, {\n cwd: context.cwd,\n env: context.env,\n hookPayload: context.hookPayload,\n pid: context.pid,\n sessionId,\n source: context.source,\n transcriptPath: context.transcriptPath,\n });\n\n if (published) {\n this.eventsEmitted += 1;\n }\n\n if (type === 'session.end') {\n this.activeSessions.delete(sessionId);\n\n if (this.currentSessionId === sessionId) {\n this.currentSessionId = null;\n }\n\n this.clearIdleTimer();\n\n return published;\n }\n\n if (type !== 'agent.idle') {\n this.resetIdleTimer();\n }\n\n return published;\n }\n\n /**\n * Shortcut for emitting a plain state transition without extra boilerplate.\n */\n protected async emitStateChange(\n type: AISnitchEventType,\n data: Omit<EventData, 'state'> = {},\n context: AdapterPublishContext = {},\n ): Promise<boolean> {\n return await this.emit(type, data, context);\n }\n\n /**\n * Updates the active session id while keeping sequence numbers monotonic per session.\n */\n protected setSessionId(sessionId: string | null): void {\n if (sessionId === null) {\n this.currentSessionId = null;\n this.clearIdleTimer();\n return;\n }\n\n if (this.currentSessionId !== sessionId) {\n this.sequenceNumber = 0;\n }\n\n this.currentSessionId = sessionId;\n this.activeSessions.add(sessionId);\n }\n\n /**\n * Marks the adapter runtime as active or stopped.\n */\n protected setRunning(running: boolean): void {\n this.running = running;\n\n if (!running) {\n this.clearIdleTimer();\n this.currentSessionId = null;\n this.sequenceNumber = 0;\n this.activeSessions.clear();\n }\n }\n\n /**\n * Shared helper for adapters that need a stable testable home directory.\n */\n protected getUserHomeDirectory(): string {\n return this.homeDirectory;\n }\n\n private clearIdleTimer(): void {\n if (this.idleTimer !== null) {\n clearTimeout(this.idleTimer);\n this.idleTimer = null;\n }\n }\n\n private resetIdleTimer(): void {\n if (!this.running || this.currentSessionId === null) {\n return;\n }\n\n this.clearIdleTimer();\n this.idleTimer = setTimeout(() => {\n if (this.currentSessionId === null) {\n return;\n }\n\n void this.emitStateChange('agent.idle');\n }, this.idleTimeoutMs);\n this.idleTimer.unref();\n }\n\n private resolveSessionId(sessionId?: string): string {\n if (sessionId !== undefined) {\n this.setSessionId(sessionId);\n\n return sessionId;\n }\n\n if (this.currentSessionId === null) {\n this.setSessionId(`${this.name}:${createUuidV7()}`);\n }\n\n if (this.currentSessionId === null) {\n throw new Error(`Adapter \"${this.name}\" failed to resolve a session id.`);\n }\n\n return this.currentSessionId;\n }\n}\n","import { validate as isUuid, v7 as uuidv7, version as uuidVersion } from 'uuid';\nimport { z } from 'zod';\n\n/**\n * @file src/core/events/schema.ts\n * @description Runtime Zod schemas and constants for the AISnitch CloudEvents-based event contract.\n * @functions\n * โ createUuidV7\n * @exports AISNITCH_EVENT_TYPES, TOOL_NAMES, ERROR_TYPES, CESP_CATEGORIES, ToolInputSchema, EventDataSchema, AISnitchEventTypeSchema, ToolNameSchema, ErrorTypeSchema, CESPCategorySchema, AISnitchEventSchema, createUuidV7\n * @see ./types.ts\n * @see ./cesp.ts\n * @see ./factory.ts\n */\n\n/**\n * ๐ AISnitch keeps the event-type list as a constant tuple so every schema,\n * inferred type, and mapping table stays aligned from one source of truth.\n */\nexport const AISNITCH_EVENT_TYPES = [\n 'session.start',\n 'session.end',\n 'task.start',\n 'task.complete',\n 'agent.thinking',\n 'agent.coding',\n 'agent.tool_call',\n 'agent.streaming',\n 'agent.asking_user',\n 'agent.idle',\n 'agent.error',\n 'agent.compact',\n] as const;\n\n/**\n * Supported AI tool identifiers recognized by AISnitch.\n */\nexport const TOOL_NAMES = [\n 'claude-code',\n 'opencode',\n 'gemini-cli',\n 'codex',\n 'goose',\n 'copilot-cli',\n 'cursor',\n 'aider',\n 'amp',\n 'cline',\n 'continue',\n 'windsurf',\n 'qwen-code',\n 'openclaw',\n 'openhands',\n 'kilo',\n 'unknown',\n] as const;\n\n/**\n * Normalized error categories attached to `agent.error` events.\n */\nexport const ERROR_TYPES = [\n 'rate_limit',\n 'context_overflow',\n 'tool_failure',\n 'api_error',\n] as const;\n\n/**\n * CESP-compatible categories used by the current mapping layer.\n */\nexport const CESP_CATEGORIES = [\n 'session.start',\n 'session.end',\n 'task.acknowledge',\n 'task.complete',\n 'input.required',\n 'task.error',\n 'resource.limit',\n] as const;\n\nconst ISO_TIMESTAMP_SCHEMA = z.string().datetime({ offset: true });\n\nfunction isUuidV7(value: string): boolean {\n return isUuid(value) && uuidVersion(value) === 7;\n}\n\nfunction isValidUriReference(value: string): boolean {\n if (value.trim().length === 0 || /\\s/u.test(value)) {\n return false;\n }\n\n try {\n new URL(value);\n return true;\n } catch {\n try {\n new URL(value, 'https://aisnitch.local');\n return true;\n } catch {\n return false;\n }\n }\n}\n\n/**\n * Generates a UUIDv7 value that matches the event schema contract.\n */\nexport function createUuidV7(): string {\n return uuidv7();\n}\n\n/**\n * Tool input metadata attached when an agent runs a concrete tool.\n */\nexport const ToolInputSchema = z\n .strictObject({\n filePath: z.string().min(1).optional(),\n command: z.string().min(1).optional(),\n })\n .refine(\n (value) => value.filePath !== undefined || value.command !== undefined,\n 'toolInput must include filePath or command',\n );\n\n/**\n * Runtime schema for the supported tool names.\n */\nexport const ToolNameSchema = z.enum(TOOL_NAMES);\n\n/**\n * Runtime schema for AISnitch event types.\n */\nexport const AISnitchEventTypeSchema = z.enum(AISNITCH_EVENT_TYPES);\n\n/**\n * Runtime schema for normalized AISnitch error categories.\n */\nexport const ErrorTypeSchema = z.enum(ERROR_TYPES);\n\n/**\n * Runtime schema for CESP categories.\n */\nexport const CESPCategorySchema = z.enum(CESP_CATEGORIES);\n\n/**\n * ๐ `raw` remains intentionally permissive because adapters need a safe place\n * to stash source-native payload fragments without forcing them into the\n * normalized contract too early.\n */\nexport const EventDataSchema = z.strictObject({\n state: AISnitchEventTypeSchema,\n project: z.string().min(1).optional(),\n projectPath: z.string().min(1).optional(),\n duration: z.number().int().min(0).optional(),\n toolName: z.string().min(1).optional(),\n toolInput: ToolInputSchema.optional(),\n activeFile: z.string().min(1).optional(),\n model: z.string().min(1).optional(),\n tokensUsed: z.number().int().min(0).optional(),\n errorMessage: z.string().min(1).optional(),\n errorType: ErrorTypeSchema.optional(),\n raw: z.record(z.string(), z.unknown()).optional(),\n terminal: z.string().min(1).optional(),\n cwd: z.string().min(1).optional(),\n pid: z.number().int().positive().optional(),\n instanceId: z.string().min(1).optional(),\n instanceIndex: z.number().int().min(1).optional(),\n instanceTotal: z.number().int().min(1).optional(),\n});\n\n/**\n * Runtime schema for the full normalized AISnitch event envelope.\n */\nexport const AISnitchEventSchema = z.strictObject({\n specversion: z.literal('1.0'),\n id: z.string().refine(isUuidV7, 'id must be a valid UUIDv7 string'),\n source: z\n .string()\n .refine(\n isValidUriReference,\n 'source must be a valid non-empty CloudEvents URI-reference',\n ),\n type: AISnitchEventTypeSchema,\n time: ISO_TIMESTAMP_SCHEMA,\n 'aisnitch.tool': ToolNameSchema,\n 'aisnitch.sessionid': z.string().min(1),\n 'aisnitch.seqnum': z.number().int().min(1),\n data: EventDataSchema,\n});\n","import { AISnitchEventSchema, createUuidV7 } from './schema.js';\nimport type { AISnitchEvent, CreateEventInput } from './types.js';\n\n/**\n * @file src/core/events/factory.ts\n * @description Factory helpers for producing validated AISnitch events with generated CloudEvents fields.\n * @functions\n * โ createEvent\n * @exports createEvent\n * @see ./schema.ts\n */\n\n/**\n * Builds a fully valid AISnitch event by attaching CloudEvents metadata and\n * validating the final payload before it leaves the factory.\n */\nexport function createEvent(input: CreateEventInput): AISnitchEvent {\n const eventCandidate = {\n ...input,\n specversion: '1.0' as const,\n id: createUuidV7(),\n time: new Date().toISOString(),\n data: {\n state: input.data?.state ?? input.type,\n ...input.data,\n },\n };\n\n /**\n * ๐ Parsing at the factory boundary gives every future adapter the same\n * guardrail: if it emits junk, it fails immediately and loudly.\n */\n return AISnitchEventSchema.parse(eventCandidate);\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { readFile, readdir, stat } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { watch, type FSWatcher } from 'chokidar';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type {\n AISnitchEventType,\n ErrorType,\n EventData,\n ToolInput,\n} from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/claude-code.ts\n * @description Claude Code adapter covering official hooks, transcript JSONL enrichment, and process fallback detection.\n * @functions\n * โ none\n * @exports ClaudeCodeAdapter, ClaudeCodeAdapterOptions\n * @see ./base.ts\n * @see ../cli/commands/setup.ts\n * @see ../../tasks/04-adapters-priority/02_adapters-priority_claude-code.md\n */\n\nconst execFile = promisify(execFileCallback);\n\nconst CLAUDE_CODE_CODING_TOOLS = new Set([\n 'Edit',\n 'MultiEdit',\n 'NotebookEdit',\n 'Write',\n]);\n\nconst ASKING_USER_NOTIFICATION_TYPES = new Set([\n 'elicitation_dialog',\n 'idle_prompt',\n 'permission_prompt',\n]);\n\n/**\n * The official Claude hooks reference currently documents 25 lifecycle events,\n * including newer events such as SessionEnd, PostCompact, and ElicitationResult.\n * AISnitch only maps the subset that materially improves live activity tracking.\n */\nexport interface ClaudeCodeAdapterOptions extends AdapterRuntimeOptions {\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n readonly projectsDirectory?: string;\n readonly watcherFactory?: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n}\n\ninterface ClaudeProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\ninterface ClaudeTranscriptObservation {\n readonly context: AdapterPublishContext;\n readonly data: Omit<EventData, 'state'>;\n readonly type: AISnitchEventType;\n}\n\n/**\n * ๐ Claude Code is AISnitch's richest adapter: hooks give precise state\n * transitions, JSONL fills in thinking/streaming detail, and process polling\n * covers the ugly \"hooks were never installed\" case.\n */\nexport class ClaudeCodeAdapter extends BaseAdapter {\n public override readonly displayName = 'Claude Code';\n\n public override readonly name = 'claude-code' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'hooks',\n 'jsonl-watch',\n 'process-detect',\n ];\n\n private fallbackProcessSessionId: string | null = null;\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n private readonly projectsDirectory: string;\n\n private readonly transcriptOffsets = new Map<string, number>();\n\n private readonly transcriptRemainders = new Map<string, string>();\n\n private watcher: FSWatcher | null = null;\n\n private readonly watcherFactory: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n\n public constructor(options: ClaudeCodeAdapterOptions) {\n super(options);\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ?? (async () => await execFile('pgrep', ['-lf', 'claude']).then((result) => result.stdout));\n this.projectsDirectory =\n options.projectsDirectory ??\n join(this.getUserHomeDirectory(), '.claude', 'projects');\n this.watcherFactory = options.watcherFactory ?? watch;\n }\n\n public override async start(): Promise<void> {\n if (this.getStatus().running) {\n return;\n }\n\n this.setRunning(true);\n await this.seedTranscriptOffsets();\n\n const transcriptGlob = join(this.projectsDirectory, '**', '*.jsonl');\n this.watcher = this.watcherFactory(transcriptGlob, {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n });\n\n this.watcher.on('add', (filePath) => {\n void this.processTranscriptUpdate(filePath, true);\n });\n this.watcher.on('change', (filePath) => {\n void this.processTranscriptUpdate(filePath, false);\n });\n this.watcher.on('error', (error) => {\n logger.warn({ error }, 'Claude transcript watcher error');\n });\n\n this.startProcessPolling();\n }\n\n public override async stop(): Promise<void> {\n if (this.watcher !== null) {\n await this.watcher.close();\n this.watcher = null;\n }\n\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n this.fallbackProcessSessionId = null;\n this.transcriptOffsets.clear();\n this.transcriptRemainders.clear();\n this.setRunning(false);\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload !== null) {\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n project: normalizedPayload.data?.project,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n transcriptPath: normalizedPayload.transcriptPath,\n }),\n });\n return;\n }\n\n if (!isRecord(payload)) {\n logger.warn({ payload }, 'Claude hook payload must be an object');\n return;\n }\n\n const hookEventName =\n getString(payload, 'hook_event_name') ??\n getString(payload, 'hook_type');\n\n if (!hookEventName) {\n logger.warn({ payload }, 'Claude hook payload is missing its event name');\n return;\n }\n\n const sessionId = resolveSessionId({\n activeFile: extractActiveFile(payload),\n cwd: getString(payload, 'cwd'),\n pid: getNumber(payload, 'pid'),\n projectPath:\n getString(payload, 'project_path') ??\n getString(payload, 'projectPath'),\n sessionId:\n getString(payload, 'session_id') ??\n getString(payload, 'sessionId'),\n tool: this.name,\n transcriptPath:\n getString(payload, 'transcript_path') ??\n getString(payload, 'transcriptPath'),\n });\n const context: AdapterPublishContext = {\n cwd: getString(payload, 'cwd'),\n hookPayload: payload,\n pid: getNumber(payload, 'pid'),\n sessionId,\n source: 'aisnitch://adapters/claude-code',\n transcriptPath:\n getString(payload, 'transcript_path') ??\n getString(payload, 'transcriptPath'),\n };\n const sharedData = {\n activeFile: extractActiveFile(payload),\n cwd: context.cwd,\n model: getString(payload, 'model'),\n projectPath:\n getString(payload, 'project_path') ??\n getString(payload, 'projectPath'),\n raw: payload,\n toolInput: extractClaudeToolInput(payload),\n toolName:\n getString(payload, 'tool_name') ??\n getString(payload, 'toolName'),\n } satisfies Omit<EventData, 'state'>;\n\n switch (hookEventName) {\n case 'SessionStart': {\n this.fallbackProcessSessionId = null;\n await this.emitStateChange('session.start', sharedData, context);\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'SessionEnd': {\n await this.emitStateChange('session.end', sharedData, context);\n return;\n }\n case 'UserPromptSubmit':\n case 'TaskCreated':\n case 'SubagentStart': {\n await this.emitStateChange('task.start', sharedData, context);\n return;\n }\n case 'Stop':\n case 'TaskCompleted':\n case 'SubagentStop': {\n await this.emitStateChange('task.complete', sharedData, context);\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'PreToolUse': {\n await this.emitStateChange('agent.tool_call', sharedData, context);\n return;\n }\n case 'PostToolUse': {\n const emittedType = isClaudeCodingTool(sharedData.toolName)\n ? 'agent.coding'\n : 'agent.tool_call';\n await this.emitStateChange(emittedType, sharedData, context);\n return;\n }\n case 'PostToolUseFailure':\n case 'StopFailure': {\n await this.emitStateChange(\n 'agent.error',\n {\n ...sharedData,\n errorMessage:\n getString(payload, 'error') ??\n getString(payload, 'message') ??\n 'Claude Code hook failure',\n errorType:\n getClaudeErrorType(payload) ??\n 'tool_failure',\n },\n context,\n );\n return;\n }\n case 'PermissionRequest': {\n await this.emitStateChange('agent.asking_user', sharedData, context);\n return;\n }\n case 'Notification': {\n const notificationType =\n getString(payload, 'notification_type') ??\n getString(payload, 'type');\n\n if (notificationType && ASKING_USER_NOTIFICATION_TYPES.has(notificationType)) {\n await this.emitStateChange('agent.asking_user', sharedData, context);\n }\n\n return;\n }\n case 'PreCompact':\n case 'PostCompact': {\n await this.emitStateChange('agent.compact', sharedData, context);\n return;\n }\n case 'TeammateIdle': {\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n default: {\n logger.debug({ hookEventName }, 'Claude hook event ignored by adapter');\n }\n }\n }\n\n private async processTranscriptUpdate(\n filePath: string,\n readFromStart: boolean,\n ): Promise<void> {\n let fileContent: Buffer;\n\n try {\n fileContent = await readFile(filePath);\n } catch (error) {\n logger.debug({ error, filePath }, 'Claude transcript read skipped');\n return;\n }\n\n const knownOffset = this.transcriptOffsets.get(filePath);\n const previousOffset =\n knownOffset ??\n (readFromStart ? 0 : fileContent.byteLength);\n const safeOffset =\n previousOffset > fileContent.byteLength ? 0 : previousOffset;\n const newChunk = fileContent.subarray(safeOffset).toString('utf8');\n const bufferedChunk =\n (safeOffset === 0 ? '' : this.transcriptRemainders.get(filePath) ?? '') +\n newChunk;\n const lines = bufferedChunk.split(/\\r?\\n/u);\n const remainder =\n bufferedChunk.endsWith('\\n') || bufferedChunk.endsWith('\\r')\n ? ''\n : (lines.pop() ?? '');\n\n this.transcriptOffsets.set(filePath, fileContent.byteLength);\n this.transcriptRemainders.set(filePath, remainder);\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n\n if (trimmedLine.length === 0) {\n continue;\n }\n\n await this.processTranscriptLine(trimmedLine, filePath);\n }\n }\n\n private async processTranscriptLine(\n line: string,\n transcriptPath: string,\n ): Promise<void> {\n let parsedLine: unknown;\n\n try {\n parsedLine = JSON.parse(line) as unknown;\n } catch (error) {\n logger.warn({ error, transcriptPath }, 'Claude transcript line is not valid JSON');\n return;\n }\n\n const observations = extractClaudeTranscriptObservations(\n parsedLine,\n transcriptPath,\n );\n\n for (const observation of observations) {\n await this.emitStateChange(\n observation.type,\n observation.data,\n observation.context,\n );\n }\n }\n\n private async seedTranscriptOffsets(): Promise<void> {\n const files = await collectFilesRecursively(this.projectsDirectory, '.jsonl');\n\n await Promise.all(\n files.map(async (filePath) => {\n try {\n const fileStats = await stat(filePath);\n\n this.transcriptOffsets.set(filePath, fileStats.size);\n } catch {\n // Ignore files that disappear between discovery and stat.\n }\n }),\n );\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.processPoller = setInterval(() => {\n void this.pollClaudeProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n\n void this.pollClaudeProcesses();\n }\n\n private async pollClaudeProcesses(): Promise<void> {\n const processes = await listProcesses(this.processListCommand);\n\n if (processes.length > 0 && this.getStatus().activeSessions === 0) {\n const processInfo = processes[0];\n\n if (!processInfo) {\n return;\n }\n\n const sessionId = `claude-process-${processInfo.pid}`;\n\n this.fallbackProcessSessionId = sessionId;\n await this.emitStateChange(\n 'session.start',\n {\n raw: {\n process: processInfo,\n source: 'process-detect',\n },\n },\n {\n pid: processInfo.pid,\n sessionId,\n source: 'aisnitch://adapters/claude-code/process-detect',\n },\n );\n return;\n }\n\n if (processes.length === 0 && this.fallbackProcessSessionId !== null) {\n const sessionId = this.fallbackProcessSessionId;\n\n this.fallbackProcessSessionId = null;\n await this.emitStateChange(\n 'session.end',\n {\n raw: {\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n sessionId,\n source: 'aisnitch://adapters/claude-code/process-detect',\n },\n );\n }\n }\n}\n\nasync function collectFilesRecursively(\n directoryPath: string,\n extension: string,\n): Promise<string[]> {\n try {\n const entries = await readdir(directoryPath, {\n withFileTypes: true,\n });\n const nestedResults = await Promise.all(\n entries.map(async (entry) => {\n const entryPath = join(directoryPath, entry.name);\n\n if (entry.isDirectory()) {\n return await collectFilesRecursively(entryPath, extension);\n }\n\n return entry.name.endsWith(extension) ? [entryPath] : [];\n }),\n );\n\n return nestedResults.flat();\n } catch (error) {\n if (isErrnoException(error) && error.code === 'ENOENT') {\n return [];\n }\n\n throw error;\n }\n}\n\nfunction extractClaudeTranscriptObservations(\n payload: unknown,\n transcriptPath: string,\n): ClaudeTranscriptObservation[] {\n if (!isRecord(payload)) {\n return [];\n }\n\n const sessionId = resolveSessionId({\n sessionId:\n getString(payload, 'session_id') ??\n basename(transcriptPath, '.jsonl'),\n tool: 'claude-code',\n transcriptPath,\n });\n const contentParts = extractClaudeContentParts(payload);\n const model =\n getString(payload, 'model') ??\n getString(getRecord(payload.message), 'model');\n const tokensUsed = extractTokenUsage(payload);\n const rawPayload = payload;\n const sharedContext: AdapterPublishContext = {\n hookPayload: rawPayload,\n sessionId,\n source: 'aisnitch://adapters/claude-code/transcript',\n transcriptPath,\n };\n const sharedData = {\n model,\n raw: rawPayload,\n tokensUsed,\n } satisfies Omit<EventData, 'state'>;\n const observations: ClaudeTranscriptObservation[] = [];\n\n if (contentParts.some((part) => part.type === 'thinking')) {\n observations.push({\n context: sharedContext,\n data: sharedData,\n type: 'agent.thinking',\n });\n }\n\n if (\n contentParts.some(\n (part) =>\n part.type === 'text' &&\n typeof part.text === 'string' &&\n part.text.trim().length > 0,\n )\n ) {\n observations.push({\n context: sharedContext,\n data: sharedData,\n type: 'agent.streaming',\n });\n }\n\n return observations;\n}\n\nfunction extractClaudeContentParts(\n payload: Record<string, unknown>,\n): Array<Record<string, unknown>> {\n const message = getRecord(payload.message);\n const content = message?.content ?? payload.content;\n\n if (!Array.isArray(content)) {\n return [];\n }\n\n return content.filter(isRecord);\n}\n\nfunction extractTokenUsage(payload: Record<string, unknown>): number | undefined {\n const tokens = getNumber(payload, 'tokens');\n\n if (tokens !== undefined) {\n return tokens;\n }\n\n const usage = getRecord(payload.usage);\n\n if (!usage) {\n return undefined;\n }\n\n const totalTokens = getNumber(usage, 'total_tokens');\n\n if (totalTokens !== undefined) {\n return totalTokens;\n }\n\n const inputTokens = getNumber(usage, 'input_tokens') ?? 0;\n const outputTokens = getNumber(usage, 'output_tokens') ?? 0;\n const usageSum = inputTokens + outputTokens;\n\n return usageSum > 0 ? usageSum : undefined;\n}\n\nfunction extractClaudeToolInput(\n payload: Record<string, unknown>,\n): ToolInput | undefined {\n const toolInput = getRecord(payload.tool_input) ?? getRecord(payload.toolInput);\n\n if (!toolInput) {\n return undefined;\n }\n\n const filePath =\n getString(toolInput, 'file_path') ??\n getString(toolInput, 'filePath') ??\n getString(toolInput, 'path');\n const command =\n getString(toolInput, 'command') ??\n getString(toolInput, 'cmd');\n\n if (!filePath && !command) {\n return undefined;\n }\n\n return {\n command,\n filePath,\n };\n}\n\nfunction extractActiveFile(payload: Record<string, unknown>): string | undefined {\n const toolInput = extractClaudeToolInput(payload);\n\n if (toolInput?.filePath) {\n return toolInput.filePath;\n }\n\n return (\n getString(payload, 'active_file') ??\n getString(payload, 'activeFile') ??\n getString(payload, 'file_path')\n );\n}\n\nfunction getClaudeErrorType(payload: Record<string, unknown>): ErrorType | undefined {\n const rawErrorType =\n getString(payload, 'error_type') ??\n getString(payload, 'errorType') ??\n getString(payload, 'stop_reason');\n\n switch (rawErrorType) {\n case 'rate_limit':\n return 'rate_limit';\n case 'max_output_tokens':\n case 'context_overflow':\n return 'context_overflow';\n case 'api_error':\n case 'server_error':\n case 'authentication_failed':\n case 'billing_error':\n case 'invalid_request':\n return 'api_error';\n default:\n return undefined;\n }\n}\n\nfunction isClaudeCodingTool(toolName?: string): boolean {\n return toolName !== undefined && CLAUDE_CODE_CODING_TOOLS.has(toolName);\n}\n\nasync function listProcesses(\n listCommand: () => Promise<string>,\n): Promise<ClaudeProcessInfo[]> {\n if (process.platform === 'win32') {\n return [];\n }\n\n try {\n const stdout = await listCommand();\n\n return stdout\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map(parseProcessLine)\n .filter((processInfo): processInfo is ClaudeProcessInfo => processInfo !== null);\n } catch (error) {\n const errorCode = isErrnoException(error) ? String(error.code) : '';\n\n if (isErrnoException(error) && (errorCode === 'ENOENT' || errorCode === '1')) {\n return [];\n }\n\n logger.debug({ error }, 'Claude process detection failed');\n return [];\n }\n}\n\nfunction parseProcessLine(line: string): ClaudeProcessInfo | null {\n const match = line.match(/^(\\d+)\\s+(.+)$/u);\n\n if (!match) {\n return null;\n }\n\n const pidText = match[1];\n const command = match[2];\n\n if (!pidText || !command) {\n return null;\n }\n\n return {\n command,\n pid: Number.parseInt(pidText, 10),\n };\n}\n\nfunction isErrnoException(\n error: unknown,\n): error is NodeJS.ErrnoException & { code?: string | number } {\n return error instanceof Error && 'code' in error;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction getNumber(\n payload: Record<string, unknown>,\n key: string,\n): number | undefined {\n const value = payload[key];\n\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined;\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { readFile, readdir, stat } from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { watch, type FSWatcher } from 'chokidar';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type { ErrorType, EventData, ToolInput } from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/copilot-cli.ts\n * @description Copilot CLI adapter covering repository hooks, passive session-state JSONL watching, workspace metadata enrichment, and process fallback detection.\n * @functions\n * โ none\n * @exports CopilotCLIAdapter, CopilotCLIAdapterOptions\n * @see ./base.ts\n * @see ../cli/commands/setup.ts\n * @see ../../tasks/06-adapters-secondary/02_adapters-secondary_goose-copilot_DONE.md\n */\n\nconst execFile = promisify(execFileCallback);\nconst COPILOT_CODING_TOOL_HINT =\n /apply|create|delete|edit|insert|move|patch|rename|replace|write/iu;\n\nexport interface CopilotCLIAdapterOptions extends AdapterRuntimeOptions {\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n readonly sessionStateDirectory?: string;\n readonly watcherFactory?: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n}\n\ninterface CopilotProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\ninterface CopilotSessionMetadata {\n readonly branch?: string;\n readonly cwd?: string;\n readonly gitRoot?: string;\n readonly model?: string;\n readonly repository?: string;\n readonly sessionId: string;\n}\n\n/**\n * ๐ Copilot's local session-state files are rich enough that hooks become a\n * precision upgrade rather than the only usable signal. The adapter therefore\n * merges both paths instead of trusting just one.\n */\nexport class CopilotCLIAdapter extends BaseAdapter {\n public override readonly displayName = 'Copilot CLI';\n\n public override readonly name = 'copilot-cli' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'hooks',\n 'jsonl-watch',\n 'process-detect',\n ];\n\n private fallbackProcessSessionId: string | null = null;\n\n private readonly observedEventIds = new Set<string>();\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n private readonly sessionMetadata = new Map<string, CopilotSessionMetadata>();\n\n private readonly sessionStateDirectory: string;\n\n private readonly transcriptOffsets = new Map<string, number>();\n\n private readonly transcriptRemainders = new Map<string, string>();\n\n private watcher: FSWatcher | null = null;\n\n private readonly watcherFactory: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n\n public constructor(options: CopilotCLIAdapterOptions) {\n super(options);\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ??\n (async () =>\n await execFile('pgrep', ['-lf', 'copilot']).then(\n (result) => result.stdout,\n ));\n this.sessionStateDirectory =\n options.sessionStateDirectory ??\n join(this.getUserHomeDirectory(), '.copilot', 'session-state');\n this.watcherFactory = options.watcherFactory ?? watch;\n }\n\n public override async start(): Promise<void> {\n if (this.getStatus().running) {\n return;\n }\n\n this.setRunning(true);\n await this.seedTranscriptOffsets();\n\n const transcriptGlob = join(this.sessionStateDirectory, '**', '*.jsonl');\n this.watcher = this.watcherFactory(transcriptGlob, {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n });\n\n this.watcher.on('add', (filePath) => {\n void this.processTranscriptUpdate(filePath, true);\n });\n this.watcher.on('change', (filePath) => {\n void this.processTranscriptUpdate(filePath, false);\n });\n this.watcher.on('error', (error) => {\n logger.warn({ error }, 'Copilot session-state watcher error');\n });\n\n this.startProcessPolling();\n }\n\n public override async stop(): Promise<void> {\n if (this.watcher !== null) {\n await this.watcher.close();\n this.watcher = null;\n }\n\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n this.fallbackProcessSessionId = null;\n this.observedEventIds.clear();\n this.sessionMetadata.clear();\n this.transcriptOffsets.clear();\n this.transcriptRemainders.clear();\n this.setRunning(false);\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload !== null) {\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n project: normalizedPayload.data?.project,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n transcriptPath: normalizedPayload.transcriptPath,\n }),\n });\n return;\n }\n\n if (!isRecord(payload)) {\n logger.warn({ payload }, 'Copilot hook payload must be an object');\n return;\n }\n\n const hookEventName =\n getString(payload, 'hook_event_name') ??\n getString(payload, 'hookEventName');\n\n if (!hookEventName) {\n logger.warn({ payload }, 'Copilot hook payload is missing its event name');\n return;\n }\n\n const sessionMetadata = await this.resolveSessionMetadata(\n this.resolveRawSessionId(payload) ?? 'copilot-hook-session',\n );\n const sessionId = resolveSessionId({\n cwd: getString(payload, 'cwd') ?? sessionMetadata.cwd,\n project: sessionMetadata.repository,\n projectPath: sessionMetadata.gitRoot ?? sessionMetadata.cwd,\n sessionId: this.resolveRawSessionId(payload),\n tool: this.name,\n });\n const context: AdapterPublishContext = {\n cwd: getString(payload, 'cwd') ?? sessionMetadata.cwd,\n hookPayload: payload,\n sessionId,\n source: 'aisnitch://adapters/copilot-cli',\n };\n const toolInput = extractCopilotHookToolInput(payload);\n const toolName =\n getString(payload, 'toolName') ?? getString(payload, 'tool_name');\n const toolResult =\n getRecord(payload.toolResult) ?? getRecord(payload.tool_result);\n const sharedData = {\n activeFile: toolInput?.filePath,\n cwd: context.cwd,\n model: sessionMetadata.model,\n project: sessionMetadata.repository,\n projectPath: sessionMetadata.gitRoot ?? sessionMetadata.cwd,\n raw: payload,\n toolInput,\n toolName,\n } satisfies Omit<EventData, 'state'>;\n\n switch (hookEventName) {\n case 'sessionStart': {\n await this.emitStateChange('session.start', sharedData, context);\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'userPromptSubmitted': {\n await this.emitStateChange(\n 'task.start',\n {\n ...sharedData,\n raw: {\n ...payload,\n prompt: getString(payload, 'prompt'),\n },\n },\n context,\n );\n return;\n }\n case 'preToolUse': {\n const emittedType = isCopilotCodingTool(toolName, toolInput)\n ? 'agent.coding'\n : 'agent.tool_call';\n\n await this.emitStateChange(emittedType, sharedData, context);\n return;\n }\n case 'postToolUse': {\n const emittedType = isCopilotCodingTool(toolName, toolInput)\n ? 'agent.coding'\n : 'agent.tool_call';\n const resultType =\n getString(toolResult, 'resultType') ??\n getString(toolResult, 'result_type');\n const resultText =\n getString(toolResult, 'textResultForLlm') ??\n getString(toolResult, 'text_result_for_llm') ??\n getString(toolResult, 'message');\n\n if (resultType === 'failure' || resultType === 'denied') {\n await this.emitStateChange(\n 'agent.error',\n {\n ...sharedData,\n errorMessage:\n resultText ??\n `Copilot tool ${toolName ?? 'unknown'} finished with ${resultType}.`,\n errorType: inferCopilotErrorType(resultText) ?? 'tool_failure',\n raw: payload,\n },\n context,\n );\n return;\n }\n\n await this.emitStateChange(emittedType, sharedData, context);\n return;\n }\n case 'sessionEnd': {\n await this.emitStateChange('session.end', sharedData, context);\n return;\n }\n case 'errorOccurred': {\n const errorPayload = getRecord(payload.error);\n const errorMessage =\n getString(errorPayload, 'message') ??\n getString(payload, 'message');\n\n await this.emitStateChange(\n 'agent.error',\n {\n ...sharedData,\n errorMessage,\n errorType: inferCopilotErrorType(errorMessage),\n raw: payload,\n },\n context,\n );\n return;\n }\n default:\n logger.debug({ hookEventName }, 'Copilot hook event ignored by adapter');\n }\n }\n\n private async processTranscriptUpdate(\n filePath: string,\n readFromStart: boolean,\n ): Promise<void> {\n let fileContent: Buffer;\n\n try {\n fileContent = await readFile(filePath);\n } catch (error) {\n logger.debug({ error, filePath }, 'Copilot transcript read skipped');\n return;\n }\n\n const knownOffset = this.transcriptOffsets.get(filePath);\n const previousOffset =\n knownOffset ??\n (readFromStart ? 0 : fileContent.byteLength);\n const safeOffset =\n previousOffset > fileContent.byteLength ? 0 : previousOffset;\n const newChunk = fileContent.subarray(safeOffset).toString('utf8');\n const bufferedChunk =\n (safeOffset === 0 ? '' : this.transcriptRemainders.get(filePath) ?? '') +\n newChunk;\n const lines = bufferedChunk.split(/\\r?\\n/u);\n const remainder =\n bufferedChunk.endsWith('\\n') || bufferedChunk.endsWith('\\r')\n ? ''\n : (lines.pop() ?? '');\n\n this.transcriptOffsets.set(filePath, fileContent.byteLength);\n this.transcriptRemainders.set(filePath, remainder);\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n\n if (trimmedLine.length === 0) {\n continue;\n }\n\n await this.processTranscriptLine(trimmedLine, filePath);\n }\n }\n\n private async processTranscriptLine(\n line: string,\n filePath: string,\n ): Promise<void> {\n let parsedLine: unknown;\n\n try {\n parsedLine = JSON.parse(line) as unknown;\n } catch (error) {\n logger.warn({ error, filePath }, 'Copilot transcript line is not valid JSON');\n return;\n }\n\n if (!isRecord(parsedLine)) {\n return;\n }\n\n const rawSessionId = this.resolveRawSessionId(parsedLine) ?? inferSessionIdFromPath(filePath);\n\n if (!rawSessionId) {\n return;\n }\n\n const metadata = await this.resolveSessionMetadata(rawSessionId, parsedLine, filePath);\n const sessionId = resolveSessionId({\n cwd: metadata.cwd,\n project: metadata.repository,\n projectPath: metadata.gitRoot ?? metadata.cwd,\n sessionId: rawSessionId,\n tool: this.name,\n });\n const eventId = getString(parsedLine, 'id');\n const dedupeKey = eventId ? `${sessionId}:${eventId}` : undefined;\n\n if (dedupeKey) {\n if (this.observedEventIds.has(dedupeKey)) {\n return;\n }\n\n if (this.observedEventIds.size >= 4096) {\n this.observedEventIds.clear();\n }\n\n this.observedEventIds.add(dedupeKey);\n }\n\n const context: AdapterPublishContext = {\n cwd: metadata.cwd,\n sessionId,\n source: 'aisnitch://adapters/copilot-cli/session-state',\n transcriptPath: filePath,\n };\n const eventType = getString(parsedLine, 'type');\n const eventData = getRecord(parsedLine.data);\n\n switch (eventType) {\n case 'session.start': {\n await this.emitStateChange(\n 'session.start',\n buildCopilotEventData(metadata, {\n raw: parsedLine,\n }),\n context,\n );\n await this.emitStateChange(\n 'agent.idle',\n buildCopilotEventData(metadata, {\n raw: parsedLine,\n }),\n context,\n );\n return;\n }\n case 'user.message': {\n await this.emitStateChange(\n 'task.start',\n buildCopilotEventData(metadata, {\n raw: {\n ...parsedLine,\n prompt: getString(eventData, 'content'),\n },\n }),\n context,\n );\n return;\n }\n case 'assistant.message': {\n await this.processAssistantMessage(parsedLine, metadata, context);\n return;\n }\n case 'tool.execution_start': {\n const toolName = getString(eventData, 'toolName');\n const toolInput = extractCopilotToolInput(eventData);\n const emittedType = isCopilotCodingTool(toolName, toolInput)\n ? 'agent.coding'\n : 'agent.tool_call';\n\n await this.emitStateChange(\n emittedType,\n buildCopilotEventData(metadata, {\n activeFile: toolInput?.filePath,\n raw: parsedLine,\n toolInput,\n toolName,\n }),\n context,\n );\n return;\n }\n case 'tool.execution_complete': {\n if (getBoolean(eventData, 'success') !== false) {\n return;\n }\n\n await this.emitStateChange(\n 'agent.error',\n buildCopilotEventData(metadata, {\n errorMessage:\n extractLooseString(getRecord(eventData?.result), ['content']) ??\n 'Tool execution failed',\n errorType: 'tool_failure',\n raw: parsedLine,\n }),\n context,\n );\n return;\n }\n case 'session.task_complete': {\n await this.emitStateChange(\n 'task.complete',\n buildCopilotEventData(metadata, {\n raw: parsedLine,\n }),\n context,\n );\n return;\n }\n case 'session.error': {\n const errorMessage = getString(eventData, 'message');\n\n await this.emitStateChange(\n 'agent.error',\n buildCopilotEventData(metadata, {\n errorMessage,\n errorType: inferCopilotErrorType(errorMessage),\n raw: parsedLine,\n }),\n context,\n );\n return;\n }\n case 'session.warning': {\n await this.emitStateChange(\n 'agent.asking_user',\n buildCopilotEventData(metadata, {\n errorMessage: getString(eventData, 'message'),\n raw: parsedLine,\n }),\n context,\n );\n return;\n }\n case 'abort': {\n await this.emitStateChange(\n 'agent.error',\n buildCopilotEventData(metadata, {\n errorMessage: 'Session aborted',\n errorType: 'api_error',\n raw: parsedLine,\n }),\n context,\n );\n return;\n }\n case 'session.model_change': {\n const model = getString(eventData, 'newModel');\n\n this.sessionMetadata.set(rawSessionId, {\n ...metadata,\n model: model ?? metadata.model,\n });\n return;\n }\n default:\n return;\n }\n }\n\n private async processAssistantMessage(\n payload: Record<string, unknown>,\n metadata: CopilotSessionMetadata,\n context: AdapterPublishContext,\n ): Promise<void> {\n const data = getRecord(payload.data);\n\n if (!data) {\n return;\n }\n\n const reasoningText = getString(data, 'reasoningText');\n const content = getString(data, 'content');\n\n if (reasoningText) {\n await this.emitStateChange(\n 'agent.thinking',\n buildCopilotEventData(metadata, {\n raw: {\n message: {\n content: [\n {\n thinking: reasoningText,\n type: 'thinking',\n },\n ],\n role: 'assistant',\n },\n source: payload,\n },\n }),\n context,\n );\n }\n\n if (content) {\n await this.emitStateChange(\n 'agent.streaming',\n buildCopilotEventData(metadata, {\n raw: {\n content,\n message: {\n content: [\n {\n text: content,\n type: 'text',\n },\n ],\n role: 'assistant',\n },\n source: payload,\n },\n }),\n context,\n );\n }\n }\n\n private async seedTranscriptOffsets(): Promise<void> {\n const files = await collectFilesRecursively(\n this.sessionStateDirectory,\n '.jsonl',\n );\n\n await Promise.all(\n files.map(async (filePath) => {\n try {\n const fileStats = await stat(filePath);\n\n this.transcriptOffsets.set(filePath, fileStats.size);\n } catch {\n // Ignore files that disappear between discovery and stat.\n }\n }),\n );\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.processPoller = setInterval(() => {\n void this.pollCopilotProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n\n void this.pollCopilotProcesses();\n }\n\n private async pollCopilotProcesses(): Promise<void> {\n const processes = await listProcesses(this.processListCommand);\n\n if (processes.length > 0 && this.getStatus().activeSessions === 0) {\n const processInfo = processes[0];\n\n if (!processInfo) {\n return;\n }\n\n const sessionId = `copilot-cli-process-${processInfo.pid}`;\n\n this.fallbackProcessSessionId = sessionId;\n await this.emitStateChange(\n 'session.start',\n {\n raw: {\n process: processInfo,\n source: 'process-detect',\n },\n },\n {\n pid: processInfo.pid,\n sessionId,\n source: 'aisnitch://adapters/copilot-cli/process-detect',\n },\n );\n return;\n }\n\n if (processes.length === 0 && this.fallbackProcessSessionId !== null) {\n const sessionId = this.fallbackProcessSessionId;\n\n this.fallbackProcessSessionId = null;\n await this.emitStateChange(\n 'session.end',\n {\n raw: {\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n sessionId,\n source: 'aisnitch://adapters/copilot-cli/process-detect',\n },\n );\n }\n }\n\n private resolveRawSessionId(payload: Record<string, unknown>): string | undefined {\n return (\n getString(payload, 'sessionId') ??\n getString(payload, 'session_id') ??\n getString(getRecord(payload.data), 'sessionId') ??\n getString(getRecord(payload.data), 'session_id')\n );\n }\n\n private async resolveSessionMetadata(\n rawSessionId: string,\n payload?: Record<string, unknown>,\n filePath?: string,\n ): Promise<CopilotSessionMetadata> {\n const cachedMetadata = this.sessionMetadata.get(rawSessionId);\n const payloadMetadata = extractCopilotSessionMetadata(payload);\n\n if (payloadMetadata.cwd) {\n const mergedMetadata = {\n ...cachedMetadata,\n ...payloadMetadata,\n sessionId: rawSessionId,\n } satisfies CopilotSessionMetadata;\n\n this.sessionMetadata.set(rawSessionId, mergedMetadata);\n return mergedMetadata;\n }\n\n const fileMetadata = await readCopilotWorkspaceMetadata(\n this.sessionStateDirectory,\n rawSessionId,\n filePath,\n );\n const mergedMetadata = {\n ...cachedMetadata,\n ...fileMetadata,\n sessionId: rawSessionId,\n } satisfies CopilotSessionMetadata;\n\n this.sessionMetadata.set(rawSessionId, mergedMetadata);\n return mergedMetadata;\n }\n}\n\nfunction buildCopilotEventData(\n metadata: CopilotSessionMetadata,\n overrides: Partial<Omit<EventData, 'state'>> = {},\n): Omit<EventData, 'state'> {\n return {\n cwd: overrides.cwd ?? metadata.cwd,\n model: overrides.model ?? metadata.model,\n project: overrides.project ?? metadata.repository,\n projectPath: overrides.projectPath ?? metadata.gitRoot ?? metadata.cwd,\n raw: overrides.raw,\n ...overrides,\n };\n}\n\nfunction extractCopilotHookToolInput(\n payload: Record<string, unknown>,\n): ToolInput | undefined {\n const toolArgsValue =\n getString(payload, 'toolArgs') ?? getString(payload, 'tool_args');\n const directArguments =\n getRecord(payload.arguments) ?? getRecord(payload.toolArgs);\n const parsedArguments =\n directArguments ?? parseJsonRecord(toolArgsValue);\n\n return extractCopilotToolInput(parsedArguments);\n}\n\nfunction extractCopilotToolInput(\n payload: Record<string, unknown> | undefined,\n): ToolInput | undefined {\n if (!payload) {\n return undefined;\n }\n\n const filePath = extractFirstString(payload, [\n 'file',\n 'file_path',\n 'filePath',\n 'path',\n 'target',\n 'target_path',\n 'targetPath',\n ]);\n const command = extractFirstString(payload, [\n 'cmd',\n 'command',\n 'script',\n ]);\n\n if (!filePath && !command) {\n return undefined;\n }\n\n return {\n command,\n filePath,\n };\n}\n\nfunction isCopilotCodingTool(\n toolName: string | undefined,\n toolInput: ToolInput | undefined,\n): boolean {\n if (toolName && COPILOT_CODING_TOOL_HINT.test(toolName)) {\n return true;\n }\n\n const filePath = toolInput?.filePath;\n\n if (!filePath) {\n return false;\n }\n\n return !/glob|grep|list|read|search|view/iu.test(toolName ?? '');\n}\n\nfunction inferCopilotErrorType(\n errorMessage: string | undefined,\n): ErrorType | undefined {\n if (!errorMessage) {\n return undefined;\n }\n\n if (/quota|credit|rate limit|too many requests/iu.test(errorMessage)) {\n return 'rate_limit';\n }\n\n if (/context|token limit|too long/iu.test(errorMessage)) {\n return 'context_overflow';\n }\n\n if (/tool/iu.test(errorMessage)) {\n return 'tool_failure';\n }\n\n return 'api_error';\n}\n\nfunction extractCopilotSessionMetadata(\n payload: Record<string, unknown> | undefined,\n): Partial<CopilotSessionMetadata> {\n const data = getRecord(payload?.data);\n const context = getRecord(data?.context);\n\n return {\n branch:\n getString(context, 'branch') ??\n getString(payload, 'branch'),\n cwd:\n getString(context, 'cwd') ??\n getString(payload, 'cwd'),\n gitRoot:\n getString(context, 'gitRoot') ??\n getString(payload, 'gitRoot'),\n repository:\n getString(context, 'repository') ??\n getString(payload, 'repository'),\n };\n}\n\nasync function readCopilotWorkspaceMetadata(\n sessionStateDirectory: string,\n rawSessionId: string,\n filePath?: string,\n): Promise<Partial<CopilotSessionMetadata>> {\n const sessionDirectory = inferSessionDirectory(\n sessionStateDirectory,\n rawSessionId,\n filePath,\n );\n const workspacePath = join(sessionDirectory, 'workspace.yaml');\n\n try {\n const fileContent = await readFile(workspacePath, 'utf8');\n\n return parseCopilotWorkspaceYaml(fileContent);\n } catch (error) {\n if (isErrnoException(error) && error.code === 'ENOENT') {\n return {};\n }\n\n logger.debug({ error, rawSessionId }, 'Copilot workspace metadata read skipped');\n return {};\n }\n}\n\nfunction parseCopilotWorkspaceYaml(\n fileContent: string,\n): Partial<CopilotSessionMetadata> {\n const metadata: {\n branch?: string;\n cwd?: string;\n gitRoot?: string;\n repository?: string;\n } = {};\n\n for (const line of fileContent.split(/\\r?\\n/u)) {\n const match = line.match(/^([a-z_]+):\\s*(.+)$/u);\n\n if (!match) {\n continue;\n }\n\n const key = match[1];\n const value = match[2]?.trim();\n\n if (!value) {\n continue;\n }\n\n switch (key) {\n case 'branch':\n metadata.branch = value;\n break;\n case 'cwd':\n metadata.cwd = value;\n break;\n case 'git_root':\n metadata.gitRoot = value;\n break;\n case 'repository':\n metadata.repository = value;\n break;\n default:\n break;\n }\n }\n\n return metadata;\n}\n\nfunction inferSessionDirectory(\n sessionStateDirectory: string,\n rawSessionId: string,\n filePath?: string,\n): string {\n if (filePath && basename(filePath) === 'events.jsonl') {\n return dirname(filePath);\n }\n\n return join(sessionStateDirectory, rawSessionId);\n}\n\nasync function collectFilesRecursively(\n directoryPath: string,\n extension: string,\n): Promise<string[]> {\n try {\n const entries = await readdir(directoryPath, {\n withFileTypes: true,\n });\n const nestedResults = await Promise.all(\n entries.map(async (entry) => {\n const entryPath = join(directoryPath, entry.name);\n\n if (entry.isDirectory()) {\n return await collectFilesRecursively(entryPath, extension);\n }\n\n return entry.name.endsWith(extension) ? [entryPath] : [];\n }),\n );\n\n return nestedResults.flat();\n } catch (error) {\n if (isErrnoException(error) && error.code === 'ENOENT') {\n return [];\n }\n\n throw error;\n }\n}\n\nasync function listProcesses(\n processListCommand: () => Promise<string>,\n): Promise<CopilotProcessInfo[]> {\n try {\n const commandOutput = await processListCommand();\n\n return commandOutput\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n const [pidPart, ...commandParts] = line.split(/\\s+/u);\n const pid = pidPart ? Number.parseInt(pidPart, 10) : Number.NaN;\n\n return {\n command: commandParts.join(' '),\n pid,\n } satisfies CopilotProcessInfo;\n })\n .filter((processInfo) => Number.isInteger(processInfo.pid));\n } catch (error) {\n logger.debug({ error }, 'Copilot process listing skipped');\n return [];\n }\n}\n\nfunction inferSessionIdFromPath(filePath: string): string | undefined {\n const fileName = basename(filePath);\n\n if (fileName === 'events.jsonl') {\n return basename(dirname(filePath));\n }\n\n return fileName.endsWith('.jsonl') ? basename(fileName, '.jsonl') : undefined;\n}\n\nfunction parseJsonRecord(\n value: string | undefined,\n): Record<string, unknown> | undefined {\n if (!value) {\n return undefined;\n }\n\n try {\n const parsedValue = JSON.parse(value) as unknown;\n\n return getRecord(parsedValue);\n } catch {\n return undefined;\n }\n}\n\nfunction extractLooseString(\n payload: Record<string, unknown> | undefined,\n keys: readonly string[],\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n for (const key of keys) {\n const directValue = getString(payload, key);\n\n if (directValue) {\n return directValue;\n }\n\n const nestedValue = getString(getRecord(payload[key]), 'content');\n\n if (nestedValue) {\n return nestedValue;\n }\n }\n\n return undefined;\n}\n\nfunction extractFirstString(\n payload: Record<string, unknown> | undefined,\n keys: readonly string[],\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n for (const key of keys) {\n const directValue = getString(payload, key);\n\n if (directValue) {\n return directValue;\n }\n }\n\n return undefined;\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction getBoolean(\n payload: Record<string, unknown> | undefined,\n key: string,\n): boolean | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction isErrnoException(\n error: unknown,\n): error is NodeJS.ErrnoException {\n return error instanceof Error && 'code' in error;\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { readFile, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { watch, type FSWatcher } from 'chokidar';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type { EventData } from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/codex.ts\n * @description Codex adapter based on passive `codex-tui.log` parsing plus process fallback detection.\n * @functions\n * โ none\n * @exports CodexAdapter, CodexAdapterOptions\n * @see ./base.ts\n * @see ../../tasks/06-adapters-secondary/01_adapters-secondary_gemini-codex.md\n */\n\nconst execFile = promisify(execFileCallback);\n\n/**\n * Codex documents `codex exec --json` for machine-readable automation, but the\n * passive observer path for AISnitch today is still the local TUI log file.\n */\nexport interface CodexAdapterOptions extends AdapterRuntimeOptions {\n readonly logPath?: string;\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n readonly watcherFactory?: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n}\n\ninterface CodexProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\n/**\n * ๐ The Codex log watcher deliberately parses only high-signal lines:\n * command executions, patch targets, model selection, and shutdown markers.\n * Anything more ambitious would be fake precision over an unstable text log.\n */\nexport class CodexAdapter extends BaseAdapter {\n public override readonly displayName = 'Codex';\n\n public override readonly name = 'codex' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'log-watch',\n 'process-detect',\n ];\n\n private fallbackProcessSessionId: string | null = null;\n\n private lastKnownCwd: string | undefined;\n\n private lastKnownModel: string | undefined;\n\n private readonly logPath: string;\n\n private logOffset = 0;\n\n private logRemainder = '';\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n private watcher: FSWatcher | null = null;\n\n private readonly watcherFactory: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n\n public constructor(options: CodexAdapterOptions) {\n super(options);\n this.logPath =\n options.logPath ??\n join(this.getUserHomeDirectory(), '.codex', 'log', 'codex-tui.log');\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ??\n (async () =>\n await execFile('pgrep', ['-lf', 'codex']).then((result) => result.stdout));\n this.watcherFactory = options.watcherFactory ?? watch;\n }\n\n public override async start(): Promise<void> {\n if (this.getStatus().running) {\n return;\n }\n\n this.setRunning(true);\n await this.seedLogOffset();\n\n this.watcher = this.watcherFactory(this.logPath, {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n });\n\n this.watcher.on('add', (filePath) => {\n void this.processLogUpdate(filePath, true);\n });\n this.watcher.on('change', (filePath) => {\n void this.processLogUpdate(filePath, false);\n });\n this.watcher.on('error', (error) => {\n logger.warn({ error }, 'Codex log watcher error');\n });\n\n this.startProcessPolling();\n }\n\n public override async stop(): Promise<void> {\n if (this.watcher !== null) {\n await this.watcher.close();\n this.watcher = null;\n }\n\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n this.fallbackProcessSessionId = null;\n this.lastKnownCwd = undefined;\n this.lastKnownModel = undefined;\n this.logOffset = 0;\n this.logRemainder = '';\n this.setRunning(false);\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload === null) {\n logger.debug({ payload }, 'Codex ignores non-normalized hook payloads');\n return;\n }\n\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n transcriptPath: normalizedPayload.transcriptPath,\n }),\n });\n }\n\n private async processLogUpdate(\n filePath: string,\n readFromStart: boolean,\n ): Promise<void> {\n let fileContent: Buffer;\n\n try {\n fileContent = await readFile(filePath);\n } catch (error) {\n logger.debug({ error, filePath }, 'Codex log read skipped');\n return;\n }\n\n const previousOffset = readFromStart ? 0 : this.logOffset;\n const safeOffset =\n previousOffset > fileContent.byteLength ? 0 : previousOffset;\n const newChunk = fileContent.subarray(safeOffset).toString('utf8');\n const bufferedChunk =\n (safeOffset === 0 ? '' : this.logRemainder) +\n newChunk;\n const lines = bufferedChunk.split(/\\r?\\n/u);\n const remainder =\n bufferedChunk.endsWith('\\n') || bufferedChunk.endsWith('\\r')\n ? ''\n : (lines.pop() ?? '');\n\n this.logOffset = fileContent.byteLength;\n this.logRemainder = remainder;\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n\n if (trimmedLine.length === 0) {\n continue;\n }\n\n await this.processLogLine(trimmedLine);\n }\n }\n\n private async processLogLine(line: string): Promise<void> {\n const modelMatch = line.match(/model:\\s*([^,]+),\\s*.*effort:\\s*([^\\s]+)$/u);\n\n if (modelMatch) {\n const parsedModel = modelMatch[1]?.trim();\n\n if (parsedModel) {\n this.lastKnownModel = parsedModel;\n\n const sessionId = this.resolveLogSessionId(this.lastKnownCwd);\n const context = this.createLogContext(sessionId, this.lastKnownCwd, line);\n\n await this.ensureObservedSession(\n sessionId,\n {\n cwd: this.lastKnownCwd,\n model: this.lastKnownModel,\n raw: {\n logLine: line,\n },\n },\n context,\n );\n }\n\n return;\n }\n\n const parsedCommand = parseCodexCommandLine(line);\n\n if (parsedCommand !== null) {\n this.lastKnownCwd = parsedCommand.workdir ?? this.lastKnownCwd;\n\n const sessionId = this.resolveLogSessionId(parsedCommand.workdir);\n const context = this.createLogContext(sessionId, parsedCommand.workdir, line);\n\n await this.ensureObservedSession(\n sessionId,\n {\n cwd: parsedCommand.workdir,\n model: this.lastKnownModel,\n raw: {\n command: parsedCommand,\n logLine: line,\n },\n },\n context,\n );\n await this.emitStateChange(\n 'agent.tool_call',\n {\n cwd: parsedCommand.workdir,\n model: this.lastKnownModel,\n raw: {\n command: parsedCommand,\n logLine: line,\n },\n toolInput: {\n command: parsedCommand.command,\n },\n toolName: 'shell',\n },\n context,\n );\n return;\n }\n\n const patchFileMatch = line.match(/^\\*\\*\\*\\s+(?:Update|Add|Delete)\\s+File:\\s+(.+)$/u);\n\n if (patchFileMatch?.[1]) {\n const activeFile = patchFileMatch[1].trim();\n const sessionId = this.resolveLogSessionId(this.lastKnownCwd);\n const context = this.createLogContext(sessionId, this.lastKnownCwd, line);\n\n await this.ensureObservedSession(\n sessionId,\n {\n activeFile,\n cwd: this.lastKnownCwd,\n model: this.lastKnownModel,\n raw: {\n logLine: line,\n },\n },\n context,\n );\n await this.emitStateChange(\n 'agent.coding',\n {\n activeFile,\n cwd: this.lastKnownCwd,\n model: this.lastKnownModel,\n raw: {\n logLine: line,\n },\n },\n context,\n );\n return;\n }\n\n if (/Shutting down Codex/iu.test(line) && this.currentSessionId !== null) {\n await this.emitStateChange(\n 'session.end',\n {\n cwd: this.lastKnownCwd,\n model: this.lastKnownModel,\n raw: {\n logLine: line,\n },\n },\n this.createLogContext(this.currentSessionId, this.lastKnownCwd, line),\n );\n }\n }\n\n private createLogContext(\n sessionId: string,\n cwd: string | undefined,\n line: string,\n ): AdapterPublishContext {\n return {\n cwd,\n hookPayload: {\n logLine: line,\n },\n sessionId,\n source: 'aisnitch://adapters/codex/log-watch',\n };\n }\n\n private resolveLogSessionId(cwd: string | undefined): string {\n return resolveSessionId({\n cwd,\n projectPath: cwd,\n sessionId: `${this.name}:session`,\n tool: this.name,\n });\n }\n\n private async ensureObservedSession(\n sessionId: string,\n data: Omit<EventData, 'state'>,\n context: AdapterPublishContext,\n ): Promise<void> {\n if (this.currentSessionId === sessionId) {\n return;\n }\n\n await this.emitStateChange('session.start', data, context);\n await this.emitStateChange('agent.idle', data, context);\n }\n\n private async seedLogOffset(): Promise<void> {\n try {\n const fileStats = await stat(this.logPath);\n\n this.logOffset = fileStats.size;\n } catch {\n this.logOffset = 0;\n }\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.processPoller = setInterval(() => {\n void this.pollCodexProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n\n void this.pollCodexProcesses();\n }\n\n private async pollCodexProcesses(): Promise<void> {\n const processes = await listProcesses(this.processListCommand);\n\n if (processes.length > 0 && this.getStatus().activeSessions === 0) {\n const processInfo = processes[0];\n\n if (!processInfo) {\n return;\n }\n\n const sessionId = `codex-process-${processInfo.pid}`;\n\n this.fallbackProcessSessionId = sessionId;\n await this.emitStateChange(\n 'session.start',\n {\n raw: {\n process: processInfo,\n source: 'process-detect',\n },\n },\n {\n pid: processInfo.pid,\n sessionId,\n source: 'aisnitch://adapters/codex/process-detect',\n },\n );\n return;\n }\n\n if (processes.length === 0 && this.fallbackProcessSessionId !== null) {\n const sessionId = this.fallbackProcessSessionId;\n\n this.fallbackProcessSessionId = null;\n await this.emitStateChange(\n 'session.end',\n {\n raw: {\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n sessionId,\n source: 'aisnitch://adapters/codex/process-detect',\n },\n );\n }\n }\n}\n\ninterface ParsedCodexCommand {\n readonly command: string;\n readonly workdir?: string;\n}\n\nfunction parseCodexCommandLine(line: string): ParsedCodexCommand | null {\n const jsonStart = line.indexOf('{');\n const jsonEnd = line.lastIndexOf('}');\n\n if (jsonStart < 0 || jsonEnd <= jsonStart) {\n return null;\n }\n\n try {\n const parsedJson = JSON.parse(line.slice(jsonStart, jsonEnd + 1)) as unknown;\n\n if (!isRecord(parsedJson)) {\n return null;\n }\n\n const command = getString(parsedJson, 'command');\n\n if (!command) {\n return null;\n }\n\n return {\n command,\n workdir: getString(parsedJson, 'workdir'),\n };\n } catch {\n return null;\n }\n}\n\nasync function listProcesses(\n listCommand: () => Promise<string>,\n): Promise<CodexProcessInfo[]> {\n if (process.platform === 'win32') {\n return [];\n }\n\n try {\n const stdout = await listCommand();\n\n return stdout\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map(parseProcessLine)\n .filter((processInfo): processInfo is CodexProcessInfo => processInfo !== null);\n } catch (error) {\n const errorCode = isErrnoException(error) ? String(error.code) : '';\n\n if (isErrnoException(error) && (errorCode === 'ENOENT' || errorCode === '1')) {\n return [];\n }\n\n logger.debug({ error }, 'Codex process detection failed');\n return [];\n }\n}\n\nfunction parseProcessLine(line: string): CodexProcessInfo | null {\n const match = line.match(/^(\\d+)\\s+(.+)$/u);\n\n if (!match) {\n return null;\n }\n\n const pidText = match[1];\n const command = match[2];\n\n if (!pidText || !command) {\n return null;\n }\n\n return {\n command,\n pid: Number.parseInt(pidText, 10),\n };\n}\n\nfunction isErrnoException(\n error: unknown,\n): error is NodeJS.ErrnoException & { code?: string | number } {\n return error instanceof Error && 'code' in error;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined;\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { watch, type FSWatcher } from 'chokidar';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type {\n ErrorType,\n EventData,\n ToolInput,\n} from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/gemini-cli.ts\n * @description Gemini CLI adapter covering command hooks, best-effort local `logs.json` watching, and process fallback detection.\n * @functions\n * โ none\n * @exports GeminiCLIAdapter, GeminiCLIAdapterOptions\n * @see ./base.ts\n * @see ../cli/commands/setup.ts\n * @see ../../tasks/06-adapters-secondary/01_adapters-secondary_gemini-codex.md\n */\n\nconst execFile = promisify(execFileCallback);\n\nconst GEMINI_CODING_TOOLS = new Set([\n 'edit',\n 'replace',\n 'write',\n 'write_file',\n]);\n\n/**\n * Gemini CLI now documents synchronous lifecycle hooks in settings.json. The\n * passive fallback here reads the per-session `logs.json` files under\n * `~/.gemini/tmp/`, which appear to contain prompt history even when hooks\n * were never installed.\n */\nexport interface GeminiCLIAdapterOptions extends AdapterRuntimeOptions {\n readonly logsDirectory?: string;\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n readonly watcherFactory?: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n}\n\ninterface GeminiProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\n/**\n * ๐ Gemini gets the same three-layer treatment as Claude/OpenCode, but the\n * file fallback is intentionally narrower: it only emits what local logs can\n * prove, instead of pretending those logs expose the full agent loop.\n */\nexport class GeminiCLIAdapter extends BaseAdapter {\n public override readonly displayName = 'Gemini CLI';\n\n public override readonly name = 'gemini-cli' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'hooks',\n 'log-watch',\n 'process-detect',\n ];\n\n private fallbackProcessSessionId: string | null = null;\n\n private readonly logsDirectory: string;\n\n private readonly observedLogMessageIds = new Map<string, Set<string>>();\n\n private readonly projectRootCache = new Map<string, string | undefined>();\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n private watcher: FSWatcher | null = null;\n\n private readonly watcherFactory: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n\n public constructor(options: GeminiCLIAdapterOptions) {\n super(options);\n this.logsDirectory =\n options.logsDirectory ??\n join(this.getUserHomeDirectory(), '.gemini', 'tmp');\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ??\n (async () =>\n await execFile('pgrep', ['-lf', 'gemini']).then((result) => result.stdout));\n this.watcherFactory = options.watcherFactory ?? watch;\n }\n\n public override async start(): Promise<void> {\n if (this.getStatus().running) {\n return;\n }\n\n this.setRunning(true);\n await this.seedObservedLogState();\n\n const logsGlob = join(this.logsDirectory, '**', 'logs.json');\n this.watcher = this.watcherFactory(logsGlob, {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n });\n\n this.watcher.on('add', (filePath) => {\n void this.processLogsFile(filePath);\n });\n this.watcher.on('change', (filePath) => {\n void this.processLogsFile(filePath);\n });\n this.watcher.on('error', (error) => {\n logger.warn({ error }, 'Gemini logs watcher error');\n });\n\n this.startProcessPolling();\n }\n\n public override async stop(): Promise<void> {\n if (this.watcher !== null) {\n await this.watcher.close();\n this.watcher = null;\n }\n\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n this.fallbackProcessSessionId = null;\n this.observedLogMessageIds.clear();\n this.projectRootCache.clear();\n this.setRunning(false);\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload !== null) {\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n transcriptPath: normalizedPayload.transcriptPath,\n }),\n });\n return;\n }\n\n if (!isRecord(payload)) {\n logger.warn({ payload }, 'Gemini hook payload must be an object');\n return;\n }\n\n const hookEventName =\n getString(payload, 'hook_event_name') ??\n getString(payload, 'hookEventName');\n\n if (!hookEventName) {\n logger.warn({ payload }, 'Gemini hook payload is missing its event name');\n return;\n }\n\n const cwd = getString(payload, 'cwd');\n const transcriptPath =\n getString(payload, 'transcript_path') ??\n getString(payload, 'transcriptPath');\n const sessionId = resolveSessionId({\n activeFile: extractGeminiActiveFile(payload),\n cwd,\n projectPath: cwd,\n sessionId:\n getString(payload, 'session_id') ??\n getString(payload, 'sessionId'),\n tool: this.name,\n transcriptPath,\n });\n const context: AdapterPublishContext = {\n cwd,\n hookPayload: payload,\n pid: getNumber(payload, 'pid'),\n sessionId,\n source: 'aisnitch://adapters/gemini-cli',\n transcriptPath,\n };\n const sharedData = {\n activeFile: extractGeminiActiveFile(payload),\n cwd,\n errorMessage: extractGeminiErrorMessage(payload),\n errorType: extractGeminiErrorType(payload),\n model: extractGeminiModel(payload),\n projectPath: cwd,\n raw: payload,\n tokensUsed: extractGeminiTokens(payload),\n toolInput: extractGeminiToolInput(payload),\n toolName: extractGeminiToolName(payload),\n } satisfies Omit<EventData, 'state'>;\n\n switch (hookEventName) {\n case 'SessionStart': {\n this.fallbackProcessSessionId = null;\n await this.emitStateChange('session.start', sharedData, context);\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'SessionEnd': {\n await this.emitStateChange('session.end', sharedData, context);\n return;\n }\n case 'BeforeAgent': {\n await this.emitStateChange('task.start', sharedData, context);\n return;\n }\n case 'AfterAgent': {\n if (sharedData.errorMessage) {\n await this.emitStateChange('agent.error', sharedData, context);\n return;\n }\n\n await this.emitStateChange('task.complete', sharedData, context);\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'BeforeTool': {\n await this.emitStateChange('agent.tool_call', sharedData, context);\n return;\n }\n case 'AfterTool': {\n if (sharedData.errorMessage) {\n await this.emitStateChange('agent.error', sharedData, context);\n return;\n }\n\n const emittedType = isGeminiCodingTool(sharedData.toolName)\n ? 'agent.coding'\n : 'agent.tool_call';\n await this.emitStateChange(emittedType, sharedData, context);\n return;\n }\n case 'AfterModel': {\n await this.emitStateChange('agent.streaming', sharedData, context);\n return;\n }\n case 'Notification': {\n await this.emitStateChange('agent.asking_user', sharedData, context);\n return;\n }\n case 'PreCompress': {\n await this.emitStateChange('agent.compact', sharedData, context);\n return;\n }\n default: {\n logger.debug({ hookEventName }, 'Gemini hook event ignored by adapter');\n }\n }\n }\n\n private async processLogsFile(filePath: string): Promise<void> {\n let fileContent: string;\n\n try {\n fileContent = await readFile(filePath, 'utf8');\n } catch (error) {\n logger.debug({ error, filePath }, 'Gemini logs read skipped');\n return;\n }\n\n let parsedContent: unknown;\n\n try {\n parsedContent = JSON.parse(fileContent) as unknown;\n } catch (error) {\n logger.warn({ error, filePath }, 'Gemini logs file is not valid JSON');\n return;\n }\n\n if (!Array.isArray(parsedContent)) {\n logger.warn({ filePath }, 'Gemini logs file does not contain an array');\n return;\n }\n\n const knownMessageIds = this.observedLogMessageIds.get(filePath) ?? new Set<string>();\n this.observedLogMessageIds.set(filePath, knownMessageIds);\n\n for (const entry of parsedContent) {\n if (!isRecord(entry)) {\n continue;\n }\n\n const messageId =\n getString(entry, 'messageId') ??\n getString(entry, 'message_id');\n\n if (!messageId || knownMessageIds.has(messageId)) {\n continue;\n }\n\n knownMessageIds.add(messageId);\n await this.processLogEntry(entry, filePath);\n }\n }\n\n private async processLogEntry(\n entry: Record<string, unknown>,\n filePath: string,\n ): Promise<void> {\n const messageType = getString(entry, 'type');\n const sessionId = resolveSessionId({\n cwd: await this.readProjectRoot(filePath),\n projectPath: await this.readProjectRoot(filePath),\n sessionId: getString(entry, 'sessionId') ?? `${this.name}:session`,\n tool: this.name,\n });\n const projectPath = await this.readProjectRoot(filePath);\n const context: AdapterPublishContext = {\n cwd: projectPath,\n hookPayload: entry,\n sessionId,\n source: 'aisnitch://adapters/gemini-cli/log-watch',\n };\n const sharedData = {\n cwd: projectPath,\n projectPath,\n raw: entry,\n } satisfies Omit<EventData, 'state'>;\n\n await this.ensureObservedSession(sessionId, sharedData, context);\n\n switch (messageType) {\n case 'user': {\n await this.emitStateChange('task.start', sharedData, context);\n return;\n }\n case 'model':\n case 'assistant': {\n await this.emitStateChange('agent.streaming', sharedData, context);\n return;\n }\n case 'thinking': {\n await this.emitStateChange('agent.thinking', sharedData, context);\n return;\n }\n default: {\n logger.debug({ filePath, messageType }, 'Gemini log entry ignored by adapter');\n }\n }\n }\n\n private async ensureObservedSession(\n sessionId: string,\n data: Omit<EventData, 'state'>,\n context: AdapterPublishContext,\n ): Promise<void> {\n if (this.currentSessionId === sessionId) {\n return;\n }\n\n await this.emitStateChange('session.start', data, context);\n await this.emitStateChange('agent.idle', data, context);\n }\n\n private async readProjectRoot(filePath: string): Promise<string | undefined> {\n if (this.projectRootCache.has(filePath)) {\n return this.projectRootCache.get(filePath);\n }\n\n const rootPath = join(dirname(filePath), '.project_root');\n\n try {\n const projectRoot = (await readFile(rootPath, 'utf8')).trim();\n const normalizedRoot = projectRoot.length > 0 ? projectRoot : undefined;\n\n this.projectRootCache.set(filePath, normalizedRoot);\n return normalizedRoot;\n } catch {\n this.projectRootCache.set(filePath, undefined);\n return undefined;\n }\n }\n\n private async seedObservedLogState(): Promise<void> {\n const files = await collectFilesRecursively(this.logsDirectory, 'logs.json');\n\n await Promise.all(\n files.map(async (filePath) => {\n try {\n const fileStats = await stat(filePath);\n\n if (!fileStats.isFile()) {\n return;\n }\n\n const fileContent = await readFile(filePath, 'utf8');\n const parsedContent = JSON.parse(fileContent) as unknown;\n const messageIds = new Set<string>();\n\n if (Array.isArray(parsedContent)) {\n for (const entry of parsedContent) {\n if (!isRecord(entry)) {\n continue;\n }\n\n const messageId =\n getString(entry, 'messageId') ??\n getString(entry, 'message_id');\n\n if (messageId) {\n messageIds.add(messageId);\n }\n }\n }\n\n this.observedLogMessageIds.set(filePath, messageIds);\n } catch {\n // Ignore files that disappear or fail while seeding.\n }\n }),\n );\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.processPoller = setInterval(() => {\n void this.pollGeminiProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n\n void this.pollGeminiProcesses();\n }\n\n private async pollGeminiProcesses(): Promise<void> {\n const processes = await listProcesses(this.processListCommand);\n\n if (processes.length > 0 && this.getStatus().activeSessions === 0) {\n const processInfo = processes[0];\n\n if (!processInfo) {\n return;\n }\n\n const sessionId = `gemini-cli-process-${processInfo.pid}`;\n\n this.fallbackProcessSessionId = sessionId;\n await this.emitStateChange(\n 'session.start',\n {\n raw: {\n process: processInfo,\n source: 'process-detect',\n },\n },\n {\n pid: processInfo.pid,\n sessionId,\n source: 'aisnitch://adapters/gemini-cli/process-detect',\n },\n );\n return;\n }\n\n if (processes.length === 0 && this.fallbackProcessSessionId !== null) {\n const sessionId = this.fallbackProcessSessionId;\n\n this.fallbackProcessSessionId = null;\n await this.emitStateChange(\n 'session.end',\n {\n raw: {\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n sessionId,\n source: 'aisnitch://adapters/gemini-cli/process-detect',\n },\n );\n }\n }\n}\n\nasync function collectFilesRecursively(\n directoryPath: string,\n fileName: string,\n): Promise<string[]> {\n try {\n const entries = await readdir(directoryPath, {\n withFileTypes: true,\n });\n const nestedResults = await Promise.all(\n entries.map(async (entry) => {\n const entryPath = join(directoryPath, entry.name);\n\n if (entry.isDirectory()) {\n return await collectFilesRecursively(entryPath, fileName);\n }\n\n return entry.name === fileName ? [entryPath] : [];\n }),\n );\n\n return nestedResults.flat();\n } catch (error) {\n if (isErrnoException(error) && error.code === 'ENOENT') {\n return [];\n }\n\n throw error;\n }\n}\n\nfunction extractGeminiToolName(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'tool_name') ??\n getString(payload, 'toolName')\n );\n}\n\nfunction extractGeminiToolInput(\n payload: Record<string, unknown>,\n): ToolInput | undefined {\n const toolInput = getRecord(payload.tool_input) ?? getRecord(payload.toolInput);\n\n if (!toolInput) {\n return undefined;\n }\n\n const filePath =\n getString(toolInput, 'file_path') ??\n getString(toolInput, 'filePath') ??\n getString(toolInput, 'path');\n const command =\n getString(toolInput, 'command') ??\n getString(toolInput, 'cmd');\n\n if (!filePath && !command) {\n return undefined;\n }\n\n return {\n command,\n filePath,\n };\n}\n\nfunction extractGeminiActiveFile(\n payload: Record<string, unknown>,\n): string | undefined {\n const toolInput = extractGeminiToolInput(payload);\n\n if (toolInput?.filePath) {\n return toolInput.filePath;\n }\n\n return (\n getString(payload, 'active_file') ??\n getString(payload, 'activeFile') ??\n getString(payload, 'file_path')\n );\n}\n\nfunction extractGeminiErrorMessage(\n payload: Record<string, unknown>,\n): string | undefined {\n const toolResponse = getRecord(payload.tool_response) ?? getRecord(payload.toolResponse);\n const llmResponse = getRecord(payload.llm_response) ?? getRecord(payload.llmResponse);\n\n return (\n getString(getRecord(toolResponse?.error), 'message') ??\n getString(payload, 'reason') ??\n getString(payload, 'message') ??\n getString(llmResponse, 'error')\n );\n}\n\nfunction extractGeminiErrorType(\n payload: Record<string, unknown>,\n): ErrorType | undefined {\n const rawType =\n getString(payload, 'error_type') ??\n getString(payload, 'errorType') ??\n getString(payload, 'stopReason');\n\n switch (rawType) {\n case 'rate_limit':\n return 'rate_limit';\n case 'max_output_tokens':\n case 'context_overflow':\n return 'context_overflow';\n case 'api_error':\n case 'provider_error':\n case 'invalid_request':\n return 'api_error';\n case 'tool_failure':\n return 'tool_failure';\n default:\n return undefined;\n }\n}\n\nfunction extractGeminiModel(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(getRecord(payload.llm_request), 'model') ??\n getString(payload, 'model')\n );\n}\n\nfunction extractGeminiTokens(\n payload: Record<string, unknown>,\n): number | undefined {\n const llmResponse = getRecord(payload.llm_response) ?? getRecord(payload.llmResponse);\n const usageMetadata = getRecord(llmResponse?.usageMetadata);\n const totalTokens =\n getNumber(usageMetadata, 'totalTokenCount') ??\n getNumber(usageMetadata, 'total_tokens');\n\n return totalTokens;\n}\n\nfunction isGeminiCodingTool(toolName?: string): boolean {\n return toolName !== undefined && GEMINI_CODING_TOOLS.has(toolName);\n}\n\nasync function listProcesses(\n listCommand: () => Promise<string>,\n): Promise<GeminiProcessInfo[]> {\n if (process.platform === 'win32') {\n return [];\n }\n\n try {\n const stdout = await listCommand();\n\n return stdout\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map(parseProcessLine)\n .filter((processInfo): processInfo is GeminiProcessInfo => processInfo !== null);\n } catch (error) {\n const errorCode = isErrnoException(error) ? String(error.code) : '';\n\n if (isErrnoException(error) && (errorCode === 'ENOENT' || errorCode === '1')) {\n return [];\n }\n\n logger.debug({ error }, 'Gemini process detection failed');\n return [];\n }\n}\n\nfunction parseProcessLine(line: string): GeminiProcessInfo | null {\n const match = line.match(/^(\\d+)\\s+(.+)$/u);\n\n if (!match) {\n return null;\n }\n\n const pidText = match[1];\n const command = match[2];\n\n if (!pidText || !command) {\n return null;\n }\n\n return {\n command,\n pid: Number.parseInt(pidText, 10),\n };\n}\n\nfunction isErrnoException(\n error: unknown,\n): error is NodeJS.ErrnoException & { code?: string | number } {\n return error instanceof Error && 'code' in error;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction getNumber(\n payload: Record<string, unknown> | undefined,\n key: string,\n): number | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined;\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { watch, type FSWatcher } from 'chokidar';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type { ErrorType, EventData, ToolInput } from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/goose.ts\n * @description Goose adapter combining goosed session discovery, SSE event streaming, SQLite session watching, and process fallback detection.\n * @functions\n * โ none\n * @exports GooseAdapter, GooseAdapterOptions\n * @see ./base.ts\n * @see ../../tasks/06-adapters-secondary/02_adapters-secondary_goose-copilot_DONE.md\n */\n\nconst execFile = promisify(execFileCallback);\nconst DEFAULT_GOOSED_BASE_URL = 'http://127.0.0.1:8080';\nconst DEFAULT_SQLITE_QUERY = [\n 'SELECT',\n ' id,',\n ' name,',\n ' working_dir,',\n ' updated_at,',\n ' message_count,',\n ' provider_name,',\n ' accumulated_total_tokens,',\n ' total_tokens,',\n ' model_config',\n 'FROM sessions',\n 'ORDER BY updated_at DESC',\n 'LIMIT 24;',\n].join('\\n');\nconst MAX_STREAMED_SESSIONS = 6;\nconst GOOSE_CODING_TOOL_HINT = /apply|create|delete|edit|move|patch|rename|replace|write/iu;\nconst GOOSE_RATE_LIMIT_HINT = /credit|quota|rate limit|exhausted/iu;\n\nexport interface GooseAdapterOptions extends AdapterRuntimeOptions {\n readonly apiBaseUrl?: string;\n readonly apiKey?: string;\n readonly databasePath?: string;\n readonly fetchImplementation?: typeof fetch;\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n readonly sqliteQueryCommand?: (\n databasePath: string,\n query: string,\n ) => Promise<string>;\n readonly watcherFactory?: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n}\n\ninterface GooseProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\ninterface GooseSessionSnapshot {\n readonly gooseSessionId: string;\n readonly sessionId: string;\n readonly messageCount?: number;\n readonly model?: string;\n readonly name?: string;\n readonly providerName?: string;\n readonly totalTokens?: number;\n readonly updatedAt?: string;\n readonly workingDir?: string;\n}\n\ninterface GooseStreamHandle {\n readonly abortController: AbortController;\n readonly promise: Promise<void>;\n}\n\ninterface GooseSessionsResponse {\n readonly sessions?: unknown;\n}\n\n/**\n * ๐ Goose is the first adapter that mixes three genuinely different sources:\n * HTTP session discovery, SSE streaming, and a coarse SQLite fallback. Each\n * layer is best-effort and intentionally conservative about what it claims.\n */\nexport class GooseAdapter extends BaseAdapter {\n public override readonly displayName = 'Goose';\n\n public override readonly name = 'goose' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'api-client',\n 'sqlite-watch',\n 'process-detect',\n ];\n\n private apiPoller: NodeJS.Timeout | null = null;\n\n private readonly apiBaseUrl: string;\n\n private readonly apiKey: string | undefined;\n\n private readonly databasePath: string;\n\n private databaseWatcher: FSWatcher | null = null;\n\n private fallbackProcessSessionId: string | null = null;\n\n private readonly fetchImplementation: typeof fetch;\n\n private apiDiscoverySeeded = false;\n\n private readonly observedSessions = new Set<string>();\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n private readonly sessionEventFingerprints = new Map<string, Set<string>>();\n\n private readonly sessionSnapshots = new Map<string, GooseSessionSnapshot>();\n\n private readonly sessionStreams = new Map<string, GooseStreamHandle>();\n\n private readonly sqliteQueryCommand: (\n databasePath: string,\n query: string,\n ) => Promise<string>;\n\n private readonly watcherFactory: (\n paths: string,\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n\n public constructor(options: GooseAdapterOptions) {\n super(options);\n this.apiBaseUrl =\n options.apiBaseUrl ??\n options.env?.AISNITCH_GOOSE_API_BASE_URL ??\n DEFAULT_GOOSED_BASE_URL;\n this.apiKey =\n options.apiKey ??\n options.env?.AISNITCH_GOOSE_API_KEY ??\n options.env?.GOOSE_API_KEY;\n this.databasePath =\n options.databasePath ??\n join(this.getUserHomeDirectory(), '.config', 'goose', 'sessions.db');\n this.fetchImplementation = options.fetchImplementation ?? fetch;\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ??\n (async () =>\n await execFile('pgrep', ['-lf', 'goose|goosed']).then(\n (result) => result.stdout,\n ));\n this.sqliteQueryCommand =\n options.sqliteQueryCommand ??\n (async (databasePath, query) =>\n await execFile('sqlite3', ['-json', databasePath, query]).then(\n (result) => result.stdout,\n ));\n this.watcherFactory = options.watcherFactory ?? watch;\n }\n\n public override async start(): Promise<void> {\n if (this.getStatus().running) {\n return;\n }\n\n this.setRunning(true);\n await this.seedSqliteSessions();\n\n this.databaseWatcher = this.watcherFactory(this.databasePath, {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n });\n\n this.databaseWatcher.on('add', () => {\n void this.pollSqliteSessions(true);\n });\n this.databaseWatcher.on('change', () => {\n void this.pollSqliteSessions(true);\n });\n this.databaseWatcher.on('error', (error) => {\n logger.warn({ error }, 'Goose SQLite watcher error');\n });\n\n this.startApiPolling();\n this.startProcessPolling();\n }\n\n public override async stop(): Promise<void> {\n if (this.databaseWatcher !== null) {\n await this.databaseWatcher.close();\n this.databaseWatcher = null;\n }\n\n if (this.apiPoller !== null) {\n clearInterval(this.apiPoller);\n this.apiPoller = null;\n }\n\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n for (const streamHandle of this.sessionStreams.values()) {\n streamHandle.abortController.abort();\n void streamHandle.promise.catch(() => undefined);\n }\n\n this.apiDiscoverySeeded = false;\n this.fallbackProcessSessionId = null;\n this.observedSessions.clear();\n this.sessionEventFingerprints.clear();\n this.sessionSnapshots.clear();\n this.sessionStreams.clear();\n this.setRunning(false);\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload === null) {\n logger.debug({ payload }, 'Goose ignores non-normalized hook payloads');\n return;\n }\n\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n transcriptPath: normalizedPayload.transcriptPath,\n }),\n });\n }\n\n private startApiPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.apiPoller = setInterval(() => {\n void this.pollGooseApi(true);\n }, this.pollIntervalMs);\n this.apiPoller.unref();\n\n void this.pollGooseApi(false);\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.processPoller = setInterval(() => {\n void this.pollGooseProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n\n void this.pollGooseProcesses();\n }\n\n private async seedSqliteSessions(): Promise<void> {\n try {\n await stat(this.databasePath);\n } catch {\n return;\n }\n\n const sessions = await this.readSqliteSessions();\n\n this.syncSessionSnapshots(sessions, false, 'sqlite-seed');\n }\n\n private async pollSqliteSessions(emitChanges: boolean): Promise<void> {\n const sessions = await this.readSqliteSessions();\n\n this.syncSessionSnapshots(sessions, emitChanges, 'sqlite');\n }\n\n private async readSqliteSessions(): Promise<GooseSessionSnapshot[]> {\n let rawOutput: string;\n\n try {\n rawOutput = await this.sqliteQueryCommand(\n this.databasePath,\n DEFAULT_SQLITE_QUERY,\n );\n } catch (error) {\n logger.debug({ error }, 'Goose SQLite session query skipped');\n return [];\n }\n\n let parsedOutput: unknown;\n\n try {\n parsedOutput = JSON.parse(rawOutput) as unknown;\n } catch (error) {\n logger.warn({ error }, 'Goose SQLite JSON output is invalid');\n return [];\n }\n\n if (!Array.isArray(parsedOutput)) {\n return [];\n }\n\n return parsedOutput\n .map((entry) => normalizeGooseSession(entry))\n .filter((entry): entry is GooseSessionSnapshot => entry !== null);\n }\n\n private async pollGooseApi(emitChanges: boolean): Promise<void> {\n let statusResponse: Response;\n\n try {\n statusResponse = await this.fetchImplementation(\n new URL('/status', this.apiBaseUrl),\n );\n } catch (error) {\n logger.debug({ error }, 'Goosed status endpoint is unavailable');\n return;\n }\n\n if (!statusResponse.ok) {\n return;\n }\n\n let sessionsResponse: Response;\n\n try {\n sessionsResponse = await this.fetchImplementation(\n new URL('/sessions', this.apiBaseUrl),\n {\n headers: this.createApiHeaders(),\n },\n );\n } catch (error) {\n logger.debug({ error }, 'Goosed sessions endpoint request failed');\n return;\n }\n\n if (!sessionsResponse.ok) {\n logger.debug(\n { status: sessionsResponse.status },\n 'Goosed sessions endpoint rejected the request',\n );\n return;\n }\n\n let parsedPayload: unknown;\n\n try {\n parsedPayload = await sessionsResponse.json();\n } catch (error) {\n logger.warn({ error }, 'Goosed sessions payload is not valid JSON');\n return;\n }\n\n const responsePayload = parsedPayload as GooseSessionsResponse;\n const rawSessions = Array.isArray(responsePayload.sessions)\n ? responsePayload.sessions\n : [];\n const sessions = rawSessions\n .map((entry) => normalizeGooseSession(entry))\n .filter((entry): entry is GooseSessionSnapshot => entry !== null);\n\n this.syncSessionSnapshots(\n sessions,\n emitChanges && this.apiDiscoverySeeded,\n 'api',\n );\n this.apiDiscoverySeeded = true;\n }\n\n private syncSessionSnapshots(\n nextSnapshots: readonly GooseSessionSnapshot[],\n emitChanges: boolean,\n source: string,\n ): void {\n for (const snapshot of nextSnapshots) {\n const previousSnapshot = this.sessionSnapshots.get(snapshot.sessionId);\n\n this.sessionSnapshots.set(snapshot.sessionId, snapshot);\n this.ensureTrackedSessionStream(snapshot);\n\n if (!emitChanges) {\n continue;\n }\n\n if (previousSnapshot === undefined) {\n void this.ensureObservedSession(snapshot, source);\n continue;\n }\n\n if (!didGooseSessionAdvance(previousSnapshot, snapshot)) {\n continue;\n }\n\n void this.ensureObservedSession(snapshot, source).then(async () => {\n await this.emitStateChange(\n 'agent.streaming',\n buildGooseSessionData(snapshot, {\n raw: {\n snapshot,\n source,\n },\n }),\n this.createSessionContext(snapshot, `aisnitch://adapters/goose/${source}`),\n );\n });\n }\n\n this.trimTrackedSessionStreams(nextSnapshots);\n }\n\n private ensureTrackedSessionStream(snapshot: GooseSessionSnapshot): void {\n if (this.sessionStreams.has(snapshot.sessionId)) {\n return;\n }\n\n const abortController = new AbortController();\n const streamPromise = this.consumeSessionEvents(snapshot, abortController).finally(\n () => {\n const activeStream = this.sessionStreams.get(snapshot.sessionId);\n\n if (activeStream?.abortController === abortController) {\n this.sessionStreams.delete(snapshot.sessionId);\n }\n },\n );\n\n this.sessionStreams.set(snapshot.sessionId, {\n abortController,\n promise: streamPromise,\n });\n }\n\n private trimTrackedSessionStreams(\n nextSnapshots: readonly GooseSessionSnapshot[],\n ): void {\n const keepSessionIds = new Set(\n [...nextSnapshots]\n .sort(compareGooseSessionsByRecency)\n .slice(0, MAX_STREAMED_SESSIONS)\n .map((snapshot) => snapshot.sessionId),\n );\n\n for (const [sessionId, streamHandle] of this.sessionStreams) {\n if (keepSessionIds.has(sessionId)) {\n continue;\n }\n\n streamHandle.abortController.abort();\n this.sessionStreams.delete(sessionId);\n }\n }\n\n private async consumeSessionEvents(\n snapshot: GooseSessionSnapshot,\n abortController: AbortController,\n ): Promise<void> {\n let response: Response;\n\n try {\n response = await this.fetchImplementation(\n new URL(\n `/sessions/${encodeURIComponent(snapshot.gooseSessionId)}/events`,\n this.apiBaseUrl,\n ),\n {\n headers: {\n ...this.createApiHeaders(),\n Accept: 'text/event-stream',\n },\n signal: abortController.signal,\n },\n );\n } catch (error) {\n if (abortController.signal.aborted) {\n return;\n }\n\n logger.debug({ error, sessionId: snapshot.sessionId }, 'Goose SSE request failed');\n return;\n }\n\n if (!response.ok || response.body === null) {\n logger.debug(\n { sessionId: snapshot.sessionId, status: response.status },\n 'Goose SSE stream is unavailable',\n );\n return;\n }\n\n const reader: ReadableStreamDefaultReader<Uint8Array> =\n response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const readResult = await reader.read();\n\n if (readResult.done) {\n break;\n }\n\n buffer += decoder.decode(readResult.value, { stream: true });\n\n while (true) {\n const delimiterIndex = buffer.indexOf('\\n\\n');\n\n if (delimiterIndex === -1) {\n break;\n }\n\n const frame = buffer.slice(0, delimiterIndex);\n\n buffer = buffer.slice(delimiterIndex + 2);\n await this.processSSEFrame(snapshot, frame);\n }\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.debug(\n { error, sessionId: snapshot.sessionId },\n 'Goose SSE stream closed unexpectedly',\n );\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n private async processSSEFrame(\n snapshot: GooseSessionSnapshot,\n frame: string,\n ): Promise<void> {\n const payloadText = frame\n .split(/\\r?\\n/u)\n .filter((line) => line.startsWith('data:'))\n .map((line) => line.slice(5).trimStart())\n .join('\\n');\n\n if (payloadText.length === 0) {\n return;\n }\n\n let parsedPayload: unknown;\n\n try {\n parsedPayload = JSON.parse(payloadText) as unknown;\n } catch (error) {\n logger.warn({ error }, 'Goose SSE frame is not valid JSON');\n return;\n }\n\n await this.processSessionEvent(snapshot, parsedPayload);\n }\n\n private async processSessionEvent(\n snapshot: GooseSessionSnapshot,\n payload: unknown,\n ): Promise<void> {\n if (!isRecord(payload)) {\n return;\n }\n\n const fingerprint = createGooseFingerprint(payload);\n\n if (fingerprint && !this.markSessionEventSeen(snapshot.sessionId, fingerprint)) {\n return;\n }\n\n const eventType = getString(payload, 'type');\n\n switch (eventType) {\n case 'Message': {\n await this.processGooseMessage(snapshot, payload);\n return;\n }\n case 'Finish': {\n await this.ensureObservedSession(snapshot, 'sse');\n await this.emitStateChange(\n 'task.complete',\n buildGooseSessionData(snapshot, {\n raw: payload,\n tokensUsed: extractGooseTokenCount(getRecord(payload.token_state)),\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n return;\n }\n case 'Error': {\n const errorMessage = getString(payload, 'error');\n\n await this.ensureObservedSession(snapshot, 'sse');\n await this.emitStateChange(\n 'agent.error',\n buildGooseSessionData(snapshot, {\n errorMessage,\n errorType: inferGooseErrorType(errorMessage),\n raw: payload,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n return;\n }\n case 'Notification': {\n await this.ensureObservedSession(snapshot, 'sse');\n await this.emitStateChange(\n 'agent.asking_user',\n buildGooseSessionData(snapshot, {\n errorMessage: extractLooseString(payload, ['message']),\n raw: payload,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n return;\n }\n default:\n return;\n }\n }\n\n private async processGooseMessage(\n snapshot: GooseSessionSnapshot,\n payload: Record<string, unknown>,\n ): Promise<void> {\n const message = getRecord(payload.message);\n\n if (!message) {\n return;\n }\n\n const role = getString(message, 'role');\n const content = getRecordArray(message.content);\n const tokenState = getRecord(payload.token_state);\n const tokensUsed = extractGooseTokenCount(tokenState);\n\n await this.ensureObservedSession(snapshot, 'sse');\n\n if (role === 'user') {\n const promptText = content\n .filter((part) => getString(part, 'type') === 'text')\n .map((part) => getString(part, 'text'))\n .filter((part): part is string => typeof part === 'string')\n .join('\\n')\n .trim();\n\n await this.emitStateChange(\n 'task.start',\n buildGooseSessionData(snapshot, {\n raw: {\n message,\n prompt: promptText,\n tokenState,\n },\n tokensUsed,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n\n return;\n }\n\n if (role !== 'assistant') {\n return;\n }\n\n for (const part of content) {\n const partType = getString(part, 'type');\n\n switch (partType) {\n case 'thinking': {\n await this.emitStateChange(\n 'agent.thinking',\n buildGooseSessionData(snapshot, {\n raw: {\n message: {\n content: [part],\n role,\n },\n tokenState,\n },\n tokensUsed,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n break;\n }\n case 'redactedThinking': {\n await this.emitStateChange(\n 'agent.thinking',\n buildGooseSessionData(snapshot, {\n raw: {\n message: {\n content: [\n {\n thinking: getString(part, 'data'),\n type: 'thinking',\n },\n ],\n role,\n },\n tokenState,\n },\n tokensUsed,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n break;\n }\n case 'text': {\n await this.emitStateChange(\n 'agent.streaming',\n buildGooseSessionData(snapshot, {\n raw: {\n message: {\n content: [part],\n role,\n },\n tokenState,\n },\n tokensUsed,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n break;\n }\n case 'toolRequest': {\n const toolName = extractGooseToolName(part);\n const toolInput = extractGooseToolInput(part);\n const activeFile = toolInput?.filePath;\n const emittedType = isGooseCodingTool(toolName, toolInput)\n ? 'agent.coding'\n : 'agent.tool_call';\n\n await this.emitStateChange(\n emittedType,\n buildGooseSessionData(snapshot, {\n activeFile,\n raw: {\n message: {\n content: [part],\n role,\n },\n tokenState,\n },\n toolInput,\n toolName,\n tokensUsed,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n break;\n }\n case 'toolConfirmationRequest':\n case 'actionRequired': {\n await this.emitStateChange(\n 'agent.asking_user',\n buildGooseSessionData(snapshot, {\n errorMessage:\n getString(part, 'prompt') ??\n extractLooseString(getRecord(part.data), ['message']),\n raw: {\n message: {\n content: [part],\n role,\n },\n tokenState,\n },\n toolInput: extractGooseToolInput(part),\n toolName: extractGooseToolName(part),\n tokensUsed,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n break;\n }\n case 'systemNotification': {\n const notificationType = getString(part, 'notificationType');\n const eventTypeToEmit =\n notificationType === 'thinkingMessage'\n ? 'agent.thinking'\n : 'agent.asking_user';\n\n await this.emitStateChange(\n eventTypeToEmit,\n buildGooseSessionData(snapshot, {\n errorMessage: getString(part, 'msg'),\n errorType:\n notificationType === 'creditsExhausted'\n ? 'rate_limit'\n : undefined,\n raw: {\n message:\n notificationType === 'thinkingMessage'\n ? {\n content: [\n {\n thinking: getString(part, 'msg'),\n type: 'thinking',\n },\n ],\n role,\n }\n : {\n content: [part],\n role,\n },\n tokenState,\n },\n tokensUsed,\n }),\n this.createSessionContext(snapshot, 'aisnitch://adapters/goose/sse'),\n );\n break;\n }\n default:\n break;\n }\n }\n }\n\n private async ensureObservedSession(\n snapshot: GooseSessionSnapshot,\n source: string,\n ): Promise<void> {\n if (this.observedSessions.has(snapshot.sessionId)) {\n return;\n }\n\n this.observedSessions.add(snapshot.sessionId);\n\n const context = this.createSessionContext(\n snapshot,\n `aisnitch://adapters/goose/${source}`,\n );\n const eventData = buildGooseSessionData(snapshot, {\n raw: {\n snapshot,\n source,\n },\n });\n\n await this.emitStateChange('session.start', eventData, context);\n await this.emitStateChange('agent.idle', eventData, context);\n }\n\n private createSessionContext(\n snapshot: GooseSessionSnapshot,\n source: string,\n ): AdapterPublishContext {\n return {\n cwd: snapshot.workingDir,\n sessionId: snapshot.sessionId,\n source,\n };\n }\n\n private markSessionEventSeen(sessionId: string, fingerprint: string): boolean {\n const knownFingerprints =\n this.sessionEventFingerprints.get(sessionId) ?? new Set<string>();\n\n if (knownFingerprints.has(fingerprint)) {\n return false;\n }\n\n if (knownFingerprints.size >= 256) {\n knownFingerprints.clear();\n }\n\n knownFingerprints.add(fingerprint);\n this.sessionEventFingerprints.set(sessionId, knownFingerprints);\n\n return true;\n }\n\n private createApiHeaders(): Record<string, string> | undefined {\n if (!this.apiKey) {\n return undefined;\n }\n\n return {\n Authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n private async pollGooseProcesses(): Promise<void> {\n const processes = await listProcesses(this.processListCommand);\n\n if (processes.length > 0 && this.getStatus().activeSessions === 0) {\n const processInfo = processes[0];\n\n if (!processInfo) {\n return;\n }\n\n const sessionId = `goose-process-${processInfo.pid}`;\n\n this.fallbackProcessSessionId = sessionId;\n await this.emitStateChange(\n 'session.start',\n {\n raw: {\n process: processInfo,\n source: 'process-detect',\n },\n },\n {\n pid: processInfo.pid,\n sessionId,\n source: 'aisnitch://adapters/goose/process-detect',\n },\n );\n return;\n }\n\n if (processes.length === 0 && this.fallbackProcessSessionId !== null) {\n const sessionId = this.fallbackProcessSessionId;\n\n this.fallbackProcessSessionId = null;\n await this.emitStateChange(\n 'session.end',\n {\n raw: {\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n sessionId,\n source: 'aisnitch://adapters/goose/process-detect',\n },\n );\n }\n }\n}\n\nfunction normalizeGooseSession(payload: unknown): GooseSessionSnapshot | null {\n if (!isRecord(payload)) {\n return null;\n }\n\n const gooseSessionId = getString(payload, 'id');\n\n if (!gooseSessionId) {\n return null;\n }\n\n const workingDir =\n getString(payload, 'working_dir') ?? getString(payload, 'workingDir');\n const name = getString(payload, 'name');\n const providerName =\n getString(payload, 'provider_name') ?? getString(payload, 'providerName');\n const updatedAt =\n getString(payload, 'updated_at') ?? getString(payload, 'updatedAt');\n const messageCount =\n getNumber(payload, 'message_count') ?? getNumber(payload, 'messageCount');\n const totalTokens =\n getNumber(payload, 'accumulated_total_tokens') ??\n getNumber(payload, 'total_tokens') ??\n getNumber(payload, 'accumulatedTotalTokens') ??\n getNumber(payload, 'totalTokens');\n const modelConfig = getRecord(payload.model_config) ?? getRecord(payload.modelConfig);\n const rawModelConfig = getString(payload, 'model_config');\n const parsedModelConfig =\n modelConfig ?? parseJsonRecord(rawModelConfig);\n const model = getString(parsedModelConfig, 'model_name') ?? getString(parsedModelConfig, 'modelName');\n const sessionId = resolveSessionId({\n cwd: workingDir,\n projectPath: workingDir,\n sessionId: gooseSessionId,\n tool: 'goose',\n });\n\n return {\n gooseSessionId,\n messageCount,\n model,\n name,\n providerName,\n sessionId,\n totalTokens,\n updatedAt,\n workingDir,\n };\n}\n\nfunction buildGooseSessionData(\n snapshot: GooseSessionSnapshot,\n overrides: Partial<Omit<EventData, 'state'>> = {},\n): Omit<EventData, 'state'> {\n return {\n cwd: overrides.cwd ?? snapshot.workingDir,\n model: overrides.model ?? snapshot.model,\n project: overrides.project ?? snapshot.name,\n projectPath: overrides.projectPath ?? snapshot.workingDir,\n raw: overrides.raw,\n tokensUsed: overrides.tokensUsed ?? snapshot.totalTokens,\n ...overrides,\n };\n}\n\nfunction compareGooseSessionsByRecency(\n left: GooseSessionSnapshot,\n right: GooseSessionSnapshot,\n): number {\n return Date.parse(right.updatedAt ?? '') - Date.parse(left.updatedAt ?? '');\n}\n\nfunction didGooseSessionAdvance(\n previousSnapshot: GooseSessionSnapshot,\n nextSnapshot: GooseSessionSnapshot,\n): boolean {\n return (\n previousSnapshot.updatedAt !== nextSnapshot.updatedAt ||\n previousSnapshot.messageCount !== nextSnapshot.messageCount ||\n previousSnapshot.totalTokens !== nextSnapshot.totalTokens\n );\n}\n\nfunction createGooseFingerprint(payload: Record<string, unknown>): string | null {\n const eventType = getString(payload, 'type');\n\n if (!eventType) {\n return null;\n }\n\n if (eventType === 'Message') {\n const message = getRecord(payload.message);\n const messageId = getString(message, 'id');\n const created = getNumber(message, 'created');\n const role = getString(message, 'role');\n\n return [eventType, messageId, created, role]\n .filter((value): value is string | number => value !== undefined)\n .join(':');\n }\n\n if (eventType === 'Finish') {\n return `${eventType}:${getString(payload, 'reason') ?? 'unknown'}`;\n }\n\n if (eventType === 'Error') {\n return `${eventType}:${getString(payload, 'error') ?? 'unknown'}`;\n }\n\n return eventType;\n}\n\nfunction extractGooseTokenCount(\n tokenState: Record<string, unknown> | undefined,\n): number | undefined {\n return (\n getNumber(tokenState, 'accumulatedTotalTokens') ??\n getNumber(tokenState, 'totalTokens')\n );\n}\n\nfunction extractGooseToolName(\n payload: Record<string, unknown>,\n): string | undefined {\n const toolCall = getRecord(payload.toolCall);\n\n return (\n getString(toolCall, 'name') ??\n getString(toolCall, 'toolName') ??\n getString(payload, 'toolName')\n );\n}\n\nfunction extractGooseToolInput(\n payload: Record<string, unknown>,\n): ToolInput | undefined {\n const toolCall = getRecord(payload.toolCall);\n const argumentsRecord =\n getRecord(toolCall?.arguments) ??\n getRecord(toolCall?.args) ??\n getRecord(toolCall?.input) ??\n getRecord(payload.arguments);\n const filePath = extractFirstString(argumentsRecord, [\n 'file',\n 'file_path',\n 'filePath',\n 'path',\n 'target',\n 'target_path',\n 'targetPath',\n ]);\n const command = extractFirstString(argumentsRecord, [\n 'cmd',\n 'command',\n 'script',\n ]);\n\n if (!filePath && !command) {\n return undefined;\n }\n\n return {\n command,\n filePath,\n };\n}\n\nfunction isGooseCodingTool(\n toolName: string | undefined,\n toolInput: ToolInput | undefined,\n): boolean {\n if (toolName && GOOSE_CODING_TOOL_HINT.test(toolName)) {\n return true;\n }\n\n const filePath = toolInput?.filePath;\n\n if (!filePath) {\n return false;\n }\n\n return !/read|view|glob|grep|list|search/iu.test(toolName ?? '');\n}\n\nfunction inferGooseErrorType(\n errorMessage: string | undefined,\n): ErrorType | undefined {\n if (!errorMessage) {\n return undefined;\n }\n\n if (GOOSE_RATE_LIMIT_HINT.test(errorMessage)) {\n return 'rate_limit';\n }\n\n if (/context|token limit|too long/iu.test(errorMessage)) {\n return 'context_overflow';\n }\n\n if (/tool/iu.test(errorMessage)) {\n return 'tool_failure';\n }\n\n return 'api_error';\n}\n\nasync function listProcesses(\n processListCommand: () => Promise<string>,\n): Promise<GooseProcessInfo[]> {\n try {\n const commandOutput = await processListCommand();\n\n return commandOutput\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n const [pidPart, ...commandParts] = line.split(/\\s+/u);\n const pid = pidPart ? Number.parseInt(pidPart, 10) : Number.NaN;\n\n return {\n command: commandParts.join(' '),\n pid,\n } satisfies GooseProcessInfo;\n })\n .filter((processInfo) => Number.isInteger(processInfo.pid));\n } catch (error) {\n logger.debug({ error }, 'Goose process listing skipped');\n return [];\n }\n}\n\nfunction parseJsonRecord(\n value: string | undefined,\n): Record<string, unknown> | undefined {\n if (!value) {\n return undefined;\n }\n\n try {\n const parsedValue = JSON.parse(value) as unknown;\n\n return getRecord(parsedValue);\n } catch {\n return undefined;\n }\n}\n\nfunction extractFirstString(\n payload: Record<string, unknown> | undefined,\n keys: readonly string[],\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n for (const key of keys) {\n const directValue = getString(payload, key);\n\n if (directValue) {\n return directValue;\n }\n }\n\n return undefined;\n}\n\nfunction extractLooseString(\n payload: Record<string, unknown> | undefined,\n keys: readonly string[],\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n for (const key of keys) {\n const directValue = getString(payload, key);\n\n if (directValue) {\n return directValue;\n }\n\n const nestedValue = getString(getRecord(payload[key]), 'message');\n\n if (nestedValue) {\n return nestedValue;\n }\n }\n\n return undefined;\n}\n\nfunction getRecordArray(value: unknown): Record<string, unknown>[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter((entry): entry is Record<string, unknown> => isRecord(entry));\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction getNumber(\n payload: Record<string, unknown> | undefined,\n key: string,\n): number | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { readFile, readdir, stat } from 'node:fs/promises';\nimport { basename, dirname, extname, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { watch, type FSWatcher } from 'chokidar';\nimport pidCwd from 'pid-cwd';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type {\n AISnitchEventType,\n ErrorType,\n EventData,\n ToolInput,\n} from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/openclaw.ts\n * @description OpenClaw adapter combining managed hook ingestion, bundled command logs, transcript watching, workspace-memory watching, and process fallback detection.\n * @functions\n * โ none\n * @exports OpenClawAdapter, OpenClawAdapterOptions\n * @see ./base.ts\n * @see ../cli/commands/setup.ts\n * @see ../../tasks/06-adapters-secondary/04_adapters-secondary_openclaw.md\n */\n\nconst execFile = promisify(execFileCallback);\n\nconst COMMAND_START_THINKING_DELAY_MS = 2_000;\nconst POST_TOOL_THINKING_DELAY_MS = 500;\nconst OPENCLAW_CODING_TOOL_HINT =\n /apply|bash|create|delete|edit|exec|file|patch|replace|shell|write/iu;\nconst OPENCLAW_ERROR_HINT =\n /denied|error|exception|failed|quota|rate limit|refused|timeout/iu;\n\nexport interface OpenClawAdapterOptions extends AdapterRuntimeOptions {\n readonly agentsDirectory?: string;\n readonly commandsLogPath?: string;\n readonly cwdResolver?: (pid: number) => Promise<string | undefined>;\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n readonly watcherFactory?: (\n paths: Parameters<typeof watch>[0],\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n}\n\ninterface OpenClawProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\ninterface OpenClawSessionSnapshot {\n readonly cwd?: string;\n readonly project?: string;\n readonly sessionId: string;\n readonly sessionKey?: string;\n readonly transcriptPath?: string;\n}\n\ninterface PendingThinkingState {\n readonly context: AdapterPublishContext;\n readonly data: Omit<EventData, 'state'>;\n}\n\n/**\n * ๐ OpenClaw has several passive surfaces, but none of them is perfect alone.\n * AISnitch therefore merges the real managed hook path with filesystem and\n * process fallbacks so operators still get signal when setup is partial.\n */\nexport class OpenClawAdapter extends BaseAdapter {\n public override readonly displayName = 'OpenClaw';\n\n public override readonly name = 'openclaw' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'hooks',\n 'log-watch',\n 'jsonl-watch',\n 'process-detect',\n ];\n\n private readonly agentsDirectory: string;\n\n private readonly commandsLogPath: string;\n\n private commandsLogWatcher: FSWatcher | null = null;\n\n private readonly cwdResolver: (pid: number) => Promise<string | undefined>;\n\n private readonly fallbackProcessSessions = new Map<number, string>();\n\n private readonly observedTranscriptEntries = new Set<string>();\n\n private readonly pendingThinking = new Map<string, NodeJS.Timeout>();\n\n private readonly pendingThinkingState = new Map<string, PendingThinkingState>();\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n private readonly sessionSnapshots = new Map<string, OpenClawSessionSnapshot>();\n\n private readonly startedSessions = new Set<string>();\n\n private transcriptWatcher: FSWatcher | null = null;\n\n private readonly watcherFactory: (\n paths: Parameters<typeof watch>[0],\n options: Parameters<typeof watch>[1],\n ) => FSWatcher;\n\n private readonly memoryRootGlobs: readonly string[];\n\n private memoryWatcher: FSWatcher | null = null;\n\n private readonly fileOffsets = new Map<string, number>();\n\n private readonly fileRemainders = new Map<string, string>();\n\n public constructor(options: OpenClawAdapterOptions) {\n super(options);\n\n const openclawHome = join(this.getUserHomeDirectory(), '.openclaw');\n\n this.agentsDirectory = options.agentsDirectory ?? join(openclawHome, 'agents');\n this.commandsLogPath =\n options.commandsLogPath ?? join(openclawHome, 'logs', 'commands.log');\n this.cwdResolver =\n options.cwdResolver ??\n (async (pid) => {\n return await pidCwd(pid);\n });\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ??\n (async () =>\n await execFile('pgrep', ['-ifl', 'openclaw']).then(\n (result) => result.stdout,\n ));\n this.watcherFactory = options.watcherFactory ?? watch;\n this.memoryRootGlobs = [\n join(openclawHome, 'workspace', 'MEMORY.md'),\n join(openclawHome, 'workspace', 'memory', '*.md'),\n join(openclawHome, 'workspace-*', 'MEMORY.md'),\n join(openclawHome, 'workspace-*', 'memory', '*.md'),\n ];\n }\n\n public override async start(): Promise<void> {\n if (this.getStatus().running) {\n return;\n }\n\n this.setRunning(true);\n await Promise.all([\n this.seedCommandsLogOffset(),\n this.seedMemoryOffsets(),\n this.seedTranscriptOffsets(),\n ]);\n\n this.commandsLogWatcher = this.watcherFactory(this.commandsLogPath, {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n });\n this.commandsLogWatcher.on('add', (filePath) => {\n void this.processCommandsLogUpdate(filePath, true);\n });\n this.commandsLogWatcher.on('change', (filePath) => {\n void this.processCommandsLogUpdate(filePath, false);\n });\n this.commandsLogWatcher.on('error', (error) => {\n logger.warn({ error }, 'OpenClaw commands.log watcher error');\n });\n\n this.transcriptWatcher = this.watcherFactory(\n join(this.agentsDirectory, '*', 'sessions', '*.jsonl'),\n {\n awaitWriteFinish: {\n stabilityThreshold: 200,\n },\n ignoreInitial: true,\n },\n );\n this.transcriptWatcher.on('add', (filePath) => {\n void this.processTranscriptUpdate(filePath, true);\n });\n this.transcriptWatcher.on('change', (filePath) => {\n void this.processTranscriptUpdate(filePath, false);\n });\n this.transcriptWatcher.on('error', (error) => {\n logger.warn({ error }, 'OpenClaw transcript watcher error');\n });\n\n this.memoryWatcher = this.watcherFactory([...this.memoryRootGlobs], {\n awaitWriteFinish: {\n stabilityThreshold: 300,\n },\n ignoreInitial: true,\n });\n this.memoryWatcher.on('add', (filePath) => {\n void this.processMemoryUpdate(filePath, true);\n });\n this.memoryWatcher.on('change', (filePath) => {\n void this.processMemoryUpdate(filePath, false);\n });\n this.memoryWatcher.on('error', (error) => {\n logger.warn({ error }, 'OpenClaw memory watcher error');\n });\n\n this.startProcessPolling();\n }\n\n public override async stop(): Promise<void> {\n if (this.commandsLogWatcher !== null) {\n await this.commandsLogWatcher.close();\n this.commandsLogWatcher = null;\n }\n\n if (this.transcriptWatcher !== null) {\n await this.transcriptWatcher.close();\n this.transcriptWatcher = null;\n }\n\n if (this.memoryWatcher !== null) {\n await this.memoryWatcher.close();\n this.memoryWatcher = null;\n }\n\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n for (const timer of this.pendingThinking.values()) {\n clearTimeout(timer);\n }\n\n this.fileOffsets.clear();\n this.fileRemainders.clear();\n this.fallbackProcessSessions.clear();\n this.observedTranscriptEntries.clear();\n this.pendingThinking.clear();\n this.pendingThinkingState.clear();\n this.sessionSnapshots.clear();\n this.startedSessions.clear();\n this.setRunning(false);\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload !== null) {\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n project: normalizedPayload.data?.project,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n transcriptPath: normalizedPayload.transcriptPath,\n }),\n });\n return;\n }\n\n if (!isRecord(payload)) {\n logger.warn({ payload }, 'OpenClaw payload must be an object');\n return;\n }\n\n await this.processNativePayload(\n payload,\n 'aisnitch://adapters/openclaw/hooks',\n extractOpenClawEventName(payload),\n );\n }\n\n private async processNativePayload(\n payload: Record<string, unknown>,\n source: string,\n eventName: string | undefined,\n transcriptPath?: string,\n ): Promise<void> {\n if (!eventName) {\n logger.debug({ payload, source }, 'OpenClaw payload missing event name');\n return;\n }\n\n const sessionId = resolveSessionId({\n activeFile: extractOpenClawActiveFile(payload),\n cwd: extractOpenClawCwd(payload),\n pid: getNumber(payload, 'pid'),\n project: extractOpenClawProject(payload),\n projectPath: extractOpenClawCwd(payload),\n sessionId: extractOpenClawSessionKey(payload),\n tool: this.name,\n transcriptPath,\n });\n const context: AdapterPublishContext = {\n cwd: extractOpenClawCwd(payload),\n hookPayload: payload,\n pid: getNumber(payload, 'pid'),\n sessionId,\n source,\n transcriptPath,\n };\n const sharedData = buildOpenClawEventData(payload);\n\n this.sessionSnapshots.set(sessionId, {\n cwd: sharedData.cwd,\n project: sharedData.project,\n sessionId,\n sessionKey: extractOpenClawSessionKey(payload),\n transcriptPath,\n });\n\n switch (eventName) {\n case 'gateway:startup':\n case 'agent:bootstrap': {\n await this.emitOpenClawSessionStart(sharedData, context);\n return;\n }\n case 'command:new':\n case '/new': {\n await this.ensureSessionStarted(sharedData, context);\n await this.emitStateChange('task.start', sharedData, context);\n this.scheduleThinking(sessionId, sharedData, context, COMMAND_START_THINKING_DELAY_MS);\n return;\n }\n case 'command:stop':\n case '/stop': {\n this.clearThinking(sessionId);\n await this.emitStateChange('task.complete', sharedData, context);\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'command:reset':\n case '/reset':\n case 'gateway:shutdown': {\n await this.emitOpenClawSessionEnd(sharedData, context);\n return;\n }\n case 'session:compact:before':\n case 'before_compaction': {\n await this.ensureSessionStarted(sharedData, context);\n this.clearThinking(sessionId);\n await this.emitStateChange('agent.compact', sharedData, context);\n return;\n }\n case 'tool_result_persist': {\n await this.ensureSessionStarted(sharedData, context);\n await this.emitStateChange(\n isOpenClawCodingTool(sharedData.toolName, sharedData.toolInput)\n ? 'agent.coding'\n : 'agent.tool_call',\n sharedData,\n context,\n );\n this.scheduleThinking(sessionId, sharedData, context, POST_TOOL_THINKING_DELAY_MS);\n return;\n }\n case 'message:received':\n case 'message:preprocessed':\n case 'session:compact:after':\n case 'after_compaction': {\n logger.debug({ eventName }, 'OpenClaw event intentionally ignored');\n return;\n }\n default: {\n logger.debug({ eventName }, 'OpenClaw event ignored by adapter');\n }\n }\n }\n\n private async emitOpenClawSessionStart(\n data: Omit<EventData, 'state'>,\n context: AdapterPublishContext,\n ): Promise<void> {\n const sessionId = context.sessionId;\n\n if (!sessionId) {\n return;\n }\n\n if (this.startedSessions.has(sessionId)) {\n await this.emitStateChange('agent.idle', data, context);\n return;\n }\n\n this.startedSessions.add(sessionId);\n await this.emitStateChange('session.start', data, context);\n await this.emitStateChange('agent.idle', data, context);\n }\n\n private async emitOpenClawSessionEnd(\n data: Omit<EventData, 'state'>,\n context: AdapterPublishContext,\n ): Promise<void> {\n const sessionId = context.sessionId;\n\n if (sessionId) {\n this.clearThinking(sessionId);\n this.startedSessions.delete(sessionId);\n this.sessionSnapshots.delete(sessionId);\n }\n\n await this.emitStateChange('session.end', data, context);\n }\n\n private async ensureSessionStarted(\n data: Omit<EventData, 'state'>,\n context: AdapterPublishContext,\n ): Promise<void> {\n const sessionId = context.sessionId;\n\n if (!sessionId || this.startedSessions.has(sessionId)) {\n return;\n }\n\n await this.emitOpenClawSessionStart(\n {\n ...data,\n raw: {\n reason: 'implicit-start',\n source: context.source,\n ...(data.raw ?? {}),\n },\n },\n context,\n );\n }\n\n private scheduleThinking(\n sessionId: string,\n data: Omit<EventData, 'state'>,\n context: AdapterPublishContext,\n delayMs: number,\n ): void {\n this.clearThinking(sessionId);\n this.pendingThinkingState.set(sessionId, { context, data });\n\n const timer = setTimeout(() => {\n const thinkingState = this.pendingThinkingState.get(sessionId);\n\n if (!thinkingState) {\n return;\n }\n\n this.pendingThinking.delete(sessionId);\n this.pendingThinkingState.delete(sessionId);\n void this.emitStateChange(\n 'agent.thinking',\n thinkingState.data,\n thinkingState.context,\n );\n }, delayMs);\n timer.unref();\n\n this.pendingThinking.set(sessionId, timer);\n }\n\n private clearThinking(sessionId: string): void {\n const timer = this.pendingThinking.get(sessionId);\n\n if (timer) {\n clearTimeout(timer);\n }\n\n this.pendingThinking.delete(sessionId);\n this.pendingThinkingState.delete(sessionId);\n }\n\n private async seedCommandsLogOffset(): Promise<void> {\n await this.seedFileOffset(this.commandsLogPath);\n }\n\n private async seedTranscriptOffsets(): Promise<void> {\n const files = await collectFilesRecursively(this.agentsDirectory, '.jsonl');\n\n await Promise.all(files.map(async (filePath) => await this.seedFileOffset(filePath)));\n }\n\n private async seedMemoryOffsets(): Promise<void> {\n for (const root of [join(this.getUserHomeDirectory(), '.openclaw', 'workspace')]) {\n await Promise.all([\n this.seedDirectoryFileOffsets(join(root, 'memory'), '.md'),\n this.seedFileOffset(join(root, 'MEMORY.md')),\n ]);\n }\n }\n\n private async seedDirectoryFileOffsets(\n directory: string,\n extension: string,\n ): Promise<void> {\n const files = await collectFilesRecursively(directory, extension);\n\n await Promise.all(files.map(async (filePath) => await this.seedFileOffset(filePath)));\n }\n\n private async seedFileOffset(filePath: string): Promise<void> {\n try {\n const fileStats = await stat(filePath);\n\n this.fileOffsets.set(filePath, fileStats.size);\n } catch {\n // Ignore missing files while the source is still dormant.\n }\n }\n\n private async processCommandsLogUpdate(\n filePath: string,\n readFromStart: boolean,\n ): Promise<void> {\n const lines = await this.readIncrementalLines(filePath, readFromStart);\n\n for (const line of lines) {\n const payload = parseJsonRecord(line);\n\n if (!payload) {\n logger.debug({ filePath, line }, 'OpenClaw commands.log line ignored');\n continue;\n }\n\n await this.processNativePayload(\n payload,\n 'aisnitch://adapters/openclaw/commands-log',\n extractOpenClawEventName(payload),\n );\n }\n }\n\n private async processTranscriptUpdate(\n filePath: string,\n readFromStart: boolean,\n ): Promise<void> {\n const lines = await this.readIncrementalLines(filePath, readFromStart);\n\n for (const line of lines) {\n const parsedLine = parseJsonRecord(line);\n\n if (!parsedLine) {\n continue;\n }\n\n await this.processTranscriptLine(parsedLine, filePath);\n }\n }\n\n private async processTranscriptLine(\n line: Record<string, unknown>,\n filePath: string,\n ): Promise<void> {\n const rawSessionId =\n extractOpenClawSessionKey(line) ??\n inferOpenClawSessionIdFromTranscriptPath(filePath);\n const cwd = extractOpenClawCwd(line) ?? dirname(dirname(filePath));\n const sessionId = resolveSessionId({\n cwd,\n projectPath: cwd,\n sessionId: rawSessionId,\n tool: this.name,\n transcriptPath: filePath,\n });\n const eventFingerprint =\n getString(line, 'id') ??\n `${filePath}:${getString(line, 'timestamp') ?? JSON.stringify(line).slice(0, 120)}`;\n const dedupeKey = `${sessionId}:${eventFingerprint}`;\n\n if (this.observedTranscriptEntries.has(dedupeKey)) {\n return;\n }\n\n if (this.observedTranscriptEntries.size >= 4096) {\n this.observedTranscriptEntries.clear();\n }\n\n this.observedTranscriptEntries.add(dedupeKey);\n\n const context: AdapterPublishContext = {\n cwd,\n sessionId,\n source: 'aisnitch://adapters/openclaw/transcript',\n transcriptPath: filePath,\n };\n const sharedData: Omit<EventData, 'state'> = {\n cwd,\n project: basename(cwd) || cwd,\n projectPath: cwd,\n raw: line,\n };\n\n this.sessionSnapshots.set(sessionId, {\n cwd,\n project: sharedData.project,\n sessionId,\n transcriptPath: filePath,\n });\n\n if (getString(line, 'type') === 'session') {\n await this.emitOpenClawSessionStart(sharedData, context);\n return;\n }\n\n if (getString(line, 'type') === 'compaction') {\n await this.ensureSessionStarted(sharedData, context);\n await this.emitStateChange('agent.compact', sharedData, context);\n return;\n }\n\n const transcriptToolObservation = extractOpenClawTranscriptToolObservation(line);\n\n if (transcriptToolObservation) {\n const toolData: Omit<EventData, 'state'> = {\n ...sharedData,\n activeFile: transcriptToolObservation.activeFile,\n toolInput: transcriptToolObservation.toolInput,\n toolName: transcriptToolObservation.toolName,\n };\n\n await this.ensureSessionStarted(toolData, context);\n await this.emitStateChange(\n transcriptToolObservation.type,\n toolData,\n context,\n );\n this.scheduleThinking(sessionId, toolData, context, POST_TOOL_THINKING_DELAY_MS);\n return;\n }\n\n const thinkingText = extractOpenClawTranscriptThinkingText(line);\n\n if (thinkingText) {\n await this.ensureSessionStarted(sharedData, context);\n await this.emitStateChange(\n 'agent.thinking',\n {\n ...sharedData,\n raw: {\n source: line,\n thinking: thinkingText,\n },\n },\n context,\n );\n return;\n }\n\n const streamingText = extractOpenClawTranscriptStreamingText(line);\n\n if (streamingText) {\n await this.ensureSessionStarted(sharedData, context);\n await this.emitStateChange(\n 'agent.streaming',\n {\n ...sharedData,\n raw: {\n content: streamingText,\n source: line,\n },\n },\n context,\n );\n }\n }\n\n private async processMemoryUpdate(\n filePath: string,\n readFromStart: boolean,\n ): Promise<void> {\n const baseName = basename(filePath);\n const resolvedSession = this.resolveMemorySession(filePath);\n\n if (!resolvedSession) {\n return;\n }\n\n const context: AdapterPublishContext = {\n cwd: resolvedSession.cwd,\n sessionId: resolvedSession.sessionId,\n source: 'aisnitch://adapters/openclaw/memory',\n };\n\n if (baseName === 'MEMORY.md') {\n await this.ensureSessionStarted(\n {\n cwd: resolvedSession.cwd,\n project: resolvedSession.project,\n projectPath: resolvedSession.cwd,\n raw: {\n filePath,\n source: 'memory-file',\n },\n },\n context,\n );\n await this.emitStateChange(\n 'agent.compact',\n {\n cwd: resolvedSession.cwd,\n project: resolvedSession.project,\n projectPath: resolvedSession.cwd,\n raw: {\n filePath,\n source: 'memory-file',\n },\n },\n context,\n );\n return;\n }\n\n const lines = await this.readIncrementalLines(filePath, readFromStart);\n const snippet = lines.at(-1)?.trim();\n\n if (!snippet) {\n return;\n }\n\n await this.ensureSessionStarted(\n {\n cwd: resolvedSession.cwd,\n project: resolvedSession.project,\n projectPath: resolvedSession.cwd,\n raw: {\n filePath,\n source: 'memory-log',\n },\n },\n context,\n );\n await this.emitStateChange(\n 'agent.thinking',\n {\n cwd: resolvedSession.cwd,\n project: resolvedSession.project,\n projectPath: resolvedSession.cwd,\n raw: {\n filePath,\n snippet,\n source: 'memory-log',\n },\n },\n context,\n );\n }\n\n private resolveMemorySession(\n filePath: string,\n ): OpenClawSessionSnapshot | undefined {\n const workspaceDirectory =\n basename(filePath) === 'MEMORY.md' ? dirname(filePath) : dirname(dirname(filePath));\n\n for (const snapshot of this.sessionSnapshots.values()) {\n if (snapshot.cwd === workspaceDirectory) {\n return snapshot;\n }\n }\n\n const sessionId = resolveSessionId({\n cwd: workspaceDirectory,\n projectPath: workspaceDirectory,\n sessionId: `openclaw:${basename(workspaceDirectory)}:memory`,\n tool: this.name,\n });\n\n return {\n cwd: workspaceDirectory,\n project: basename(workspaceDirectory) || workspaceDirectory,\n sessionId,\n };\n }\n\n private async readIncrementalLines(\n filePath: string,\n readFromStart: boolean,\n ): Promise<readonly string[]> {\n let fileContent: Buffer;\n\n try {\n fileContent = await readFile(filePath);\n } catch (error) {\n logger.debug({ error, filePath }, 'OpenClaw source read skipped');\n return [];\n }\n\n const knownOffset = this.fileOffsets.get(filePath);\n const previousOffset =\n knownOffset ??\n (readFromStart ? 0 : fileContent.byteLength);\n const safeOffset =\n previousOffset > fileContent.byteLength ? 0 : previousOffset;\n const newChunk = fileContent.subarray(safeOffset).toString('utf8');\n const bufferedChunk =\n (safeOffset === 0 ? '' : this.fileRemainders.get(filePath) ?? '') +\n newChunk;\n const lines = bufferedChunk.split(/\\r?\\n/u);\n const remainder =\n bufferedChunk.endsWith('\\n') || bufferedChunk.endsWith('\\r')\n ? ''\n : (lines.pop() ?? '');\n\n this.fileOffsets.set(filePath, fileContent.byteLength);\n this.fileRemainders.set(filePath, remainder);\n\n return lines\n .map((line) => line.trimEnd())\n .filter((line) => line.trim().length > 0);\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.processPoller = setInterval(() => {\n void this.pollOpenClawProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n\n void this.pollOpenClawProcesses();\n }\n\n private async pollOpenClawProcesses(): Promise<void> {\n const processes = await listOpenClawProcesses(this.processListCommand);\n const observedPids = new Set<number>();\n\n for (const processInfo of processes) {\n observedPids.add(processInfo.pid);\n\n if (this.fallbackProcessSessions.has(processInfo.pid)) {\n continue;\n }\n\n const cwd = await this.cwdResolver(processInfo.pid);\n const sessionId = resolveSessionId({\n cwd,\n pid: processInfo.pid,\n projectPath: cwd,\n sessionId: `openclaw-process-${processInfo.pid}`,\n tool: this.name,\n });\n const data: Omit<EventData, 'state'> = {\n cwd,\n project: cwd ? basename(cwd) || cwd : undefined,\n projectPath: cwd,\n raw: {\n process: processInfo,\n source: 'process-detect',\n },\n };\n const context: AdapterPublishContext = {\n cwd,\n pid: processInfo.pid,\n sessionId,\n source: 'aisnitch://adapters/openclaw/process-detect',\n };\n\n this.fallbackProcessSessions.set(processInfo.pid, sessionId);\n this.sessionSnapshots.set(sessionId, {\n cwd,\n project: data.project,\n sessionId,\n });\n await this.emitOpenClawSessionStart(data, context);\n }\n\n for (const [pid, sessionId] of this.fallbackProcessSessions) {\n if (observedPids.has(pid)) {\n continue;\n }\n\n this.fallbackProcessSessions.delete(pid);\n await this.emitOpenClawSessionEnd(\n {\n raw: {\n pid,\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n sessionId,\n source: 'aisnitch://adapters/openclaw/process-detect',\n },\n );\n }\n }\n}\n\nasync function collectFilesRecursively(\n directory: string,\n extension: string,\n): Promise<string[]> {\n try {\n const directoryEntries = await readdir(directory, {\n withFileTypes: true,\n });\n const nestedFiles = await Promise.all(\n directoryEntries.map(async (entry) => {\n const entryPath = join(directory, entry.name);\n\n if (entry.isDirectory()) {\n return await collectFilesRecursively(entryPath, extension);\n }\n\n return extname(entry.name) === extension ? [entryPath] : [];\n }),\n );\n\n return nestedFiles.flat();\n } catch {\n return [];\n }\n}\n\nasync function listOpenClawProcesses(\n listCommand: () => Promise<string>,\n): Promise<OpenClawProcessInfo[]> {\n if (process.platform === 'win32') {\n return [];\n }\n\n try {\n const stdout = await listCommand();\n\n return stdout\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n const match = line.match(/^(\\d+)\\s+(.+)$/u);\n\n if (!match) {\n return null;\n }\n\n const pidText = match[1];\n const command = match[2];\n\n if (!pidText || !command) {\n return null;\n }\n\n return {\n command,\n pid: Number.parseInt(pidText, 10),\n } satisfies OpenClawProcessInfo;\n })\n .filter((value): value is OpenClawProcessInfo => value !== null);\n } catch (error) {\n const errorCode =\n error instanceof Error && 'code' in error ? String(error.code) : '';\n\n if (\n error instanceof Error &&\n 'code' in error &&\n (errorCode === 'ENOENT' || errorCode === '1')\n ) {\n return [];\n }\n\n logger.debug({ error }, 'OpenClaw process detection failed');\n return [];\n }\n}\n\nfunction buildOpenClawEventData(\n payload: Record<string, unknown>,\n): Omit<EventData, 'state'> {\n const cwd = extractOpenClawCwd(payload);\n const project = extractOpenClawProject(payload);\n const toolInput = extractOpenClawToolInput(payload);\n\n return {\n activeFile: extractOpenClawActiveFile(payload) ?? toolInput?.filePath,\n cwd,\n errorMessage: extractOpenClawErrorMessage(payload),\n errorType: inferOpenClawErrorType(payload),\n model: extractOpenClawModel(payload),\n project,\n projectPath: cwd,\n raw: payload,\n toolInput,\n toolName: extractOpenClawToolName(payload),\n tokensUsed: extractOpenClawTokens(payload),\n };\n}\n\nfunction extractOpenClawEventName(\n payload: Record<string, unknown>,\n): string | undefined {\n const explicitEvent =\n getString(payload, 'event') ??\n getString(payload, 'hook_event_name') ??\n getString(payload, 'hookEventName');\n\n if (explicitEvent) {\n return explicitEvent;\n }\n\n const type = getString(payload, 'type');\n const action = getString(payload, 'action');\n\n if (!type) {\n return undefined;\n }\n\n if (!action) {\n return type;\n }\n\n if (type === 'command' && !action.startsWith('/') && !action.includes(':')) {\n return `command:${action}`;\n }\n\n return `${type}:${action}`;\n}\n\nfunction extractOpenClawSessionKey(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'sessionKey') ??\n getString(payload, 'sessionId') ??\n getString(payload, 'session_id') ??\n getString(getRecord(payload.context), 'sessionKey') ??\n getString(getRecord(payload.context), 'sessionId') ??\n getString(getRecord(payload.context), 'session_id') ??\n getString(getRecord(payload.context), 'sessionEntry')\n );\n}\n\nfunction extractOpenClawCwd(\n payload: Record<string, unknown>,\n): string | undefined {\n const context = getRecord(payload.context);\n\n return (\n getString(payload, 'cwd') ??\n getString(payload, 'workspaceDir') ??\n getString(context, 'workspaceDir') ??\n getString(context, 'cwd')\n );\n}\n\nfunction extractOpenClawProject(\n payload: Record<string, unknown>,\n): string | undefined {\n const cwd = extractOpenClawCwd(payload);\n\n if (cwd) {\n return basename(cwd) || cwd;\n }\n\n return (\n getString(payload, 'project') ??\n getString(getRecord(payload.context), 'project')\n );\n}\n\nfunction extractOpenClawActiveFile(\n payload: Record<string, unknown>,\n): string | undefined {\n const toolInput = extractOpenClawToolInput(payload);\n\n return (\n getString(payload, 'activeFile') ??\n getString(payload, 'filePath') ??\n getString(getRecord(payload.context), 'filePath') ??\n toolInput?.filePath\n );\n}\n\nfunction extractOpenClawToolName(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'toolName') ??\n getString(payload, 'tool_name') ??\n getString(getRecord(payload.tool), 'name') ??\n getString(getRecord(payload.data), 'toolName') ??\n getString(getRecord(payload.result), 'toolName')\n );\n}\n\nfunction extractOpenClawToolInput(\n payload: Record<string, unknown>,\n): ToolInput | undefined {\n const context = getRecord(payload.context);\n const argsRecord =\n getRecord(payload.toolInput) ??\n getRecord(payload.tool_input) ??\n getRecord(payload.params) ??\n getRecord(payload.arguments) ??\n getRecord(getRecord(payload.tool)?.params) ??\n getRecord(getRecord(payload.tool)?.arguments) ??\n getRecord(context?.params) ??\n getRecord(context?.arguments);\n const filePath =\n getString(payload, 'filePath') ??\n getString(argsRecord, 'filePath') ??\n getString(argsRecord, 'path');\n const command =\n getString(payload, 'command') ??\n getString(argsRecord, 'command') ??\n getString(argsRecord, 'cmd');\n\n if (!filePath && !command) {\n return undefined;\n }\n\n return {\n ...(command ? { command } : {}),\n ...(filePath ? { filePath } : {}),\n };\n}\n\nfunction extractOpenClawErrorMessage(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'error') ??\n getString(payload, 'message') ??\n getString(getRecord(payload.error), 'message') ??\n getString(getRecord(payload.result), 'error')\n );\n}\n\nfunction inferOpenClawErrorType(\n payload: Record<string, unknown>,\n): ErrorType | undefined {\n const errorMessage = extractOpenClawErrorMessage(payload);\n\n if (!errorMessage) {\n return undefined;\n }\n\n const normalizedMessage = errorMessage.toLowerCase();\n\n if (normalizedMessage.includes('rate limit') || normalizedMessage.includes('quota')) {\n return 'rate_limit';\n }\n\n if (\n normalizedMessage.includes('context window') ||\n normalizedMessage.includes('context length') ||\n normalizedMessage.includes('too many tokens')\n ) {\n return 'context_overflow';\n }\n\n return OPENCLAW_ERROR_HINT.test(errorMessage) ? 'tool_failure' : 'api_error';\n}\n\nfunction extractOpenClawModel(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'model') ??\n getString(getRecord(payload.context), 'model') ??\n getString(getRecord(payload.sessionEntry), 'model')\n );\n}\n\nfunction extractOpenClawTokens(\n payload: Record<string, unknown>,\n): number | undefined {\n const directTokens =\n getNumber(payload, 'totalTokens') ??\n getNumber(payload, 'tokensUsed') ??\n getNumber(getRecord(payload.sessionEntry), 'totalTokens') ??\n getNumber(getRecord(payload.stats), 'totalTokens');\n\n return directTokens === undefined ? undefined : Math.max(0, directTokens);\n}\n\nfunction isOpenClawCodingTool(\n toolName: string | undefined,\n toolInput: ToolInput | undefined,\n): boolean {\n return Boolean(\n toolInput?.filePath ||\n (toolName && OPENCLAW_CODING_TOOL_HINT.test(toolName)),\n );\n}\n\nfunction inferOpenClawSessionIdFromTranscriptPath(\n filePath: string,\n): string | undefined {\n const fileName = basename(filePath, extname(filePath));\n\n return fileName.length > 0 ? fileName : undefined;\n}\n\nfunction extractOpenClawTranscriptToolObservation(\n payload: Record<string, unknown>,\n):\n | {\n readonly activeFile?: string;\n readonly toolInput?: ToolInput;\n readonly toolName?: string;\n readonly type: AISnitchEventType;\n }\n | null {\n const nestedMessage = getRecord(payload.message) ?? getRecord(payload.data);\n const role =\n getString(payload, 'role') ??\n getString(nestedMessage, 'role') ??\n getString(getRecord(payload.entry), 'role');\n const toolName =\n extractOpenClawToolName(payload) ??\n getString(nestedMessage, 'name') ??\n getString(getRecord(payload.tool), 'name');\n const toolInput = extractOpenClawToolInput(payload);\n const activeFile =\n extractOpenClawActiveFile(payload) ??\n getString(nestedMessage, 'filePath') ??\n toolInput?.filePath;\n const content = getString(nestedMessage, 'content');\n const looksLikeToolPayload = Boolean(\n role === 'tool' ||\n role === 'tool_result' ||\n toolName ||\n getString(payload, 'type') === 'tool_result' ||\n content?.includes('tool') ||\n Array.isArray(getRecord(nestedMessage)?.content),\n );\n\n if (!looksLikeToolPayload) {\n return null;\n }\n\n return {\n activeFile,\n toolInput,\n toolName,\n type: isOpenClawCodingTool(toolName, toolInput)\n ? 'agent.coding'\n : 'agent.tool_call',\n };\n}\n\nfunction extractOpenClawTranscriptThinkingText(\n payload: Record<string, unknown>,\n): string | undefined {\n const directReasoning =\n getString(payload, 'reasoning') ??\n getString(getRecord(payload.message), 'reasoning') ??\n getString(getRecord(payload.data), 'reasoning');\n\n if (directReasoning) {\n return directReasoning;\n }\n\n const content = getRecord(payload.message)?.content;\n\n if (!Array.isArray(content)) {\n return undefined;\n }\n\n for (const item of content) {\n const itemRecord = getRecord(item);\n const itemType = getString(itemRecord, 'type');\n\n if (itemType === 'thinking' || itemType === 'reasoning') {\n return (\n getString(itemRecord, 'thinking') ??\n getString(itemRecord, 'text') ??\n getString(itemRecord, 'content')\n );\n }\n }\n\n return undefined;\n}\n\nfunction extractOpenClawTranscriptStreamingText(\n payload: Record<string, unknown>,\n): string | undefined {\n const directText =\n getString(payload, 'text') ??\n getString(getRecord(payload.message), 'text') ??\n getString(getRecord(payload.data), 'text');\n\n if (directText) {\n return directText;\n }\n\n const content = getRecord(payload.message)?.content;\n\n if (!Array.isArray(content)) {\n return undefined;\n }\n\n for (const item of content) {\n const itemRecord = getRecord(item);\n const itemType = getString(itemRecord, 'type');\n\n if (itemType === 'text' || itemType === 'output_text') {\n return getString(itemRecord, 'text') ?? getString(itemRecord, 'content');\n }\n }\n\n return undefined;\n}\n\nfunction parseJsonRecord(value: string): Record<string, unknown> | null {\n try {\n const parsedValue = JSON.parse(value) as unknown;\n\n return getRecord(parsedValue) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n const value = payload?.[key];\n\n return typeof value === 'string' && value.trim().length > 0\n ? value\n : undefined;\n}\n\nfunction getNumber(\n payload: Record<string, unknown> | undefined,\n key: string,\n): number | undefined {\n const value = payload?.[key];\n\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport { logger } from '../core/engine/logger.js';\nimport { resolveSessionId } from '../core/session-identity.js';\nimport type { ErrorType, EventData, ToolInput } from '../core/events/types.js';\nimport {\n type AdapterPublishContext,\n type AdapterRuntimeOptions,\n BaseAdapter,\n type InterceptionStrategy,\n} from './base.js';\n\n/**\n * @file src/adapters/opencode.ts\n * @description OpenCode adapter centered on the official plugin system plus process fallback detection.\n * @functions\n * โ none\n * @exports OpenCodeAdapter, OpenCodeAdapterOptions\n * @see ./base.ts\n * @see ../cli/commands/setup.ts\n * @see ../../tasks/04-adapters-priority/03_adapters-priority_opencode.md\n */\n\nconst execFile = promisify(execFileCallback);\n\nconst OPENCODE_CODING_TOOLS = new Set(['edit', 'multi_edit', 'write']);\n\n/**\n * OpenCode officially documents plugin hooks and ACP subprocess support.\n * The plugin path is the stable passive-observer option for AISnitch today;\n * ACP is interactive editor transport, not a passive tap into a running TUI.\n */\nexport interface OpenCodeAdapterOptions extends AdapterRuntimeOptions {\n readonly pollIntervalMs?: number;\n readonly processListCommand?: () => Promise<string>;\n}\n\ninterface ProcessInfo {\n readonly command: string;\n readonly pid: number;\n}\n\n/**\n * ๐ The setup command already installs an OpenCode plugin that forwards\n * events over HTTP, so this adapter mostly focuses on mapping that stream\n * cleanly and falling back to process detection when setup was skipped.\n */\nexport class OpenCodeAdapter extends BaseAdapter {\n public override readonly displayName = 'OpenCode';\n\n public override readonly name = 'opencode' as const;\n\n public override readonly strategies: readonly InterceptionStrategy[] = [\n 'hooks',\n 'process-detect',\n ];\n\n private fallbackProcessSessionId: string | null = null;\n\n private readonly pollIntervalMs: number;\n\n private processPoller: NodeJS.Timeout | null = null;\n\n private readonly processListCommand: () => Promise<string>;\n\n public constructor(options: OpenCodeAdapterOptions) {\n super(options);\n this.pollIntervalMs = options.pollIntervalMs ?? 5_000;\n this.processListCommand =\n options.processListCommand ?? (async () => await execFile('pgrep', ['-lf', 'opencode']).then((result) => result.stdout));\n }\n\n public override start(): Promise<void> {\n if (this.getStatus().running) {\n return Promise.resolve();\n }\n\n this.setRunning(true);\n this.startProcessPolling();\n\n return Promise.resolve();\n }\n\n public override stop(): Promise<void> {\n if (this.processPoller !== null) {\n clearInterval(this.processPoller);\n this.processPoller = null;\n }\n\n this.fallbackProcessSessionId = null;\n this.setRunning(false);\n\n return Promise.resolve();\n }\n\n public override async handleHook(payload: unknown): Promise<void> {\n const normalizedPayload = this.parseNormalizedHookPayload(payload);\n\n if (normalizedPayload !== null) {\n await this.emitNormalizedPayload({\n ...normalizedPayload,\n sessionId: resolveSessionId({\n activeFile: normalizedPayload.data?.activeFile,\n cwd: normalizedPayload.data?.cwd ?? normalizedPayload.cwd,\n pid: normalizedPayload.pid,\n project: normalizedPayload.data?.project,\n projectPath: normalizedPayload.data?.projectPath,\n sessionId: normalizedPayload.sessionId,\n tool: this.name,\n }),\n });\n return;\n }\n\n if (!isRecord(payload)) {\n logger.warn({ payload }, 'OpenCode payload must be an object');\n return;\n }\n\n const eventType = getString(payload, 'type');\n\n if (!eventType) {\n logger.warn({ payload }, 'OpenCode payload is missing its event type');\n return;\n }\n\n const sessionId = resolveSessionId({\n activeFile: extractOpenCodeActiveFile(payload),\n cwd: extractOpenCodeCwd(payload),\n pid: getNumber(payload, 'pid'),\n project: extractOpenCodeProject(payload),\n sessionId: extractOpenCodeSessionId(payload),\n tool: this.name,\n });\n const context: AdapterPublishContext = {\n cwd: extractOpenCodeCwd(payload),\n hookPayload: payload,\n pid: getNumber(payload, 'pid'),\n sessionId,\n source: 'aisnitch://adapters/opencode',\n };\n const sharedData = {\n activeFile: extractOpenCodeActiveFile(payload),\n cwd: context.cwd,\n errorMessage: extractOpenCodeErrorMessage(payload),\n errorType: extractOpenCodeErrorType(payload),\n project: extractOpenCodeProject(payload),\n raw: payload,\n toolInput: extractOpenCodeToolInput(payload),\n toolName: extractOpenCodeToolName(payload),\n } satisfies Omit<EventData, 'state'>;\n\n switch (eventType) {\n case 'session.created': {\n this.fallbackProcessSessionId = null;\n await this.emitStateChange('session.start', sharedData, context);\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'session.deleted': {\n await this.emitStateChange('session.end', sharedData, context);\n return;\n }\n case 'session.error': {\n await this.emitStateChange('agent.error', sharedData, context);\n return;\n }\n case 'session.idle': {\n await this.emitStateChange('agent.idle', sharedData, context);\n return;\n }\n case 'session.compacted': {\n await this.emitStateChange('agent.compact', sharedData, context);\n return;\n }\n case 'message.updated':\n case 'message.part.updated': {\n await this.emitStateChange('agent.streaming', sharedData, context);\n return;\n }\n case 'permission.asked': {\n await this.emitStateChange('agent.asking_user', sharedData, context);\n return;\n }\n case 'tool.execute.before': {\n await this.emitStateChange('agent.tool_call', sharedData, context);\n return;\n }\n case 'tool.execute.after': {\n const emittedType = isOpenCodeCodingTool(sharedData.toolName)\n ? 'agent.coding'\n : 'agent.tool_call';\n await this.emitStateChange(emittedType, sharedData, context);\n return;\n }\n default: {\n logger.debug({ eventType }, 'OpenCode event ignored by adapter');\n }\n }\n }\n\n private startProcessPolling(): void {\n if (this.pollIntervalMs <= 0) {\n return;\n }\n\n this.processPoller = setInterval(() => {\n void this.pollOpenCodeProcesses();\n }, this.pollIntervalMs);\n this.processPoller.unref();\n\n void this.pollOpenCodeProcesses();\n }\n\n private async pollOpenCodeProcesses(): Promise<void> {\n const processes = await listProcesses(this.processListCommand);\n\n if (processes.length > 0 && this.getStatus().activeSessions === 0) {\n const processInfo = processes[0];\n\n if (!processInfo) {\n return;\n }\n\n const sessionId = `opencode-process-${processInfo.pid}`;\n\n this.fallbackProcessSessionId = sessionId;\n await this.emitStateChange(\n 'session.start',\n {\n raw: {\n process: processInfo,\n source: 'process-detect',\n },\n },\n {\n pid: processInfo.pid,\n sessionId,\n source: 'aisnitch://adapters/opencode/process-detect',\n },\n );\n return;\n }\n\n if (processes.length === 0 && this.fallbackProcessSessionId !== null) {\n const sessionId = this.fallbackProcessSessionId;\n\n this.fallbackProcessSessionId = null;\n await this.emitStateChange(\n 'session.end',\n {\n raw: {\n reason: 'process-exit',\n source: 'process-detect',\n },\n },\n {\n sessionId,\n source: 'aisnitch://adapters/opencode/process-detect',\n },\n );\n }\n }\n}\n\nasync function listProcesses(\n listCommand: () => Promise<string>,\n): Promise<ProcessInfo[]> {\n if (process.platform === 'win32') {\n return [];\n }\n\n try {\n const stdout = await listCommand();\n\n return stdout\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n const match = line.match(/^(\\d+)\\s+(.+)$/u);\n\n if (!match) {\n return null;\n }\n\n const pidText = match[1];\n const command = match[2];\n\n if (!pidText || !command) {\n return null;\n }\n\n return {\n command,\n pid: Number.parseInt(pidText, 10),\n } satisfies ProcessInfo;\n })\n .filter((processInfo): processInfo is ProcessInfo => processInfo !== null);\n } catch (error) {\n const errorCode =\n error instanceof Error && 'code' in error ? String(error.code) : '';\n\n if (\n error instanceof Error &&\n 'code' in error &&\n (errorCode === 'ENOENT' || errorCode === '1')\n ) {\n return [];\n }\n\n logger.debug({ error }, 'OpenCode process detection failed');\n return [];\n }\n}\n\nfunction extractOpenCodeSessionId(\n payload: Record<string, unknown>,\n): string | undefined {\n const directSessionId =\n getString(payload, 'sessionID') ??\n getString(payload, 'sessionId');\n\n if (directSessionId) {\n return directSessionId;\n }\n\n const properties = getRecord(payload.properties);\n\n return getString(properties, 'sessionID') ?? getString(properties, 'sessionId');\n}\n\nfunction extractOpenCodeCwd(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'cwd') ??\n getString(getRecord(payload.properties), 'cwd')\n );\n}\n\nfunction extractOpenCodeProject(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'project') ??\n getString(getRecord(payload.properties), 'project')\n );\n}\n\nfunction extractOpenCodeToolName(\n payload: Record<string, unknown>,\n): string | undefined {\n const tool = getRecord(payload.tool);\n\n return getString(tool, 'name') ?? getString(payload, 'tool');\n}\n\nfunction extractOpenCodeActiveFile(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(payload, 'file') ??\n getString(getRecord(payload.properties), 'file') ??\n extractOpenCodeToolInput(payload)?.filePath\n );\n}\n\nfunction extractOpenCodeToolInput(\n payload: Record<string, unknown>,\n): ToolInput | undefined {\n const args =\n getRecord(payload.args) ??\n getRecord(getRecord(payload.output)?.args) ??\n getRecord(getRecord(payload.properties)?.args);\n\n if (!args) {\n return undefined;\n }\n\n const command =\n getString(args, 'command') ??\n getString(args, 'cmd');\n const filePath =\n getString(args, 'filePath') ??\n getString(args, 'file_path') ??\n getString(args, 'path');\n\n if (!command && !filePath) {\n return undefined;\n }\n\n return {\n command,\n filePath,\n };\n}\n\nfunction extractOpenCodeErrorMessage(\n payload: Record<string, unknown>,\n): string | undefined {\n return (\n getString(getRecord(payload.error), 'message') ??\n getString(payload, 'message')\n );\n}\n\nfunction extractOpenCodeErrorType(\n payload: Record<string, unknown>,\n): ErrorType | undefined {\n const rawType =\n getString(payload, 'errorType') ??\n getString(getRecord(payload.error), 'type');\n\n switch (rawType) {\n case 'rate_limit':\n return 'rate_limit';\n case 'context_overflow':\n return 'context_overflow';\n case 'tool_failure':\n return 'tool_failure';\n case 'api_error':\n case 'provider_error':\n return 'api_error';\n default:\n return undefined;\n }\n}\n\nfunction isOpenCodeCodingTool(toolName?: string): boolean {\n return toolName !== undefined && OPENCODE_CODING_TOOLS.has(toolName);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction getNumber(\n payload: Record<string, unknown>,\n key: string,\n): number | undefined {\n const value = payload[key];\n\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined;\n}\n","import type { AISnitchConfig } from '../core/config/schema.js';\nimport type { ToolName } from '../core/events/types.js';\nimport type { AdapterStatus, BaseAdapter } from './base.js';\n\n/**\n * @file src/adapters/registry.ts\n * @description Adapter registry that owns built-in adapter instances and orchestrates their lifecycle.\n * @functions\n * โ none\n * @exports AdapterRegistry\n * @see ./base.ts\n * @see ./index.ts\n */\n\n/**\n * ๐ The registry is intentionally tiny: one place to register adapters, one\n * place to start/stop them, and one place to ask what is alive right now.\n */\nexport class AdapterRegistry {\n private readonly adapters = new Map<ToolName, BaseAdapter>();\n\n /**\n * Registers one built-in or community adapter instance.\n */\n public register(adapter: BaseAdapter): void {\n if (this.adapters.has(adapter.name)) {\n throw new Error(`Adapter \"${adapter.name}\" is already registered.`);\n }\n\n this.adapters.set(adapter.name, adapter);\n }\n\n /**\n * Returns one adapter instance by its tool name.\n */\n public get(toolName: ToolName): BaseAdapter | undefined {\n return this.adapters.get(toolName);\n }\n\n /**\n * Lists every registered adapter.\n */\n public list(): BaseAdapter[] {\n return [...this.adapters.values()];\n }\n\n /**\n * Returns one status snapshot per registered adapter.\n */\n public getStatus(): AdapterStatus[] {\n return this.list().map((adapter) => adapter.getStatus());\n }\n\n /**\n * Starts every adapter enabled in the current AISnitch config.\n */\n public async startAll(config: AISnitchConfig): Promise<void> {\n for (const adapter of this.list()) {\n if (config.adapters[adapter.name]?.enabled !== true) {\n continue;\n }\n\n await adapter.start();\n }\n }\n\n /**\n * Stops every adapter in reverse registration order.\n */\n public async stopAll(): Promise<void> {\n const adapters = this.list().reverse();\n\n for (const adapter of adapters) {\n await adapter.stop();\n }\n }\n}\n","import { basename } from 'node:path';\n\nimport { spawn as spawnPty, type IPty } from '@lydell/node-pty';\nimport stripAnsi from 'strip-ansi';\n\nimport { createEvent } from '../core/events/factory.js';\nimport type {\n AISnitchEvent,\n AISnitchEventType,\n ErrorType,\n EventData,\n ToolName,\n} from '../core/events/types.js';\nimport { ContextDetector } from '../core/engine/context-detector.js';\nimport { resolveSessionId } from '../core/session-identity.js';\n\n/**\n * @file src/adapters/generic-pty.ts\n * @description Generic PTY wrapper used by `aisnitch wrap` to observe interactive tools without first-class adapters.\n * @functions\n * โ analyzeTerminalOutputChunk\n * @exports GenericPTYSession, GenericPTYSessionOptions, GenericPTYObservation, analyzeTerminalOutputChunk\n * @see ../cli/runtime.ts\n * @see ../../tasks/06-adapters-secondary/03_adapters-secondary_aider-pty_DONE.md\n */\n\nconst PTY_ERROR_HINT = /error|exception|failed|traceback|refused|denied/iu;\nconst PTY_ASKING_USER_HINT =\n /\\b\\(Y(?:es)?\\/N(?:o)?\\)|\\bPress Enter\\b|\\bcontinue\\?\\b|\\bselect\\b|\\bchoose\\b|\\bapprove\\b/iu;\nconst PTY_THINKING_HINT =\n /thinking|analyzing|planning|reasoning|reflecting|compacting|summarizing/iu;\nconst PTY_CODING_HINT =\n /apply_patch|creating|deleting|editing|patch|renaming|replacing|search\\/replace|updating|writing|<<<<<<<|>>>>>>>|diff --git/iu;\nconst PTY_SPINNER_FRAME_HINT = /[|/\\\\-]|[โ โ โ นโ ธโ ผโ ดโ ฆโ งโ โ ]/u;\n\nexport interface GenericPTYSessionOptions {\n readonly args: readonly string[];\n readonly command: string;\n readonly cwd: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly publishEvent: (\n event: AISnitchEvent,\n context?: {\n readonly cwd?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly pid?: number;\n },\n ) => Promise<boolean>;\n readonly rows?: number;\n readonly cols?: number;\n readonly stdin?: NodeJS.ReadStream;\n readonly stdout?: NodeJS.WriteStream;\n}\n\nexport interface GenericPTYObservation {\n readonly fingerprint: string;\n readonly type: AISnitchEventType;\n readonly data: Omit<EventData, 'state'>;\n}\n\n/**\n * ๐ The wrapper deliberately uses heuristics instead of pretending it has a\n * stable protocol. Its job is to recover useful live signals from messy ANSI.\n */\nexport class GenericPTYSession {\n private readonly args: readonly string[];\n\n private readonly cols: number;\n\n private readonly command: string;\n\n private readonly commandLine: string;\n\n private readonly contextDetector = new ContextDetector();\n\n private readonly cwd: string;\n\n private readonly env: NodeJS.ProcessEnv;\n\n private lastObservationFingerprint: string | null = null;\n\n private readonly publishEvent: GenericPTYSessionOptions['publishEvent'];\n\n private readonly rows: number;\n\n private sequenceNumber = 0;\n\n private readonly stdin: NodeJS.ReadStream;\n\n private readonly stdout: NodeJS.WriteStream;\n\n private readonly tool: ToolName;\n\n private userInputBuffer = '';\n\n public constructor(options: GenericPTYSessionOptions) {\n this.args = options.args;\n this.command = options.command;\n this.commandLine = [options.command, ...options.args].join(' ').trim();\n this.cols = options.cols ?? process.stdout.columns ?? 120;\n this.cwd = options.cwd;\n this.env = {\n ...process.env,\n ...options.env,\n };\n this.publishEvent = options.publishEvent;\n this.rows = options.rows ?? process.stdout.rows ?? 32;\n this.stdin = options.stdin ?? process.stdin;\n this.stdout = options.stdout ?? process.stdout;\n this.tool = inferWrappedToolName(options.command, options.args);\n }\n\n /**\n * Launches the wrapped PTY session and resolves with the wrapped exit code.\n */\n public async run(): Promise<number> {\n const pty = spawnPty(this.command, [...this.args], {\n cols: this.cols,\n cwd: this.cwd,\n env: normalizePtyEnvironment(this.env),\n rows: this.rows,\n });\n const sessionId = resolveSessionId({\n cwd: this.cwd,\n pid: pty.pid,\n tool: this.tool,\n });\n const terminal = this.contextDetector.detectTerminal(this.env);\n\n await this.emitEvent(\n pty.pid,\n sessionId,\n 'session.start',\n {\n cwd: this.cwd,\n pid: pty.pid,\n project: basename(this.cwd) || this.cwd,\n projectPath: this.cwd,\n raw: {\n args: this.args,\n command: this.command,\n source: 'pty-wrap',\n },\n terminal,\n toolInput: {\n command: this.commandLine,\n },\n toolName: basename(this.command) || this.command,\n },\n );\n await this.emitEvent(\n pty.pid,\n sessionId,\n 'task.start',\n {\n cwd: this.cwd,\n pid: pty.pid,\n project: basename(this.cwd) || this.cwd,\n projectPath: this.cwd,\n raw: {\n args: this.args,\n command: this.command,\n source: 'pty-wrap',\n },\n terminal,\n toolInput: {\n command: this.commandLine,\n },\n },\n );\n\n return await new Promise<number>((resolve) => {\n let settled = false;\n let exitPoller: NodeJS.Timeout | null = null;\n const finalize = (exitCode: number, signal?: number) => {\n if (settled) {\n return;\n }\n\n settled = true;\n if (exitPoller !== null) {\n clearInterval(exitPoller);\n }\n void this.handleExit(pty, sessionId, terminal, exitCode, signal).finally(() => {\n inputCleanup();\n resizeCleanup();\n signalCleanup();\n dataDisposable.dispose();\n exitDisposable.dispose();\n resolve(exitCode);\n });\n };\n const dataDisposable = pty.onData((chunk: string) => {\n this.stdout.write(chunk);\n void this.handleOutputChunk(pty, sessionId, terminal, chunk);\n });\n const exitDisposable = pty.onExit(\n ({ exitCode, signal }: { exitCode: number; signal?: number }) => {\n finalize(exitCode, signal);\n },\n );\n exitPoller = setInterval(() => {\n if (!isPidRunning(pty.pid)) {\n finalize(0);\n }\n }, 200);\n exitPoller.unref();\n const inputCleanup = this.attachStdin(pty, sessionId, terminal);\n const resizeCleanup = this.attachResize(pty);\n const signalCleanup = this.attachParentSignals(pty);\n });\n }\n\n private attachParentSignals(pty: IPty): () => void {\n const handleSigterm = () => {\n pty.kill('SIGTERM');\n };\n const handleSigint = () => {\n pty.kill('SIGINT');\n };\n\n process.on('SIGTERM', handleSigterm);\n process.on('SIGINT', handleSigint);\n\n return () => {\n process.off('SIGTERM', handleSigterm);\n process.off('SIGINT', handleSigint);\n };\n }\n\n private attachResize(pty: IPty): () => void {\n if (!this.stdout.isTTY) {\n return () => undefined;\n }\n\n const handleResize = () => {\n pty.resize(process.stdout.columns ?? this.cols, process.stdout.rows ?? this.rows);\n };\n\n this.stdout.on('resize', handleResize);\n\n return () => {\n this.stdout.off('resize', handleResize);\n };\n }\n\n private attachStdin(\n pty: IPty,\n sessionId: string,\n terminal: string,\n ): () => void {\n const input = this.stdin;\n\n if (!input.isTTY) {\n return () => undefined;\n }\n\n const handleInput = (chunk: Buffer) => {\n pty.write(chunk);\n void this.captureUserInput(pty, sessionId, terminal, chunk.toString('utf8'));\n };\n\n input.resume();\n input.setRawMode?.(true);\n input.on('data', handleInput);\n\n return () => {\n input.off('data', handleInput);\n input.setRawMode?.(false);\n void this.flushUserInput(sessionId, pty.pid, terminal);\n };\n }\n\n private async captureUserInput(\n pty: IPty,\n sessionId: string,\n terminal: string,\n chunk: string,\n ): Promise<void> {\n const sanitizedChunk = stripTerminalControlCharacters(chunk);\n\n if (sanitizedChunk.includes('\\r') || sanitizedChunk.includes('\\n')) {\n await this.flushUserInput(sessionId, pty.pid, terminal);\n return;\n }\n\n const printableChunk = sanitizedChunk.trim();\n\n if (printableChunk.length === 0) {\n return;\n }\n\n this.userInputBuffer = `${this.userInputBuffer}${printableChunk}`;\n\n if (this.userInputBuffer.length >= 120) {\n await this.flushUserInput(sessionId, pty.pid, terminal);\n }\n }\n\n private async flushUserInput(\n sessionId: string,\n pid: number,\n terminal: string,\n ): Promise<void> {\n const input = this.userInputBuffer.trim();\n\n if (input.length === 0) {\n this.userInputBuffer = '';\n return;\n }\n\n this.userInputBuffer = '';\n\n await this.emitEvent(\n pid,\n sessionId,\n 'agent.asking_user',\n {\n cwd: this.cwd,\n pid,\n raw: {\n input,\n source: 'pty-stdin',\n },\n terminal,\n },\n );\n }\n\n private async handleOutputChunk(\n pty: IPty,\n sessionId: string,\n terminal: string,\n chunk: string,\n ): Promise<void> {\n const observation = analyzeTerminalOutputChunk({\n chunk,\n commandLine: this.commandLine,\n tool: this.tool,\n });\n\n if (!observation) {\n return;\n }\n\n if (this.lastObservationFingerprint === observation.fingerprint) {\n return;\n }\n\n this.lastObservationFingerprint = observation.fingerprint;\n await this.emitEvent(pty.pid, sessionId, observation.type, {\n cwd: this.cwd,\n pid: pty.pid,\n project: basename(this.cwd) || this.cwd,\n projectPath: this.cwd,\n terminal,\n ...observation.data,\n });\n }\n\n private async handleExit(\n pty: IPty,\n sessionId: string,\n terminal: string,\n exitCode: number,\n signal: number | undefined,\n ): Promise<void> {\n await this.flushUserInput(sessionId, pty.pid, terminal);\n\n if (exitCode !== 0) {\n await this.emitEvent(\n pty.pid,\n sessionId,\n 'agent.error',\n {\n cwd: this.cwd,\n errorMessage: `Wrapped process exited with code ${exitCode}.`,\n errorType: 'tool_failure',\n pid: pty.pid,\n raw: {\n exitCode,\n signal,\n source: 'pty-wrap',\n },\n terminal,\n },\n );\n }\n\n await this.emitEvent(\n pty.pid,\n sessionId,\n 'session.end',\n {\n cwd: this.cwd,\n pid: pty.pid,\n raw: {\n exitCode,\n signal,\n source: 'pty-wrap',\n },\n terminal,\n },\n );\n }\n\n private async emitEvent(\n pid: number,\n sessionId: string,\n type: AISnitchEventType,\n data: Omit<EventData, 'state'>,\n ): Promise<void> {\n this.sequenceNumber += 1;\n\n await this.publishEvent(\n createEvent({\n source: `aisnitch://adapters/${this.tool}/pty-wrap`,\n type,\n 'aisnitch.tool': this.tool,\n 'aisnitch.sessionid': sessionId,\n 'aisnitch.seqnum': this.sequenceNumber,\n data,\n }),\n {\n cwd: this.cwd,\n env: this.env,\n pid,\n },\n );\n }\n}\n\n/**\n * Interprets one PTY chunk into the best-effort AISnitch activity state.\n */\nexport function analyzeTerminalOutputChunk(input: {\n readonly chunk: string;\n readonly commandLine: string;\n readonly tool: ToolName;\n}): GenericPTYObservation | null {\n const strippedText = stripAnsi(input.chunk)\n .replaceAll('\\u0007', '');\n const normalizedText = stripTerminalControlCharacters(strippedText)\n .replaceAll('\\r', '\\n')\n .trim();\n\n if (normalizedText.length === 0) {\n return null;\n }\n\n const activeFile = extractPathReference(normalizedText);\n const raw = {\n chunk: input.chunk,\n output: normalizedText,\n source: 'pty-wrap',\n } satisfies Record<string, unknown>;\n\n if (containsRedAnsi(input.chunk) || PTY_ERROR_HINT.test(normalizedText)) {\n return {\n data: {\n activeFile,\n errorMessage: normalizedText,\n errorType: classifyPtyErrorType(normalizedText),\n raw,\n },\n fingerprint: createPtyFingerprint('agent.error', normalizedText, activeFile),\n type: 'agent.error',\n };\n }\n\n if (PTY_ASKING_USER_HINT.test(normalizedText)) {\n return {\n data: {\n activeFile,\n raw,\n },\n fingerprint: createPtyFingerprint(\n 'agent.asking_user',\n normalizedText,\n activeFile,\n ),\n type: 'agent.asking_user',\n };\n }\n\n if (\n PTY_CODING_HINT.test(normalizedText) ||\n (activeFile !== undefined && /\\.(?:[cm]?[jt]sx?|json|md|py|rb|rs|sh|ya?ml)$/u.test(activeFile))\n ) {\n return {\n data: {\n activeFile,\n raw,\n toolInput: activeFile\n ? {\n filePath: activeFile,\n }\n : {\n command: input.commandLine,\n },\n toolName: activeFile ? 'file-edit' : basename(input.commandLine) || 'shell',\n },\n fingerprint: createPtyFingerprint('agent.coding', normalizedText, activeFile),\n type: 'agent.coding',\n };\n }\n\n if (containsSpinnerHint(input.chunk) || PTY_THINKING_HINT.test(normalizedText)) {\n return {\n data: {\n raw,\n },\n fingerprint: createPtyFingerprint('agent.thinking', normalizedText, activeFile),\n type: 'agent.thinking',\n };\n }\n\n return {\n data: {\n activeFile,\n raw,\n },\n fingerprint: createPtyFingerprint('agent.streaming', normalizedText, activeFile),\n type: 'agent.streaming',\n };\n}\n\nfunction normalizePtyEnvironment(\n env: NodeJS.ProcessEnv,\n): Record<string, string | undefined> {\n return Object.fromEntries(\n Object.entries(env).map(([key, value]) => [key, value]),\n );\n}\n\nfunction inferWrappedToolName(\n command: string,\n args: readonly string[],\n): ToolName {\n const commandBaseName = basename(command).toLowerCase();\n const fullCommandLine = [commandBaseName, ...args].join(' ').toLowerCase();\n const toolMatchers: readonly [ToolName, RegExp][] = [\n ['aider', /\\baider\\b/u],\n ['amp', /\\bamp\\b/u],\n ['claude-code', /\\bclaude\\b/u],\n ['copilot-cli', /\\bcopilot\\b/u],\n ['codex', /\\bcodex\\b/u],\n ['continue', /\\bcontinue\\b/u],\n ['cursor', /\\bcursor\\b/u],\n ['gemini-cli', /\\bgemini\\b/u],\n ['goose', /\\bgoose\\b/u],\n ['kilo', /\\bkilo\\b/u],\n ['openclaw', /\\bopenclaw\\b/u],\n ['opencode', /\\bopencode\\b/u],\n ['openhands', /\\bopenhands\\b/u],\n ['qwen-code', /\\bqwen\\b/u],\n ['windsurf', /\\bwindsurf\\b/u],\n ];\n\n for (const [toolName, matcher] of toolMatchers) {\n if (matcher.test(fullCommandLine)) {\n return toolName;\n }\n }\n\n return 'unknown';\n}\n\nfunction extractPathReference(text: string): string | undefined {\n const pathMatch = text.match(\n /(?:^|[\\s'\"])((?:\\.{0,2}\\/|\\/)?[A-Za-z0-9._/-]+\\.[A-Za-z0-9._-]+)(?=$|[\\s'\":,)])/u,\n );\n\n return pathMatch?.[1];\n}\n\nfunction classifyPtyErrorType(message: string): ErrorType {\n if (/rate limit|quota|too many requests/iu.test(message)) {\n return 'rate_limit';\n }\n\n if (/context|token limit|context window/iu.test(message)) {\n return 'context_overflow';\n }\n\n if (/write|edit|patch|apply|command failed|exit code/iu.test(message)) {\n return 'tool_failure';\n }\n\n return 'api_error';\n}\n\nfunction createPtyFingerprint(\n type: AISnitchEventType,\n text: string,\n activeFile?: string,\n): string {\n return [type, activeFile ?? '', text.replace(/\\s+/gu, ' ').slice(0, 240)].join(\n '::',\n );\n}\n\nfunction stripTerminalControlCharacters(value: string): string {\n return [...value]\n .filter((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n\n return !(\n (codePoint >= 0x00 && codePoint <= 0x08) ||\n (codePoint >= 0x0b && codePoint <= 0x1a) ||\n (codePoint >= 0x1c && codePoint <= 0x1f) ||\n codePoint === 0x7f\n );\n })\n .join('');\n}\n\nfunction containsRedAnsi(value: string): boolean {\n return (\n value.includes('\\u001B[31m') ||\n value.includes('\\u001B[0;31m') ||\n value.includes('\\u001B[91m')\n );\n}\n\nfunction containsSpinnerHint(value: string): boolean {\n return (\n (value.includes('\\r') || value.includes('\\u0008')) &&\n PTY_SPINNER_FRAME_HINT.test(value)\n );\n}\n\nfunction isPidRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error: unknown) {\n if (\n error instanceof Error &&\n 'code' in error &&\n (error.code === 'ESRCH' || error.code === 'ENOENT')\n ) {\n return false;\n }\n\n return true;\n }\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { basename } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport pidCwd from 'pid-cwd';\n\nimport type { AISnitchEvent, ToolName } from '../events/types.js';\nimport { logger } from './logger.js';\n\nconst execFile = promisify(execFileCallback);\n\n/**\n * @file src/core/engine/context-detector.ts\n * @description Best-effort runtime context enrichment for terminal, cwd, pid, and instance metadata.\n * @functions\n * โ none\n * @exports ProcessInfo, ProcessContext, EnrichedContextFields, ContextDetector\n * @see ../events/schema.ts\n */\n\n/**\n * Lightweight process metadata used during instance enumeration.\n */\nexport interface ProcessInfo {\n readonly pid: number;\n readonly cwd?: string;\n}\n\n/**\n * Context captured from a tool process, transcript path, or hook payload.\n */\nexport interface ProcessContext {\n readonly pid?: number;\n readonly env?: NodeJS.ProcessEnv;\n readonly sessionId?: string;\n readonly transcriptPath?: string;\n readonly hookPayload?: Record<string, unknown>;\n}\n\n/**\n * Context fields that AISnitch attaches into `event.data`.\n */\nexport interface EnrichedContextFields {\n readonly terminal?: string;\n readonly cwd?: string;\n readonly pid?: number;\n readonly instanceId?: string;\n readonly instanceIndex?: number;\n readonly instanceTotal?: number;\n}\n\ninterface CachedProcessContext {\n readonly terminal?: string;\n readonly cwd?: string;\n readonly instanceIndex?: number;\n readonly instanceTotal?: number;\n readonly expiresAt: number;\n}\n\ninterface CommandExecutionOptions {\n readonly timeoutMs?: number;\n}\n\ninterface ContextDetectorOptions {\n readonly cacheTtlMs?: number;\n readonly commandTimeoutMs?: number;\n readonly cwdResolver?: (pid: number) => Promise<string | undefined>;\n readonly execCommand?: (\n command: string,\n args: readonly string[],\n options?: CommandExecutionOptions,\n ) => Promise<string>;\n readonly now?: () => number;\n}\n\nconst TERM_PROGRAM_MAP: Record<string, string> = {\n Apple_Terminal: 'Terminal.app',\n Hyper: 'Hyper',\n 'iTerm.app': 'iTerm2',\n WezTerm: 'WezTerm',\n ghostty: 'Ghostty',\n tmux: 'tmux',\n vscode: 'VS Code',\n zed: 'Zed',\n};\n\nconst PROCESS_NAME_MAP: Record<string, string> = {\n Alacritty: 'Alacritty',\n Hyper: 'Hyper',\n Terminal: 'Terminal.app',\n Warp: 'Warp',\n WezTerm: 'WezTerm',\n ghostty: 'Ghostty',\n iTerm2: 'iTerm2',\n kitty: 'kitty',\n screen: 'screen',\n tmux: 'tmux',\n 'tmux: server': 'tmux',\n};\n\nconst TOOL_BINARY_MAP: Record<ToolName, string> = {\n aider: 'aider',\n amp: 'amp',\n cline: 'cline',\n 'claude-code': 'claude',\n 'copilot-cli': 'copilot',\n codex: 'codex',\n continue: 'continue',\n cursor: 'cursor',\n 'gemini-cli': 'gemini',\n goose: 'goose',\n kilo: 'kilo',\n openclaw: 'openclaw',\n opencode: 'opencode',\n openhands: 'openhands',\n 'qwen-code': 'qwen',\n unknown: 'unknown',\n windsurf: 'windsurf',\n};\n\n/**\n * ๐ Context enrichment is always best-effort. Failing to detect a terminal or\n * cwd must never break the event stream itself.\n */\nexport class ContextDetector {\n private readonly cache = new Map<number, CachedProcessContext>();\n\n private readonly cacheTtlMs: number;\n\n private readonly commandTimeoutMs: number;\n\n private readonly cwdResolver: (pid: number) => Promise<string | undefined>;\n\n private readonly execCommand: (\n command: string,\n args: readonly string[],\n options?: CommandExecutionOptions,\n ) => Promise<string>;\n\n private readonly now: () => number;\n\n public constructor(options: ContextDetectorOptions = {}) {\n this.cacheTtlMs = options.cacheTtlMs ?? 30_000;\n this.commandTimeoutMs = options.commandTimeoutMs ?? 500;\n this.cwdResolver =\n options.cwdResolver ?? ((pid) => this.resolveCwdWithPidCwd(pid));\n this.execCommand =\n options.execCommand ??\n ((command, args, commandOptions) =>\n this.defaultExecCommand(command, args, commandOptions));\n this.now = options.now ?? Date.now;\n }\n\n /**\n * Detects the terminal display name from environment variables.\n */\n public detectTerminal(env: NodeJS.ProcessEnv = {}): string {\n if (env.ITERM_SESSION_ID) {\n return 'iTerm2';\n }\n\n if (env.KITTY_WINDOW_ID) {\n return 'kitty';\n }\n\n if (env.WEZTERM_EXECUTABLE) {\n return 'WezTerm';\n }\n\n if (env.TERM_PROGRAM) {\n return TERM_PROGRAM_MAP[env.TERM_PROGRAM] ?? env.TERM_PROGRAM;\n }\n\n if (env.TERM === 'alacritty' || env.TERM?.includes('alacritty')) {\n return 'Alacritty';\n }\n\n if (env.TERM?.includes('ghostty')) {\n return 'Ghostty';\n }\n\n if (env.TMUX) {\n return 'tmux';\n }\n\n return 'unknown';\n }\n\n /**\n * Walks the parent-process chain looking for a known terminal emulator.\n */\n public async getTerminalFromPPIDChain(pid: number): Promise<string> {\n let currentPid = pid;\n\n for (let depth = 0; depth < 4 && currentPid > 0; depth += 1) {\n try {\n const stdout = await this.execCommand(\n 'ps',\n ['-p', String(currentPid), '-o', 'ppid=,comm='],\n { timeoutMs: this.commandTimeoutMs },\n );\n const line = stdout.trim();\n const match = line.match(/^(\\d+)\\s+(.+)$/u);\n\n if (!match) {\n return 'unknown';\n }\n\n const parentPidToken = match[1];\n const commandText = match[2];\n\n if (!parentPidToken || !commandText) {\n return 'unknown';\n }\n\n const nextPid = Number.parseInt(parentPidToken, 10);\n const normalizedProcessName = basename(commandText).replace(/\\.app$/u, '');\n const mappedTerminal =\n PROCESS_NAME_MAP[normalizedProcessName] ??\n PROCESS_NAME_MAP[commandText.trim()];\n\n if (mappedTerminal) {\n return mappedTerminal;\n }\n\n currentPid = nextPid;\n } catch (error: unknown) {\n logger.debug({ error, pid }, 'Terminal PPID chain lookup failed');\n return 'unknown';\n }\n }\n\n return 'unknown';\n }\n\n /**\n * Resolves the working directory for a running process with a fast timeout.\n */\n public async getCWDForPID(pid: number): Promise<string | undefined> {\n try {\n return await this.withTimeout(this.cwdResolver(pid));\n } catch (error: unknown) {\n logger.warn({ error, pid }, 'Primary PID cwd lookup failed');\n }\n\n if (process.platform !== 'darwin') {\n return undefined;\n }\n\n try {\n const stdout = await this.execCommand(\n 'lsof',\n ['-a', '-p', String(pid), '-d', 'cwd', '-Fn'],\n { timeoutMs: this.commandTimeoutMs },\n );\n const cwdLine = stdout\n .split('\\n')\n .find((line) => line.startsWith('n') && line.length > 1);\n\n return cwdLine?.slice(1) || undefined;\n } catch (error: unknown) {\n logger.warn({ error, pid }, 'Fallback PID cwd lookup failed');\n return undefined;\n }\n }\n\n /**\n * Decodes a Claude transcript path into its original project cwd when possible.\n */\n public decodeCWDFromTranscriptPath(\n transcriptPath: string,\n ): string | undefined {\n const match = transcriptPath.match(/\\.claude\\/projects\\/([^/]+)\\//u);\n\n if (!match?.[1] || !match[1].startsWith('-')) {\n return undefined;\n }\n\n return match[1].replace(/-/gu, '/');\n }\n\n /**\n * Enumerates active instances for a given tool binary using `pgrep`.\n */\n public async enumerateInstances(toolBinary: string): Promise<ProcessInfo[]> {\n if (process.platform === 'win32' || toolBinary === 'unknown') {\n return [];\n }\n\n try {\n const stdout = await this.execCommand(\n 'pgrep',\n ['-fl', toolBinary],\n { timeoutMs: this.commandTimeoutMs },\n );\n const lines = stdout\n .trim()\n .split('\\n')\n .filter((line) => line.trim().length > 0);\n\n const processRows: ProcessInfo[] = [];\n\n for (const line of lines) {\n const [pidToken] = line.trim().split(/\\s+/u, 1);\n const parsedPid = Number.parseInt(pidToken ?? '', 10);\n\n if (!Number.isFinite(parsedPid)) {\n continue;\n }\n\n processRows.push({\n pid: parsedPid,\n cwd: await this.getCWDForPID(parsedPid),\n });\n }\n\n return processRows.sort((left, right) => left.pid - right.pid);\n } catch (error: unknown) {\n logger.debug({ error, toolBinary }, 'Instance enumeration failed');\n return [];\n }\n }\n\n /**\n * Returns the 1-based position of the PID among active tool instances.\n */\n public async getInstanceIndex(\n pid: number,\n toolBinary: string,\n ): Promise<{ readonly index: number; readonly total: number }> {\n const instances = await this.enumerateInstances(toolBinary);\n const index = instances.findIndex((instance) => instance.pid === pid);\n\n return {\n index: index >= 0 ? index + 1 : 1,\n total: Math.max(instances.length, 1),\n };\n }\n\n /**\n * Builds a stable identifier for one tool instance.\n */\n public buildInstanceId(\n toolName: ToolName,\n pid: number,\n sessionId?: string,\n ): string {\n return `${toolName}:${sessionId ?? pid}`;\n }\n\n /**\n * Enriches an AISnitch event with best-effort runtime context.\n */\n public async enrich(\n event: AISnitchEvent,\n context: ProcessContext = {},\n ): Promise<AISnitchEvent> {\n const pid = context.pid ?? event.data.pid;\n const toolName = event['aisnitch.tool'];\n const toolBinary = TOOL_BINARY_MAP[toolName];\n const hookPayloadCwd = this.getHookPayloadCwd(context.hookPayload);\n const explicitTerminal =\n event.data.terminal ??\n (context.env ? this.detectTerminal(context.env) : 'unknown');\n const explicitCwd =\n event.data.cwd ??\n hookPayloadCwd ??\n (context.transcriptPath\n ? this.decodeCWDFromTranscriptPath(context.transcriptPath)\n : undefined);\n\n if (!pid || pid <= 0) {\n return {\n ...event,\n data: {\n ...event.data,\n terminal:\n explicitTerminal !== 'unknown' ? explicitTerminal : event.data.terminal,\n cwd: explicitCwd ?? event.data.cwd,\n instanceId: context.sessionId\n ? this.buildInstanceId(toolName, 0, context.sessionId)\n : event.data.instanceId,\n },\n };\n }\n\n const cachedContext = this.getCachedContext(pid);\n const detectedContext =\n cachedContext ?? (await this.detectContext(pid, toolBinary, explicitTerminal));\n\n if (!cachedContext) {\n this.cache.set(pid, {\n ...detectedContext,\n expiresAt: this.now() + this.cacheTtlMs,\n });\n }\n\n const instanceId = this.buildInstanceId(\n toolName,\n pid,\n context.sessionId ?? event['aisnitch.sessionid'],\n );\n\n return {\n ...event,\n data: {\n ...event.data,\n terminal:\n explicitTerminal !== 'unknown'\n ? explicitTerminal\n : detectedContext.terminal ?? event.data.terminal,\n cwd:\n explicitCwd ??\n detectedContext.cwd ??\n event.data.cwd,\n pid,\n instanceId,\n instanceIndex:\n event.data.instanceIndex ?? detectedContext.instanceIndex,\n instanceTotal:\n event.data.instanceTotal ?? detectedContext.instanceTotal,\n },\n };\n }\n\n private async detectContext(\n pid: number,\n toolBinary: string,\n explicitTerminal: string,\n ): Promise<Omit<CachedProcessContext, 'expiresAt'>> {\n const cwdPromise = this.getCWDForPID(pid);\n const instancePromise = this.getInstanceIndex(pid, toolBinary);\n const terminalPromise =\n explicitTerminal !== 'unknown'\n ? Promise.resolve(explicitTerminal)\n : this.getTerminalFromPPIDChain(pid);\n\n const [cwd, instanceInfo, terminal] = await Promise.all([\n cwdPromise.catch(() => undefined),\n instancePromise.catch(() => ({ index: 1, total: 1 })),\n terminalPromise.catch(() => 'unknown'),\n ]);\n\n return {\n cwd,\n terminal: terminal !== 'unknown' ? terminal : undefined,\n instanceIndex: instanceInfo.index,\n instanceTotal: instanceInfo.total,\n };\n }\n\n private getCachedContext(pid: number): Omit<CachedProcessContext, 'expiresAt'> | undefined {\n const cachedContext = this.cache.get(pid);\n\n if (!cachedContext) {\n return undefined;\n }\n\n if (cachedContext.expiresAt <= this.now()) {\n this.cache.delete(pid);\n return undefined;\n }\n\n const { expiresAt: _expiresAt, ...context } = cachedContext;\n return context;\n }\n\n private getHookPayloadCwd(\n hookPayload: Record<string, unknown> | undefined,\n ): string | undefined {\n if (!hookPayload) {\n return undefined;\n }\n\n const rawCwd = hookPayload.cwd;\n\n return typeof rawCwd === 'string' && rawCwd.length > 0 ? rawCwd : undefined;\n }\n\n private async resolveCwdWithPidCwd(pid: number): Promise<string | undefined> {\n const cwd = (await pidCwd(pid)) as string | null | undefined;\n\n return cwd ?? undefined;\n }\n\n private async defaultExecCommand(\n command: string,\n args: readonly string[],\n options: CommandExecutionOptions = {},\n ): Promise<string> {\n const result = await execFile(command, [...args], {\n encoding: 'utf8',\n timeout: options.timeoutMs ?? this.commandTimeoutMs,\n maxBuffer: 1024 * 1024,\n });\n\n return result.stdout;\n }\n\n private async withTimeout<T>(promise: Promise<T>): Promise<T> {\n return await Promise.race([\n promise,\n new Promise<never>((_resolve, reject) => {\n setTimeout(() => {\n reject(new Error('Context detection timed out.'));\n }, this.commandTimeoutMs).unref();\n }),\n ]);\n }\n}\n","/**\n * @file src/adapters/index.ts\n * @description Barrel exports for the built-in AISnitch adapter system and factory.\n * @functions\n * โ createDefaultAdapters\n * @exports all adapter primitives plus createDefaultAdapters\n * @see ./base.ts\n * @see ./registry.ts\n * @see ./aider.ts\n * @see ./claude-code.ts\n * @see ./copilot-cli.ts\n * @see ./gemini-cli.ts\n * @see ./generic-pty.ts\n * @see ./goose.ts\n * @see ./codex.ts\n * @see ./openclaw.ts\n * @see ./opencode.ts\n */\n\nimport type { AdapterRuntimeOptions } from './base.js';\nimport { AiderAdapter } from './aider.js';\nimport { ClaudeCodeAdapter } from './claude-code.js';\nimport { CopilotCLIAdapter } from './copilot-cli.js';\nimport { CodexAdapter } from './codex.js';\nimport { GeminiCLIAdapter } from './gemini-cli.js';\nimport { GooseAdapter } from './goose.js';\nimport { OpenClawAdapter } from './openclaw.js';\nimport { OpenCodeAdapter } from './opencode.js';\n\nexport * from './base.js';\nexport * from './registry.js';\nexport * from './aider.js';\nexport * from './claude-code.js';\nexport * from './copilot-cli.js';\nexport * from './codex.js';\nexport * from './gemini-cli.js';\nexport * from './generic-pty.js';\nexport * from './goose.js';\nexport * from './openclaw.js';\nexport * from './opencode.js';\n\n/**\n * Instantiates the built-in adapters that ship with AISnitch.\n */\nexport function createDefaultAdapters(options: AdapterRuntimeOptions) {\n return [\n new AiderAdapter(options),\n new ClaudeCodeAdapter(options),\n new CopilotCLIAdapter(options),\n new GeminiCLIAdapter(options),\n new GooseAdapter(options),\n new CodexAdapter(options),\n new OpenClawAdapter(options),\n new OpenCodeAdapter(options),\n ] as const;\n}\n","import type { infer as ZodInfer } from 'zod';\nimport { z } from 'zod';\n\nimport { ToolNameSchema } from '../events/schema.js';\n\n/**\n * @file src/core/config/schema.ts\n * @description Zod schemas and inferred types for the persistent AISnitch configuration file.\n * @functions\n * โ none\n * @exports LOG_LEVELS, AdapterConfigSchema, ConfigSchema, AISnitchConfig, AdapterConfig\n * @see ./loader.ts\n */\n\n/**\n * Supported log levels for the daemon runtime.\n */\nexport const LOG_LEVELS = ['debug', 'info', 'warn', 'error'] as const;\n\n/**\n * Per-adapter toggle stored inside the config file.\n */\nexport const AdapterConfigSchema = z.strictObject({\n enabled: z.boolean().default(true),\n});\n\n/**\n * Runtime schema for the full persisted configuration contract.\n */\nexport const ConfigSchema = z.strictObject({\n wsPort: z.number().int().min(1024).max(65535).default(4820),\n httpPort: z.number().int().min(1024).max(65535).default(4821),\n /**\n * ๐ This is intentionally a partial record because most users will only\n * override a couple of adapters instead of all supported tools at once.\n */\n adapters: z.partialRecord(ToolNameSchema, AdapterConfigSchema).default({}),\n idleTimeoutMs: z.number().int().min(10_000).default(120_000),\n logLevel: z.enum(LOG_LEVELS).default('info'),\n});\n\n/**\n * Inferred TypeScript view of a single adapter config entry.\n */\nexport type AdapterConfig = ZodInfer<typeof AdapterConfigSchema>;\n\n/**\n * Inferred TypeScript view of the persisted AISnitch config.\n */\nexport type AISnitchConfig = ZodInfer<typeof ConfigSchema>;\n","import type { AISnitchConfig } from './schema.js';\n\n/**\n * @file src/core/config/defaults.ts\n * @description Central default values for the AISnitch runtime configuration.\n * @functions\n * โ none\n * @exports DEFAULT_CONFIG\n * @see ./schema.ts\n */\n\n/**\n * ๐ Keeping defaults in plain data makes them reusable for docs, tests,\n * config bootstrapping, and eventual `aisnitch config` CLI commands.\n */\nexport const DEFAULT_CONFIG: AISnitchConfig = {\n wsPort: 4820,\n httpPort: 4821,\n adapters: {},\n idleTimeoutMs: 120_000,\n logLevel: 'info',\n};\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\n\nimport { DEFAULT_CONFIG } from './defaults.js';\nimport { ConfigSchema } from './schema.js';\nimport type { AISnitchConfig } from './schema.js';\n\n/**\n * @file src/core/config/loader.ts\n * @description File-system backed helpers for reading, writing, and resolving AISnitch config paths and ports.\n * @functions\n * โ getAISnitchHomePath\n * โ getConfigPath\n * โ ensureConfigDir\n * โ loadConfig\n * โ saveConfig\n * โ resolveAvailablePort\n * @exports ConfigPathOptions, PortResolutionOptions, getAISnitchHomePath, getConfigPath, ensureConfigDir, loadConfig, saveConfig, resolveAvailablePort\n * @see ./schema.ts\n * @see ./defaults.ts\n */\n\n/**\n * Common options for redirecting config path resolution during tests.\n */\nexport interface ConfigPathOptions {\n readonly env?: NodeJS.ProcessEnv;\n readonly homeDirectory?: string;\n readonly configPath?: string;\n}\n\n/**\n * Options for port selection and lightweight logging during bootstrap.\n */\nexport interface PortResolutionOptions {\n readonly host?: string;\n readonly maxAttempts?: number;\n readonly logger?: (message: string) => void;\n}\n\n/**\n * Returns the root directory used by AISnitch to store config and daemon state.\n */\nexport function getAISnitchHomePath(options: ConfigPathOptions = {}): string {\n if (options.configPath && options.configPath.trim().length > 0) {\n return dirname(resolve(options.configPath));\n }\n\n const configuredHome = options.env?.AISNITCH_HOME;\n\n if (configuredHome && configuredHome.trim().length > 0) {\n return resolve(configuredHome);\n }\n\n return join(options.homeDirectory ?? homedir(), '.aisnitch');\n}\n\n/**\n * Resolves the absolute path of `config.json`, honoring `AISNITCH_HOME`.\n */\nexport function getConfigPath(options: ConfigPathOptions = {}): string {\n if (options.configPath && options.configPath.trim().length > 0) {\n return resolve(options.configPath);\n }\n\n return join(getAISnitchHomePath(options), 'config.json');\n}\n\n/**\n * Ensures the AISnitch home directory exists before reading or writing config.\n */\nexport async function ensureConfigDir(\n options: ConfigPathOptions = {},\n): Promise<string> {\n const directoryPath = getAISnitchHomePath(options);\n\n await mkdir(directoryPath, { recursive: true });\n\n return directoryPath;\n}\n\n/**\n * Loads, validates, and default-fills the AISnitch config from disk.\n */\nexport async function loadConfig(\n options: ConfigPathOptions = {},\n): Promise<AISnitchConfig> {\n const configPath = getConfigPath(options);\n\n try {\n const rawConfig = await readFile(configPath, 'utf8');\n const parsedJson: unknown = JSON.parse(rawConfig);\n\n return ConfigSchema.parse(parsedJson);\n } catch (error: unknown) {\n if (\n error instanceof Error &&\n 'code' in error &&\n error.code === 'ENOENT'\n ) {\n return ConfigSchema.parse(DEFAULT_CONFIG);\n }\n\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid JSON in AISnitch config at ${configPath}`, {\n cause: error,\n });\n }\n\n throw error;\n }\n}\n\n/**\n * Writes a validated AISnitch config back to disk using stable pretty JSON.\n */\nexport async function saveConfig(\n config: AISnitchConfig,\n options: ConfigPathOptions = {},\n): Promise<string> {\n const validatedConfig = ConfigSchema.parse(config);\n const configPath = getConfigPath(options);\n\n await ensureConfigDir(options);\n await writeFile(\n configPath,\n `${JSON.stringify(validatedConfig, null, 2)}\\n`,\n 'utf8',\n );\n\n return configPath;\n}\n\nasync function canBindPort(port: number, host: string): Promise<boolean> {\n return await new Promise<boolean>((resolveAvailability, reject) => {\n const server = createServer();\n\n server.once('error', (error: NodeJS.ErrnoException) => {\n server.close();\n\n if (error.code === 'EADDRINUSE') {\n resolveAvailability(false);\n return;\n }\n\n reject(error);\n });\n\n server.once('listening', () => {\n server.close((closeError) => {\n if (closeError) {\n reject(closeError);\n return;\n }\n\n resolveAvailability(true);\n });\n });\n\n server.listen(port, host);\n });\n}\n\n/**\n * Resolves a usable port by trying the requested port first and then the next\n * sequential ports up to a bounded retry count.\n */\nexport async function resolveAvailablePort(\n requestedPort: number,\n options: PortResolutionOptions = {},\n): Promise<number> {\n const host = options.host ?? '127.0.0.1';\n const maxAttempts = options.maxAttempts ?? 10;\n\n for (let attempt = 0; attempt < maxAttempts; attempt += 1) {\n const candidatePort = requestedPort + attempt;\n const available = await canBindPort(candidatePort, host);\n\n if (!available) {\n continue;\n }\n\n if (candidatePort === requestedPort) {\n options.logger?.(`AISnitch will use requested port ${candidatePort}.`);\n } else {\n options.logger?.(\n `AISnitch port ${requestedPort} is busy, using ${candidatePort} instead.`,\n );\n }\n\n return candidatePort;\n }\n\n throw new Error(\n `Unable to find an available port from ${requestedPort} to ${\n requestedPort + maxAttempts - 1\n }.`,\n );\n}\n","import { EventEmitter } from 'eventemitter3';\n\nimport { AISnitchEventSchema } from '../events/schema.js';\nimport type { AISnitchEvent, AISnitchEventType } from '../events/types.js';\nimport { logger } from './logger.js';\n\n/**\n * @file src/core/engine/event-bus.ts\n * @description Typed in-memory pub/sub bus used by the AISnitch runtime pipeline.\n * @functions\n * โ none\n * @exports EventHandler, EventBusStats, EventBus\n * @see ./logger.ts\n * @see ../events/schema.ts\n */\n\n/**\n * Listener signature used by the EventBus.\n */\nexport type EventHandler = (event: AISnitchEvent) => void;\n\ntype EventBusChannels = {\n event: (event: AISnitchEvent) => void;\n} & {\n [K in AISnitchEventType as `event:${K}`]: (event: AISnitchEvent) => void;\n};\n\n/**\n * Metrics exposed by the in-memory event bus.\n */\nexport interface EventBusStats {\n readonly publishedEvents: number;\n readonly rejectedEvents: number;\n readonly subscriberCount: number;\n}\n\n/**\n * ๐ The EventBus is the single fan-out point inside the process. Adapters,\n * hook receivers, and IPC ingress all publish here before anything reaches WS.\n */\nexport class EventBus {\n private readonly emitter: EventEmitter<EventBusChannels> =\n new EventEmitter<EventBusChannels>();\n\n private readonly globalHandlers = new Set<EventHandler>();\n\n private readonly typedHandlers = new Map<AISnitchEventType, Set<EventHandler>>();\n\n private publishedEvents = 0;\n\n private rejectedEvents = 0;\n\n /**\n * Validates and publishes an event to all generic and type-specific listeners.\n */\n publish(event: unknown): event is AISnitchEvent {\n const parsedEvent = AISnitchEventSchema.safeParse(event);\n\n if (!parsedEvent.success) {\n this.rejectedEvents += 1;\n logger.warn(\n {\n issues: parsedEvent.error.issues,\n },\n 'Rejected invalid event',\n );\n return false;\n }\n\n this.publishedEvents += 1;\n\n logger.debug(\n {\n eventId: parsedEvent.data.id,\n instanceId: parsedEvent.data.data.instanceId,\n sessionId: parsedEvent.data['aisnitch.sessionid'],\n eventType: parsedEvent.data.type,\n tool: parsedEvent.data['aisnitch.tool'],\n },\n 'Published event',\n );\n\n this.emitter.emit('event', parsedEvent.data);\n this.emitter.emit(`event:${parsedEvent.data.type}`, parsedEvent.data);\n\n return true;\n }\n\n /**\n * Subscribes to all valid events emitted on the bus.\n */\n subscribe(handler: EventHandler): () => void {\n this.globalHandlers.add(handler);\n this.emitter.on('event', handler);\n\n return () => {\n this.unsubscribe(handler);\n };\n }\n\n /**\n * Subscribes to only one normalized event type.\n */\n subscribeType(type: AISnitchEventType, handler: EventHandler): () => void {\n const channel = `event:${type}` as const;\n const handlersForType = this.typedHandlers.get(type) ?? new Set<EventHandler>();\n\n handlersForType.add(handler);\n this.typedHandlers.set(type, handlersForType);\n this.emitter.on(channel, handler);\n\n return () => {\n this.unsubscribeType(type, handler);\n };\n }\n\n /**\n * Removes a previously subscribed catch-all handler.\n */\n unsubscribe(handler: EventHandler): void {\n this.globalHandlers.delete(handler);\n this.emitter.off('event', handler);\n }\n\n /**\n * Removes all listeners and clears internal handler tracking.\n */\n unsubscribeAll(): void {\n this.globalHandlers.clear();\n this.typedHandlers.clear();\n this.emitter.removeAllListeners();\n }\n\n /**\n * Returns current in-memory bus statistics.\n */\n getStats(): EventBusStats {\n const typedSubscriberCount = [...this.typedHandlers.values()].reduce(\n (count, handlers) => count + handlers.size,\n 0,\n );\n\n return {\n publishedEvents: this.publishedEvents,\n rejectedEvents: this.rejectedEvents,\n subscriberCount: this.globalHandlers.size + typedSubscriberCount,\n };\n }\n\n private unsubscribeType(type: AISnitchEventType, handler: EventHandler): void {\n const channel = `event:${type}` as const;\n const handlersForType = this.typedHandlers.get(type);\n\n if (!handlersForType) {\n return;\n }\n\n handlersForType.delete(handler);\n\n if (handlersForType.size === 0) {\n this.typedHandlers.delete(type);\n }\n\n this.emitter.off(channel, handler);\n }\n}\n","/**\n * @file src/core/engine/ring-buffer.ts\n * @description Fixed-size oldest-first ring buffer used to absorb temporary consumer backpressure.\n * @functions\n * โ none\n * @exports RingBuffer\n */\n\n/**\n * ๐ This buffer intentionally drops the oldest item when full. For a live\n * stream UI that is exactly the right tradeoff: newest activity beats stale UI.\n */\nexport class RingBuffer<T> {\n private readonly items: Array<T | undefined>;\n\n private head = 0;\n\n private count = 0;\n\n public constructor(private readonly maxCapacity: number) {\n if (!Number.isInteger(maxCapacity) || maxCapacity <= 0) {\n throw new Error('RingBuffer capacity must be a positive integer.');\n }\n\n this.items = new Array<T | undefined>(maxCapacity);\n }\n\n /**\n * Pushes one item into the buffer and returns the dropped oldest item if full.\n */\n push(item: T): T | undefined {\n if (this.count < this.maxCapacity) {\n const insertIndex = (this.head + this.count) % this.maxCapacity;\n this.items[insertIndex] = item;\n this.count += 1;\n return undefined;\n }\n\n const droppedItem = this.items[this.head];\n\n this.items[this.head] = item;\n this.head = (this.head + 1) % this.maxCapacity;\n\n return droppedItem;\n }\n\n /**\n * Removes and returns the oldest item in the buffer.\n */\n shift(): T | undefined {\n if (this.count === 0) {\n return undefined;\n }\n\n const item = this.items[this.head];\n\n this.items[this.head] = undefined;\n this.head = (this.head + 1) % this.maxCapacity;\n this.count -= 1;\n\n return item;\n }\n\n /**\n * Drains and returns all items in oldest-first order.\n */\n drain(): T[] {\n const drainedItems: T[] = [];\n\n while (this.count > 0) {\n const item = this.shift();\n\n if (item !== undefined) {\n drainedItems.push(item);\n }\n }\n\n return drainedItems;\n }\n\n /**\n * Clears the buffer contents.\n */\n clear(): void {\n this.items.fill(undefined);\n this.head = 0;\n this.count = 0;\n }\n\n public get capacity(): number {\n return this.maxCapacity;\n }\n\n public get size(): number {\n return this.count;\n }\n\n public get isFull(): boolean {\n return this.count === this.maxCapacity;\n }\n}\n","import { once } from 'node:events';\nimport type { AddressInfo } from 'node:net';\n\nimport { WebSocket, WebSocketServer } from 'ws';\n\nimport type { AISnitchEvent, ToolName } from '../events/types.js';\nimport type { EventBus } from './event-bus.js';\nimport { logger } from './logger.js';\nimport { RingBuffer } from './ring-buffer.js';\n\n/**\n * @file src/core/engine/ws-server.ts\n * @description Localhost-only WebSocket event stream server with per-consumer buffering and heartbeat handling.\n * @functions\n * โ none\n * @exports WelcomeMessage, WSServerStartOptions, WSServerStats, WSServer\n * @see ./ring-buffer.ts\n * @see ./event-bus.ts\n */\n\n/**\n * Message sent immediately after a new consumer connects.\n */\nexport interface WelcomeMessage {\n readonly type: 'welcome';\n readonly version: string;\n readonly tools: readonly ToolName[];\n}\n\n/**\n * Startup configuration for the WebSocket server.\n */\nexport interface WSServerStartOptions {\n readonly port: number;\n readonly eventBus: EventBus;\n readonly activeTools?: readonly ToolName[];\n readonly host?: string;\n readonly bufferCapacity?: number;\n readonly backpressureThresholdBytes?: number;\n readonly heartbeatIntervalMs?: number;\n readonly pongTimeoutMs?: number;\n}\n\n/**\n * Observable runtime stats for the WebSocket server.\n */\nexport interface WSServerStats {\n readonly listening: boolean;\n readonly host: string;\n readonly port: number | null;\n readonly consumerCount: number;\n readonly eventsSent: number;\n readonly droppedEvents: number;\n}\n\ninterface ConsumerState {\n readonly buffer: RingBuffer<string>;\n lastPingAt: number;\n awaitingPongSince: number | null;\n}\n\n/**\n * ๐ Every consumer gets its own ring buffer so one slow UI cannot block the\n * others or force the daemon to keep unbounded queued output in memory.\n */\nexport class WSServer {\n private wss: WebSocketServer | undefined;\n\n private host = '127.0.0.1';\n\n private port: number | null = null;\n\n private readonly consumers = new Map<WebSocket, ConsumerState>();\n\n private unsubscribeFromBus: (() => void) | undefined;\n\n private maintenanceTimer: NodeJS.Timeout | undefined;\n\n private eventsSent = 0;\n\n private droppedEvents = 0;\n\n /**\n * Starts the localhost WebSocket server and subscribes it to the event bus.\n */\n public async start(options: WSServerStartOptions): Promise<number> {\n if (this.wss) {\n return this.port ?? options.port;\n }\n\n this.host = options.host ?? '127.0.0.1';\n\n const bufferCapacity = options.bufferCapacity ?? 1_000;\n const backpressureThresholdBytes =\n options.backpressureThresholdBytes ?? 64 * 1024;\n const heartbeatIntervalMs = options.heartbeatIntervalMs ?? 30_000;\n const pongTimeoutMs = options.pongTimeoutMs ?? 10_000;\n const activeTools = options.activeTools ?? [];\n\n this.wss = new WebSocketServer({\n host: this.host,\n port: options.port,\n });\n\n this.wss.on('connection', (socket) => {\n this.handleConnection(\n socket,\n {\n activeTools,\n bufferCapacity,\n backpressureThresholdBytes,\n },\n );\n });\n\n this.wss.on('error', (error) => {\n logger.error({ error }, 'WebSocket server error');\n });\n\n await once(this.wss, 'listening');\n\n const address = this.wss.address();\n\n if (!address || typeof address === 'string') {\n throw new Error('Unable to resolve WebSocket server address.');\n }\n\n this.port = (address as AddressInfo).port;\n\n this.unsubscribeFromBus = options.eventBus.subscribe((event) => {\n this.broadcastEvent(event, backpressureThresholdBytes);\n });\n\n this.maintenanceTimer = setInterval(() => {\n this.runMaintenance(backpressureThresholdBytes, heartbeatIntervalMs, pongTimeoutMs);\n }, 1_000);\n this.maintenanceTimer.unref();\n\n logger.info(\n {\n host: this.host,\n port: this.port,\n },\n 'WebSocket server started',\n );\n\n return this.port;\n }\n\n /**\n * Stops the server and closes all consumer connections.\n */\n public async stop(): Promise<void> {\n this.unsubscribeFromBus?.();\n this.unsubscribeFromBus = undefined;\n\n if (this.maintenanceTimer) {\n clearInterval(this.maintenanceTimer);\n this.maintenanceTimer = undefined;\n }\n\n for (const socket of this.consumers.keys()) {\n socket.terminate();\n }\n this.consumers.clear();\n\n if (!this.wss) {\n this.port = null;\n return;\n }\n\n const wss = this.wss;\n this.wss = undefined;\n\n await new Promise<void>((resolve, reject) => {\n wss.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n\n resolve();\n });\n });\n\n this.port = null;\n\n logger.info('WebSocket server stopped');\n }\n\n /**\n * Returns live server metrics used by health and status reporting.\n */\n public getStats(): WSServerStats {\n return {\n listening: this.wss !== undefined,\n host: this.host,\n port: this.port,\n consumerCount: this.consumers.size,\n eventsSent: this.eventsSent,\n droppedEvents: this.droppedEvents,\n };\n }\n\n private handleConnection(\n socket: WebSocket,\n options: {\n readonly activeTools: readonly ToolName[];\n readonly bufferCapacity: number;\n readonly backpressureThresholdBytes: number;\n },\n ): void {\n const state: ConsumerState = {\n buffer: new RingBuffer<string>(options.bufferCapacity),\n lastPingAt: Date.now(),\n awaitingPongSince: null,\n };\n\n this.consumers.set(socket, state);\n\n socket.on('pong', () => {\n state.awaitingPongSince = null;\n this.flushConsumer(socket, state, options.backpressureThresholdBytes);\n });\n\n socket.on('close', () => {\n this.consumers.delete(socket);\n });\n\n socket.on('error', (error) => {\n logger.warn({ error }, 'WebSocket consumer error');\n });\n\n const welcomeMessage: WelcomeMessage = {\n type: 'welcome',\n version: '0.1.0',\n tools: options.activeTools,\n };\n\n this.trySendOrQueue(\n socket,\n state,\n JSON.stringify(welcomeMessage),\n options.backpressureThresholdBytes,\n );\n }\n\n private broadcastEvent(\n event: AISnitchEvent,\n backpressureThresholdBytes: number,\n ): void {\n const serializedEvent = JSON.stringify(event);\n\n for (const [socket, state] of this.consumers) {\n this.trySendOrQueue(\n socket,\n state,\n serializedEvent,\n backpressureThresholdBytes,\n );\n }\n }\n\n private trySendOrQueue(\n socket: WebSocket,\n state: ConsumerState,\n serializedPayload: string,\n backpressureThresholdBytes: number,\n ): void {\n if (socket.readyState !== WebSocket.OPEN) {\n return;\n }\n\n if (state.buffer.size === 0 && socket.bufferedAmount < backpressureThresholdBytes) {\n socket.send(serializedPayload, (error) => {\n if (error) {\n logger.warn({ error }, 'Failed to send WebSocket payload');\n }\n });\n this.eventsSent += 1;\n return;\n }\n\n const droppedPayload = state.buffer.push(serializedPayload);\n\n if (droppedPayload !== undefined) {\n this.droppedEvents += 1;\n }\n }\n\n private flushConsumer(\n socket: WebSocket,\n state: ConsumerState,\n backpressureThresholdBytes: number,\n ): void {\n while (\n socket.readyState === WebSocket.OPEN &&\n state.buffer.size > 0 &&\n socket.bufferedAmount < backpressureThresholdBytes\n ) {\n const nextPayload = state.buffer.shift();\n\n if (nextPayload === undefined) {\n break;\n }\n\n socket.send(nextPayload, (error) => {\n if (error) {\n logger.warn({ error }, 'Failed to flush buffered WebSocket payload');\n }\n });\n\n this.eventsSent += 1;\n }\n }\n\n private runMaintenance(\n backpressureThresholdBytes: number,\n heartbeatIntervalMs: number,\n pongTimeoutMs: number,\n ): void {\n const now = Date.now();\n\n for (const [socket, state] of this.consumers) {\n this.flushConsumer(socket, state, backpressureThresholdBytes);\n\n if (state.awaitingPongSince !== null) {\n if (now - state.awaitingPongSince > pongTimeoutMs) {\n socket.terminate();\n }\n continue;\n }\n\n if (now - state.lastPingAt >= heartbeatIntervalMs) {\n state.lastPingAt = now;\n state.awaitingPongSince = now;\n\n if (socket.readyState === WebSocket.OPEN) {\n socket.ping();\n }\n }\n }\n }\n}\n","import { once } from 'node:events';\nimport {\n createServer,\n type IncomingMessage,\n type Server,\n type ServerResponse,\n} from 'node:http';\n\nimport { ToolNameSchema } from '../events/schema.js';\nimport type { ToolName } from '../events/types.js';\nimport { logger } from './logger.js';\n\n/**\n * @file src/core/engine/http-receiver.ts\n * @description Lightweight localhost-only HTTP receiver for tool hooks and daemon health checks.\n * @functions\n * โ none\n * @exports HealthSnapshot, HTTPReceiverStartOptions, HTTPReceiverStats, HTTPReceiver\n * @see ./pipeline.ts\n */\n\n/**\n * Health payload returned by the HTTP receiver.\n */\nexport interface HealthSnapshot {\n readonly status: 'ok';\n readonly uptime: number;\n readonly consumers: number;\n readonly events: number;\n readonly droppedEvents: number;\n}\n\n/**\n * Startup configuration for the HTTP hook receiver.\n */\nexport interface HTTPReceiverStartOptions {\n readonly port: number;\n readonly host?: string;\n readonly onHook: (tool: ToolName, payload: unknown) => Promise<void> | void;\n readonly getHealthSnapshot: () => HealthSnapshot;\n}\n\n/**\n * Observable runtime stats for the HTTP receiver.\n */\nexport interface HTTPReceiverStats {\n readonly listening: boolean;\n readonly host: string;\n readonly port: number | null;\n readonly requestCount: number;\n readonly invalidRequestCount: number;\n readonly acceptedHooks: number;\n}\n\n/**\n * ๐ The hook receiver keeps zero framework magic on purpose. One endpoint plus\n * one health route do not justify hauling a whole server framework into core.\n */\nexport class HTTPReceiver {\n private server: Server | undefined;\n\n private host = '127.0.0.1';\n\n private port: number | null = null;\n\n private requestCount = 0;\n\n private invalidRequestCount = 0;\n\n private acceptedHooks = 0;\n\n /**\n * Starts the HTTP receiver on localhost and exposes hook and health routes.\n */\n public async start(options: HTTPReceiverStartOptions): Promise<number> {\n if (this.server) {\n return this.port ?? options.port;\n }\n\n this.host = options.host ?? '127.0.0.1';\n\n this.server = createServer((request, response) => {\n void this.handleRequest(request, response, options);\n });\n\n this.server.on('error', (error) => {\n logger.error({ error }, 'HTTP receiver error');\n });\n\n this.server.listen(options.port, this.host);\n await once(this.server, 'listening');\n\n const address = this.server.address();\n\n if (!address || typeof address === 'string') {\n throw new Error('Unable to resolve HTTP receiver address.');\n }\n\n this.port = address.port;\n\n logger.info(\n {\n host: this.host,\n port: this.port,\n },\n 'HTTP receiver started',\n );\n\n return this.port;\n }\n\n /**\n * Stops the receiver and closes the listening socket.\n */\n public async stop(): Promise<void> {\n if (!this.server) {\n this.port = null;\n return;\n }\n\n const server = this.server;\n this.server = undefined;\n\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n\n resolve();\n });\n });\n\n this.port = null;\n\n logger.info('HTTP receiver stopped');\n }\n\n /**\n * Returns live HTTP receiver stats for health/status endpoints.\n */\n public getStats(): HTTPReceiverStats {\n return {\n listening: this.server !== undefined,\n host: this.host,\n port: this.port,\n requestCount: this.requestCount,\n invalidRequestCount: this.invalidRequestCount,\n acceptedHooks: this.acceptedHooks,\n };\n }\n\n private async handleRequest(\n request: IncomingMessage,\n response: ServerResponse,\n options: HTTPReceiverStartOptions,\n ): Promise<void> {\n this.requestCount += 1;\n\n const requestUrl = new URL(\n request.url ?? '/',\n `http://${this.host}:${this.port ?? options.port}`,\n );\n\n if (request.method === 'GET' && requestUrl.pathname === '/health') {\n this.sendJson(response, 200, options.getHealthSnapshot());\n return;\n }\n\n if (request.method === 'POST' && requestUrl.pathname.startsWith('/hooks/')) {\n const toolSegment = decodeURIComponent(\n requestUrl.pathname.slice('/hooks/'.length),\n );\n const parsedTool = ToolNameSchema.safeParse(toolSegment);\n\n if (!parsedTool.success || parsedTool.data === 'unknown') {\n this.invalidRequestCount += 1;\n this.sendJson(response, 404, {\n error: 'unknown tool',\n });\n return;\n }\n\n let payload: unknown;\n\n try {\n payload = await this.readJsonBody(request);\n } catch (error: unknown) {\n this.invalidRequestCount += 1;\n this.sendJson(response, 400, {\n error: error instanceof Error ? error.message : 'invalid json body',\n });\n return;\n }\n\n this.acceptedHooks += 1;\n this.sendJson(response, 202, {\n status: 'accepted',\n });\n\n queueMicrotask(() => {\n void Promise.resolve(options.onHook(parsedTool.data, payload)).catch((error) => {\n logger.error(\n {\n error,\n tool: parsedTool.data,\n },\n 'Hook handler failed',\n );\n });\n });\n return;\n }\n\n this.invalidRequestCount += 1;\n this.sendJson(response, 404, {\n error: 'not found',\n });\n }\n\n private async readJsonBody(request: IncomingMessage): Promise<unknown> {\n let rawBody = '';\n let bodyLength = 0;\n\n for await (const chunk of request) {\n const chunkText =\n typeof chunk === 'string'\n ? chunk\n : Buffer.from(chunk).toString('utf8');\n\n bodyLength += Buffer.byteLength(chunkText);\n\n if (bodyLength > 1_000_000) {\n throw new Error('request body too large');\n }\n\n rawBody += chunkText;\n }\n\n if (rawBody.length === 0) {\n throw new Error('missing json body');\n }\n\n try {\n return JSON.parse(rawBody) as unknown;\n } catch (error: unknown) {\n throw new Error('malformed json body', {\n cause: error,\n });\n }\n }\n\n private sendJson(\n response: ServerResponse,\n statusCode: number,\n payload: unknown,\n ): void {\n response.writeHead(statusCode, {\n 'content-type': 'application/json; charset=utf-8',\n });\n response.end(`${JSON.stringify(payload)}\\n`);\n }\n}\n","import { access, rm } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { createConnection, createServer, type Server, type Socket } from 'node:net';\nimport { createInterface } from 'node:readline';\nimport { once } from 'node:events';\n\nimport { AISnitchEventSchema } from '../events/schema.js';\nimport type { AISnitchEvent } from '../events/types.js';\nimport { logger } from './logger.js';\n\n/**\n * @file src/core/engine/uds-server.ts\n * @description NDJSON Unix domain socket ingress for out-of-process AISnitch adapters.\n * @functions\n * โ none\n * @exports UDSServerStartOptions, UDSServerStats, UDSServer\n * @see ./pipeline.ts\n */\n\n/**\n * Startup configuration for the UDS server.\n */\nexport interface UDSServerStartOptions {\n readonly socketPath: string;\n readonly onEvent: (event: AISnitchEvent) => Promise<void> | void;\n}\n\n/**\n * Observable runtime stats for the UDS server.\n */\nexport interface UDSServerStats {\n readonly listening: boolean;\n readonly socketPath: string | null;\n readonly activeConnections: number;\n readonly acceptedConnections: number;\n readonly receivedEvents: number;\n readonly rejectedMessages: number;\n}\n\n/**\n * ๐ UDS is the low-friction IPC path for community adapters. NDJSON keeps the\n * protocol debuggable with shell tools and trivial to implement elsewhere.\n */\nexport class UDSServer {\n private server: Server | undefined;\n\n private socketPath: string | null = null;\n\n private readonly sockets = new Set<Socket>();\n\n private acceptedConnections = 0;\n\n private receivedEvents = 0;\n\n private rejectedMessages = 0;\n\n /**\n * Starts listening on the provided socket path.\n */\n public async start(options: UDSServerStartOptions): Promise<string> {\n if (this.server) {\n return this.socketPath ?? options.socketPath;\n }\n\n await this.ensureSocketPathAvailable(options.socketPath);\n\n this.server = createServer((socket) => {\n this.handleSocket(socket, options.onEvent);\n });\n\n this.server.on('error', (error) => {\n logger.error({ error }, 'UDS server error');\n });\n\n this.server.listen(options.socketPath);\n await once(this.server, 'listening');\n\n this.socketPath = options.socketPath;\n\n logger.info(\n {\n socketPath: this.socketPath,\n },\n 'UDS server started',\n );\n\n return this.socketPath;\n }\n\n /**\n * Stops the UDS server and removes the socket file.\n */\n public async stop(): Promise<void> {\n for (const socket of this.sockets) {\n socket.destroy();\n }\n this.sockets.clear();\n\n if (this.server) {\n const server = this.server;\n this.server = undefined;\n\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n\n resolve();\n });\n });\n }\n\n if (this.socketPath && process.platform !== 'win32') {\n await rm(this.socketPath, { force: true });\n }\n\n this.socketPath = null;\n\n logger.info('UDS server stopped');\n }\n\n /**\n * Returns current runtime metrics for the UDS ingress channel.\n */\n public getStats(): UDSServerStats {\n return {\n listening: this.server !== undefined,\n socketPath: this.socketPath,\n activeConnections: this.sockets.size,\n acceptedConnections: this.acceptedConnections,\n receivedEvents: this.receivedEvents,\n rejectedMessages: this.rejectedMessages,\n };\n }\n\n private handleSocket(\n socket: Socket,\n onEvent: (event: AISnitchEvent) => Promise<void> | void,\n ): void {\n this.sockets.add(socket);\n this.acceptedConnections += 1;\n\n socket.on('close', () => {\n this.sockets.delete(socket);\n });\n\n socket.on('error', (error) => {\n logger.warn({ error }, 'UDS client socket error');\n });\n\n const lineReader = createInterface({\n input: socket,\n crlfDelay: Infinity,\n });\n\n lineReader.on('line', (line) => {\n if (line.trim().length === 0) {\n return;\n }\n\n let parsedPayload: unknown;\n\n try {\n parsedPayload = JSON.parse(line) as unknown;\n } catch (error: unknown) {\n this.rejectedMessages += 1;\n logger.warn({ error, line }, 'Rejected malformed UDS NDJSON payload');\n return;\n }\n\n const parsedEvent = AISnitchEventSchema.safeParse(parsedPayload);\n\n if (!parsedEvent.success) {\n this.rejectedMessages += 1;\n logger.warn(\n {\n issues: parsedEvent.error.issues,\n },\n 'Rejected invalid UDS event payload',\n );\n return;\n }\n\n this.receivedEvents += 1;\n\n queueMicrotask(() => {\n void Promise.resolve(onEvent(parsedEvent.data)).catch((error) => {\n logger.error({ error }, 'UDS event handler failed');\n });\n });\n });\n }\n\n private async ensureSocketPathAvailable(socketPath: string): Promise<void> {\n if (process.platform === 'win32') {\n return;\n }\n\n try {\n await access(socketPath, constants.F_OK);\n } catch (error: unknown) {\n if (\n error instanceof Error &&\n 'code' in error &&\n error.code === 'ENOENT'\n ) {\n return;\n }\n\n throw error;\n }\n\n const staleSocket = await new Promise<boolean>((resolve, reject) => {\n const probe = createConnection(socketPath);\n\n probe.once('connect', () => {\n probe.destroy();\n resolve(false);\n });\n\n probe.once('error', (error: NodeJS.ErrnoException) => {\n if (\n error.code === 'ECONNREFUSED' ||\n error.code === 'ENOENT' ||\n error.code === 'EINVAL' ||\n error.code === 'ENOTSOCK'\n ) {\n resolve(true);\n return;\n }\n\n reject(error);\n });\n });\n\n if (!staleSocket) {\n throw new Error(`Socket path is already in use: ${socketPath}`);\n }\n\n await rm(socketPath, { force: true });\n }\n}\n","import { join } from 'node:path';\n\nimport { z } from 'zod';\n\nimport { AdapterRegistry, createDefaultAdapters } from '../../adapters/index.js';\nimport {\n DEFAULT_CONFIG,\n type ConfigPathOptions,\n ensureConfigDir,\n getAISnitchHomePath,\n resolveAvailablePort,\n} from '../config/index.js';\nimport {\n AISnitchEventSchema,\n AISnitchEventTypeSchema,\n EventDataSchema,\n ToolNameSchema,\n createEvent,\n} from '../events/index.js';\nimport type { AISnitchConfig } from '../config/index.js';\nimport type { AISnitchEvent, ToolName } from '../events/index.js';\nimport { resolveSessionId } from '../session-identity.js';\nimport { ContextDetector, type ProcessContext } from './context-detector.js';\nimport { EventBus, type EventBusStats } from './event-bus.js';\nimport {\n HTTPReceiver,\n type HealthSnapshot,\n type HTTPReceiverStats,\n} from './http-receiver.js';\nimport { logger } from './logger.js';\nimport { UDSServer, type UDSServerStats } from './uds-server.js';\nimport { WSServer, type WSServerStats } from './ws-server.js';\n\n/**\n * @file src/core/engine/pipeline.ts\n * @description Orchestrates the in-memory AISnitch core pipeline and ingress/egress components.\n * @functions\n * โ getSocketPath\n * @exports HookHandler, PipelineStartOptions, PipelineStatus, Pipeline\n * @see ./event-bus.ts\n * @see ./ws-server.ts\n * @see ./http-receiver.ts\n * @see ./uds-server.ts\n * @see ./context-detector.ts\n */\n\nconst HookIngressPayloadSchema = z.strictObject({\n type: AISnitchEventTypeSchema,\n source: z.string().min(1).optional(),\n sessionId: z.string().min(1).optional(),\n seqnum: z.number().int().min(1).optional(),\n data: EventDataSchema.partial().optional(),\n pid: z.number().int().positive().optional(),\n transcriptPath: z.string().min(1).optional(),\n cwd: z.string().min(1).optional(),\n env: z.record(z.string(), z.string()).optional(),\n hookPayload: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Hook handler signature for future adapter-specific hook processors.\n */\nexport type HookHandler = (payload: unknown) => Promise<void> | void;\n\n/**\n * Startup options for the orchestrating pipeline.\n */\nexport interface PipelineStartOptions {\n readonly config?: AISnitchConfig;\n readonly configPath?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly homeDirectory?: string;\n}\n\n/**\n * Snapshot of the full runtime pipeline state.\n */\nexport interface PipelineStatus {\n readonly running: boolean;\n readonly uptimeMs: number;\n readonly wsPort: number | null;\n readonly httpPort: number | null;\n readonly socketPath: string | null;\n readonly eventBus: EventBusStats;\n readonly websocket: WSServerStats;\n readonly http: HTTPReceiverStats;\n readonly uds: UDSServerStats;\n}\n\n/**\n * Returns the platform-specific IPC socket path for the AISnitch daemon.\n */\nexport function getSocketPath(aisnitchHomePath: string): string {\n if (process.platform === 'win32') {\n return '\\\\\\\\.\\\\pipe\\\\aisnitch.sock';\n }\n\n return join(aisnitchHomePath, 'aisnitch.sock');\n}\n\n/**\n * ๐ The pipeline is the real in-process backbone: one EventBus in the middle,\n * ingress on HTTP/UDS, egress on WS, and context enrichment before fan-out.\n */\nexport class Pipeline {\n private readonly eventBus = new EventBus();\n\n private readonly wsServer = new WSServer();\n\n private readonly httpReceiver = new HTTPReceiver();\n\n private readonly udsServer = new UDSServer();\n\n private readonly contextDetector = new ContextDetector();\n\n private adapterRegistry: AdapterRegistry | null = null;\n\n private enabledTools = new Set<ToolName>();\n\n private readonly hookHandlers = new Map<ToolName, HookHandler>();\n\n private startedAt: number | null = null;\n\n private wsPort: number | null = null;\n\n private httpPort: number | null = null;\n\n private socketPath: string | null = null;\n\n /**\n * Starts the full in-memory core pipeline.\n */\n public async start(options: PipelineStartOptions = {}): Promise<PipelineStatus> {\n if (this.startedAt !== null) {\n return this.getStatus();\n }\n\n const config = options.config ?? DEFAULT_CONFIG;\n const pathOptions: ConfigPathOptions = {\n configPath: options.configPath,\n env: options.env,\n homeDirectory: options.homeDirectory,\n };\n\n await ensureConfigDir(pathOptions);\n\n const resolvedWsPort = await resolveAvailablePort(config.wsPort, {\n logger: (message) => logger.info(message),\n });\n let resolvedHttpPort = await resolveAvailablePort(config.httpPort, {\n logger: (message) => logger.info(message),\n });\n\n if (resolvedHttpPort === resolvedWsPort) {\n /**\n * ๐ Port probing happens before either server is actually listening, so\n * two independent probes can \"win\" the same candidate port. Reserve the\n * WebSocket choice first and bump HTTP to the next free candidate.\n */\n resolvedHttpPort = await resolveAvailablePort(resolvedHttpPort + 1, {\n logger: (message) => logger.info(message),\n });\n }\n const aisnitchHomePath = getAISnitchHomePath(pathOptions);\n const socketPath = getSocketPath(aisnitchHomePath);\n const activeTools = Object.entries(config.adapters)\n .filter((entry): entry is [ToolName, { enabled: boolean }] => {\n const [toolName, adapterConfig] = entry;\n return (\n ToolNameSchema.safeParse(toolName).success &&\n adapterConfig?.enabled === true\n );\n })\n .map(([toolName]) => toolName);\n const adapterRegistry = new AdapterRegistry();\n\n for (const adapter of createDefaultAdapters({\n config,\n env: options.env,\n homeDirectory: options.homeDirectory,\n publishEvent: async (event, context) => {\n return await this.publishEvent(event, context);\n },\n })) {\n adapterRegistry.register(adapter);\n }\n\n this.adapterRegistry = adapterRegistry;\n this.enabledTools = new Set(activeTools);\n this.hookHandlers.clear();\n\n for (const toolName of activeTools) {\n const adapter = this.adapterRegistry.get(toolName);\n\n if (!adapter) {\n continue;\n }\n\n this.registerHookHandler(toolName, async (payload) => {\n await adapter.handleHook(payload);\n });\n }\n\n this.startedAt = Date.now();\n\n this.wsPort = await this.wsServer.start({\n port: resolvedWsPort,\n eventBus: this.eventBus,\n activeTools,\n });\n this.httpPort = await this.httpReceiver.start({\n port: resolvedHttpPort,\n onHook: async (tool, payload) => {\n await this.handleHook(tool, payload);\n },\n getHealthSnapshot: () => this.getHealthSnapshot(),\n });\n this.socketPath = await this.udsServer.start({\n socketPath,\n onEvent: async (event) => {\n await this.publishEvent(event);\n },\n });\n await this.adapterRegistry.startAll(config);\n\n logger.info(this.getStatus(), 'Core pipeline started');\n\n return this.getStatus();\n }\n\n /**\n * Stops every pipeline component in reverse dependency order.\n */\n public async stop(): Promise<void> {\n await this.adapterRegistry?.stopAll();\n await this.httpReceiver.stop();\n await this.udsServer.stop();\n await this.wsServer.stop();\n\n this.eventBus.unsubscribeAll();\n this.adapterRegistry = null;\n this.enabledTools.clear();\n this.hookHandlers.clear();\n\n this.startedAt = null;\n this.wsPort = null;\n this.httpPort = null;\n this.socketPath = null;\n\n logger.info('Core pipeline stopped');\n }\n\n /**\n * Registers a future adapter-specific hook handler for one tool.\n */\n public registerHookHandler(tool: ToolName, handler: HookHandler): void {\n this.hookHandlers.set(tool, handler);\n }\n\n /**\n * Publishes an event after best-effort context enrichment.\n */\n public async publishEvent(\n event: AISnitchEvent,\n context: ProcessContext = {},\n ): Promise<boolean> {\n const enrichedEvent = await this.contextDetector.enrich(event, context);\n\n return this.eventBus.publish(enrichedEvent);\n }\n\n /**\n * Exposes current pipeline state for tests, health checks, and future status commands.\n */\n public getStatus(): PipelineStatus {\n return {\n running: this.startedAt !== null,\n uptimeMs: this.startedAt === null ? 0 : Date.now() - this.startedAt,\n wsPort: this.wsPort,\n httpPort: this.httpPort,\n socketPath: this.socketPath,\n eventBus: this.eventBus.getStats(),\n websocket: this.wsServer.getStats(),\n http: this.httpReceiver.getStats(),\n uds: this.udsServer.getStats(),\n };\n }\n\n /**\n * Returns the in-process event bus for direct wiring in tests or future TUI code.\n */\n public getEventBus(): EventBus {\n return this.eventBus;\n }\n\n private getHealthSnapshot(): HealthSnapshot {\n const status = this.getStatus();\n\n return {\n status: 'ok',\n uptime: status.uptimeMs,\n consumers: status.websocket.consumerCount,\n events: status.eventBus.publishedEvents,\n droppedEvents: status.websocket.droppedEvents,\n };\n }\n\n private async handleHook(tool: ToolName, payload: unknown): Promise<void> {\n if (!this.enabledTools.has(tool)) {\n logger.debug({ tool }, 'Ignoring hook for disabled tool');\n return;\n }\n\n const registeredHandler = this.hookHandlers.get(tool);\n\n if (registeredHandler) {\n await registeredHandler(payload);\n return;\n }\n\n const alreadyNormalizedEvent = AISnitchEventSchema.safeParse(payload);\n\n if (alreadyNormalizedEvent.success) {\n await this.publishEvent(alreadyNormalizedEvent.data);\n return;\n }\n\n const normalizedHook = HookIngressPayloadSchema.safeParse(payload);\n\n if (!normalizedHook.success) {\n logger.warn(\n {\n tool,\n issues: normalizedHook.error.issues,\n },\n 'Unable to normalize hook payload',\n );\n return;\n }\n\n const resolvedSessionId = resolveSessionId({\n activeFile: normalizedHook.data.data?.activeFile,\n cwd: normalizedHook.data.data?.cwd ?? normalizedHook.data.cwd,\n pid: normalizedHook.data.pid,\n project: normalizedHook.data.data?.project,\n projectPath: normalizedHook.data.data?.projectPath,\n sessionId: normalizedHook.data.sessionId,\n tool,\n transcriptPath: normalizedHook.data.transcriptPath,\n });\n const event = createEvent({\n source: normalizedHook.data.source ?? `aisnitch://hooks/${tool}`,\n type: normalizedHook.data.type,\n 'aisnitch.tool': tool,\n 'aisnitch.sessionid': resolvedSessionId,\n 'aisnitch.seqnum': normalizedHook.data.seqnum ?? 1,\n data: {\n ...normalizedHook.data.data,\n cwd:\n normalizedHook.data.data?.cwd ??\n normalizedHook.data.cwd,\n },\n });\n\n await this.publishEvent(event, {\n pid: normalizedHook.data.pid,\n env: normalizedHook.data.env,\n sessionId: resolvedSessionId,\n transcriptPath: normalizedHook.data.transcriptPath,\n hookPayload:\n normalizedHook.data.hookPayload ??\n (this.isPlainRecord(payload) ? payload : undefined),\n });\n }\n\n private isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n}\n","import type { AISnitchEvent, AISnitchEventType, CESPCategory } from './types.js';\n\n/**\n * @file src/core/events/cesp.ts\n * @description CESP compatibility helpers for mapping normalized AISnitch events into legacy categories.\n * @functions\n * โ getCESPCategory\n * @exports CESP_MAP, getCESPCategory\n * @see ./types.ts\n */\n\n/**\n * ๐ Some normalized states have no direct CESP equivalent. Returning `null`\n * makes that gap explicit instead of inventing fake sound-pack categories.\n */\nexport const CESP_MAP: Record<AISnitchEventType, CESPCategory | null> = {\n 'session.start': 'session.start',\n 'session.end': 'session.end',\n 'task.start': 'task.acknowledge',\n 'task.complete': 'task.complete',\n 'agent.thinking': null,\n 'agent.coding': null,\n 'agent.tool_call': null,\n 'agent.streaming': null,\n 'agent.asking_user': 'input.required',\n 'agent.idle': null,\n 'agent.error': 'task.error',\n 'agent.compact': 'resource.limit',\n};\n\n/**\n * Resolves the CESP category for either a full event object or an event type.\n */\nexport function getCESPCategory(\n eventOrType: AISnitchEvent | AISnitchEventType,\n): CESPCategory | null {\n const eventType =\n typeof eventOrType === 'string' ? eventOrType : eventOrType.type;\n\n return CESP_MAP[eventType];\n}\n","/**\n * @file src/package-info.ts\n * @description Shared package metadata constants consumed by the public index, CLI, and TUI without creating import cycles.\n * @functions\n * โ getPackageScaffoldInfo\n * @exports AISNITCH_PACKAGE_NAME, AISNITCH_VERSION, AISNITCH_DESCRIPTION, AISnitchScaffoldInfo, getPackageScaffoldInfo\n * @see ./index.ts\n * @see ./cli/program.ts\n * @see ./tui/index.tsx\n */\n\n/**\n * ๐ This constant keeps the published package identity in one place so the\n * CLI and TUI can reuse a single source of truth without reaching through the\n * package root export barrel.\n */\nexport const AISNITCH_PACKAGE_NAME = 'aisnitch';\n\n/**\n * ๐ The published version is kept in source so runtime entrypoints can expose\n * stable metadata without reading package.json at runtime.\n */\nexport const AISNITCH_VERSION = '0.1.0';\n\n/**\n * ๐ The shared description stays close to the package identity so commander\n * help output and future docs surfaces stay aligned.\n */\nexport const AISNITCH_DESCRIPTION =\n 'Universal bridge for AI coding tool activity โ capture, normalize, stream.';\n\n/**\n * Represents the stable scaffold metadata exposed by the package root.\n */\nexport interface AISnitchScaffoldInfo {\n readonly name: string;\n readonly version: string;\n readonly description: string;\n readonly supportedNodeRange: string;\n}\n\n/**\n * Builds a small metadata snapshot that other modules can consume without\n * reading package.json at runtime.\n */\nexport function getPackageScaffoldInfo(): AISnitchScaffoldInfo {\n return {\n name: AISNITCH_PACKAGE_NAME,\n version: AISNITCH_VERSION,\n description: AISNITCH_DESCRIPTION,\n supportedNodeRange: '>=20.0.0',\n };\n}\n","import React from 'react';\nimport { render } from 'ink';\nimport WebSocket from 'ws';\n\nimport { AISNITCH_VERSION } from '../package-info.js';\nimport type { EventBus, PipelineStatus, ToolName } from '../core/index.js';\nimport { App } from './App.js';\nimport type { TuiInitialFilters } from './types.js';\n\n/**\n * @file src/tui/index.tsx\n * @description Foreground Ink renderer entrypoint plus barrel exports for TUI modules.\n * @functions\n * โ renderForegroundTui\n * @exports renderForegroundTui and all TUI modules\n * @see ./App.tsx\n * @see ./live-monitor.ts\n * @see ../../tasks/05-tui/01_tui_foundation-layout_DONE.md\n */\n\n/**\n * Props required to render the foreground TUI.\n */\nexport interface ForegroundTuiOptions {\n readonly configuredAdapters: readonly ToolName[];\n readonly eventBus: EventBus;\n readonly initialFilters?: TuiInitialFilters;\n readonly onQuit?: () => void;\n readonly status: PipelineStatus;\n}\n\n/**\n * Props required to render the attached WebSocket TUI.\n */\nexport interface AttachedTuiOptions {\n readonly configuredAdapters: readonly ToolName[];\n readonly initialFilters?: TuiInitialFilters;\n readonly onQuit?: () => void;\n readonly status: {\n readonly consumerCount: number;\n readonly eventCount: number;\n readonly uptimeMs: number;\n };\n readonly wsUrl: string;\n}\n\n/**\n * Renders the foreground Ink TUI and resolves once the app exits.\n */\nexport async function renderForegroundTui(\n options: ForegroundTuiOptions,\n): Promise<void> {\n const app = render(\n <App\n configuredAdapters={options.configuredAdapters}\n initialFilters={options.initialFilters}\n onQuit={options.onQuit}\n source={{\n kind: 'event-bus',\n eventBus: options.eventBus,\n }}\n status={{\n connected: true,\n connectionLabel: 'Foreground Bus',\n consumerCount: options.status.websocket.consumerCount,\n eventCount: options.status.eventBus.publishedEvents,\n uptimeMs: options.status.uptimeMs,\n }}\n version={AISNITCH_VERSION}\n />,\n );\n\n await app.waitUntilExit();\n}\n\n/**\n * Renders the TUI against a remote AISnitch daemon over WebSocket.\n */\nexport async function renderAttachedTui(\n options: AttachedTuiOptions,\n): Promise<void> {\n const socket = new WebSocket(options.wsUrl);\n const app = render(\n <App\n configuredAdapters={options.configuredAdapters}\n initialFilters={options.initialFilters}\n onQuit={options.onQuit}\n source={{\n kind: 'websocket',\n socket,\n }}\n status={{\n connected: true,\n connectionLabel: 'Attached Stream',\n consumerCount: options.status.consumerCount,\n eventCount: options.status.eventCount,\n uptimeMs: options.status.uptimeMs,\n }}\n version={AISNITCH_VERSION}\n />,\n );\n\n try {\n await app.waitUntilExit();\n } finally {\n if (\n socket.readyState === WebSocket.OPEN ||\n socket.readyState === WebSocket.CONNECTING\n ) {\n socket.close();\n }\n }\n}\n\nexport * from './App.js';\nexport * from './types.js';\nexport * from './filters.js';\nexport * from './theme.js';\nexport * from './live-monitor.js';\nexport * from './hooks/useEventStream.js';\nexport * from './hooks/useKeyBinds.js';\nexport * from './hooks/useSessions.js';\nexport * from './components/EventLine.js';\nexport * from './components/EventStream.js';\nexport * from './components/FilterBar.js';\nexport * from './components/GlobalBadge.js';\nexport * from './components/Header.js';\nexport * from './components/HelpOverlay.js';\nexport * from './components/Layout.js';\nexport * from './components/SessionPanel.js';\nexport * from './components/StatusBar.js';\n","import React, { useEffect, useState } from 'react';\nimport { Box, useApp, useStdout } from 'ink';\n\nimport type { ToolName } from '../core/index.js';\nimport { EventInspector } from './components/EventInspector.js';\nimport { EventStream } from './components/EventStream.js';\nimport { FilterBar } from './components/FilterBar.js';\nimport { Header } from './components/Header.js';\nimport { HelpOverlay } from './components/HelpOverlay.js';\nimport { Panel, PanelStack } from './components/Layout.js';\nimport { SessionPanel } from './components/SessionPanel.js';\nimport { StatusBar } from './components/StatusBar.js';\nimport {\n applyEventFilters,\n applySessionFilters,\n countActiveFilters,\n} from './filters.js';\nimport { buildEventInspectorLines } from './event-inspector.js';\nimport { TUI_THEME } from './theme.js';\nimport type { TuiInitialFilters, TuiStatusSnapshot } from './types.js';\nimport {\n getPendingFrozenEventCount,\n getVisibleEventWindow,\n type EventStreamSource,\n useEventStream,\n} from './hooks/useEventStream.js';\nimport { useKeyBinds } from './hooks/useKeyBinds.js';\nimport {\n deriveGlobalActivityStatus,\n useSessions,\n} from './hooks/useSessions.js';\n\n/**\n * @file src/tui/App.tsx\n * @description Root Ink application for the AISnitch terminal UI foundation, including layout chrome and live summary state.\n * @functions\n * โ App\n * @exports App, type AppProps\n * @see ./index.tsx\n * @see ./hooks/useEventStream.ts\n * @see ./components/EventStream.tsx\n * @see ./components/Header.tsx\n * @see ./components/Layout.tsx\n * @see ./components/StatusBar.tsx\n */\n\n/**\n * Props injected by the foreground runtime renderer.\n */\nexport interface AppProps {\n readonly configuredAdapters: readonly ToolName[];\n readonly initialFilters?: TuiInitialFilters;\n readonly onQuit?: () => void;\n readonly source: EventStreamSource;\n readonly status: TuiStatusSnapshot;\n readonly version: string;\n}\n\n/**\n * ๐ This first TUI pass focuses on shape and feel: strong header, framed\n * panels, responsive composition, and just enough live state to prove the\n * foreground runtime is now a real terminal app instead of a raw log stream.\n */\nexport function App({\n configuredAdapters,\n initialFilters,\n onQuit,\n source,\n status,\n version,\n}: AppProps): React.JSX.Element {\n const { exit } = useApp();\n const { stdout } = useStdout();\n const [columns, setColumns] = useState(stdout.columns ?? 80);\n const [rows, setRows] = useState(stdout.rows ?? 24);\n const [inspectorLineOffset, setInspectorLineOffset] = useState(0);\n const [selectedEventIndex, setSelectedEventIndex] = useState<number | null>(\n null,\n );\n const [uptimeMs, setUptimeMs] = useState(status.uptimeMs);\n const initialTuiFilters = {\n eventType: initialFilters?.type ?? null,\n query: initialFilters?.query ?? '',\n tool: initialFilters?.tool ?? null,\n };\n const initialFullDataMode = initialFilters?.view === 'full-data';\n\n useEffect(() => {\n const handleResize = (): void => {\n setColumns(stdout.columns ?? 80);\n setRows(stdout.rows ?? 24);\n };\n\n stdout.on('resize', handleResize);\n\n return () => {\n stdout.off('resize', handleResize);\n };\n }, [stdout]);\n\n const compactLayout = columns < 112;\n const eventStream = useEventStream(\n source,\n {\n initialTotalEvents: status.eventCount,\n visibleCount: compactLayout ? 4 : 6,\n },\n );\n const sessions = useSessions(eventStream.bufferedEvents);\n const [frozenFilteredEventCount, setFrozenFilteredEventCount] = useState<\n number | null\n >(null);\n const inspectorVisibleLineCount = Math.max(\n 10,\n compactLayout ? rows - 22 : rows - 18,\n );\n const keyBinds = useKeyBinds({\n fullDataModeEnabled: initialFullDataMode,\n initialFilters: initialTuiFilters,\n onClearStream: () => {\n eventStream.clearEvents();\n setFrozenFilteredEventCount(null);\n setSelectedEventIndex(null);\n setInspectorLineOffset(0);\n },\n onInspectorPageScroll: (delta) => {\n setInspectorLineOffset((currentValue) =>\n Math.max(0, currentValue + delta * inspectorVisibleLineCount),\n );\n },\n onInspectorScroll: (delta) => {\n setInspectorLineOffset((currentValue) =>\n Math.max(0, currentValue + delta),\n );\n },\n onQuit: () => {\n onQuit?.();\n exit();\n },\n onSelectNextEvent: () => {\n setSelectedEventIndex((currentValue) => {\n if (displayedEvents.length === 0) {\n return null;\n }\n\n return Math.min(\n displayedEvents.length - 1,\n (currentValue ?? displayedEvents.length - 1) + 1,\n );\n });\n },\n onSelectPreviousEvent: () => {\n setSelectedEventIndex((currentValue) => {\n if (displayedEvents.length === 0) {\n return null;\n }\n\n return Math.max(0, (currentValue ?? displayedEvents.length - 1) - 1);\n });\n },\n onToggleFreeze: () => {\n const nextFrozen = !eventStream.isFrozen;\n\n eventStream.toggleFrozen();\n setFrozenFilteredEventCount(nextFrozen ? displayedEvents.length : null);\n },\n onToggleFullDataMode: () => {\n setInspectorLineOffset(0);\n },\n toolOptions: configuredAdapters,\n });\n const displayedEvents = applyEventFilters(\n eventStream.bufferedEvents,\n keyBinds.filters,\n );\n const fullDataModeEnabled = keyBinds.viewMode === 'full-data';\n const displayedSessions = applySessionFilters(sessions, keyBinds.filters);\n const safeSelectedEventIndex =\n displayedEvents.length === 0\n ? null\n : Math.min(\n selectedEventIndex ?? displayedEvents.length - 1,\n displayedEvents.length - 1,\n );\n const selectedEvent =\n safeSelectedEventIndex === null\n ? null\n : displayedEvents[safeSelectedEventIndex] ?? null;\n const inspectorLines =\n selectedEvent === null ? [] : buildEventInspectorLines(selectedEvent);\n const maxInspectorLineOffset = Math.max(\n 0,\n inspectorLines.length - inspectorVisibleLineCount,\n );\n const pendingFilteredEvents = eventStream.isFrozen\n ? getPendingFrozenEventCount(\n displayedEvents.length,\n frozenFilteredEventCount,\n )\n : 0;\n const visibleEvents = getVisibleEventWindow(displayedEvents, {\n anchorIndex: fullDataModeEnabled ? safeSelectedEventIndex : null,\n frozenAtTotalEvents: eventStream.isFrozen ? frozenFilteredEventCount : null,\n totalEvents: displayedEvents.length,\n visibleCount: compactLayout ? 4 : 6,\n });\n const globalStatus = deriveGlobalActivityStatus(displayedSessions);\n const activeFilterCount = countActiveFilters(keyBinds.filters);\n\n useEffect(() => {\n const startedAt = Date.now() - status.uptimeMs;\n const uptimeTimer = setInterval(() => {\n setUptimeMs(Date.now() - startedAt);\n }, 1_000);\n uptimeTimer.unref();\n\n return () => {\n clearInterval(uptimeTimer);\n };\n }, [status.uptimeMs]);\n\n useEffect(() => {\n if (eventStream.isFrozen) {\n setFrozenFilteredEventCount(displayedEvents.length);\n }\n }, [\n displayedEvents.length,\n eventStream.isFrozen,\n keyBinds.filters.eventType,\n keyBinds.filters.query,\n keyBinds.filters.tool,\n ]);\n\n useEffect(() => {\n if (displayedEvents.length === 0) {\n setSelectedEventIndex(null);\n return;\n }\n\n if (!fullDataModeEnabled) {\n setSelectedEventIndex(displayedEvents.length - 1);\n return;\n }\n\n setSelectedEventIndex((currentValue) => {\n if (currentValue === null) {\n return displayedEvents.length - 1;\n }\n\n return Math.min(currentValue, displayedEvents.length - 1);\n });\n }, [displayedEvents.length, fullDataModeEnabled]);\n\n useEffect(() => {\n setInspectorLineOffset(0);\n }, [selectedEvent?.id]);\n\n useEffect(() => {\n setInspectorLineOffset((currentValue) =>\n Math.min(currentValue, maxInspectorLineOffset),\n );\n }, [maxInspectorLineOffset]);\n\n return (\n <Box flexDirection=\"column\">\n <Header\n adapterCount={configuredAdapters.length}\n columns={columns}\n connectionLabel={status.connectionLabel}\n connected={status.connected}\n globalStatus={globalStatus}\n version={version}\n />\n <FilterBar\n filters={keyBinds.filters}\n focusPanel={keyBinds.focusPanel}\n interaction={keyBinds.interaction}\n viewMode={keyBinds.viewMode}\n />\n {keyBinds.interaction.kind === 'help' ? <HelpOverlay /> : null}\n <Box marginTop={1}>\n <PanelStack compact={compactLayout}>\n <Panel\n accentColor={TUI_THEME.warning}\n focused={keyBinds.focusPanel === 'events'}\n title=\"Event Stream\"\n >\n <EventStream\n emptyState={\n eventStream.bufferedEvents.length === 0 ? 'no-events' : 'no-match'\n }\n events={visibleEvents}\n frozen={eventStream.isFrozen}\n pendingEventCount={pendingFilteredEvents}\n selectedEventId={selectedEvent?.id ?? null}\n />\n </Panel>\n <Panel\n accentColor={fullDataModeEnabled ? TUI_THEME.warning : TUI_THEME.success}\n focused={keyBinds.focusPanel === 'sessions'}\n title={fullDataModeEnabled ? 'Full Data Inspector' : 'Sessions'}\n >\n {fullDataModeEnabled ? (\n <EventInspector\n event={selectedEvent}\n lineOffset={inspectorLineOffset}\n selectedEventIndex={safeSelectedEventIndex}\n totalEventCount={displayedEvents.length}\n visibleLineCount={inspectorVisibleLineCount}\n />\n ) : (\n <SessionPanel sessions={displayedSessions} />\n )}\n </Panel>\n </PanelStack>\n </Box>\n <Box marginTop={1}>\n <StatusBar\n activeFilterCount={activeFilterCount}\n adapterCount={configuredAdapters.length}\n columns={columns}\n connected={status.connected}\n consumerCount={status.consumerCount}\n eventCount={eventStream.totalEvents}\n focusPanel={keyBinds.focusPanel}\n latestEvent={displayedEvents.at(-1) ?? eventStream.latestEvent}\n pendingEventCount={pendingFilteredEvents}\n streamFrozen={eventStream.isFrozen}\n uptimeMs={uptimeMs}\n viewMode={keyBinds.viewMode}\n />\n </Box>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nimport type { AISnitchEvent } from '../../core/index.js';\nimport {\n buildEventInspectorLines,\n getVisibleInspectorWindow,\n} from '../event-inspector.js';\nimport { TUI_THEME } from '../theme.js';\n\n/**\n * @file src/tui/components/EventInspector.tsx\n * @description Scrollable full-data event inspector for the Ink TUI, rendering colorful metadata and the complete selected payload.\n * @functions\n * โ EventInspector\n * @exports EventInspector, type EventInspectorProps\n * @see ../event-inspector.ts\n * @see ../App.tsx\n */\n\n/**\n * Props required by the full-data inspector panel.\n */\nexport interface EventInspectorProps {\n readonly event: AISnitchEvent | null;\n readonly lineOffset: number;\n readonly selectedEventIndex: number | null;\n readonly totalEventCount: number;\n readonly visibleLineCount: number;\n}\n\n/**\n * Renders the currently selected event with a colorful, scrollable full-data view.\n */\nexport function EventInspector({\n event,\n lineOffset,\n selectedEventIndex,\n totalEventCount,\n visibleLineCount,\n}: EventInspectorProps): React.JSX.Element {\n if (event === null || selectedEventIndex === null) {\n return (\n <Box flexDirection=\"column\">\n <Text color={TUI_THEME.panelTitle}>\n No event selected yet.\n </Text>\n <Text color={TUI_THEME.muted}>\n Press [v] to open full-data mode, then use [โ/โ] on the event panel to pick one event.\n </Text>\n </Box>\n );\n }\n\n const inspectorLines = buildEventInspectorLines(event);\n const visibleLines = getVisibleInspectorWindow(inspectorLines, {\n lineOffset,\n visibleLineCount,\n });\n const hiddenAbove = Math.max(0, lineOffset);\n const hiddenBelow = Math.max(\n 0,\n inspectorLines.length - (lineOffset + visibleLines.length),\n );\n\n return (\n <Box flexDirection=\"column\">\n <Text color={TUI_THEME.panelBody}>\n {`Selected ${selectedEventIndex + 1}/${totalEventCount} โข ${inspectorLines.length} lines โข [v] close โข [โ/โ] scroll โข [[/]] page`}\n </Text>\n {hiddenAbove > 0 ? (\n <Text color={TUI_THEME.muted}>\n {`โ ${hiddenAbove} line${hiddenAbove === 1 ? '' : 's'} above`}\n </Text>\n ) : null}\n {visibleLines.map((line, lineIndex) => (\n <Text key={`${event.id}:${lineOffset + lineIndex}`}>\n {line.length === 0 || line.every((segment) => segment.text.length === 0)\n ? ' '\n : line.map((segment, segmentIndex) => (\n <Text\n key={`${event.id}:${lineOffset + lineIndex}:${segmentIndex}`}\n bold={segment.bold}\n color={segment.color}\n >\n {segment.text}\n </Text>\n ))}\n </Text>\n ))}\n {hiddenBelow > 0 ? (\n <Text color={TUI_THEME.muted}>\n {`โ ${hiddenBelow} line${hiddenBelow === 1 ? '' : 's'} below`}\n </Text>\n ) : null}\n </Box>\n );\n}\n","import type { AISnitchEvent } from '../core/events/types.js';\n\n/**\n * @file src/tui/event-details.ts\n * @description Shared event-detail extraction for the Ink stream and plain-text monitor output.\n * @functions\n * โ formatEventDetail\n * โ getEventDetailSegments\n * @exports formatEventDetail, getEventDetailSegments\n * @see ./components/EventLine.tsx\n * @see ./live-monitor.ts\n */\n\nconst DETAIL_SEGMENT_LIMIT = 120;\n\n/**\n * ๐ The adapters already stash richer source-native payloads in `data.raw`.\n * This helper squeezes the high-signal parts back out into short human-readable\n * fragments so operators can see prompts, thinking, tool targets, and streamed\n * assistant text without opening raw JSON.\n */\nexport function formatEventDetail(event: AISnitchEvent): string | null {\n const segments = getEventDetailSegments(event);\n\n return segments.length > 0 ? segments.join(' | ') : null;\n}\n\n/**\n * Returns stable, truncated detail segments for one event.\n */\nexport function getEventDetailSegments(event: AISnitchEvent): string[] {\n const raw = getRecord(event.data.raw);\n const segments: Array<string | undefined> = [];\n\n switch (event.type) {\n case 'agent.tool_call':\n case 'agent.coding':\n segments.push(formatToolSegment(event));\n segments.push(formatModelSegment(event.data.model));\n segments.push(formatTokenSegment(event.data.tokensUsed));\n break;\n\n case 'agent.thinking':\n segments.push(formatThinkingSegment(raw));\n segments.push(formatModelSegment(event.data.model));\n segments.push(formatTokenSegment(event.data.tokensUsed));\n segments.push(event.data.activeFile ?? event.data.cwd);\n break;\n\n case 'agent.streaming':\n segments.push(formatStreamingSegment(raw));\n segments.push(formatModelSegment(event.data.model));\n segments.push(formatTokenSegment(event.data.tokensUsed));\n segments.push(event.data.activeFile ?? event.data.cwd);\n break;\n\n case 'task.start':\n segments.push(formatPromptSegment(raw));\n segments.push(event.data.projectPath ?? event.data.project ?? event.data.cwd);\n break;\n\n case 'task.complete':\n segments.push(\n event.data.duration !== undefined\n ? `duration ${event.data.duration}ms`\n : undefined,\n );\n segments.push(formatTokenSegment(event.data.tokensUsed));\n segments.push(event.data.activeFile ?? event.data.projectPath ?? event.data.cwd);\n break;\n\n case 'agent.error':\n segments.push(event.data.errorType);\n segments.push(event.data.errorMessage);\n break;\n\n case 'agent.compact':\n segments.push('context compaction');\n segments.push(event.data.projectPath ?? event.data.cwd);\n break;\n\n case 'agent.asking_user':\n segments.push(\n getString(raw, 'notification_type') ??\n getString(raw, 'notificationType') ??\n getString(raw, 'type'),\n );\n segments.push(event.data.errorMessage ?? extractLooseString(raw, [\n 'message',\n 'reason',\n ]));\n break;\n\n case 'agent.idle':\n segments.push(event.data.activeFile ?? event.data.projectPath ?? event.data.cwd);\n break;\n\n case 'session.start':\n case 'session.end':\n segments.push(event.data.projectPath ?? event.data.project ?? event.data.cwd);\n segments.push(formatModelSegment(event.data.model));\n break;\n\n default:\n break;\n }\n\n return segments\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n .map((value) => truncateSegment(value));\n}\n\nfunction formatToolSegment(event: AISnitchEvent): string | undefined {\n const toolName = event.data.toolName;\n const filePath = event.data.toolInput?.filePath ?? event.data.activeFile;\n const command = event.data.toolInput?.command;\n\n if (!toolName && !filePath && !command) {\n return undefined;\n }\n\n const label = toolName ?? 'tool';\n\n if (filePath && command) {\n return `${label}: ${filePath} | cmd ${command}`;\n }\n\n if (filePath) {\n return `${label}: ${filePath}`;\n }\n\n if (command) {\n return `${label}: ${command}`;\n }\n\n return label;\n}\n\nfunction formatThinkingSegment(\n raw: Record<string, unknown> | undefined,\n): string | undefined {\n const snippet =\n extractContentPart(raw, 'thinking', 'thinking') ??\n extractLooseString(raw, ['thinking', 'message']);\n\n return snippet ? `thinking: ${snippet}` : undefined;\n}\n\nfunction formatStreamingSegment(\n raw: Record<string, unknown> | undefined,\n): string | undefined {\n const snippet =\n extractContentPart(raw, 'text', 'text') ??\n extractLooseString(raw, ['message', 'text', 'content']);\n\n return snippet ? `reply: ${snippet}` : undefined;\n}\n\nfunction formatPromptSegment(\n raw: Record<string, unknown> | undefined,\n): string | undefined {\n const snippet = extractLooseString(raw, [\n 'prompt',\n 'query',\n 'message',\n 'text',\n 'content',\n ]);\n\n return snippet ? `prompt: ${snippet}` : undefined;\n}\n\nfunction formatModelSegment(model: string | undefined): string | undefined {\n return model ? `model ${model}` : undefined;\n}\n\nfunction formatTokenSegment(tokensUsed: number | undefined): string | undefined {\n return tokensUsed !== undefined ? `${tokensUsed.toLocaleString('en-US')} tok` : undefined;\n}\n\nfunction extractContentPart(\n raw: Record<string, unknown> | undefined,\n partType: string,\n valueKey: string,\n): string | undefined {\n if (!raw) {\n return undefined;\n }\n\n const message = getRecord(raw.message);\n const content = message?.content ?? raw.content;\n\n if (!Array.isArray(content)) {\n return undefined;\n }\n\n for (const part of content) {\n const record = getRecord(part);\n\n if (!record || getString(record, 'type') !== partType) {\n continue;\n }\n\n const value = getString(record, valueKey);\n\n if (value) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction extractLooseString(\n raw: Record<string, unknown> | undefined,\n keys: readonly string[],\n): string | undefined {\n if (!raw) {\n return undefined;\n }\n\n for (const key of keys) {\n const directValue = getString(raw, key);\n\n if (directValue) {\n return directValue;\n }\n\n const nestedRecord = getRecord(raw[key]);\n const nestedValue =\n getString(nestedRecord, 'text') ??\n getString(nestedRecord, 'message') ??\n getString(nestedRecord, 'content');\n\n if (nestedValue) {\n return nestedValue;\n }\n }\n\n return undefined;\n}\n\nfunction truncateSegment(value: string): string {\n const normalized = value.replace(/\\s+/gu, ' ').trim();\n\n if (normalized.length <= DETAIL_SEGMENT_LIMIT) {\n return normalized;\n }\n\n return `${normalized.slice(0, DETAIL_SEGMENT_LIMIT - 1)}โฆ`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction getString(\n payload: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n if (!payload) {\n return undefined;\n }\n\n const value = payload[key];\n\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;\n}\n","import type { AISnitchEventType, ToolName } from '../core/index.js';\n\n/**\n * @file src/tui/theme.ts\n * @description Shared color palette and presentation constants for the Ink-based AISnitch terminal UI.\n * @functions\n * โ none\n * @exports TOOL_COLORS, EVENT_COLORS, TUI_THEME, type TuiThemeColor\n * @see ./App.tsx\n * @see ./components/Header.tsx\n * @see ./components/StatusBar.tsx\n */\n\n/**\n * Hex color string used across the terminal UI theme.\n */\nexport type TuiThemeColor = `#${string}`;\n\n/**\n * ๐ Tools keep distinct colors so operators can scan mixed activity without\n * having to read every label in a busy stream.\n */\nexport const TOOL_COLORS: Record<ToolName, TuiThemeColor> = {\n aider: '#14b8a6',\n amp: '#fb7185',\n 'claude-code': '#f59e0b',\n cline: '#f43f5e',\n codex: '#f97316',\n continue: '#06b6d4',\n 'copilot-cli': '#60a5fa',\n cursor: '#8b5cf6',\n 'gemini-cli': '#38bdf8',\n goose: '#ec4899',\n kilo: '#84cc16',\n openclaw: '#ef4444',\n opencode: '#10b981',\n openhands: '#facc15',\n 'qwen-code': '#22c55e',\n unknown: '#94a3b8',\n windsurf: '#c084fc',\n};\n\n/**\n * Event types get their own accents so state changes read as a visual rhythm.\n */\nexport const EVENT_COLORS: Record<AISnitchEventType, TuiThemeColor> = {\n 'agent.asking_user': '#ef4444',\n 'agent.coding': '#22c55e',\n 'agent.compact': '#f97316',\n 'agent.error': '#ef4444',\n 'agent.idle': '#64748b',\n 'agent.streaming': '#22d3ee',\n 'agent.thinking': '#facc15',\n 'agent.tool_call': '#fb7185',\n 'session.end': '#94a3b8',\n 'session.start': '#10b981',\n 'task.complete': '#34d399',\n 'task.start': '#60a5fa',\n};\n\n/**\n * Global palette used for layout chrome and section accents.\n */\nexport const TUI_THEME = {\n background: '#111827',\n border: '#1f2937',\n danger: '#ef4444',\n footer: '#0f172a',\n frame: '#334155',\n headerGradient: ['#f59e0b', '#fb7185', '#22d3ee'] as const,\n muted: '#94a3b8',\n panelBody: '#e2e8f0',\n panelTitle: '#f8fafc',\n success: '#22c55e',\n warning: '#facc15',\n} as const;\n","import { formatSessionLabelFromEvent, type AISnitchEvent } from '../core/index.js';\nimport { formatEventDetail } from './event-details.js';\nimport { EVENT_COLORS, TOOL_COLORS, TUI_THEME, type TuiThemeColor } from './theme.js';\n\n/**\n * @file src/tui/event-inspector.ts\n * @description Visual full-data formatter for the TUI event inspector, including colorful metadata rows and syntax-highlighted JSON blocks.\n * @functions\n * โ buildEventInspectorLines\n * โ getVisibleInspectorWindow\n * @exports InspectorSegment, InspectorLine, buildEventInspectorLines, getVisibleInspectorWindow\n * @see ./components/EventInspector.tsx\n * @see ./App.tsx\n */\n\nconst JSON_TOKEN_PATTERN =\n /(\"(?:\\\\.|[^\"])*\"(?=\\s*:))|(\"(?:\\\\.|[^\"])*\")|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|[[\\]{}:,]/gu;\n\n/**\n * Small token model rendered by the Ink inspector component.\n */\nexport interface InspectorSegment {\n readonly bold?: boolean;\n readonly color?: TuiThemeColor;\n readonly text: string;\n}\n\n/**\n * One rendered line inside the full-data inspector.\n */\nexport type InspectorLine = readonly InspectorSegment[];\n\n/**\n * ๐ The inspector deliberately mixes curated metadata with raw pretty JSON.\n * Operators get a friendly summary first, then the complete payload without\n * needing to mentally decode one enormous unstyled blob.\n */\nexport function buildEventInspectorLines(\n event: AISnitchEvent,\n): readonly InspectorLine[] {\n const eventColor = EVENT_COLORS[event.type];\n const toolColor = TOOL_COLORS[event['aisnitch.tool']];\n const sessionLabel = formatSessionLabelFromEvent(event);\n const detailSummary = formatEventDetail(event);\n const normalizedData = removeRawPayload(event.data);\n const rawPayload = event.data.raw ?? {\n note: 'No adapter raw payload was attached to this event.',\n };\n\n return [\n [\n { color: eventColor, text: 'โ ' },\n {\n bold: true,\n color: eventColor,\n text: event.type,\n },\n { color: TUI_THEME.muted, text: ' ' },\n { bold: true, color: toolColor, text: `[${event['aisnitch.tool']}]` },\n ],\n [\n { color: TUI_THEME.muted, text: 'session ' },\n { color: TUI_THEME.panelBody, text: sessionLabel },\n { color: TUI_THEME.muted, text: ' โข ' },\n { color: TUI_THEME.panelBody, text: formatEventTimestamp(event.time) },\n { color: TUI_THEME.muted, text: ' โข seq ' },\n { color: TUI_THEME.panelBody, text: `#${event['aisnitch.seqnum']}` },\n ],\n [\n { color: TUI_THEME.warning, text: 'โโ Spotlight โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ' },\n ],\n ...buildOptionalKeyValueLines([\n ['summary', detailSummary],\n ['project', event.data.projectPath ?? event.data.project],\n ['cwd', event.data.cwd],\n ['active_file', event.data.activeFile],\n ['command', event.data.toolInput?.command],\n ['model', event.data.model],\n [\n 'tokens',\n event.data.tokensUsed !== undefined\n ? `${event.data.tokensUsed.toLocaleString('en-US')} tok`\n : undefined,\n ],\n ['terminal', event.data.terminal],\n ['pid', event.data.pid],\n [\n 'instance',\n event.data.instanceIndex !== undefined &&\n event.data.instanceTotal !== undefined\n ? `${event.data.instanceIndex}/${event.data.instanceTotal}`\n : event.data.instanceId,\n ],\n ]),\n [{ text: '' }],\n [\n { color: TUI_THEME.warning, text: 'โโ Envelope โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ' },\n ],\n ...buildKeyValueLines([\n ['id', event.id],\n ['source', event.source],\n ['specversion', event.specversion],\n ['seq', String(event['aisnitch.seqnum'])],\n ['session_id', event['aisnitch.sessionid']],\n ['tool', event['aisnitch.tool']],\n ['time', event.time],\n ['type', event.type],\n ]),\n [{ text: '' }],\n [\n { color: TUI_THEME.success, text: 'โโ Normalized Data โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ' },\n ],\n ...buildJsonLines(normalizedData),\n [{ text: '' }],\n [\n { color: TUI_THEME.warning, text: 'โโ Raw Source Payload โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ' },\n ],\n ...buildJsonLines(rawPayload),\n ];\n}\n\n/**\n * Returns the visible scroll window for inspector lines.\n */\nexport function getVisibleInspectorWindow(\n lines: readonly InspectorLine[],\n options: {\n readonly lineOffset: number;\n readonly visibleLineCount: number;\n },\n): readonly InspectorLine[] {\n const safeLineOffset = Math.max(0, options.lineOffset);\n const safeVisibleLineCount = Math.max(1, options.visibleLineCount);\n\n return lines.slice(safeLineOffset, safeLineOffset + safeVisibleLineCount);\n}\n\nfunction buildKeyValueLines(\n entries: readonly (readonly [string, unknown])[],\n): readonly InspectorLine[] {\n return entries.map(([key, value]) => [\n { color: TUI_THEME.muted, text: ' ' },\n { color: '#7dd3fc', text: `${key}: ` },\n { color: TUI_THEME.panelBody, text: formatKeyValue(value) },\n ]);\n}\n\nfunction buildOptionalKeyValueLines(\n entries: readonly (readonly [string, unknown])[],\n): readonly InspectorLine[] {\n return buildKeyValueLines(\n entries.filter((entry): entry is readonly [string, unknown] => {\n const [, value] = entry;\n\n return hasDisplayValue(value);\n }),\n );\n}\n\nfunction buildJsonLines(value: unknown): readonly InspectorLine[] {\n const prettyJson = JSON.stringify(value, null, 2);\n\n if (!prettyJson) {\n return [[{ color: TUI_THEME.muted, text: ' (empty)' }]];\n }\n\n return prettyJson.split('\\n').map((line) => highlightJsonLine(line));\n}\n\nfunction highlightJsonLine(line: string): InspectorLine {\n if (line.length === 0) {\n return [{ text: '' }];\n }\n\n const segments: InspectorSegment[] = [];\n let lastIndex = 0;\n\n for (const match of line.matchAll(JSON_TOKEN_PATTERN)) {\n const matchedValue = match[0];\n const matchIndex = match.index ?? 0;\n\n if (matchIndex > lastIndex) {\n segments.push({\n color: TUI_THEME.panelBody,\n text: line.slice(lastIndex, matchIndex),\n });\n }\n\n segments.push({\n color: resolveJsonTokenColor(matchedValue, match),\n text: matchedValue,\n });\n lastIndex = matchIndex + matchedValue.length;\n }\n\n if (lastIndex < line.length) {\n segments.push({\n color: TUI_THEME.panelBody,\n text: line.slice(lastIndex),\n });\n }\n\n return segments.length > 0\n ? segments\n : [{ color: TUI_THEME.panelBody, text: line }];\n}\n\nfunction resolveJsonTokenColor(\n token: string,\n match: RegExpMatchArray,\n): TuiThemeColor {\n if (match[1]) {\n return '#7dd3fc';\n }\n\n if (match[2]) {\n return '#86efac';\n }\n\n if (token === 'true' || token === 'false') {\n return '#c084fc';\n }\n\n if (token === 'null') {\n return TUI_THEME.muted;\n }\n\n if (/^-?\\d/u.test(token)) {\n return '#fb923c';\n }\n\n return TUI_THEME.muted;\n}\n\nfunction removeRawPayload(\n data: AISnitchEvent['data'],\n): Record<string, unknown> {\n const { raw: _raw, ...normalizedData } = data;\n\n return normalizedData;\n}\n\nfunction formatKeyValue(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n\n if (value === null || value === undefined) {\n return 'n/a';\n }\n\n return JSON.stringify(value);\n}\n\nfunction hasDisplayValue(value: unknown): boolean {\n if (value === undefined || value === null) {\n return false;\n }\n\n if (typeof value === 'string') {\n return value.length > 0;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean') {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n\n return Object.keys(value).length > 0;\n}\n\nfunction formatEventTimestamp(timestamp: string): string {\n return new Intl.DateTimeFormat('en-GB', {\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n month: '2-digit',\n second: '2-digit',\n }).format(new Date(timestamp));\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nimport type { AISnitchEvent } from '../../core/index.js';\nimport { TUI_THEME } from '../theme.js';\nimport { EventLine } from './EventLine.js';\n\n/**\n * @file src/tui/components/EventStream.tsx\n * @description Live event stream panel content for the Ink TUI, rendering the visible event window and frozen-state hints.\n * @functions\n * โ EventStream\n * @exports EventStream, type EventStreamProps\n * @see ./EventLine.tsx\n * @see ../hooks/useEventStream.ts\n */\n\n/**\n * Props accepted by the live event stream component.\n */\nexport interface EventStreamProps {\n readonly emptyState?: 'no-events' | 'no-match';\n readonly events: readonly AISnitchEvent[];\n readonly frozen: boolean;\n readonly pendingEventCount: number;\n readonly selectedEventId?: string | null;\n}\n\n/**\n * Renders the current visible portion of the live event stream.\n */\nexport function EventStream({\n emptyState = 'no-events',\n events,\n frozen,\n pendingEventCount,\n selectedEventId = null,\n}: EventStreamProps): React.JSX.Element {\n if (events.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text color={TUI_THEME.panelTitle}>\n {emptyState === 'no-events'\n ? 'No events yet. Start with Claude Code or OpenCode and the foreground bus will light up here.'\n : 'No buffered events match the current filters.'}\n </Text>\n <Text color={TUI_THEME.muted}>\n {emptyState === 'no-events'\n ? 'Use [f], [t], [/], and [?] to shape the live view once events start flowing.'\n : 'Change the active filters or clear them with Esc.'}\n </Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n {events.map((event) => (\n <EventLine\n key={event.id}\n event={event}\n selected={selectedEventId === event.id}\n />\n ))}\n <Text color={TUI_THEME.muted}>\n {frozen\n ? `Frozen tail: ${pendingEventCount} newer ${\n pendingEventCount === 1 ? 'event is' : 'events are'\n } buffered.`\n : 'Live tail: newest events stay in view automatically.'}\n </Text>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nimport {\n formatSessionLabelFromEvent,\n type AISnitchEvent,\n type AISnitchEventType,\n} from '../../core/index.js';\nimport { formatEventDetail } from '../event-details.js';\nimport { EVENT_COLORS, TOOL_COLORS, TUI_THEME } from '../theme.js';\n\n/**\n * @file src/tui/components/EventLine.tsx\n * @description Single formatted event row for the Ink live stream, including icon mapping, timestamp formatting, and optional detail output.\n * @functions\n * โ EventLine\n * โ formatEventTime\n * โ formatEventDetail\n * @exports EVENT_ICONS, EventLine, formatEventTime, formatEventDetail\n * @see ./EventStream.tsx\n * @see ../hooks/useEventStream.ts\n */\n\n/**\n * ๐ The stream gets much easier to scan when each normalized state has a\n * stable visual marker instead of relying on color alone.\n */\nexport const EVENT_ICONS: Record<AISnitchEventType, string> = {\n 'session.start': '๐',\n 'session.end': '๐',\n 'task.start': '๐',\n 'task.complete': 'โ
',\n 'agent.thinking': '๐ค',\n 'agent.coding': 'โจ๏ธ',\n 'agent.tool_call': '๐ง',\n 'agent.streaming': '๐ฌ',\n 'agent.asking_user': 'โ',\n 'agent.idle': '๐ค',\n 'agent.error': 'โ',\n 'agent.compact': '๐ง ',\n};\n\n/**\n * Props required to render one formatted event row.\n */\nexport interface EventLineProps {\n readonly event: AISnitchEvent;\n readonly selected?: boolean;\n}\n\n/**\n * Renders a single event row plus its optional detail line.\n */\nexport function EventLine({\n event,\n selected = false,\n}: EventLineProps): React.JSX.Element {\n const detail = formatEventDetail(event);\n const sessionLabel = formatSessionLabelFromEvent(event);\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text color={selected ? TUI_THEME.warning : TUI_THEME.muted}>\n {selected ? 'โบ' : ' '}\n </Text>\n <Text> </Text>\n <Text color={TUI_THEME.muted}>{formatEventTime(event.time)}</Text>\n <Text> </Text>\n <Text>{EVENT_ICONS[event.type]}</Text>\n <Text> </Text>\n <Text color={TOOL_COLORS[event['aisnitch.tool']]}>\n [{event['aisnitch.tool']}]\n </Text>\n <Text> </Text>\n <Text bold color={EVENT_COLORS[event.type]}>\n {event.type}\n </Text>\n {sessionLabel !== event['aisnitch.tool'] ? (\n <>\n <Text color={TUI_THEME.muted}> ยท </Text>\n <Text color={TUI_THEME.muted}>{sessionLabel}</Text>\n </>\n ) : null}\n </Box>\n {detail ? (\n <Box marginLeft={4}>\n <Text color={selected ? TUI_THEME.panelBody : TUI_THEME.muted}>\n โโ {detail}\n </Text>\n </Box>\n ) : null}\n </Box>\n );\n}\n\n/**\n * Converts an ISO timestamp into a compact wall-clock string.\n */\nexport function formatEventTime(timestamp: string): string {\n return new Intl.DateTimeFormat('en-GB', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n }).format(new Date(timestamp));\n}\nexport { formatEventDetail } from '../event-details.js';\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nimport { countActiveFilters, type TuiFilters } from '../filters.js';\nimport type {\n FocusedPanel,\n TuiInteractionMode,\n} from '../hooks/useKeyBinds.js';\nimport { TUI_THEME } from '../theme.js';\nimport type { TuiViewMode } from '../types.js';\n\n/**\n * @file src/tui/components/FilterBar.tsx\n * @description Filter and command prompt bar for the AISnitch TUI, showing active filters, focus, and current interaction mode.\n * @functions\n * โ FilterBar\n * @exports FilterBar, type FilterBarProps\n * @see ../hooks/useKeyBinds.ts\n * @see ../filters.ts\n * @see ../App.tsx\n */\n\n/**\n * Props accepted by the TUI filter bar.\n */\nexport interface FilterBarProps {\n readonly filters: TuiFilters;\n readonly focusPanel: FocusedPanel;\n readonly interaction: TuiInteractionMode;\n readonly viewMode: TuiViewMode;\n}\n\n/**\n * Renders the currently active filters and the inline prompt state.\n */\nexport function FilterBar({\n filters,\n focusPanel,\n interaction,\n viewMode,\n}: FilterBarProps): React.JSX.Element {\n const activeFilterCount = countActiveFilters(filters);\n const focusLabel =\n focusPanel === 'events'\n ? 'events'\n : viewMode === 'full-data'\n ? 'inspector'\n : 'sessions';\n\n return (\n <Box\n borderColor={TUI_THEME.border}\n borderStyle=\"round\"\n flexDirection=\"column\"\n marginTop={1}\n paddingX={1}\n >\n <Text color={TUI_THEME.panelBody}>\n {`Focus ${focusLabel} | View ${viewMode} | Active filters ${activeFilterCount} | ${formatFilterSummary(\n filters,\n )}`}\n </Text>\n <Text color={TUI_THEME.muted}>\n {formatInteractionHint(interaction, focusPanel, viewMode)}\n </Text>\n </Box>\n );\n}\n\nfunction formatFilterSummary(filters: TuiFilters): string {\n const parts = [\n filters.tool ? `tool=${filters.tool}` : null,\n filters.eventType ? `type=${filters.eventType}` : null,\n filters.query.trim().length > 0 ? `search=\"${filters.query}\"` : null,\n ].filter((value): value is string => value !== null);\n\n return parts.length > 0 ? parts.join(' | ') : 'no filters active';\n}\n\nfunction formatInteractionHint(\n interaction: TuiInteractionMode,\n focusPanel: FocusedPanel,\n viewMode: TuiViewMode,\n): string {\n switch (interaction.kind) {\n case 'tool-filter':\n return `Tool filter > ${\n interaction.options[interaction.selectedIndex]?.label ?? 'All tools'\n } (โ/โ select, Enter apply, Esc clear)`;\n case 'type-filter':\n return `Type filter > ${\n interaction.options[interaction.selectedIndex]?.label ?? 'All event types'\n } (โ/โ select, Enter apply, Esc clear)`;\n case 'search':\n return `Search > ${interaction.draft}`;\n case 'help':\n return 'Help open (? or Esc to close)';\n default:\n if (viewMode === 'full-data') {\n return focusPanel === 'events'\n ? 'Commands: [v] summary [โ/โ or j/k] select event [Tab] inspector [f/t//] filters'\n : 'Commands: [v] summary [โ/โ or j/k] scroll [[/]] page [Tab] events';\n }\n\n return 'Commands: [v] full-data [f] tool [t] type [/] search [Esc] clear filters [Tab] focus';\n }\n}\n","import type {\n AISnitchEvent,\n AISnitchEventType,\n ToolName,\n} from '../core/index.js';\nimport { formatEventDetail } from './event-details.js';\n\n/**\n * @file src/tui/filters.ts\n * @description Pure filtering helpers shared by the TUI event stream, session panel, and CLI pre-filter handling.\n * @functions\n * โ applyEventFilters\n * โ applySessionFilters\n * โ countActiveFilters\n * @exports TuiFilters, SessionFilterTarget, DEFAULT_TUI_FILTERS, applyEventFilters, applySessionFilters, countActiveFilters\n * @see ./App.tsx\n * @see ./hooks/useKeyBinds.ts\n * @see ./hooks/useSessions.ts\n */\n\n/**\n * Global filter state applied across the TUI.\n */\nexport interface TuiFilters {\n readonly eventType: AISnitchEventType | null;\n readonly query: string;\n readonly tool: ToolName | null;\n}\n\n/**\n * Structural session shape accepted by the generic session filter helper.\n */\nexport interface SessionFilterTarget {\n readonly activeFile?: string;\n readonly currentState: AISnitchEventType;\n readonly cwd?: string;\n readonly displayLabel?: string;\n readonly project?: string;\n readonly projectPath?: string;\n readonly sessionId: string;\n readonly shortSessionId?: string;\n readonly tool: ToolName;\n}\n\n/**\n * Default empty filter state used by the TUI.\n */\nexport const DEFAULT_TUI_FILTERS: TuiFilters = {\n eventType: null,\n query: '',\n tool: null,\n};\n\n/**\n * Filters buffered events by tool, event type, and free-text search.\n */\nexport function applyEventFilters(\n events: readonly AISnitchEvent[],\n filters: TuiFilters,\n): readonly AISnitchEvent[] {\n return events.filter((event) => {\n if (filters.tool !== null && event['aisnitch.tool'] !== filters.tool) {\n return false;\n }\n\n if (filters.eventType !== null && event.type !== filters.eventType) {\n return false;\n }\n\n if (!matchesTextQuery(getEventSearchFields(event), filters.query)) {\n return false;\n }\n\n return true;\n });\n}\n\n/**\n * Filters active sessions using the same global TUI filter state.\n */\nexport function applySessionFilters<T extends SessionFilterTarget>(\n sessions: readonly T[],\n filters: TuiFilters,\n): readonly T[] {\n return sessions.filter((session) => {\n if (filters.tool !== null && session.tool !== filters.tool) {\n return false;\n }\n\n if (filters.eventType !== null && session.currentState !== filters.eventType) {\n return false;\n }\n\n if (\n !matchesTextQuery(\n [\n session.sessionId,\n session.tool,\n session.currentState,\n session.displayLabel,\n session.project,\n session.projectPath,\n session.cwd,\n session.activeFile,\n session.shortSessionId,\n ],\n filters.query,\n )\n ) {\n return false;\n }\n\n return true;\n });\n}\n\n/**\n * Counts how many filter categories are currently active.\n */\nexport function countActiveFilters(filters: TuiFilters): number {\n let count = 0;\n\n if (filters.tool !== null) {\n count += 1;\n }\n\n if (filters.eventType !== null) {\n count += 1;\n }\n\n if (filters.query.trim().length > 0) {\n count += 1;\n }\n\n return count;\n}\n\nfunction getEventSearchFields(event: AISnitchEvent): readonly (string | undefined)[] {\n return [\n event['aisnitch.tool'],\n event.type,\n event['aisnitch.sessionid'],\n formatEventDetail(event) ?? undefined,\n event.data.toolName,\n event.data.toolInput?.filePath,\n event.data.toolInput?.command,\n event.data.activeFile,\n event.data.errorMessage,\n event.data.cwd,\n event.data.project,\n event.data.projectPath,\n ];\n}\n\nfunction matchesTextQuery(\n values: readonly (string | undefined)[],\n query: string,\n): boolean {\n const normalizedQuery = query.trim().toLowerCase();\n\n if (normalizedQuery.length === 0) {\n return true;\n }\n\n return values.some((value) => value?.toLowerCase().includes(normalizedQuery));\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport BigText from 'ink-big-text';\nimport Gradient from 'ink-gradient';\nimport Spinner from 'ink-spinner';\n\nimport type { GlobalActivityStatus } from '../hooks/useSessions.js';\nimport { TUI_THEME } from '../theme.js';\nimport { GlobalBadge } from './GlobalBadge.js';\n\n/**\n * @file src/tui/components/Header.tsx\n * @description Header chrome for the AISnitch TUI, including title treatment and connection status badge.\n * @functions\n * โ Header\n * @exports Header, type HeaderProps\n * @see ../App.tsx\n * @see ./StatusBar.tsx\n */\n\n/**\n * Props accepted by the header component.\n */\nexport interface HeaderProps {\n readonly adapterCount: number;\n readonly columns: number;\n readonly connectionLabel: string;\n readonly connected: boolean;\n readonly globalStatus: GlobalActivityStatus;\n readonly version: string;\n}\n\n/**\n * ๐ The header does the \"vitrine\" job from the spec: bold title treatment,\n * a little theater, and the essential runtime badges in one glance.\n */\nexport function Header({\n adapterCount,\n columns,\n connectionLabel,\n connected,\n globalStatus,\n version,\n}: HeaderProps): React.JSX.Element {\n const showBigTitle = columns >= 88;\n\n return (\n <Box\n borderColor={TUI_THEME.border}\n borderStyle=\"round\"\n flexDirection=\"column\"\n paddingX={1}\n paddingY={0}\n >\n <Box justifyContent=\"space-between\">\n <Text color={TUI_THEME.muted}>memory-only live bridge</Text>\n <Text color={TUI_THEME.muted}>v{version}</Text>\n </Box>\n <Box justifyContent=\"space-between\">\n <Box flexDirection=\"column\" flexGrow={1}>\n {showBigTitle ? (\n <Gradient colors={[...TUI_THEME.headerGradient]}>\n <BigText font=\"tiny\" text=\"AISnitch\" />\n </Gradient>\n ) : (\n <Gradient colors={[...TUI_THEME.headerGradient]}>\n <Text bold> AISnitch </Text>\n </Gradient>\n )}\n <Text color={TUI_THEME.muted}>\n live AI tool telemetry with adapter-driven normalization\n </Text>\n </Box>\n <Box\n alignItems=\"flex-end\"\n flexDirection=\"column\"\n marginLeft={2}\n minWidth={26}\n >\n <Box>\n {connected ? (\n <Text bold color={TUI_THEME.success}>\n โ Connected ยท {connectionLabel}\n </Text>\n ) : (\n <>\n <Text bold color={TUI_THEME.warning}>\n <Spinner type=\"dots\" />\n </Text>\n <Text color={TUI_THEME.warning}> reconnecting</Text>\n </>\n )}\n </Box>\n <GlobalBadge status={globalStatus} />\n <Text color={TUI_THEME.muted}>{adapterCount} adapters armed</Text>\n </Box>\n </Box>\n </Box>\n );\n}\n","import React from 'react';\nimport { Text } from 'ink';\n\nimport type { GlobalActivityStatus } from '../hooks/useSessions.js';\nimport { TUI_THEME } from '../theme.js';\n\n/**\n * @file src/tui/components/GlobalBadge.tsx\n * @description Compact activity badge for the TUI header, summarizing whether the system is idle, busy, or waiting on the user.\n * @functions\n * โ GlobalBadge\n * @exports GlobalBadge, type GlobalBadgeProps\n * @see ./Header.tsx\n * @see ../hooks/useSessions.ts\n */\n\n/**\n * Props accepted by the global activity badge.\n */\nexport interface GlobalBadgeProps {\n readonly status: GlobalActivityStatus;\n}\n\n/**\n * Renders the high-level activity badge displayed in the TUI header.\n */\nexport function GlobalBadge({\n status,\n}: GlobalBadgeProps): React.JSX.Element {\n switch (status) {\n case 'action-required':\n return (\n <Text bold color={TUI_THEME.danger}>\n โ Action Required\n </Text>\n );\n case 'working':\n return (\n <Text bold color={TUI_THEME.warning}>\n โฆ Working\n </Text>\n );\n default:\n return (\n <Text bold color={TUI_THEME.success}>\n โ Ready\n </Text>\n );\n }\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nimport { TUI_THEME } from '../theme.js';\n\n/**\n * @file src/tui/components/HelpOverlay.tsx\n * @description Compact help overlay listing the current AISnitch TUI keybinds.\n * @functions\n * โ HelpOverlay\n * @exports HelpOverlay\n * @see ../hooks/useKeyBinds.ts\n * @see ../App.tsx\n */\n\nconst HELP_LINES = [\n 'q / Ctrl+C quit cleanly',\n 'v toggle full-data inspector',\n 'f filter by tool',\n 't filter by event type',\n '/ free-text search',\n 'Esc clear filters',\n 'Space freeze or resume stream',\n 'c clear buffered stream',\n 'โ/โ or j/k inspect-mode navigate / scroll',\n '[ / ] inspect-mode page scroll',\n '? toggle help',\n 'Tab cycle focused panel',\n];\n\n/**\n * Renders the help box shown above the main panels.\n */\nexport function HelpOverlay(): React.JSX.Element {\n return (\n <Box\n borderColor={TUI_THEME.warning}\n borderStyle=\"round\"\n flexDirection=\"column\"\n marginTop={1}\n paddingX={1}\n >\n <Text bold color={TUI_THEME.panelTitle}>\n Keybinds\n </Text>\n {HELP_LINES.map((line) => (\n <Text key={line} color={TUI_THEME.panelBody}>\n {line}\n </Text>\n ))}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nimport { TUI_THEME, type TuiThemeColor } from '../theme.js';\n\n/**\n * @file src/tui/components/Layout.tsx\n * @description Reusable layout primitives for bordered panels and responsive panel stacks in the AISnitch TUI.\n * @functions\n * โ Panel\n * โ PanelStack\n * @exports Panel, PanelStack, type PanelProps, type PanelStackProps\n * @see ../App.tsx\n * @see ./Header.tsx\n * @see ./StatusBar.tsx\n */\n\n/**\n * Props for a single framed panel.\n */\nexport interface PanelProps {\n readonly accentColor: TuiThemeColor;\n readonly children: React.ReactNode;\n readonly flexGrow?: number;\n readonly focused?: boolean;\n readonly title: string;\n}\n\n/**\n * Props for a responsive panel stack.\n */\nexport interface PanelStackProps {\n readonly children: React.ReactNode;\n readonly compact?: boolean;\n}\n\n/**\n * ๐ A thin panel primitive keeps the TUI consistent without hiding Ink's\n * flexbox model behind too much framework glue.\n */\nexport function Panel({\n accentColor,\n children,\n flexGrow = 1,\n focused = false,\n title,\n}: PanelProps): React.JSX.Element {\n return (\n <Box\n borderColor={focused ? accentColor : TUI_THEME.frame}\n borderStyle=\"round\"\n flexDirection=\"column\"\n flexGrow={flexGrow}\n minHeight={8}\n paddingX={1}\n paddingY={0}\n >\n <Box marginBottom={1}>\n <Text bold color={accentColor}>\n {title}\n </Text>\n </Box>\n <Box flexDirection=\"column\" flexGrow={1}>\n {children}\n </Box>\n </Box>\n );\n}\n\n/**\n * Renders the main body panels side by side on wide terminals and stacked on narrow ones.\n */\nexport function PanelStack({\n children,\n compact = false,\n}: PanelStackProps): React.JSX.Element {\n return (\n <Box\n columnGap={1}\n flexDirection={compact ? 'column' : 'row'}\n flexGrow={1}\n rowGap={1}\n >\n {children}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\n\nimport type { SessionState } from '../hooks/useSessions.js';\nimport { TOOL_COLORS, TUI_THEME } from '../theme.js';\n\n/**\n * @file src/tui/components/SessionPanel.tsx\n * @description Grouped active-session renderer for the AISnitch TUI, including state-specific visual cues and durations.\n * @functions\n * โ SessionPanel\n * @exports SessionPanel, type SessionPanelProps\n * @see ../hooks/useSessions.ts\n * @see ../App.tsx\n */\n\n/**\n * Props accepted by the session panel renderer.\n */\nexport interface SessionPanelProps {\n readonly sessions: readonly SessionState[];\n}\n\n/**\n * ๐ Session grouping stays intentionally compact so operators can tell \"who\n * is doing what\" without the panel becoming wider than the event stream.\n */\nexport function SessionPanel({\n sessions,\n}: SessionPanelProps): React.JSX.Element {\n if (sessions.length === 0) {\n return (\n <Text color={TUI_THEME.muted}>\n No active sessions match the current view.\n </Text>\n );\n }\n\n const groupedSessions = groupSessionsByTool(sessions);\n\n return (\n <Box flexDirection=\"column\">\n {groupedSessions.map(([toolName, toolSessions]) => (\n <Box key={toolName} flexDirection=\"column\" marginBottom={1}>\n <Text bold color={TOOL_COLORS[toolName]}>\n {toolName} ({toolSessions.length})\n </Text>\n {toolSessions.map((session) => (\n <Box key={session.sessionId} flexDirection=\"column\" marginLeft={1}>\n <Text color={TOOL_COLORS[session.tool]}>\n โ {session.displayLabel}\n </Text>\n {formatSessionLocation(session) ? (\n <Text color={TUI_THEME.muted}>\n {` โณ ${formatSessionLocation(session)}`}\n </Text>\n ) : null}\n <Box marginLeft={2}>\n {renderStateLabel(session)}\n <Text color={TUI_THEME.muted}>\n {` ยท ${session.eventCount} events ยท ${formatDuration(session.durationMs)}`}\n </Text>\n {session.shortSessionId ? (\n <Text color={TUI_THEME.muted}>\n {` ยท sid ${session.shortSessionId}`}\n </Text>\n ) : null}\n </Box>\n </Box>\n ))}\n </Box>\n ))}\n </Box>\n );\n}\n\nfunction renderStateLabel(session: SessionState): React.JSX.Element {\n switch (session.currentState) {\n case 'agent.coding':\n return (\n <Text color={TUI_THEME.success}>\n <Spinner type=\"runner\" /> coding\n </Text>\n );\n case 'agent.thinking':\n return (\n <Text color={TUI_THEME.warning}>\n <Spinner type=\"dots\" /> thinking\n </Text>\n );\n case 'agent.asking_user':\n return (\n <Text bold color={TUI_THEME.danger}>\n โ asking_user\n </Text>\n );\n case 'agent.error':\n return (\n <Text bold color={TUI_THEME.danger}>\n โ error\n </Text>\n );\n case 'agent.idle':\n return <Text color={TUI_THEME.muted}>idle</Text>;\n default:\n return (\n <Text color={TUI_THEME.panelBody}>{session.currentState}</Text>\n );\n }\n}\n\nfunction groupSessionsByTool(\n sessions: readonly SessionState[],\n): readonly [SessionState['tool'], readonly SessionState[]][] {\n const groupedSessions = new Map<SessionState['tool'], SessionState[]>();\n\n for (const session of sessions) {\n const toolSessions = groupedSessions.get(session.tool) ?? [];\n\n toolSessions.push(session);\n groupedSessions.set(session.tool, toolSessions);\n }\n\n return [...groupedSessions.entries()];\n}\n\nfunction formatSessionLocation(session: SessionState): string | null {\n return session.activeFile ?? session.projectPath ?? session.cwd ?? null;\n}\n\nfunction formatDuration(durationMs: number): string {\n const totalSeconds = Math.max(0, Math.floor(durationMs / 1_000));\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n\n if (minutes === 0) {\n return `${seconds}s`;\n }\n\n return `${minutes}m ${seconds}s`;\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nimport type { AISnitchEvent } from '../../core/index.js';\nimport type { FocusedPanel } from '../hooks/useKeyBinds.js';\nimport { TUI_THEME } from '../theme.js';\nimport type { TuiViewMode } from '../types.js';\n\n/**\n * @file src/tui/components/StatusBar.tsx\n * @description Footer status bar for runtime counts, uptime, and keybind hints in the AISnitch TUI.\n * @functions\n * โ StatusBar\n * @exports StatusBar, type StatusBarProps\n * @see ../App.tsx\n */\n\n/**\n * Props accepted by the status bar component.\n */\nexport interface StatusBarProps {\n readonly activeFilterCount: number;\n readonly adapterCount: number;\n readonly columns: number;\n readonly connected: boolean;\n readonly consumerCount: number;\n readonly eventCount: number;\n readonly focusPanel: FocusedPanel;\n readonly latestEvent: AISnitchEvent | null;\n readonly pendingEventCount?: number;\n readonly streamFrozen: boolean;\n readonly uptimeMs: number;\n readonly viewMode: TuiViewMode;\n}\n\n/**\n * Renders the lower chrome with lightweight stats and keyboard hints.\n */\nexport function StatusBar({\n activeFilterCount,\n adapterCount,\n columns,\n connected,\n consumerCount,\n eventCount,\n focusPanel,\n latestEvent,\n pendingEventCount = 0,\n streamFrozen,\n uptimeMs,\n viewMode,\n}: StatusBarProps): React.JSX.Element {\n const streamState = streamFrozen\n ? `Frozen +${pendingEventCount}`\n : latestEvent?.type ?? 'Live';\n const focusLabel =\n focusPanel === 'events'\n ? 'events'\n : viewMode === 'full-data'\n ? 'inspector'\n : 'sessions';\n\n return (\n <Box\n borderColor={TUI_THEME.border}\n borderStyle=\"round\"\n flexDirection=\"column\"\n paddingX={1}\n paddingY={0}\n >\n <Text color={TUI_THEME.panelBody}>\n {`Events ${eventCount} | Adapters ${adapterCount} | Consumers ${consumerCount} | Filters ${activeFilterCount} | Focus ${focusLabel} | View ${viewMode} | Up ${formatUptime(\n uptimeMs,\n )} | ${streamState} | Size ${columns}c`}\n </Text>\n <Text color={TUI_THEME.muted}>\n {connected\n ? streamFrozen\n ? '[space] resume [v] full-data [q] quit [?] help [f/t//] filters [c] clear'\n : '[space] freeze [v] full-data [q] quit [?] help [f/t//] filters [c] clear'\n : '[q] quit waiting for foreground bus'}\n </Text>\n </Box>\n );\n}\n\nfunction formatUptime(uptimeMs: number): string {\n const totalSeconds = Math.max(0, Math.floor(uptimeMs / 1_000));\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n\n if (minutes === 0) {\n return `${seconds}s`;\n }\n\n return `${minutes}m ${seconds}s`;\n}\n","import { useEffect, useState } from 'react';\nimport type { RawData, WebSocket } from 'ws';\n\nimport {\n AISnitchEventSchema,\n type AISnitchEvent,\n type EventBus,\n} from '../../core/index.js';\n\n/**\n * @file src/tui/hooks/useEventStream.ts\n * @description React hook and pure helpers for collecting, bounding, and freezing the live AISnitch event stream.\n * @functions\n * โ useEventStream\n * โ appendEventToStream\n * โ getVisibleEventWindow\n * โ getPendingFrozenEventCount\n * @exports EVENT_STREAM_LIMIT, EventStreamSource, UseEventStreamOptions, UseEventStreamState, useEventStream, appendEventToStream, getVisibleEventWindow, getPendingFrozenEventCount\n * @see ../components/EventStream.tsx\n * @see ../../core/engine/event-bus.ts\n * @see ../../core/engine/ws-server.ts\n */\n\n/**\n * Maximum number of live events kept in memory for the TUI stream.\n */\nexport const EVENT_STREAM_LIMIT = 500;\n\n/**\n * Default number of rendered events kept in the visible terminal window.\n */\nexport const DEFAULT_VISIBLE_EVENT_COUNT = 8;\n\n/**\n * Supported live sources for the event stream hook.\n */\nexport type EventStreamSource =\n | {\n readonly kind: 'event-bus';\n readonly eventBus: EventBus;\n }\n | {\n readonly kind: 'websocket';\n readonly socket: Pick<WebSocket, 'on' | 'off'>;\n };\n\n/**\n * Configuration accepted by the event stream hook.\n */\nexport interface UseEventStreamOptions {\n readonly initialTotalEvents?: number;\n readonly limit?: number;\n readonly visibleCount?: number;\n}\n\n/**\n * State returned by the live event stream hook.\n */\nexport interface UseEventStreamState {\n readonly bufferedEvents: readonly AISnitchEvent[];\n readonly clearEvents: () => void;\n readonly isFrozen: boolean;\n readonly latestEvent: AISnitchEvent | null;\n readonly pendingEventCount: number;\n readonly toggleFrozen: () => void;\n readonly totalEvents: number;\n readonly visibleEvents: readonly AISnitchEvent[];\n}\n\n/**\n * ๐ The hook owns stream mechanics so `App` can stay focused on layout and\n * panel composition instead of juggling buffer trimming, freeze anchors, and\n * source-specific subscription code.\n */\nexport function useEventStream(\n source: EventStreamSource,\n options: UseEventStreamOptions = {},\n): UseEventStreamState {\n const limit = options.limit ?? EVENT_STREAM_LIMIT;\n const visibleCount = options.visibleCount ?? DEFAULT_VISIBLE_EVENT_COUNT;\n const [bufferedEvents, setBufferedEvents] = useState<readonly AISnitchEvent[]>(\n [],\n );\n const [totalEvents, setTotalEvents] = useState(options.initialTotalEvents ?? 0);\n const [latestEvent, setLatestEvent] = useState<AISnitchEvent | null>(null);\n const [frozenAtTotalEvents, setFrozenAtTotalEvents] = useState<number | null>(\n null,\n );\n\n useEffect(() => {\n const unsubscribe = subscribeToEventStream(source, (event) => {\n setLatestEvent(event);\n setTotalEvents((currentValue) => currentValue + 1);\n setBufferedEvents((currentValue) =>\n appendEventToStream(currentValue, event, limit),\n );\n });\n\n return () => {\n unsubscribe();\n };\n }, [limit, source]);\n\n const pendingEventCount = getPendingFrozenEventCount(\n totalEvents,\n frozenAtTotalEvents,\n );\n const visibleEvents = getVisibleEventWindow(bufferedEvents, {\n totalEvents,\n frozenAtTotalEvents,\n visibleCount,\n });\n\n return {\n bufferedEvents,\n clearEvents: () => {\n setBufferedEvents([]);\n setFrozenAtTotalEvents(null);\n setLatestEvent(null);\n },\n isFrozen: frozenAtTotalEvents !== null,\n latestEvent,\n pendingEventCount,\n toggleFrozen: () => {\n setFrozenAtTotalEvents((currentValue) =>\n currentValue === null ? totalEvents : null,\n );\n },\n totalEvents,\n visibleEvents,\n };\n}\n\n/**\n * Appends a new event while keeping the TUI stream buffer size bounded.\n */\nexport function appendEventToStream(\n currentEvents: readonly AISnitchEvent[],\n event: AISnitchEvent,\n limit = EVENT_STREAM_LIMIT,\n): readonly AISnitchEvent[] {\n const nextEvents = [...currentEvents, event];\n\n if (nextEvents.length <= limit) {\n return nextEvents;\n }\n\n return nextEvents.slice(-limit);\n}\n\n/**\n * Calculates the currently visible event window, respecting frozen tail mode.\n */\nexport function getVisibleEventWindow(\n bufferedEvents: readonly AISnitchEvent[],\n options: {\n readonly anchorIndex?: number | null;\n readonly frozenAtTotalEvents?: number | null;\n readonly totalEvents: number;\n readonly visibleCount: number;\n },\n): readonly AISnitchEvent[] {\n if (options.anchorIndex !== undefined && options.anchorIndex !== null) {\n const clampedAnchorIndex = Math.max(\n 0,\n Math.min(options.anchorIndex, Math.max(0, bufferedEvents.length - 1)),\n );\n const halfWindow = Math.floor(options.visibleCount / 2);\n const tentativeStartIndex = Math.max(0, clampedAnchorIndex - halfWindow);\n const tentativeEndIndex = Math.min(\n bufferedEvents.length,\n tentativeStartIndex + options.visibleCount,\n );\n const visibleStartIndex = Math.max(\n 0,\n tentativeEndIndex - options.visibleCount,\n );\n\n return bufferedEvents.slice(visibleStartIndex, tentativeEndIndex);\n }\n\n const pendingEventCount = getPendingFrozenEventCount(\n options.totalEvents,\n options.frozenAtTotalEvents ?? null,\n );\n const visibleEndIndex =\n pendingEventCount === 0\n ? bufferedEvents.length\n : Math.max(0, bufferedEvents.length - pendingEventCount);\n const visibleStartIndex = Math.max(0, visibleEndIndex - options.visibleCount);\n\n return bufferedEvents.slice(visibleStartIndex, visibleEndIndex);\n}\n\n/**\n * Returns how many newer events are hidden while the stream is frozen.\n */\nexport function getPendingFrozenEventCount(\n totalEvents: number,\n frozenAtTotalEvents: number | null,\n): number {\n if (frozenAtTotalEvents === null) {\n return 0;\n }\n\n return Math.max(0, totalEvents - frozenAtTotalEvents);\n}\n\nfunction subscribeToEventStream(\n source: EventStreamSource,\n onEvent: (event: AISnitchEvent) => void,\n): () => void {\n if (source.kind === 'event-bus') {\n return source.eventBus.subscribe(onEvent);\n }\n\n const handleMessage = (data: RawData): void => {\n const parsedPayload = parseSocketPayload(data);\n\n if (parsedPayload !== null) {\n onEvent(parsedPayload);\n }\n };\n\n source.socket.on('message', handleMessage);\n\n return () => {\n source.socket.off('message', handleMessage);\n };\n}\n\nfunction parseSocketPayload(data: RawData): AISnitchEvent | null {\n const parsedPayload = parseUnknownPayload(data);\n\n if (\n typeof parsedPayload === 'object' &&\n parsedPayload !== null\n ) {\n const messageCandidate = parsedPayload as Record<string, unknown>;\n\n if (messageCandidate.type === 'welcome') {\n return null;\n }\n }\n\n const parsedEvent = AISnitchEventSchema.safeParse(parsedPayload);\n\n return parsedEvent.success ? parsedEvent.data : null;\n}\n\nfunction parseUnknownPayload(data: RawData): unknown {\n if (typeof data === 'string') {\n return JSON.parse(data) as unknown;\n }\n\n if (Array.isArray(data)) {\n return JSON.parse(Buffer.concat(data).toString('utf8')) as unknown;\n }\n\n if (data instanceof ArrayBuffer) {\n return JSON.parse(\n Buffer.from(new Uint8Array(data)).toString('utf8'),\n ) as unknown;\n }\n\n return JSON.parse(Buffer.from(data).toString('utf8')) as unknown;\n}\n","import { useState, type Dispatch, type SetStateAction } from 'react';\nimport { useInput } from 'ink';\n\nimport {\n AISNITCH_EVENT_TYPES,\n type AISnitchEventType,\n type ToolName,\n} from '../../core/index.js';\nimport {\n DEFAULT_TUI_FILTERS,\n type TuiFilters,\n} from '../filters.js';\nimport type { TuiViewMode } from '../types.js';\n\n/**\n * @file src/tui/hooks/useKeyBinds.ts\n * @description Centralized keyboard controller for the AISnitch TUI, including filters, focus, help, and stream actions.\n * @functions\n * โ useKeyBinds\n * @exports FocusedPanel, SelectorOption, TuiInteractionMode, UseKeyBindsOptions, UseKeyBindsState, useKeyBinds\n * @see ../components/FilterBar.tsx\n * @see ../components/HelpOverlay.tsx\n * @see ../App.tsx\n */\n\n/**\n * Panel focus ids supported by the current TUI.\n */\nexport type FocusedPanel = 'events' | 'sessions';\n\n/**\n * Generic selector option used by tool/type filter pickers.\n */\nexport interface SelectorOption<TValue> {\n readonly label: string;\n readonly value: TValue;\n}\n\n/**\n * Current interactive mode of the TUI.\n */\nexport type TuiInteractionMode =\n | {\n readonly kind: 'normal';\n }\n | {\n readonly kind: 'help';\n }\n | {\n readonly kind: 'search';\n readonly draft: string;\n }\n | {\n readonly kind: 'tool-filter';\n readonly options: readonly SelectorOption<ToolName | null>[];\n readonly selectedIndex: number;\n }\n | {\n readonly kind: 'type-filter';\n readonly options: readonly SelectorOption<AISnitchEventType | null>[];\n readonly selectedIndex: number;\n };\n\n/**\n * Inputs needed by the keyboard controller.\n */\nexport interface UseKeyBindsOptions {\n readonly fullDataModeEnabled?: boolean;\n readonly initialFilters?: Partial<TuiFilters>;\n readonly onClearStream: () => void;\n readonly onInspectorPageScroll?: (delta: number) => void;\n readonly onInspectorScroll?: (delta: number) => void;\n readonly onQuit?: () => void;\n readonly onSelectNextEvent?: () => void;\n readonly onSelectPreviousEvent?: () => void;\n readonly onToggleFreeze: () => void;\n readonly onToggleFullDataMode?: () => void;\n readonly toolOptions: readonly ToolName[];\n}\n\n/**\n * State returned by the keyboard controller.\n */\nexport interface UseKeyBindsState {\n readonly filters: TuiFilters;\n readonly focusPanel: FocusedPanel;\n readonly interaction: TuiInteractionMode;\n readonly viewMode: TuiViewMode;\n}\n\n/**\n * ๐ Keeping key handling in one hook prevents `App` from turning into a pile\n * of unrelated `useInput` branches as the TUI grows more interactive.\n */\nexport function useKeyBinds(\n options: UseKeyBindsOptions,\n): UseKeyBindsState {\n const toolOptions = buildToolOptions(options.toolOptions);\n const typeOptions = buildTypeOptions();\n const [filters, setFilters] = useState<TuiFilters>({\n ...DEFAULT_TUI_FILTERS,\n ...options.initialFilters,\n query: options.initialFilters?.query ?? '',\n });\n const [focusPanel, setFocusPanel] = useState<FocusedPanel>('events');\n const [interaction, setInteraction] = useState<TuiInteractionMode>({\n kind: 'normal',\n });\n const [viewMode, setViewMode] = useState<TuiViewMode>(\n options.fullDataModeEnabled === true ? 'full-data' : 'summary',\n );\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n options.onQuit?.();\n return;\n }\n\n if (interaction.kind === 'search') {\n if (key.escape) {\n clearFilters(setFilters, setInteraction);\n return;\n }\n\n if (key.return) {\n setInteraction({\n kind: 'normal',\n });\n return;\n }\n\n if (key.backspace || key.delete) {\n const nextDraft = interaction.draft.slice(0, -1);\n\n setFilters((currentValue) => ({\n ...currentValue,\n query: nextDraft,\n }));\n setInteraction({\n kind: 'search',\n draft: nextDraft,\n });\n return;\n }\n\n if (!key.ctrl && !key.meta && input.length > 0) {\n const nextDraft = `${interaction.draft}${input}`;\n\n setFilters((currentValue) => ({\n ...currentValue,\n query: nextDraft,\n }));\n setInteraction({\n kind: 'search',\n draft: nextDraft,\n });\n }\n\n return;\n }\n\n if (\n interaction.kind === 'tool-filter' ||\n interaction.kind === 'type-filter'\n ) {\n if (key.escape) {\n clearFilters(setFilters, setInteraction);\n return;\n }\n\n if (key.upArrow || input === 'k') {\n setInteraction(moveSelector(interaction, -1));\n return;\n }\n\n if (key.downArrow || input === 'j') {\n setInteraction(moveSelector(interaction, 1));\n return;\n }\n\n if (key.return) {\n if (interaction.kind === 'tool-filter') {\n setFilters((currentValue) => ({\n ...currentValue,\n tool: interaction.options[interaction.selectedIndex]?.value ?? null,\n }));\n } else {\n setFilters((currentValue) => ({\n ...currentValue,\n eventType:\n interaction.options[interaction.selectedIndex]?.value ?? null,\n }));\n }\n\n setInteraction({\n kind: 'normal',\n });\n }\n\n return;\n }\n\n if (interaction.kind === 'help') {\n if (input === 'q') {\n options.onQuit?.();\n return;\n }\n\n if (input === '?' || key.escape || key.return) {\n setInteraction({\n kind: 'normal',\n });\n }\n\n return;\n }\n\n if (input === 'q') {\n options.onQuit?.();\n return;\n }\n\n if (input === 'v') {\n const nextViewMode = viewMode === 'summary' ? 'full-data' : 'summary';\n\n options.onToggleFullDataMode?.();\n setViewMode(nextViewMode);\n\n if (nextViewMode === 'summary' && focusPanel === 'sessions') {\n setFocusPanel('events');\n }\n\n return;\n }\n\n if (input === ' ') {\n options.onToggleFreeze();\n return;\n }\n\n if (input === 'c') {\n options.onClearStream();\n return;\n }\n\n if (input === '?') {\n setInteraction({\n kind: 'help',\n });\n return;\n }\n\n if (input === 'f') {\n setInteraction({\n kind: 'tool-filter',\n options: toolOptions,\n selectedIndex: getSelectedIndex(toolOptions, filters.tool),\n });\n return;\n }\n\n if (input === 't') {\n setInteraction({\n kind: 'type-filter',\n options: typeOptions,\n selectedIndex: getSelectedIndex(typeOptions, filters.eventType),\n });\n return;\n }\n\n if (input === '/') {\n setInteraction({\n kind: 'search',\n draft: filters.query,\n });\n return;\n }\n\n if (key.escape) {\n clearFilters(setFilters, setInteraction);\n return;\n }\n\n if (\n viewMode === 'full-data' &&\n (key.upArrow || input === 'k')\n ) {\n if (focusPanel === 'events') {\n options.onSelectPreviousEvent?.();\n } else {\n options.onInspectorScroll?.(-1);\n }\n return;\n }\n\n if (\n viewMode === 'full-data' &&\n (key.downArrow || input === 'j')\n ) {\n if (focusPanel === 'events') {\n options.onSelectNextEvent?.();\n } else {\n options.onInspectorScroll?.(1);\n }\n return;\n }\n\n if (viewMode === 'full-data' && input === '[') {\n options.onInspectorPageScroll?.(-1);\n return;\n }\n\n if (viewMode === 'full-data' && input === ']') {\n options.onInspectorPageScroll?.(1);\n return;\n }\n\n if (key.tab) {\n setFocusPanel((currentValue) =>\n currentValue === 'events' ? 'sessions' : 'events',\n );\n }\n });\n\n return {\n filters,\n focusPanel,\n interaction,\n viewMode,\n };\n}\n\nfunction buildToolOptions(\n tools: readonly ToolName[],\n): readonly SelectorOption<ToolName | null>[] {\n return [\n {\n label: 'All tools',\n value: null,\n },\n ...tools.map((tool) => ({\n label: tool,\n value: tool,\n })),\n ];\n}\n\nfunction buildTypeOptions(): readonly SelectorOption<AISnitchEventType | null>[] {\n return [\n {\n label: 'All event types',\n value: null,\n },\n ...AISNITCH_EVENT_TYPES.map((eventType) => ({\n label: eventType,\n value: eventType,\n })),\n ];\n}\n\nfunction getSelectedIndex<TValue>(\n options: readonly SelectorOption<TValue>[],\n value: TValue,\n): number {\n const selectedIndex = options.findIndex((option) => option.value === value);\n\n return selectedIndex === -1 ? 0 : selectedIndex;\n}\n\nfunction moveSelector(\n interaction:\n | Extract<TuiInteractionMode, { readonly kind: 'tool-filter' }>\n | Extract<TuiInteractionMode, { readonly kind: 'type-filter' }>,\n delta: number,\n):\n | Extract<TuiInteractionMode, { readonly kind: 'tool-filter' }>\n | Extract<TuiInteractionMode, { readonly kind: 'type-filter' }> {\n const nextIndex =\n (interaction.selectedIndex + delta + interaction.options.length) %\n interaction.options.length;\n\n return {\n ...interaction,\n selectedIndex: nextIndex,\n };\n}\n\nfunction clearFilters(\n setFilters: Dispatch<SetStateAction<TuiFilters>>,\n setInteraction: Dispatch<SetStateAction<TuiInteractionMode>>,\n): void {\n setFilters(DEFAULT_TUI_FILTERS);\n setInteraction({\n kind: 'normal',\n });\n}\n","import { useEffect, useState } from 'react';\n\nimport type {\n AISnitchEvent,\n AISnitchEventType,\n ToolName,\n} from '../../core/index.js';\nimport { formatSessionLabel, formatSessionShortId } from '../../core/index.js';\n\n/**\n * @file src/tui/hooks/useSessions.ts\n * @description Session aggregation helpers for the TUI, including active-session derivation and high-level activity status.\n * @functions\n * โ useSessions\n * โ deriveSessions\n * โ deriveGlobalActivityStatus\n * @exports SESSION_STALE_AFTER_MS, SessionState, GlobalActivityStatus, useSessions, deriveSessions, deriveGlobalActivityStatus\n * @see ../components/SessionPanel.tsx\n * @see ../components/GlobalBadge.tsx\n * @see ../App.tsx\n */\n\n/**\n * Default timeout used to evict stale sessions that never emitted `session.end`.\n */\nexport const SESSION_STALE_AFTER_MS = 120_000;\n\n/**\n * Derived session model rendered by the TUI.\n */\nexport interface SessionState {\n readonly activeFile?: string;\n readonly cwd?: string;\n readonly currentState: AISnitchEventType;\n readonly displayLabel: string;\n readonly durationMs: number;\n readonly eventCount: number;\n readonly instanceIndex?: number;\n readonly instanceTotal?: number;\n readonly lastEventAt: string;\n readonly pid?: number;\n readonly project?: string;\n readonly projectPath?: string;\n readonly sessionId: string;\n readonly shortSessionId?: string;\n readonly startedAt: string;\n readonly tool: ToolName;\n}\n\n/**\n * High-level activity summary used by the header badge.\n */\nexport type GlobalActivityStatus = 'action-required' | 'ready' | 'working';\n\n/**\n * ๐ Sessions are derived from normalized events instead of being tracked as a\n * second independent runtime channel. That keeps the TUI honest: if the event\n * contract says one thing and the session panel says another, the bug is local\n * and debuggable.\n */\nexport function useSessions(\n events: readonly AISnitchEvent[],\n options: {\n readonly staleAfterMs?: number;\n } = {},\n): readonly SessionState[] {\n const [now, setNow] = useState(Date.now());\n\n useEffect(() => {\n const timer = setInterval(() => {\n setNow(Date.now());\n }, 1_000);\n timer.unref();\n\n return () => {\n clearInterval(timer);\n };\n }, []);\n\n return deriveSessions(events, {\n now,\n staleAfterMs: options.staleAfterMs,\n });\n}\n\n/**\n * Builds the active-session list from the normalized event buffer.\n */\nexport function deriveSessions(\n events: readonly AISnitchEvent[],\n options: {\n readonly now?: number;\n readonly staleAfterMs?: number;\n } = {},\n): readonly SessionState[] {\n const now = options.now ?? Date.now();\n const staleAfterMs = options.staleAfterMs ?? SESSION_STALE_AFTER_MS;\n const sessionMap = new Map<string, SessionState>();\n\n for (const event of events) {\n const existingSession = sessionMap.get(event['aisnitch.sessionid']);\n const startedAt =\n existingSession?.startedAt ??\n (event.type === 'session.start' ? event.time : event.time);\n const nextSession: SessionState = {\n activeFile: event.data.activeFile ?? existingSession?.activeFile,\n cwd: event.data.cwd ?? existingSession?.cwd,\n currentState: event.type,\n displayLabel: formatSessionLabel({\n activeFile: event.data.activeFile ?? existingSession?.activeFile,\n cwd: event.data.cwd ?? existingSession?.cwd,\n instanceIndex: event.data.instanceIndex ?? existingSession?.instanceIndex,\n instanceTotal: event.data.instanceTotal ?? existingSession?.instanceTotal,\n pid: event.data.pid ?? existingSession?.pid,\n project: event.data.project ?? existingSession?.project,\n projectPath: event.data.projectPath ?? existingSession?.projectPath,\n sessionId: event['aisnitch.sessionid'],\n tool: event['aisnitch.tool'],\n }),\n durationMs: Math.max(0, now - Date.parse(startedAt)),\n eventCount: (existingSession?.eventCount ?? 0) + 1,\n instanceIndex:\n event.data.instanceIndex ?? existingSession?.instanceIndex,\n instanceTotal:\n event.data.instanceTotal ?? existingSession?.instanceTotal,\n lastEventAt: event.time,\n pid: event.data.pid ?? existingSession?.pid,\n project: event.data.project ?? existingSession?.project,\n projectPath: event.data.projectPath ?? existingSession?.projectPath,\n sessionId: event['aisnitch.sessionid'],\n shortSessionId: formatSessionShortId(\n event['aisnitch.tool'],\n event['aisnitch.sessionid'],\n ),\n startedAt,\n tool: event['aisnitch.tool'],\n };\n\n sessionMap.set(event['aisnitch.sessionid'], nextSession);\n }\n\n return [...sessionMap.values()]\n .filter((session) => {\n if (session.currentState === 'session.end') {\n return false;\n }\n\n return now - Date.parse(session.lastEventAt) <= staleAfterMs;\n })\n .sort((left, right) => {\n return Date.parse(right.lastEventAt) - Date.parse(left.lastEventAt);\n });\n}\n\n/**\n * Derives the global activity badge state from the active sessions list.\n */\nexport function deriveGlobalActivityStatus(\n sessions: readonly SessionState[],\n): GlobalActivityStatus {\n if (\n sessions.some((session) =>\n session.currentState === 'agent.asking_user' ||\n session.currentState === 'agent.error',\n )\n ) {\n return 'action-required';\n }\n\n if (\n sessions.some((session) =>\n session.currentState === 'agent.coding' ||\n session.currentState === 'agent.thinking' ||\n session.currentState === 'agent.tool_call' ||\n session.currentState === 'agent.streaming' ||\n session.currentState === 'task.start',\n )\n ) {\n return 'working';\n }\n\n return 'ready';\n}\n","import type { AISnitchEventType, ToolName } from '../core/index.js';\n\n/**\n * @file src/tui/types.ts\n * @description Shared TUI runtime types reused by the renderer entrypoints, app shell, and CLI integration layer.\n * @functions\n * โ none\n * @exports TUI_VIEW_MODES, TuiViewMode, TuiInitialFilters, TuiStatusSnapshot\n * @see ./App.tsx\n * @see ./index.tsx\n */\n\n/**\n * Supported body views for the interactive TUI.\n */\nexport const TUI_VIEW_MODES = ['summary', 'full-data'] as const;\n\n/**\n * Union of the TUI body views accepted by CLI and renderer code.\n */\nexport type TuiViewMode = (typeof TUI_VIEW_MODES)[number];\n\n/**\n * CLI or runtime-provided filters applied when the TUI opens.\n */\nexport interface TuiInitialFilters {\n readonly query?: string;\n readonly tool?: ToolName;\n readonly type?: AISnitchEventType;\n readonly view?: TuiViewMode;\n}\n\n/**\n * Lightweight runtime snapshot consumed by the TUI shell.\n */\nexport interface TuiStatusSnapshot {\n readonly connected: boolean;\n readonly connectionLabel: string;\n readonly consumerCount: number;\n readonly eventCount: number;\n readonly uptimeMs: number;\n}\n","import { once } from 'node:events';\n\nimport WebSocket, { type RawData } from 'ws';\n\nimport { AISnitchEventSchema } from '../core/events/index.js';\nimport type {\n AISnitchEvent,\n EventBus,\n WelcomeMessage,\n} from '../core/index.js';\nimport { formatSessionLabelFromEvent } from '../core/index.js';\nimport { formatEventDetail } from './event-details.js';\n\n/**\n * @file src/tui/live-monitor.ts\n * @description Lightweight plain-text live event monitor formatter retained for tests and fallback console output.\n * @functions\n * โ formatEventLine\n * โ formatWelcomeLine\n * โ attachEventBusMonitor\n * โ attachWebSocketMonitor\n * @exports MonitorOutput, MonitorCloseHandler, formatEventLine, formatWelcomeLine, attachEventBusMonitor, attachWebSocketMonitor\n * @see ../core/engine/ws-server.ts\n * @see ../core/events/schema.ts\n */\n\n/**\n * Minimal output contract shared by CLI monitor renderers.\n */\nexport interface MonitorOutput {\n readonly stdout: (text: string) => void;\n readonly stderr: (text: string) => void;\n}\n\n/**\n * Async close callback returned by monitor attach helpers.\n */\nexport type MonitorCloseHandler = () => Promise<void> | void;\n\n/**\n * ๐ The Ink TUI is now the primary operator surface, but these formatters are\n * still useful for tests and any future low-friction text fallbacks.\n */\nexport function formatEventLine(event: AISnitchEvent): string {\n const detail = formatEventDetail(event);\n const summary = detail ? ` :: ${detail}` : '';\n\n return [\n `[${event.time}]`,\n event['aisnitch.tool'],\n event.type,\n `session=${formatSessionLabelFromEvent(event)}`,\n `sid=${event['aisnitch.sessionid']}`,\n event.data.cwd ? `cwd=${event.data.cwd}` : undefined,\n ]\n .filter((value): value is string => typeof value === 'string')\n .join(' ') + summary;\n}\n\n/**\n * Formats the WebSocket welcome payload for human-readable output.\n */\nexport function formatWelcomeLine(message: WelcomeMessage): string {\n const tools =\n message.tools.length > 0 ? message.tools.join(', ') : 'none configured';\n\n return `Connected to AISnitch ${message.version} (tools: ${tools})`;\n}\n\n/**\n * Attaches a live writer to the in-process EventBus.\n */\nexport function attachEventBusMonitor(\n eventBus: EventBus,\n output: MonitorOutput,\n): MonitorCloseHandler {\n output.stdout('AISnitch live monitor attached (foreground mode).\\n');\n\n return eventBus.subscribe((event) => {\n output.stdout(`${formatEventLine(event)}\\n`);\n });\n}\n\n/**\n * Attaches to an existing daemon over WebSocket and streams monitor lines.\n */\nexport async function attachWebSocketMonitor(\n url: string,\n output: MonitorOutput,\n): Promise<MonitorCloseHandler> {\n const socket = new WebSocket(url);\n\n socket.on('message', (data) => {\n const parsedPayload = parseSocketMessage(data);\n\n if (isWelcomeMessage(parsedPayload)) {\n output.stdout(`${formatWelcomeLine(parsedPayload)}\\n`);\n return;\n }\n\n const parsedEvent = AISnitchEventSchema.safeParse(parsedPayload);\n\n if (parsedEvent.success) {\n output.stdout(`${formatEventLine(parsedEvent.data)}\\n`);\n return;\n }\n\n output.stderr('Received an unrecognized monitor payload.\\n');\n });\n\n socket.on('error', (error) => {\n output.stderr(\n `AISnitch attach socket error: ${\n error instanceof Error ? error.message : 'unknown error'\n }\\n`,\n );\n });\n\n await once(socket, 'open');\n\n return async () => {\n if (\n socket.readyState === WebSocket.CLOSING ||\n socket.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n socket.close();\n await once(socket, 'close');\n };\n}\n\nfunction parseSocketMessage(data: RawData): unknown {\n if (typeof data === 'string') {\n return JSON.parse(data) as unknown;\n }\n\n if (Array.isArray(data)) {\n return JSON.parse(Buffer.concat(data).toString('utf8')) as unknown;\n }\n\n if (data instanceof ArrayBuffer) {\n return JSON.parse(\n Buffer.from(new Uint8Array(data)).toString('utf8'),\n ) as unknown;\n }\n\n return JSON.parse(Buffer.from(data).toString('utf8')) as unknown;\n}\n\nfunction isWelcomeMessage(payload: unknown): payload is WelcomeMessage {\n if (typeof payload !== 'object' || payload === null) {\n return false;\n }\n\n const candidate = payload as Record<string, unknown>;\n\n return (\n candidate.type === 'welcome' &&\n typeof candidate.version === 'string' &&\n Array.isArray(candidate.tools)\n );\n}\n"],"mappings":"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","names":["import_node_path","pino","import_zod","isUuid","uuidVersion","uuidv7","execFileCallback","pidCwd","import_node_child_process","import_promises","import_node_path","import_node_util","import_chokidar","execFile","execFileCallback","import_node_child_process","import_promises","import_node_path","import_node_util","import_chokidar","execFile","execFileCallback","isRecord","getString","getRecord","collectFilesRecursively","listProcesses","mergedMetadata","isErrnoException","import_node_child_process","import_promises","import_node_path","import_node_util","import_chokidar","execFile","execFileCallback","listProcesses","isRecord","getString","parseProcessLine","isErrnoException","import_node_child_process","import_promises","import_node_path","import_node_util","import_chokidar","execFile","execFileCallback","isRecord","getString","getNumber","collectFilesRecursively","listProcesses","isErrnoException","getRecord","parseProcessLine","import_node_child_process","import_promises","import_node_path","import_node_util","import_chokidar","execFile","execFileCallback","isRecord","getString","getRecord","extractLooseString","listProcesses","getNumber","parseJsonRecord","extractFirstString","import_node_child_process","import_promises","import_node_path","import_node_util","import_chokidar","import_pid_cwd","execFile","execFileCallback","pidCwd","isRecord","getNumber","collectFilesRecursively","parseJsonRecord","getString","getRecord","import_node_child_process","import_node_util","execFile","execFileCallback","isRecord","getString","getNumber","listProcesses","getRecord","import_node_path","import_node_child_process","import_node_path","import_node_util","import_pid_cwd","execFile","execFileCallback","pidCwd","spawnPty","resolve","stripAnsi","import_zod","import_promises","import_node_os","import_node_path","resolve","import_node_events","resolve","import_promises","import_node_net","import_node_events","resolve","import_node_path","import_zod","import_ink","import_ws","import_react","import_ink","getRecord","getString","extractLooseString","isRecord","import_ink","import_ink","import_jsx_runtime","import_jsx_runtime","import_ink","import_jsx_runtime","import_ink","import_ink","import_jsx_runtime","import_jsx_runtime","Gradient","BigText","Spinner","import_ink","import_jsx_runtime","import_ink","import_jsx_runtime","import_ink","import_ink_spinner","import_jsx_runtime","Spinner","import_ink","import_jsx_runtime","visibleStartIndex","import_react","import_ink","import_react","import_jsx_runtime","import_node_events","import_ws","WebSocket","import_jsx_runtime","WebSocket"]}
|