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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/program.ts","../../src/package-info.ts","../../src/core/events/schema.ts","../../src/core/events/factory.ts","../../src/cli/mock/scenarios.ts","../../src/cli/commands/mock.ts","../../src/cli/commands/setup.ts","../../src/core/config/schema.ts","../../src/core/config/defaults.ts","../../src/core/config/loader.ts","../../src/cli/runtime.ts","../../src/adapters/generic-pty.ts","../../src/core/engine/context-detector.ts","../../src/core/engine/logger.ts","../../src/core/session-identity.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/adapters/aider.ts","../../src/adapters/base.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/index.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","../../src/cli/pid.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { CommanderError } from 'commander';\n\nimport { createProgram } from './program.js';\n\n/**\n * @file src/cli/index.ts\n * @description Executable AISnitch CLI entrypoint with centralized commander bootstrapping and error handling.\n * @functions\n * → runCli\n * → handleCliError\n * @exports runCli, createProgram\n * @see ./program.ts\n * @see ./runtime.ts\n */\n\n/**\n * Runs the AISnitch CLI against the provided argv vector.\n */\nexport async function runCli(\n argv: readonly string[] = process.argv,\n): Promise<void> {\n const program = createProgram();\n\n await program.parseAsync(argv, {\n from: 'node',\n });\n}\n\n/**\n * 📖 Commander already formats validation and help errors nicely, so this\n * wrapper only normalizes everything else into one stable stderr path.\n */\nfunction handleCliError(error: unknown): void {\n if (error instanceof CommanderError && error.exitCode === 0) {\n process.exitCode = 0;\n return;\n }\n\n const message =\n error instanceof Error ? error.message : 'Unknown AISnitch CLI error';\n\n process.stderr.write(`AISnitch CLI failed: ${message}\\n`);\n process.exitCode = 1;\n}\n\nasync function main(): Promise<void> {\n try {\n await runCli();\n } catch (error: unknown) {\n handleCliError(error);\n }\n}\n\nvoid main();\n","import { Command, InvalidArgumentError } from 'commander';\n\nimport {\n AISNITCH_DESCRIPTION,\n AISNITCH_PACKAGE_NAME,\n AISNITCH_VERSION,\n} from '../package-info.js';\nimport {\n parseMockDurationOption,\n parseMockSpeedOption,\n parseMockToolSelection,\n} from './commands/mock.js';\nimport {\n parseSetupToolName,\n type SetupCliOptions,\n type SetupToolName,\n} from './commands/setup.js';\nimport {\n createCliRuntime,\n parseEventTypeFilterOption,\n parseLogLevelOption,\n parsePortOption,\n parseTuiViewModeOption,\n parseToolFilterOption,\n type CliRuntime,\n type AttachCliOptions,\n type CommonCliOptions,\n type MockCliOptions,\n type StartCliOptions,\n type WrapCliOptions,\n} from './runtime.js';\n\n/**\n * @file src/cli/program.ts\n * @description Commander-based CLI definition for AISnitch commands and shared options.\n * @functions\n * → createProgram\n * @exports createProgram\n * @see ./runtime.ts\n * @see ./pid.ts\n */\n\ninterface ProgramDependencies {\n readonly runtime?: CliRuntime;\n}\n\n/**\n * 📖 Commander wiring stays isolated here so the entrypoint can stay tiny and\n * the runtime logic remains testable without shelling out to the real binary.\n */\nexport function createProgram(\n dependencies: ProgramDependencies = {},\n): Command {\n const runtime = dependencies.runtime ?? createCliRuntime();\n const program = new Command();\n\n program\n .name(AISNITCH_PACKAGE_NAME)\n .description(AISNITCH_DESCRIPTION)\n .version(AISNITCH_VERSION)\n .showHelpAfterError()\n .showSuggestionAfterError()\n .addHelpText(\n 'after',\n `\nExamples:\n aisnitch start\n aisnitch start --daemon\n aisnitch start --view full-data\n aisnitch start --mock\n aisnitch status\n aisnitch attach\n aisnitch attach --view full-data\n aisnitch setup claude-code\n aisnitch setup aider\n aisnitch setup gemini-cli\n aisnitch setup goose\n aisnitch setup codex\n aisnitch setup copilot-cli\n aisnitch setup openclaw\n aisnitch mock all --speed 2 --duration 20\n aisnitch wrap aider --model sonnet\n aisnitch install\n`,\n );\n\n addStartCommand(program, runtime);\n addStopCommand(program, runtime);\n addStatusCommand(program, runtime);\n addAdaptersCommand(program, runtime);\n addSetupCommand(program, runtime);\n addAttachCommand(program, runtime);\n addMockCommand(program, runtime);\n addWrapCommand(program, runtime);\n addInstallCommand(program, runtime);\n addUninstallCommand(program, runtime);\n addDaemonRunCommand(program, runtime);\n addAiderNotifyCommand(program, runtime);\n\n return program;\n}\n\nfunction addCommonOptions(command: Command): Command {\n return command.option(\n '--config <path>',\n 'Override the config.json path used by AISnitch',\n );\n}\n\nfunction addStartCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program\n .command('start', { isDefault: true })\n .description('Start AISnitch in foreground mode by default')\n .option('--daemon', 'Run AISnitch as a detached daemon')\n .option(\n '--mock [tool]',\n 'Inject deterministic mock events (defaults to \"all\" when no tool is specified)',\n wrapOptionParser(parseMockToolSelection),\n )\n .option(\n '--mock-speed <factor>',\n 'Speed factor for mock replay',\n wrapOptionParser(parseMockSpeedOption),\n )\n .option('--mock-loop', 'Loop the mock scenario until stopped')\n .option(\n '--mock-duration <seconds>',\n 'Duration of mock replay in seconds',\n wrapOptionParser(parseMockDurationOption),\n )\n .option(\n '--tool <tool>',\n 'Pre-filter the foreground TUI by tool',\n wrapOptionParser(parseToolFilterOption),\n )\n .option(\n '--type <type>',\n 'Pre-filter the foreground TUI by event type',\n wrapOptionParser(parseEventTypeFilterOption),\n )\n .option(\n '--view <view>',\n 'Open the foreground TUI in summary or full-data mode',\n wrapOptionParser(parseTuiViewModeOption),\n )\n .option(\n '--ws-port <port>',\n 'Override the WebSocket port',\n wrapOptionParser(parsePortOption),\n )\n .option(\n '--http-port <port>',\n 'Override the HTTP hook port',\n wrapOptionParser(parsePortOption),\n )\n .option(\n '--log-level <level>',\n 'Override the runtime log level',\n wrapOptionParser(parseLogLevelOption),\n ),\n ).action(async (options: StartCliOptions & { mock?: unknown }) => {\n await runtime.start({\n ...options,\n mock: normalizeMockSelection(options.mock),\n });\n });\n}\n\nfunction addStopCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program.command('stop').description('Stop the detached AISnitch daemon'),\n ).action(async (options: CommonCliOptions) => {\n await runtime.stop(options);\n });\n}\n\nfunction addStatusCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program.command('status').description('Show current AISnitch daemon status'),\n ).action(async (options: CommonCliOptions) => {\n await runtime.status(options);\n });\n}\n\nfunction addAdaptersCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program.command('adapters').description('List configured AISnitch adapters'),\n ).action(async (options: CommonCliOptions) => {\n await runtime.adapters(options);\n });\n}\n\nfunction addSetupCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program\n .command('setup')\n .description('Configure supported AI tools to forward events into AISnitch')\n .argument(\n '<tool>',\n 'Tool to configure (claude-code, opencode, gemini-cli, aider, codex, goose, copilot-cli, openclaw)',\n parseSetupToolName,\n )\n .option('--revert', 'Restore the previous tool configuration from backup'),\n ).action(async (toolName: SetupToolName, options: SetupCliOptions) => {\n await runtime.setup(toolName, options);\n });\n}\n\nfunction addMockCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program\n .command('mock')\n .description('Replay deterministic mock event scenarios through the normal AISnitch pipeline')\n .argument(\n '<tool>',\n 'Mock tool or scenario to replay (claude-code, opencode, all)',\n parseMockToolSelection,\n )\n .option(\n '--speed <factor>',\n 'Speed factor for mock replay',\n wrapOptionParser(parseMockSpeedOption),\n )\n .option('--loop', 'Loop the selected scenario until the duration budget is reached')\n .option(\n '--duration <seconds>',\n 'Duration of mock replay in seconds',\n wrapOptionParser(parseMockDurationOption),\n ),\n ).action(async (toolName: Parameters<CliRuntime['mock']>[0], options: MockCliOptions) => {\n await runtime.mock(toolName, options);\n });\n}\n\nfunction addAttachCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program\n .command('attach')\n .description('Attach the Ink TUI to the running daemon')\n .option(\n '--tool <tool>',\n 'Pre-filter the attached TUI by tool',\n wrapOptionParser(parseToolFilterOption),\n )\n .option(\n '--type <type>',\n 'Pre-filter the attached TUI by event type',\n wrapOptionParser(parseEventTypeFilterOption),\n )\n .option(\n '--view <view>',\n 'Open the attached TUI in summary or full-data mode',\n wrapOptionParser(parseTuiViewModeOption),\n ),\n ).action(async (options: AttachCliOptions) => {\n await runtime.attach(options);\n });\n}\n\nfunction addWrapCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program\n .command('wrap')\n .description('Run a command inside a PTY while AISnitch observes its terminal activity')\n .allowUnknownOption(true)\n .argument('<command>', 'Command to wrap')\n .argument('[args...]', 'Arguments forwarded to the wrapped command')\n .option('--cwd <path>', 'Run the wrapped command from a specific working directory'),\n ).action(\n async (command: string, args: string[], options: WrapCliOptions) => {\n await runtime.wrap(command, args, options);\n },\n );\n}\n\nfunction addInstallCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program.command('install').description('Install a macOS LaunchAgent for AISnitch'),\n ).action(async (options: CommonCliOptions) => {\n await runtime.install(options);\n });\n}\n\nfunction addUninstallCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program.command('uninstall').description('Remove the AISnitch macOS LaunchAgent'),\n ).action(async (options: CommonCliOptions) => {\n await runtime.uninstall(options);\n });\n}\n\nfunction addDaemonRunCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program\n .command('daemon-run')\n .description('Internal headless daemon bootstrap command')\n .option(\n '--ws-port <port>',\n 'Override the WebSocket port',\n wrapOptionParser(parsePortOption),\n )\n .option(\n '--http-port <port>',\n 'Override the HTTP hook port',\n wrapOptionParser(parsePortOption),\n )\n .option(\n '--log-level <level>',\n 'Override the runtime log level',\n wrapOptionParser(parseLogLevelOption),\n ),\n ).action(async (options: StartCliOptions) => {\n await runtime.runDaemonProcess(options);\n });\n}\n\nfunction addAiderNotifyCommand(program: Command, runtime: CliRuntime): void {\n addCommonOptions(\n program\n .command('aider-notify')\n .description('Internal aider notifications-command bridge'),\n ).action(async (options: CommonCliOptions) => {\n await runtime.aiderNotify(options);\n });\n}\n\nfunction wrapOptionParser<T>(\n parser: (value: string) => T,\n): (value: string) => T {\n return (value) => {\n try {\n return parser(value);\n } catch (error: unknown) {\n throw new InvalidArgumentError(\n error instanceof Error ? error.message : 'Invalid option value.',\n );\n }\n };\n}\n\nfunction normalizeMockSelection(value: unknown): StartCliOptions['mock'] {\n if (value === undefined) {\n return undefined;\n }\n\n if (value === true) {\n return 'all';\n }\n\n if (value === 'all' || value === 'claude-code' || value === 'opencode') {\n return value;\n }\n\n throw new InvalidArgumentError('Unsupported mock scenario selection.');\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 { 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 { createEvent } from '../../core/events/factory.js';\nimport type {\n AISnitchEvent,\n AISnitchEventType,\n ToolName,\n} from '../../core/events/types.js';\n\n/**\n * @file src/cli/mock/scenarios.ts\n * @description Deterministic mock event timelines used by the CLI demo/testing flows to simulate realistic multi-tool activity.\n * @functions\n * → buildMockScenario\n * @exports MOCK_TOOL_SELECTIONS, MockToolSelection, MockScenario, MockScenarioEvent, buildMockScenario\n * @see ../commands/mock.ts\n * @see ../../test-utils/index.ts\n */\n\nexport const MOCK_TOOL_SELECTIONS = [\n 'claude-code',\n 'opencode',\n 'all',\n] as const;\n\nexport type MockToolSelection = (typeof MOCK_TOOL_SELECTIONS)[number];\n\nexport interface MockScenarioEvent {\n readonly atMs: number;\n readonly event: AISnitchEvent;\n}\n\nexport interface MockScenario {\n readonly label: string;\n readonly selection: MockToolSelection;\n readonly timeline: readonly MockScenarioEvent[];\n}\n\nconst DEMO_PROJECT_ROOT = '/Users/demo/Projects/AutoSnitch';\n\n/**\n * 📖 Mock scenarios are intentionally opinionated and slightly theatrical. They\n * are for demos, CI, and TUI development, so the output should feel plausible\n * and informative rather than perfectly mirroring one exact provider transcript.\n */\nexport function buildMockScenario(selection: MockToolSelection): MockScenario {\n if (selection === 'claude-code') {\n return {\n label: 'Claude Code',\n selection,\n timeline: buildClaudeCodeTimeline(0),\n };\n }\n\n if (selection === 'opencode') {\n return {\n label: 'OpenCode',\n selection,\n timeline: buildOpenCodeTimeline(0),\n };\n }\n\n return {\n label: 'All Tools',\n selection: 'all',\n timeline: [\n ...buildClaudeCodeTimeline(0),\n ...buildOpenCodeTimeline(900),\n ...buildGeminiTimeline(1_700),\n ].sort((left, right) => left.atMs - right.atMs),\n };\n}\n\nfunction buildClaudeCodeTimeline(offsetMs: number): MockScenarioEvent[] {\n const sessionId = 'mock:claude-code:auto-snitch';\n let sequenceNumber = 0;\n const nextSequenceNumber = () => {\n sequenceNumber += 1;\n return sequenceNumber;\n };\n\n return [\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 0,\n 'session.start',\n {\n model: 'claude-sonnet-4-20250514',\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 500,\n 'task.start',\n {\n raw: {\n prompt: 'Trace why the config loader fails in CI.',\n },\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 2_500,\n 'agent.thinking',\n {\n raw: {\n thinking: 'Inspecting the config loader and the failing test fixture.',\n },\n tokensUsed: 960,\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 3_500,\n 'agent.tool_call',\n {\n toolInput: {\n filePath: 'src/core/config/loader.ts',\n },\n toolName: 'Read',\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 4_500,\n 'agent.thinking',\n {\n raw: {\n thinking: 'The path resolution fallback is using the wrong base directory.',\n },\n tokensUsed: 1_580,\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 7_500,\n 'agent.coding',\n {\n activeFile: 'src/core/config/loader.ts',\n toolInput: {\n filePath: 'src/core/config/loader.ts',\n },\n toolName: 'Edit',\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 9_500,\n 'agent.tool_call',\n {\n toolInput: {\n filePath: 'src/core/config/loader.ts',\n },\n toolName: 'Write',\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 10_250,\n 'task.complete',\n {\n tokensUsed: 3_420,\n },\n ),\n createMockTimelineEvent(\n 'claude-code',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 14_500,\n 'agent.idle',\n {},\n ),\n ];\n}\n\nfunction buildOpenCodeTimeline(offsetMs: number): MockScenarioEvent[] {\n const sessionId = 'mock:opencode:auto-snitch';\n let sequenceNumber = 0;\n const nextSequenceNumber = () => {\n sequenceNumber += 1;\n return sequenceNumber;\n };\n\n return [\n createMockTimelineEvent(\n 'opencode',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 0,\n 'session.start',\n {\n model: 'openai/gpt-4.1',\n },\n ),\n createMockTimelineEvent(\n 'opencode',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 600,\n 'task.start',\n {\n raw: {\n prompt: 'Summarize the websocket reconnect path.',\n },\n },\n ),\n createMockTimelineEvent(\n 'opencode',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 1_600,\n 'agent.thinking',\n {\n raw: {\n thinking: 'Checking the reconnect loop and exponential backoff.',\n },\n tokensUsed: 760,\n },\n ),\n createMockTimelineEvent(\n 'opencode',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 3_600,\n 'agent.coding',\n {\n activeFile: 'src/core/engine/ws-server.ts',\n toolInput: {\n filePath: 'src/core/engine/ws-server.ts',\n },\n toolName: 'Edit',\n },\n ),\n createMockTimelineEvent(\n 'opencode',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 5_800,\n 'agent.tool_call',\n {\n toolInput: {\n command: 'pnpm test -- src/core/engine/__tests__/ws-server.test.ts',\n },\n toolName: 'Bash',\n },\n ),\n createMockTimelineEvent(\n 'opencode',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 6_400,\n 'task.complete',\n {\n tokensUsed: 2_180,\n },\n ),\n createMockTimelineEvent(\n 'opencode',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 10_000,\n 'agent.idle',\n {},\n ),\n ];\n}\n\nfunction buildGeminiTimeline(offsetMs: number): MockScenarioEvent[] {\n const sessionId = 'mock:gemini-cli:auto-snitch';\n let sequenceNumber = 0;\n const nextSequenceNumber = () => {\n sequenceNumber += 1;\n return sequenceNumber;\n };\n\n return [\n createMockTimelineEvent(\n 'gemini-cli',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 0,\n 'session.start',\n {\n model: 'gemini-2.5-pro',\n },\n ),\n createMockTimelineEvent(\n 'gemini-cli',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 450,\n 'task.start',\n {\n raw: {\n prompt: 'Check whether our package tarball includes dist/ only.',\n },\n },\n ),\n createMockTimelineEvent(\n 'gemini-cli',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 1_300,\n 'agent.tool_call',\n {\n toolInput: {\n filePath: 'package.json',\n },\n toolName: 'Read',\n },\n ),\n createMockTimelineEvent(\n 'gemini-cli',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 2_200,\n 'agent.thinking',\n {\n raw: {\n thinking: 'Tarball config looks mostly right; verifying scripts and engines.',\n },\n tokensUsed: 1_120,\n },\n ),\n createMockTimelineEvent(\n 'gemini-cli',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 4_100,\n 'task.complete',\n {\n tokensUsed: 1_880,\n },\n ),\n createMockTimelineEvent(\n 'gemini-cli',\n sessionId,\n nextSequenceNumber(),\n offsetMs + 6_500,\n 'agent.idle',\n {},\n ),\n ];\n}\n\nfunction createMockTimelineEvent(\n tool: ToolName,\n sessionId: string,\n sequenceNumber: number,\n atMs: number,\n type: AISnitchEventType,\n data: Partial<AISnitchEvent['data']>,\n): MockScenarioEvent {\n return {\n atMs,\n event: createEvent({\n source: `aisnitch://mock/${tool}`,\n type,\n 'aisnitch.tool': tool,\n 'aisnitch.sessionid': sessionId,\n 'aisnitch.seqnum': sequenceNumber,\n data: {\n cwd: DEMO_PROJECT_ROOT,\n project: 'AutoSnitch',\n projectPath: DEMO_PROJECT_ROOT,\n raw: {\n mock: true,\n scenario: tool,\n type,\n },\n ...data,\n },\n }),\n };\n}\n","import type { AISnitchEvent } from '../../core/events/types.js';\nimport {\n MOCK_TOOL_SELECTIONS,\n buildMockScenario,\n type MockToolSelection,\n} from '../mock/scenarios.js';\n\nexport type { MockToolSelection } from '../mock/scenarios.js';\n\n/**\n * @file src/cli/commands/mock.ts\n * @description Mock scenario parsing and execution helpers used by `aisnitch mock` and `aisnitch start --mock`.\n * @functions\n * → parseMockToolSelection\n * → parseMockDurationOption\n * → parseMockSpeedOption\n * → runMockScenario\n * @exports MockCommandOptions, MockRunnerResult, MockRunnerDependencies, MockRunnerOptions, parseMockToolSelection, parseMockDurationOption, parseMockSpeedOption, runMockScenario\n * @see ../mock/scenarios.ts\n * @see ../runtime.ts\n */\n\nexport interface MockCommandOptions {\n readonly duration?: number;\n readonly loop?: boolean;\n readonly speed?: number;\n}\n\nexport interface MockRunnerOptions {\n readonly durationSeconds: number;\n readonly loop: boolean;\n readonly publishEvent: (event: AISnitchEvent) => Promise<boolean>;\n readonly selection: MockToolSelection;\n readonly speed: number;\n}\n\nexport interface MockRunnerDependencies {\n readonly now?: () => number;\n readonly sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface MockRunnerResult {\n readonly loopCount: number;\n readonly publishedEvents: number;\n}\n\n/**\n * Parses one supported mock tool/scenario selection from CLI input.\n */\nexport function parseMockToolSelection(rawValue: string): MockToolSelection {\n if ((MOCK_TOOL_SELECTIONS as readonly string[]).includes(rawValue)) {\n return rawValue as MockToolSelection;\n }\n\n throw new Error(\n `Unsupported mock tool: ${rawValue}. Supported tools: ${MOCK_TOOL_SELECTIONS.join(', ')}`,\n );\n}\n\n/**\n * Parses one positive mock speed factor from the CLI.\n */\nexport function parseMockSpeedOption(rawValue: string): number {\n const parsedValue = Number.parseFloat(rawValue);\n\n if (!Number.isFinite(parsedValue) || parsedValue <= 0) {\n throw new Error('Mock speed must be a positive number.');\n }\n\n return parsedValue;\n}\n\n/**\n * Parses one positive mock duration in seconds from the CLI.\n */\nexport function parseMockDurationOption(rawValue: string): number {\n const parsedValue = Number.parseInt(rawValue, 10);\n\n if (!Number.isInteger(parsedValue) || parsedValue <= 0) {\n throw new Error('Mock duration must be a positive integer of seconds.');\n }\n\n return parsedValue;\n}\n\n/**\n * 📖 The runner replays one deterministic event timeline at configurable speed.\n * It deliberately uses the same publish callback shape as the real pipeline so\n * demos, tests, and `start --mock` all exercise the normal event path.\n */\nexport async function runMockScenario(\n options: MockRunnerOptions,\n dependencies: MockRunnerDependencies = {},\n): Promise<MockRunnerResult> {\n const now = dependencies.now ?? Date.now;\n const sleep =\n dependencies.sleep ??\n (async (ms: number) => {\n await new Promise<void>((resolve) => {\n setTimeout(resolve, ms).unref();\n });\n });\n const deadline = now() + options.durationSeconds * 1_000;\n let loopCount = 0;\n let publishedEvents = 0;\n\n do {\n const scenario = buildMockScenario(options.selection);\n let previousAtMs = 0;\n\n loopCount += 1;\n\n for (const timelineEvent of scenario.timeline) {\n const waitMs = Math.max(\n 0,\n (timelineEvent.atMs - previousAtMs) / options.speed,\n );\n previousAtMs = timelineEvent.atMs;\n\n if (waitMs > 0) {\n if (now() + waitMs > deadline) {\n return {\n loopCount,\n publishedEvents,\n };\n }\n\n await sleep(waitMs);\n }\n\n if (now() > deadline) {\n return {\n loopCount,\n publishedEvents,\n };\n }\n\n await options.publishEvent(timelineEvent.event);\n publishedEvents += 1;\n }\n } while (options.loop && now() < deadline);\n\n return {\n loopCount,\n publishedEvents,\n };\n}\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { access, copyFile, mkdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { createInterface } from 'node:readline/promises';\nimport { promisify } from 'node:util';\n\nimport JSON5 from 'json5';\n\nimport {\n loadConfig,\n saveConfig,\n type AdapterConfig,\n type AISnitchConfig,\n type ConfigPathOptions,\n} from '../../core/config/index.js';\n\n/**\n * @file src/cli/commands/setup.ts\n * @description Interactive setup command for configuring external tool hooks and plugins to forward activity into AISnitch.\n * @functions\n * → parseSetupToolName\n * → createToolSetup\n * → runSetupCommand\n * @exports SetupToolName, SetupCliOptions, SetupOutput, ToolSetup, ClaudeCodeSetup, GeminiCLISetup, AiderSetup, GooseSetup, CodexSetup, CopilotCLISetup, OpenClawSetup, OpenCodeSetup, parseSetupToolName, createToolSetup, runSetupCommand\n * @see ../program.ts\n * @see ../runtime.ts\n*/\n\nconst execFile = promisify(execFileCallback);\n\nconst SETUP_TOOL_NAMES = [\n 'claude-code',\n 'opencode',\n 'gemini-cli',\n 'aider',\n 'codex',\n 'goose',\n 'copilot-cli',\n 'openclaw',\n] as const;\nconst ANSI_RESET = '\\u001B[0m';\nconst ANSI_RED = '\\u001B[31m';\nconst ANSI_GREEN = '\\u001B[32m';\nconst ANSI_CYAN = '\\u001B[36m';\nconst CLAUDE_FILE_CHANGED_MATCHER = '.*';\n\nconst CLAUDE_CODE_HOOK_EVENTS = [\n 'SessionStart',\n 'UserPromptSubmit',\n 'PreToolUse',\n 'PermissionRequest',\n 'PostToolUse',\n 'PostToolUseFailure',\n 'Notification',\n 'SubagentStart',\n 'SubagentStop',\n 'TaskCreated',\n 'TaskCompleted',\n 'Stop',\n 'StopFailure',\n 'TeammateIdle',\n 'InstructionsLoaded',\n 'ConfigChange',\n 'CwdChanged',\n 'FileChanged',\n 'WorktreeCreate',\n 'WorktreeRemove',\n 'PreCompact',\n 'PostCompact',\n 'Elicitation',\n 'ElicitationResult',\n 'SessionEnd',\n] as const;\n\nconst GEMINI_HOOK_EVENTS = [\n 'SessionStart',\n 'SessionEnd',\n 'BeforeAgent',\n 'AfterAgent',\n 'BeforeTool',\n 'AfterTool',\n 'Notification',\n 'PreCompress',\n] as const;\n\nconst COPILOT_HOOK_EVENTS = [\n 'sessionStart',\n 'sessionEnd',\n 'userPromptSubmitted',\n 'preToolUse',\n 'postToolUse',\n 'errorOccurred',\n] as const;\n\ntype ClaudeHookEventName = (typeof CLAUDE_CODE_HOOK_EVENTS)[number];\n\ninterface ClaudeHookHandler extends Record<string, unknown> {\n readonly async?: boolean;\n readonly type: string;\n readonly url?: string;\n}\n\ninterface ClaudeHookMatcherGroup extends Record<string, unknown> {\n readonly hooks: ClaudeHookHandler[];\n readonly matcher?: string;\n}\n\ninterface ClaudeSettings extends Record<string, unknown> {\n readonly hooks?: Record<string, ClaudeHookMatcherGroup[]>;\n}\n\ninterface GeminiHookHandler extends Record<string, unknown> {\n readonly command?: string;\n readonly description?: string;\n readonly name?: string;\n readonly timeout?: number;\n readonly type: string;\n}\n\ninterface GeminiHookMatcherGroup extends Record<string, unknown> {\n readonly hooks: GeminiHookHandler[];\n readonly matcher?: string;\n readonly sequential?: boolean;\n}\n\ninterface GeminiSettings extends Record<string, unknown> {\n readonly hooks?: Record<string, GeminiHookMatcherGroup[]>;\n}\n\ninterface CopilotHookHandler extends Record<string, unknown> {\n readonly bash?: string;\n readonly cwd?: string;\n readonly powershell?: string;\n readonly timeoutSec?: number;\n readonly type: string;\n}\n\ninterface CopilotHooksFile extends Record<string, unknown> {\n readonly hooks?: Record<string, CopilotHookHandler[]>;\n readonly version: number;\n}\n\ninterface OpenClawHookEntryConfig extends Record<string, unknown> {\n readonly enabled?: boolean;\n}\n\ninterface OpenClawInternalHooksConfig extends Record<string, unknown> {\n readonly enabled?: boolean;\n readonly entries?: Record<string, OpenClawHookEntryConfig>;\n}\n\ninterface OpenClawHooksConfig extends Record<string, unknown> {\n readonly internal?: OpenClawInternalHooksConfig;\n}\n\ninterface OpenClawSettings extends Record<string, unknown> {\n readonly hooks?: OpenClawHooksConfig;\n}\n\ninterface ToolSetupDependencies {\n readonly aiderConfigPath?: string;\n readonly binaryExists?: (binaryName: string) => Promise<boolean>;\n readonly confirm?: (diff: string, prompt: string) => Promise<boolean>;\n readonly homeDirectory?: string;\n readonly claudeSettingsPath?: string;\n readonly geminiSettingsPath?: string;\n readonly opencodeConfigDirectory?: string;\n readonly codexHomeDirectory?: string;\n readonly gooseHomeDirectory?: string;\n readonly openclawHomeDirectory?: string;\n readonly workspaceDirectory?: string;\n readonly output?: SetupOutput;\n}\n\ninterface FileMutationSnapshot {\n readonly changed: boolean;\n readonly currentContent: string | null;\n readonly nextContent: string;\n}\n\n/**\n * Setup-capable tool names for the CLI.\n */\nexport type SetupToolName = (typeof SETUP_TOOL_NAMES)[number];\n\n/**\n * Shared options accepted by `aisnitch setup`.\n */\nexport interface SetupCliOptions {\n readonly config?: string;\n readonly revert?: boolean;\n}\n\n/**\n * Minimal output contract for interactive setup commands.\n */\nexport interface SetupOutput {\n readonly stderr: (text: string) => void;\n readonly stdout: (text: string) => void;\n}\n\n/**\n * Generic setup contract implemented by each supported tool.\n */\nexport interface ToolSetup {\n readonly toolName: SetupToolName;\n detect(): Promise<boolean>;\n getConfigPath(): string;\n computeDiff(): Promise<string>;\n apply(): Promise<void>;\n revert(): Promise<void>;\n}\n\n/**\n * Parses and validates the setup tool argument.\n */\nexport function parseSetupToolName(rawValue: string): SetupToolName {\n if ((SETUP_TOOL_NAMES as readonly string[]).includes(rawValue)) {\n return rawValue as SetupToolName;\n }\n\n throw new Error(\n `Unsupported setup tool: ${rawValue}. Supported tools: ${SETUP_TOOL_NAMES.join(', ')}`,\n );\n}\n\n/**\n * 📖 Setup needs deterministic file writes and reversible backups because it\n * edits user-owned tool configuration rather than internal project state.\n */\nabstract class FileToolSetupBase implements ToolSetup {\n protected readonly binaryExists: (binaryName: string) => Promise<boolean>;\n\n protected constructor(\n public readonly toolName: SetupToolName,\n binaryExists?: (binaryName: string) => Promise<boolean>,\n ) {\n this.binaryExists = binaryExists ?? isBinaryAvailable;\n }\n\n public abstract detect(): Promise<boolean>;\n\n public abstract getConfigPath(): string;\n\n public async computeDiff(): Promise<string> {\n const snapshot = await this.buildSnapshot();\n\n if (!snapshot.changed) {\n return `${ANSI_CYAN}No changes required for ${this.toolName}.${ANSI_RESET}\\n`;\n }\n\n return renderColoredDiff(\n this.getConfigPath(),\n snapshot.currentContent,\n snapshot.nextContent,\n );\n }\n\n public async apply(): Promise<void> {\n const snapshot = await this.buildSnapshot();\n\n if (!snapshot.changed) {\n return;\n }\n\n const configPath = this.getConfigPath();\n\n await mkdir(dirname(configPath), { recursive: true });\n\n if (snapshot.currentContent !== null) {\n await copyFile(configPath, this.getBackupPath());\n }\n\n await writeFile(configPath, snapshot.nextContent, 'utf8');\n }\n\n public async revert(): Promise<void> {\n const configPath = this.getConfigPath();\n const backupPath = this.getBackupPath();\n\n if (await fileExists(backupPath)) {\n await copyFile(backupPath, configPath);\n await rm(backupPath, { force: true });\n return;\n }\n\n await rm(configPath, { force: true });\n }\n\n protected abstract buildNextContent(\n currentContent: string | null,\n ): Promise<string>;\n\n protected getBackupPath(): string {\n return `${this.getConfigPath()}.bak`;\n }\n\n private async buildSnapshot(): Promise<FileMutationSnapshot> {\n const currentContent = await this.readCurrentContent();\n const nextContent = await this.buildNextContent(currentContent);\n\n return {\n changed: currentContent !== nextContent,\n currentContent,\n nextContent,\n };\n }\n\n private async readCurrentContent(): Promise<string | null> {\n try {\n return await readFile(this.getConfigPath(), 'utf8');\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}\n\n/**\n * Claude Code setup mutates `~/.claude/settings.json` and merges one AISnitch\n * HTTP hook group per event without overwriting unrelated user hooks.\n */\nexport class ClaudeCodeSetup extends FileToolSetupBase {\n private readonly settingsPath: string;\n\n private readonly hookUrl: string;\n\n public constructor(\n httpPort: number,\n dependencies: ToolSetupDependencies = {},\n ) {\n super('claude-code', dependencies.binaryExists);\n this.settingsPath =\n dependencies.claudeSettingsPath ??\n join(dependencies.homeDirectory ?? homedir(), '.claude', 'settings.json');\n this.hookUrl = `http://localhost:${httpPort}/hooks/claude-code`;\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('claude')) ||\n (await fileExists(this.settingsPath))\n );\n }\n\n public getConfigPath(): string {\n return this.settingsPath;\n }\n\n protected buildNextContent(\n currentContent: string | null,\n ): Promise<string> {\n const parsedSettings = parseClaudeSettings(currentContent);\n const currentHooks = parsedSettings.hooks ?? {};\n const nextHooks: Record<string, ClaudeHookMatcherGroup[]> = {\n ...currentHooks,\n };\n\n for (const hookEventName of CLAUDE_CODE_HOOK_EVENTS) {\n nextHooks[hookEventName] = ensureClaudeAISnitchHook(\n currentHooks[hookEventName] ?? [],\n hookEventName,\n this.hookUrl,\n );\n }\n\n const nextSettings: ClaudeSettings = {\n ...parsedSettings,\n hooks: nextHooks,\n };\n\n return Promise.resolve(`${JSON.stringify(nextSettings, null, 2)}\\n`);\n }\n}\n\n/**\n * OpenCode setup uses the officially supported local plugin directory and\n * drops a dependency-free plugin that forwards a curated event subset to AISnitch.\n */\nexport class OpenCodeSetup extends FileToolSetupBase {\n private readonly pluginPath: string;\n\n private readonly configDirectory: string;\n\n private readonly hookUrl: string;\n\n public constructor(\n httpPort: number,\n dependencies: ToolSetupDependencies = {},\n ) {\n super('opencode', dependencies.binaryExists);\n this.configDirectory =\n dependencies.opencodeConfigDirectory ??\n join(dependencies.homeDirectory ?? homedir(), '.config', 'opencode');\n this.pluginPath = join(this.configDirectory, 'plugins', 'aisnitch.ts');\n this.hookUrl = `http://localhost:${httpPort}/hooks/opencode`;\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('opencode')) ||\n (await fileExists(this.configDirectory))\n );\n }\n\n public getConfigPath(): string {\n return this.pluginPath;\n }\n\n protected buildNextContent(): Promise<string> {\n return Promise.resolve(buildOpenCodePluginSource(this.hookUrl));\n }\n}\n\n/**\n * Gemini CLI setup mutates `~/.gemini/settings.json` and merges wildcard\n * command hooks that forward the raw stdin JSON into AISnitch over HTTP.\n */\nexport class GeminiCLISetup extends FileToolSetupBase {\n private readonly settingsPath: string;\n\n private readonly hookUrl: string;\n\n public constructor(\n httpPort: number,\n dependencies: ToolSetupDependencies = {},\n ) {\n super('gemini-cli', dependencies.binaryExists);\n this.settingsPath =\n dependencies.geminiSettingsPath ??\n join(dependencies.homeDirectory ?? homedir(), '.gemini', 'settings.json');\n this.hookUrl = `http://localhost:${httpPort}/hooks/gemini-cli`;\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('gemini')) ||\n (await fileExists(this.settingsPath))\n );\n }\n\n public getConfigPath(): string {\n return this.settingsPath;\n }\n\n protected buildNextContent(\n currentContent: string | null,\n ): Promise<string> {\n const parsedSettings = parseGeminiSettings(currentContent);\n const currentHooks = parsedSettings.hooks ?? {};\n const nextHooks: Record<string, GeminiHookMatcherGroup[]> = {\n ...currentHooks,\n };\n\n for (const hookEventName of GEMINI_HOOK_EVENTS) {\n nextHooks[hookEventName] = ensureGeminiAISnitchHook(\n currentHooks[hookEventName] ?? [],\n this.hookUrl,\n );\n }\n\n const nextSettings: GeminiSettings = {\n ...parsedSettings,\n hooks: nextHooks,\n };\n\n return Promise.resolve(`${JSON.stringify(nextSettings, null, 2)}\\n`);\n }\n}\n\n/**\n * Aider setup is intentionally conservative: AISnitch only toggles top-level\n * notification keys inside the user config and leaves the rest of the YAML alone.\n */\nexport class AiderSetup extends FileToolSetupBase {\n private readonly configPath: string;\n\n private readonly notificationCommand: string;\n\n public constructor(\n dependencies: ToolSetupDependencies = {},\n options: SetupCliOptions = {},\n ) {\n super('aider', dependencies.binaryExists);\n this.configPath =\n dependencies.aiderConfigPath ??\n join(dependencies.homeDirectory ?? homedir(), '.aider.conf.yml');\n this.notificationCommand = buildAiderNotificationCommand(options);\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('aider')) ||\n (await fileExists(this.configPath))\n );\n }\n\n public getConfigPath(): string {\n return this.configPath;\n }\n\n protected buildNextContent(\n currentContent: string | null,\n ): Promise<string> {\n let nextContent =\n currentContent ??\n '# AISnitch helper settings for aider notifications.\\n';\n\n nextContent = upsertYamlScalar(nextContent, ['notifications'], {\n key: 'notifications',\n value: 'true',\n });\n nextContent = upsertYamlScalar(\n nextContent,\n ['notifications-command', 'notifications_command'],\n {\n key: 'notifications-command',\n value: JSON.stringify(this.notificationCommand),\n },\n );\n\n return Promise.resolve(`${nextContent.trimEnd()}\\n`);\n }\n}\n\n/**\n * Goose is passive for the MVP: AISnitch watches goosed + SQLite sources and\n * this setup flow simply arms the adapter in config with clear operator hints.\n */\nexport class GooseSetup implements ToolSetup {\n private readonly gooseHomeDirectory: string;\n\n public readonly toolName = 'goose' as const;\n\n private readonly binaryExists: (binaryName: string) => Promise<boolean>;\n\n public constructor(dependencies: ToolSetupDependencies = {}) {\n this.binaryExists = dependencies.binaryExists ?? isBinaryAvailable;\n this.gooseHomeDirectory =\n dependencies.gooseHomeDirectory ??\n join(dependencies.homeDirectory ?? homedir(), '.config', 'goose');\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('goose')) ||\n (await fileExists(this.gooseHomeDirectory))\n );\n }\n\n public getConfigPath(): string {\n return join(this.gooseHomeDirectory, 'sessions.db');\n }\n\n public computeDiff(): Promise<string> {\n return Promise.resolve(\n [\n `${ANSI_CYAN}--- ${this.getConfigPath()} (passive source)${ANSI_RESET}`,\n `${ANSI_GREEN}+ Enable passive Goose discovery in AISnitch.${ANSI_RESET}`,\n `${ANSI_GREEN}+ AISnitch will try goosed at http://127.0.0.1:8080 and fall back to SQLite session watching.${ANSI_RESET}`,\n ].join('\\n'),\n );\n }\n\n public apply(): Promise<void> {\n return Promise.resolve();\n }\n\n public revert(): Promise<void> {\n return Promise.resolve();\n }\n}\n\n/**\n * Codex uses passive log watching for the MVP, so setup only arms the adapter\n * and documents the watched source path rather than editing Codex files.\n */\nexport class CodexSetup implements ToolSetup {\n private readonly codexHomeDirectory: string;\n\n public readonly toolName = 'codex' as const;\n\n private readonly binaryExists: (binaryName: string) => Promise<boolean>;\n\n public constructor(dependencies: ToolSetupDependencies = {}) {\n this.binaryExists = dependencies.binaryExists ?? isBinaryAvailable;\n this.codexHomeDirectory =\n dependencies.codexHomeDirectory ??\n join(dependencies.homeDirectory ?? homedir(), '.codex');\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('codex')) ||\n (await fileExists(this.getConfigPath()))\n );\n }\n\n public getConfigPath(): string {\n return join(this.codexHomeDirectory, 'log', 'codex-tui.log');\n }\n\n public computeDiff(): Promise<string> {\n return Promise.resolve(\n [\n `${ANSI_CYAN}--- ${this.getConfigPath()} (passive source)${ANSI_RESET}`,\n `${ANSI_GREEN}+ Enable passive Codex log watching in AISnitch.${ANSI_RESET}`,\n `${ANSI_GREEN}+ No external Codex config changes are required for this adapter.${ANSI_RESET}`,\n ].join('\\n'),\n );\n }\n\n public apply(): Promise<void> {\n return Promise.resolve();\n }\n\n public revert(): Promise<void> {\n return Promise.resolve();\n }\n}\n\n/**\n * Copilot CLI uses repository-scoped hook configs. AISnitch installs one hook\n * file plus a tiny Node bridge script so Bash and PowerShell can share logic.\n */\nexport class CopilotCLISetup implements ToolSetup {\n private readonly binaryExists: (binaryName: string) => Promise<boolean>;\n\n private readonly configPath: string;\n\n private readonly hookUrl: string;\n\n private readonly scriptPath: string;\n\n public readonly toolName = 'copilot-cli' as const;\n\n private readonly workspaceDirectory: string;\n\n public constructor(\n httpPort: number,\n dependencies: ToolSetupDependencies = {},\n ) {\n this.binaryExists = dependencies.binaryExists ?? isBinaryAvailable;\n this.workspaceDirectory = dependencies.workspaceDirectory ?? process.cwd();\n this.configPath = join(\n this.workspaceDirectory,\n '.github',\n 'hooks',\n 'aisnitch.json',\n );\n this.scriptPath = join(\n this.workspaceDirectory,\n '.github',\n 'hooks',\n 'scripts',\n 'aisnitch-forward.mjs',\n );\n this.hookUrl = `http://localhost:${httpPort}/hooks/copilot-cli`;\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('copilot')) ||\n (await fileExists(join(this.workspaceDirectory, '.git'))) ||\n (await fileExists(this.workspaceDirectory))\n );\n }\n\n public getConfigPath(): string {\n return this.configPath;\n }\n\n public async computeDiff(): Promise<string> {\n const currentConfigContent = await readOptionalFile(this.configPath);\n const currentScriptContent = await readOptionalFile(this.scriptPath);\n const nextConfigContent = this.buildNextConfigContent(currentConfigContent);\n const nextScriptContent = buildCopilotForwardScriptSource();\n\n return [\n renderColoredDiff(\n this.configPath,\n currentConfigContent,\n nextConfigContent,\n ),\n '',\n renderColoredDiff(\n this.scriptPath,\n currentScriptContent,\n nextScriptContent,\n ),\n ].join('\\n');\n }\n\n public async apply(): Promise<void> {\n const currentConfigContent = await readOptionalFile(this.configPath);\n const currentScriptContent = await readOptionalFile(this.scriptPath);\n const nextConfigContent = this.buildNextConfigContent(currentConfigContent);\n const nextScriptContent = buildCopilotForwardScriptSource();\n\n await mkdir(dirname(this.configPath), { recursive: true });\n await mkdir(dirname(this.scriptPath), { recursive: true });\n\n if (currentConfigContent !== null) {\n await copyFile(this.configPath, this.getBackupPath(this.configPath));\n }\n\n if (currentScriptContent !== null) {\n await copyFile(this.scriptPath, this.getBackupPath(this.scriptPath));\n }\n\n await writeFile(this.configPath, nextConfigContent, 'utf8');\n await writeFile(this.scriptPath, nextScriptContent, 'utf8');\n }\n\n public async revert(): Promise<void> {\n await restoreBackupOrRemove(this.configPath);\n await restoreBackupOrRemove(this.scriptPath);\n }\n\n private buildNextConfigContent(currentContent: string | null): string {\n const parsedConfig = parseCopilotHooksFile(currentContent);\n const currentHooks = parsedConfig.hooks ?? {};\n const nextHooks: Record<string, CopilotHookHandler[]> = {\n ...currentHooks,\n };\n\n for (const hookEventName of COPILOT_HOOK_EVENTS) {\n nextHooks[hookEventName] = ensureCopilotAISnitchHook(\n currentHooks[hookEventName] ?? [],\n hookEventName,\n this.hookUrl,\n );\n }\n\n const nextConfig: CopilotHooksFile = {\n ...parsedConfig,\n hooks: nextHooks,\n version: 1,\n };\n\n return `${JSON.stringify(nextConfig, null, 2)}\\n`;\n }\n\n private getBackupPath(path: string): string {\n return `${path}.bak`;\n }\n}\n\n/**\n * OpenClaw currently documents managed hooks plus bundled hook toggles, not a\n * native outbound AISnitch webhook block. AISnitch therefore installs one\n * managed hook directory and enables the relevant internal hooks in JSON5 config.\n */\nexport class OpenClawSetup implements ToolSetup {\n private readonly binaryExists: (binaryName: string) => Promise<boolean>;\n\n private readonly configPath: string;\n\n private readonly hookDirectory: string;\n\n private readonly hookDocumentPath: string;\n\n private readonly hookHandlerPath: string;\n\n private readonly hookUrl: string;\n\n private readonly openclawHomeDirectory: string;\n\n public readonly toolName = 'openclaw' as const;\n\n public constructor(\n httpPort: number,\n dependencies: ToolSetupDependencies = {},\n ) {\n this.binaryExists = dependencies.binaryExists ?? isBinaryAvailable;\n this.openclawHomeDirectory =\n dependencies.openclawHomeDirectory ??\n join(dependencies.homeDirectory ?? homedir(), '.openclaw');\n this.configPath = join(this.openclawHomeDirectory, 'openclaw.json');\n this.hookDirectory = join(\n this.openclawHomeDirectory,\n 'hooks',\n 'aisnitch-forward',\n );\n this.hookDocumentPath = join(this.hookDirectory, 'HOOK.md');\n this.hookHandlerPath = join(this.hookDirectory, 'handler.ts');\n this.hookUrl = `http://localhost:${httpPort}/hooks/openclaw`;\n }\n\n public async detect(): Promise<boolean> {\n return (\n (await this.binaryExists('openclaw')) ||\n (await fileExists(this.openclawHomeDirectory)) ||\n (await fileExists('/Applications/OpenClaw.app'))\n );\n }\n\n public getConfigPath(): string {\n return this.configPath;\n }\n\n public async computeDiff(): Promise<string> {\n const currentConfigContent = await readOptionalFile(this.configPath);\n const currentHookDocument = await readOptionalFile(this.hookDocumentPath);\n const currentHookHandler = await readOptionalFile(this.hookHandlerPath);\n const nextConfigContent = this.buildNextConfigContent(currentConfigContent);\n const nextHookDocument = buildOpenClawHookDocumentSource();\n const nextHookHandler = buildOpenClawHookHandlerSource(this.hookUrl);\n\n return [\n renderColoredDiff(\n this.configPath,\n currentConfigContent,\n nextConfigContent,\n ),\n '',\n renderColoredDiff(\n this.hookDocumentPath,\n currentHookDocument,\n nextHookDocument,\n ),\n '',\n renderColoredDiff(\n this.hookHandlerPath,\n currentHookHandler,\n nextHookHandler,\n ),\n ].join('\\n');\n }\n\n public async apply(): Promise<void> {\n const currentConfigContent = await readOptionalFile(this.configPath);\n const currentHookDocument = await readOptionalFile(this.hookDocumentPath);\n const currentHookHandler = await readOptionalFile(this.hookHandlerPath);\n const nextConfigContent = this.buildNextConfigContent(currentConfigContent);\n const nextHookDocument = buildOpenClawHookDocumentSource();\n const nextHookHandler = buildOpenClawHookHandlerSource(this.hookUrl);\n\n await mkdir(dirname(this.configPath), { recursive: true });\n await mkdir(this.hookDirectory, { recursive: true });\n\n if (currentConfigContent !== null) {\n await copyFile(this.configPath, this.getBackupPath(this.configPath));\n }\n\n if (currentHookDocument !== null) {\n await copyFile(\n this.hookDocumentPath,\n this.getBackupPath(this.hookDocumentPath),\n );\n }\n\n if (currentHookHandler !== null) {\n await copyFile(\n this.hookHandlerPath,\n this.getBackupPath(this.hookHandlerPath),\n );\n }\n\n await writeFile(this.configPath, nextConfigContent, 'utf8');\n await writeFile(this.hookDocumentPath, nextHookDocument, 'utf8');\n await writeFile(this.hookHandlerPath, nextHookHandler, 'utf8');\n }\n\n public async revert(): Promise<void> {\n await restoreBackupOrRemove(this.configPath);\n await restoreBackupOrRemove(this.hookDocumentPath);\n await restoreBackupOrRemove(this.hookHandlerPath);\n }\n\n private buildNextConfigContent(currentContent: string | null): string {\n const parsedConfig = parseOpenClawSettings(currentContent);\n const currentHooks = parsedConfig.hooks ?? {};\n const currentInternalHooks = currentHooks.internal ?? {};\n const currentEntries = currentInternalHooks.entries ?? {};\n const nextEntries: Record<string, OpenClawHookEntryConfig> = {\n ...currentEntries,\n 'aisnitch-forward': {\n ...(currentEntries['aisnitch-forward'] ?? {}),\n enabled: true,\n },\n 'command-logger': {\n ...(currentEntries['command-logger'] ?? {}),\n enabled: true,\n },\n 'session-memory': {\n ...(currentEntries['session-memory'] ?? {}),\n enabled: true,\n },\n };\n const nextConfig: OpenClawSettings = {\n ...parsedConfig,\n hooks: {\n ...currentHooks,\n internal: {\n ...currentInternalHooks,\n enabled: true,\n entries: nextEntries,\n },\n },\n };\n\n return `${JSON.stringify(nextConfig, null, 2)}\\n`;\n }\n\n private getBackupPath(path: string): string {\n return `${path}.bak`;\n }\n}\n\n/**\n * Creates one concrete setup implementation for the selected tool.\n */\nexport async function createToolSetup(\n toolName: SetupToolName,\n options: SetupCliOptions = {},\n dependencies: ToolSetupDependencies = {},\n): Promise<ToolSetup> {\n const config = await loadConfig(toConfigPathOptions(options));\n const httpPort = config.httpPort;\n\n if (toolName === 'claude-code') {\n return new ClaudeCodeSetup(httpPort, dependencies);\n }\n\n if (toolName === 'gemini-cli') {\n return new GeminiCLISetup(httpPort, dependencies);\n }\n\n if (toolName === 'aider') {\n return new AiderSetup(dependencies, options);\n }\n\n if (toolName === 'goose') {\n return new GooseSetup(dependencies);\n }\n\n if (toolName === 'codex') {\n return new CodexSetup(dependencies);\n }\n\n if (toolName === 'copilot-cli') {\n return new CopilotCLISetup(httpPort, dependencies);\n }\n\n if (toolName === 'openclaw') {\n return new OpenClawSetup(httpPort, dependencies);\n }\n\n if (toolName === 'opencode') {\n return new OpenCodeSetup(httpPort, dependencies);\n }\n\n return new ClaudeCodeSetup(httpPort, dependencies);\n}\n\n/**\n * Runs the interactive setup flow, including diff rendering, confirmation,\n * backup creation, and optional revert.\n */\nexport async function runSetupCommand(\n toolName: SetupToolName,\n options: SetupCliOptions = {},\n dependencies: ToolSetupDependencies = {},\n): Promise<void> {\n const output = dependencies.output ?? createProcessSetupOutput();\n const setup = await createToolSetup(toolName, options, dependencies);\n\n if (!(await setup.detect())) {\n throw new Error(\n `Unable to detect ${toolName}. Make sure the tool is installed or its config directory already exists.`,\n );\n }\n\n if (options.revert) {\n await setup.revert();\n await setAdapterEnabled(toolName, false, options);\n output.stdout(\n `${toolName} setup reverted at ${setup.getConfigPath()}.\\n`,\n );\n return;\n }\n\n const diff = await setup.computeDiff();\n\n output.stdout(`${diff}${diff.endsWith('\\n') ? '' : '\\n'}`);\n\n if (diff.includes('No changes required')) {\n await setAdapterEnabled(toolName, true, options);\n output.stdout(\n `${toolName} is already configured for AISnitch.\\n`,\n );\n return;\n }\n\n const confirm =\n dependencies.confirm ?? defaultConfirm;\n const approved = await confirm(\n diff,\n `Apply AISnitch setup for ${toolName}? [Y/n] `,\n );\n\n if (!approved) {\n output.stdout('Setup aborted.\\n');\n return;\n }\n\n await setup.apply();\n await setAdapterEnabled(toolName, true, options);\n\n output.stdout(\n `Configured ${toolName} for AISnitch at ${setup.getConfigPath()}.\\n`,\n );\n}\n\nfunction buildOpenCodePluginSource(hookUrl: string): string {\n return `/**\n * AISnitch OpenCode plugin\n *\n * 📖 This plugin forwards a curated subset of OpenCode runtime events to the\n * local AISnitch HTTP ingress without requiring extra dependencies.\n */\n\nconst AISNITCH_ENDPOINT = ${JSON.stringify(hookUrl)};\n\nconst EVENT_TYPE_MAP = {\n \"permission.asked\": \"agent.asking_user\",\n \"session.compacted\": \"agent.compact\",\n \"session.created\": \"session.start\",\n \"session.deleted\": \"session.end\",\n \"session.error\": \"agent.error\",\n \"session.idle\": \"agent.idle\",\n \"tool.execute.before\": \"agent.tool_call\"\n};\n\nlet sequenceNumber = 0;\nconst OBSERVED_SESSION_IDS = new Set();\nconst MESSAGE_ROLE_BY_ID = new Map();\nconst STARTED_MESSAGE_IDS = new Set();\n\nfunction getRecord(value) {\n return typeof value === \"object\" && value !== null ? value : {};\n}\n\nfunction getString(value) {\n return typeof value === \"string\" && value.trim().length > 0 ? value : undefined;\n}\n\nfunction getPathTail(value) {\n if (typeof value !== \"string\" || value.length === 0) {\n return undefined;\n }\n\n const parts = value.split(/[\\\\\\\\/]+/).filter(Boolean);\n return parts.length > 0 ? parts[parts.length - 1] : undefined;\n}\n\nfunction sanitizeToken(value) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return undefined;\n }\n\n const normalized = value\n .trim()\n .replace(/[\\\\\\\\/]+/g, \"-\")\n .replace(/[^A-Za-z0-9._-]+/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^[-_.]+|[-_.]+$/g, \"\");\n\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction getSessionId(event, fallbackDirectory) {\n if (typeof event.sessionID === \"string\" && event.sessionID.length > 0) {\n return event.sessionID;\n }\n\n if (typeof event.sessionId === \"string\" && event.sessionId.length > 0) {\n return event.sessionId;\n }\n\n const properties = getRecord(event.properties);\n if (typeof properties.sessionID === \"string\" && properties.sessionID.length > 0) {\n return properties.sessionID;\n }\n\n const project =\n typeof event.project === \"string\"\n ? event.project\n : typeof properties.project === \"string\"\n ? properties.project\n : undefined;\n const cwd =\n typeof event.cwd === \"string\"\n ? event.cwd\n : typeof properties.cwd === \"string\"\n ? properties.cwd\n : fallbackDirectory;\n const scope =\n sanitizeToken(project) ??\n sanitizeToken(getPathTail(cwd)) ??\n \"workspace\";\n const pid =\n typeof process !== \"undefined\" && typeof process.pid === \"number\"\n ? \"p\" + process.pid\n : \"session\";\n\n return \"opencode:\" + scope + \":\" + pid;\n}\n\nfunction getMessageId(event) {\n const properties = getRecord(event.properties);\n const info = getRecord(properties.info);\n const part = getRecord(properties.part);\n\n return (\n getString(info.id) ??\n getString(part.messageID) ??\n getString(part.messageId)\n );\n}\n\nfunction getMessageRole(event) {\n const properties = getRecord(event.properties);\n const info = getRecord(properties.info);\n\n return getString(info.role);\n}\n\nfunction getMessageText(event) {\n const properties = getRecord(event.properties);\n const part = getRecord(properties.part);\n\n return (\n getString(part.text) ??\n getString(event.text) ??\n getString(getRecord(properties.message).text)\n );\n}\n\nfunction getToolInput(event) {\n const payload = getRecord(event);\n const properties = getRecord(payload.properties);\n const output = getRecord(payload.output);\n const args = getRecord(payload.args);\n const outputArgs = getRecord(output.args);\n const propertyArgs = getRecord(properties.args);\n const sourceArgs = Object.keys(args).length > 0\n ? args\n : Object.keys(outputArgs).length > 0\n ? outputArgs\n : propertyArgs;\n const command = getString(sourceArgs.command) ?? getString(sourceArgs.cmd);\n const filePath =\n getString(sourceArgs.filePath) ??\n getString(sourceArgs.file_path) ??\n getString(sourceArgs.path);\n\n if (!command && !filePath) {\n return undefined;\n }\n\n return {\n command,\n filePath\n };\n}\n\nfunction getEventData(event, fallbackDirectory, overrides = {}) {\n const payload = getRecord(event);\n const properties = getRecord(payload.properties);\n const info = getRecord(properties.info);\n const infoPath = getRecord(info.path);\n const infoTokens = getRecord(info.tokens);\n const tool = getRecord(payload.tool);\n const error = getRecord(payload.error);\n const toolInput = getToolInput(event);\n const inputTokens = typeof infoTokens.input === \"number\" ? infoTokens.input : 0;\n const outputTokens = typeof infoTokens.output === \"number\" ? infoTokens.output : 0;\n const reasoningTokens = typeof infoTokens.reasoning === \"number\" ? infoTokens.reasoning : 0;\n const tokensUsed = inputTokens + outputTokens + reasoningTokens;\n const rawOverrides = getRecord(overrides.raw);\n\n return {\n activeFile:\n typeof payload.file === \"string\"\n ? payload.file\n : typeof properties.file === \"string\"\n ? properties.file\n : toolInput?.filePath,\n cwd:\n typeof payload.cwd === \"string\"\n ? payload.cwd\n : typeof properties.cwd === \"string\"\n ? properties.cwd\n : getString(infoPath.cwd) ??\n getString(infoPath.root) ??\n fallbackDirectory,\n errorMessage:\n typeof error.message === \"string\"\n ? error.message\n : typeof payload.message === \"string\"\n ? payload.message\n : undefined,\n model:\n getString(info.modelID)\n ? ((getString(info.providerID) ?? \"unknown\") + \"/\" + getString(info.modelID))\n : undefined,\n project:\n typeof payload.project === \"string\"\n ? payload.project\n : getString(properties.project)\n ? properties.project\n : typeof infoPath.root === \"string\"\n ? getPathTail(infoPath.root)\n : undefined,\n tokensUsed: tokensUsed > 0 ? tokensUsed : undefined,\n toolInput,\n toolName:\n typeof tool.name === \"string\"\n ? tool.name\n : typeof payload.tool === \"string\"\n ? payload.tool\n : undefined,\n raw: {\n opencodeEvent: event,\n ...rawOverrides\n }\n };\n}\n\nfunction createPayload(type, event, fallbackDirectory, overrides) {\n sequenceNumber += 1;\n\n return {\n cwd:\n typeof event.cwd === \"string\" && event.cwd.length > 0\n ? event.cwd\n : fallbackDirectory,\n hookPayload: event,\n pid: typeof process !== \"undefined\" ? process.pid : undefined,\n seqnum: sequenceNumber,\n sessionId: getSessionId(event, fallbackDirectory),\n source: \"aisnitch://plugins/opencode\",\n type,\n data: getEventData(event, fallbackDirectory, overrides)\n };\n}\n\nfunction buildPayloads(event, fallbackDirectory) {\n const eventType = getString(event.type);\n\n if (!eventType) {\n return [];\n }\n\n const payloads = [];\n const sessionId = getSessionId(event, fallbackDirectory);\n\n if (eventType === \"session.updated\" && !OBSERVED_SESSION_IDS.has(sessionId)) {\n OBSERVED_SESSION_IDS.add(sessionId);\n payloads.push(createPayload(\"session.start\", event, fallbackDirectory));\n return payloads;\n }\n\n if (eventType === \"message.updated\") {\n const messageId = getMessageId(event);\n const role = getMessageRole(event);\n\n if (messageId && role) {\n MESSAGE_ROLE_BY_ID.set(messageId, role);\n }\n\n if (role === \"assistant\") {\n payloads.push(createPayload(\"agent.streaming\", event, fallbackDirectory));\n }\n\n return payloads;\n }\n\n if (eventType === \"message.part.updated\") {\n const messageId = getMessageId(event);\n const role = messageId ? MESSAGE_ROLE_BY_ID.get(messageId) : undefined;\n const text = getMessageText(event);\n\n if (role === \"user\") {\n if (messageId && !STARTED_MESSAGE_IDS.has(messageId)) {\n STARTED_MESSAGE_IDS.add(messageId);\n payloads.push(\n createPayload(\"task.start\", event, fallbackDirectory, {\n raw: {\n prompt: text\n }\n })\n );\n }\n\n return payloads;\n }\n\n payloads.push(\n createPayload(\"agent.streaming\", event, fallbackDirectory, {\n raw: {\n streamingText: text\n }\n })\n );\n\n return payloads;\n }\n\n const mappedType = EVENT_TYPE_MAP[eventType];\n\n if (!mappedType) {\n return payloads;\n }\n\n if (mappedType === \"session.start\") {\n OBSERVED_SESSION_IDS.add(sessionId);\n }\n\n payloads.push(createPayload(mappedType, event, fallbackDirectory));\n return payloads;\n}\n\nasync function postPayload(payload) {\n try {\n await fetch(AISNITCH_ENDPOINT, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\"\n },\n body: JSON.stringify(payload)\n });\n } catch {\n // Ignore transport failures so the plugin never blocks OpenCode itself.\n }\n}\n\nexport const AISnitchPlugin = async ({ directory }) => {\n return {\n event: async ({ event }) => {\n for (const payload of buildPayloads(event, directory)) {\n await postPayload(payload);\n }\n }\n };\n};\n`;\n}\n\nfunction createProcessSetupOutput(): SetupOutput {\n return {\n stderr: (text) => {\n process.stderr.write(text);\n },\n stdout: (text) => {\n process.stdout.write(text);\n },\n };\n}\n\nasync function defaultConfirm(_diff: string, prompt: string): Promise<boolean> {\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n throw new Error(\n 'AISnitch setup confirmation requires an interactive terminal.',\n );\n }\n\n const readlineInterface = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n try {\n const answer = (await readlineInterface.question(prompt)).trim().toLowerCase();\n\n return answer === '' || answer === 'y' || answer === 'yes';\n } finally {\n readlineInterface.close();\n }\n}\n\nfunction ensureClaudeAISnitchHook(\n groups: readonly ClaudeHookMatcherGroup[],\n hookEventName: ClaudeHookEventName,\n hookUrl: string,\n): ClaudeHookMatcherGroup[] {\n const clonedGroups = groups.map((group) => ({\n ...group,\n hooks: group.hooks.map((handler) => ({ ...handler })),\n }));\n const matcher = hookEventName === 'FileChanged'\n ? CLAUDE_FILE_CHANGED_MATCHER\n : undefined;\n const matchingGroup = clonedGroups.find((group) => group.matcher === matcher);\n\n if (matchingGroup) {\n const existingHook = matchingGroup.hooks.find((handler) => isClaudeAISnitchHook(handler, hookUrl));\n\n if (existingHook) {\n if (existingHook.async !== true) {\n existingHook.async = true;\n }\n\n return clonedGroups;\n }\n\n matchingGroup.hooks.push(createClaudeAISnitchHook(hookUrl));\n return clonedGroups;\n }\n\n const nextGroup: ClaudeHookMatcherGroup =\n matcher === undefined\n ? {\n hooks: [createClaudeAISnitchHook(hookUrl)],\n }\n : {\n matcher,\n hooks: [createClaudeAISnitchHook(hookUrl)],\n };\n\n clonedGroups.push(nextGroup);\n return clonedGroups;\n}\n\nfunction createClaudeAISnitchHook(hookUrl: string): ClaudeHookHandler {\n return {\n async: true,\n type: 'http',\n url: hookUrl,\n };\n}\n\nfunction isClaudeAISnitchHook(\n handler: ClaudeHookHandler,\n hookUrl: string,\n): boolean {\n return handler.type === 'http' && handler.url === hookUrl;\n}\n\nfunction ensureGeminiAISnitchHook(\n groups: readonly GeminiHookMatcherGroup[],\n hookUrl: string,\n): GeminiHookMatcherGroup[] {\n const clonedGroups = groups.map((group) => ({\n ...group,\n hooks: group.hooks.map((handler) => ({ ...handler })),\n }));\n const matchingGroup = clonedGroups.find((group) => group.matcher === '*');\n\n if (matchingGroup) {\n const existingHook = matchingGroup.hooks.find((handler) =>\n isGeminiAISnitchHook(handler, hookUrl),\n );\n\n if (existingHook) {\n return clonedGroups;\n }\n\n matchingGroup.hooks.push(createGeminiAISnitchHook(hookUrl));\n return clonedGroups;\n }\n\n clonedGroups.push({\n hooks: [createGeminiAISnitchHook(hookUrl)],\n matcher: '*',\n });\n\n return clonedGroups;\n}\n\nfunction createGeminiAISnitchHook(hookUrl: string): GeminiHookHandler {\n return {\n command: buildGeminiForwardCommand(hookUrl),\n description: 'Forward Gemini CLI hook payloads to AISnitch.',\n name: 'aisnitch-forward',\n timeout: 5_000,\n type: 'command',\n };\n}\n\nfunction buildGeminiForwardCommand(hookUrl: string): string {\n return `sh -c 'curl -fsS -X POST -H \"content-type: application/json\" --data-binary @- ${hookUrl} >/dev/null 2>&1 || true'`;\n}\n\nfunction isGeminiAISnitchHook(\n handler: GeminiHookHandler,\n hookUrl: string,\n): boolean {\n return (\n handler.type === 'command' &&\n typeof handler.command === 'string' &&\n handler.command.includes(hookUrl)\n );\n}\n\nfunction ensureCopilotAISnitchHook(\n handlers: readonly CopilotHookHandler[],\n hookEventName: (typeof COPILOT_HOOK_EVENTS)[number],\n hookUrl: string,\n): CopilotHookHandler[] {\n const clonedHandlers = handlers.map((handler) => ({ ...handler }));\n const existingHook = clonedHandlers.find((handler) =>\n isCopilotAISnitchHook(handler, hookEventName, hookUrl),\n );\n\n if (existingHook) {\n return clonedHandlers;\n }\n\n clonedHandlers.push(createCopilotAISnitchHook(hookEventName, hookUrl));\n return clonedHandlers;\n}\n\nfunction createCopilotAISnitchHook(\n hookEventName: (typeof COPILOT_HOOK_EVENTS)[number],\n hookUrl: string,\n): CopilotHookHandler {\n const command = buildCopilotForwardCommand(hookEventName, hookUrl);\n\n return {\n bash: command,\n cwd: '.github/hooks',\n powershell: command,\n timeoutSec: 10,\n type: 'command',\n };\n}\n\nfunction buildCopilotForwardCommand(\n hookEventName: (typeof COPILOT_HOOK_EVENTS)[number],\n hookUrl: string,\n): string {\n return `node ./scripts/aisnitch-forward.mjs ${hookEventName} ${hookUrl}`;\n}\n\nfunction isCopilotAISnitchHook(\n handler: CopilotHookHandler,\n hookEventName: (typeof COPILOT_HOOK_EVENTS)[number],\n hookUrl: string,\n): boolean {\n return (\n handler.type === 'command' &&\n typeof handler.bash === 'string' &&\n handler.bash.includes(`aisnitch-forward.mjs ${hookEventName}`) &&\n handler.bash.includes(hookUrl)\n );\n}\n\nfunction buildCopilotForwardScriptSource(): string {\n return `#!/usr/bin/env node\n/**\n * AISnitch Copilot CLI hook bridge\n *\n * 📖 Copilot hooks are repository-scoped and synchronous. This script keeps\n * the hook config tiny by tagging the incoming stdin payload with the hook\n * name, then forwarding it to the local AISnitch HTTP receiver.\n */\n\nfunction isRecord(value) {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nasync function readInput() {\n const chunks = [];\n\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"));\n }\n\n return chunks.join(\"\");\n}\n\nasync function main() {\n const hookEventName = process.argv[2] ?? \"unknown\";\n const endpoint = process.argv[3] ?? \"http://localhost:4821/hooks/copilot-cli\";\n const rawInput = await readInput();\n let payload = {};\n\n if (rawInput.trim().length > 0) {\n try {\n const parsedPayload = JSON.parse(rawInput);\n\n if (isRecord(parsedPayload)) {\n payload = parsedPayload;\n }\n } catch {\n payload = {\n raw: rawInput\n };\n }\n }\n\n try {\n await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\"\n },\n body: JSON.stringify({\n ...payload,\n hook_event_name: hookEventName\n })\n });\n } catch {\n // Ignore transport failures so Copilot itself never gets blocked by AISnitch.\n }\n}\n\nvoid main();\n`;\n}\n\nfunction buildOpenClawHookDocumentSource(): string {\n return `---\nname: aisnitch-forward\ndescription: \"Forward key OpenClaw lifecycle events to AISnitch\"\nmetadata:\n {\n \"openclaw\": {\n \"emoji\": \"🛰️\",\n \"events\": [\n \"gateway:startup\",\n \"agent:bootstrap\",\n \"command:new\",\n \"command:reset\",\n \"command:stop\",\n \"session:compact:before\"\n ]\n }\n }\n---\n\n# AISnitch Forwarder\n\n📖 This managed hook forwards high-signal OpenClaw lifecycle events into the\nlocal AISnitch HTTP receiver. Tool-result details are complemented by AISnitch's\ntranscript watcher, while this hook covers startup, command, reset, stop, and\npre-compaction lifecycle changes with near-zero latency.\n`;\n}\n\nfunction buildOpenClawHookHandlerSource(hookUrl: string): string {\n return `/**\n * AISnitch OpenClaw managed hook\n *\n * 📖 OpenClaw's current public docs describe managed hooks plus bundled\n * command/session hooks. This handler forwards those lifecycle events to the\n * local AISnitch HTTP ingress and stays fire-and-forget so OpenClaw never\n * blocks on observability.\n */\n\nconst AISNITCH_ENDPOINT = ${JSON.stringify(hookUrl)};\nconst ENABLED_EVENTS = new Set([\n \"gateway:startup\",\n \"agent:bootstrap\",\n \"command:new\",\n \"command:reset\",\n \"command:stop\",\n \"session:compact:before\"\n]);\n\nfunction getRecord(value) {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? value\n : {};\n}\n\nfunction getEventName(event) {\n if (typeof event.event === \"string\" && event.event.length > 0) {\n return event.event;\n }\n\n if (typeof event.type !== \"string\" || event.type.length === 0) {\n return undefined;\n }\n\n if (typeof event.action !== \"string\" || event.action.length === 0) {\n return event.type;\n }\n\n if (event.type === \"command\" && !event.action.startsWith(\"/\") && !event.action.includes(\":\")) {\n return \"command:\" + event.action;\n }\n\n return event.type + \":\" + event.action;\n}\n\nfunction getPrimaryMessage(event) {\n const context = getRecord(event.context);\n\n if (typeof event.message === \"string\" && event.message.length > 0) {\n return event.message;\n }\n\n if (typeof context.content === \"string\" && context.content.length > 0) {\n return context.content;\n }\n\n if (typeof context.bodyForAgent === \"string\" && context.bodyForAgent.length > 0) {\n return context.bodyForAgent;\n }\n\n if (typeof context.body === \"string\" && context.body.length > 0) {\n return context.body;\n }\n\n if (Array.isArray(event.messages) && typeof event.messages[0] === \"string\") {\n return event.messages[0];\n }\n\n return undefined;\n}\n\nasync function postPayload(payload) {\n try {\n await fetch(AISNITCH_ENDPOINT, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\"\n },\n body: JSON.stringify(payload)\n });\n } catch {\n // Ignore local transport failures so OpenClaw keeps running.\n }\n}\n\nexport default async function aisnitchForward(event) {\n const eventName = getEventName(getRecord(event));\n\n if (!eventName || !ENABLED_EVENTS.has(eventName)) {\n return;\n }\n\n const context = getRecord(event.context);\n\n await postPayload({\n action: typeof event.action === \"string\" ? event.action : undefined,\n context,\n cwd:\n typeof context.workspaceDir === \"string\"\n ? context.workspaceDir\n : typeof context.cwd === \"string\"\n ? context.cwd\n : undefined,\n event: eventName,\n message: getPrimaryMessage(getRecord(event)),\n messages: Array.isArray(event.messages) ? event.messages : undefined,\n pid: typeof process !== \"undefined\" ? process.pid : undefined,\n raw: event,\n sessionKey:\n typeof event.sessionKey === \"string\" && event.sessionKey.length > 0\n ? event.sessionKey\n : typeof context.sessionKey === \"string\" && context.sessionKey.length > 0\n ? context.sessionKey\n : undefined,\n timestamp:\n event.timestamp instanceof Date\n ? event.timestamp.toISOString()\n : typeof event.timestamp === \"string\"\n ? event.timestamp\n : undefined,\n type: typeof event.type === \"string\" ? event.type : undefined\n });\n}\n`;\n}\n\nfunction parseOpenClawSettings(currentContent: string | null): OpenClawSettings {\n if (currentContent === null || currentContent.trim().length === 0) {\n return {};\n }\n\n const parsedConfig: unknown = JSON5.parse(currentContent);\n\n if (!isRecord(parsedConfig)) {\n throw new Error('OpenClaw openclaw.json must contain an object.');\n }\n\n if (parsedConfig.hooks !== undefined && !isRecord(parsedConfig.hooks)) {\n throw new Error('OpenClaw hooks config must be an object when present.');\n }\n\n if (\n isRecord(parsedConfig.hooks) &&\n parsedConfig.hooks.internal !== undefined &&\n !isRecord(parsedConfig.hooks.internal)\n ) {\n throw new Error('OpenClaw hooks.internal config must be an object when present.');\n }\n\n return parsedConfig;\n}\n\nfunction parseClaudeSettings(currentContent: string | null): ClaudeSettings {\n if (currentContent === null || currentContent.trim().length === 0) {\n return {};\n }\n\n const parsedJson: unknown = JSON.parse(currentContent);\n\n if (!isRecord(parsedJson)) {\n throw new Error('Claude Code settings.json must contain a JSON object.');\n }\n\n if (parsedJson.hooks !== undefined && !isRecord(parsedJson.hooks)) {\n throw new Error('Claude Code hooks configuration must be an object.');\n }\n\n const parsedHooks =\n parsedJson.hooks === undefined\n ? undefined\n : Object.fromEntries(\n Object.entries(parsedJson.hooks).map(([hookEventName, value]) => {\n if (!Array.isArray(value)) {\n throw new Error(\n `Claude Code hook group \"${hookEventName}\" must be an array.`,\n );\n }\n\n const groups = value.map((group) => parseClaudeHookMatcherGroup(group, hookEventName));\n\n return [hookEventName, groups];\n }),\n );\n\n return {\n ...parsedJson,\n hooks: parsedHooks,\n };\n}\n\nfunction parseCopilotHooksFile(currentContent: string | null): CopilotHooksFile {\n if (currentContent === null || currentContent.trim().length === 0) {\n return {\n version: 1,\n };\n }\n\n const parsedJson: unknown = JSON.parse(currentContent);\n\n if (!isRecord(parsedJson)) {\n throw new Error('Copilot hooks config must contain a JSON object.');\n }\n\n if (parsedJson.version !== undefined && typeof parsedJson.version !== 'number') {\n throw new Error('Copilot hooks config version must be a number.');\n }\n\n if (parsedJson.hooks !== undefined && !isRecord(parsedJson.hooks)) {\n throw new Error('Copilot hooks configuration must be an object.');\n }\n\n const parsedHooks =\n parsedJson.hooks === undefined\n ? undefined\n : Object.fromEntries(\n Object.entries(parsedJson.hooks).map(([hookEventName, value]) => {\n if (!Array.isArray(value)) {\n throw new Error(\n `Copilot hook group \"${hookEventName}\" must be an array.`,\n );\n }\n\n const handlers = value.map((handler) =>\n parseCopilotHookHandler(handler, hookEventName),\n );\n\n return [hookEventName, handlers];\n }),\n );\n\n return {\n ...parsedJson,\n hooks: parsedHooks,\n version: parsedJson.version === undefined ? 1 : parsedJson.version,\n } satisfies CopilotHooksFile;\n}\n\nfunction parseGeminiSettings(currentContent: string | null): GeminiSettings {\n if (currentContent === null || currentContent.trim().length === 0) {\n return {};\n }\n\n const parsedJson: unknown = JSON.parse(currentContent);\n\n if (!isRecord(parsedJson)) {\n throw new Error('Gemini CLI settings.json must contain a JSON object.');\n }\n\n if (parsedJson.hooks !== undefined && !isRecord(parsedJson.hooks)) {\n throw new Error('Gemini CLI hooks configuration must be an object.');\n }\n\n const parsedHooks =\n parsedJson.hooks === undefined\n ? undefined\n : Object.fromEntries(\n Object.entries(parsedJson.hooks).map(([hookEventName, value]) => {\n if (!Array.isArray(value)) {\n throw new Error(\n `Gemini hook group \"${hookEventName}\" must be an array.`,\n );\n }\n\n const groups = value.map((group) =>\n parseGeminiHookMatcherGroup(group, hookEventName),\n );\n\n return [hookEventName, groups];\n }),\n );\n\n return {\n ...parsedJson,\n hooks: parsedHooks,\n };\n}\n\nfunction parseClaudeHookMatcherGroup(\n value: unknown,\n hookEventName: string,\n): ClaudeHookMatcherGroup {\n if (!isRecord(value)) {\n throw new Error(\n `Claude Code hook matcher group \"${hookEventName}\" must be an object.`,\n );\n }\n\n if (!Array.isArray(value.hooks)) {\n throw new Error(\n `Claude Code matcher group \"${hookEventName}\" must include a hooks array.`,\n );\n }\n\n const hooks = value.hooks.map((handler) => parseClaudeHookHandler(handler, hookEventName));\n const matcher =\n value.matcher === undefined\n ? undefined\n : typeof value.matcher === 'string'\n ? value.matcher\n : (() => {\n throw new Error(\n `Claude Code matcher \"${hookEventName}\" must be a string when present.`,\n );\n })();\n\n return {\n ...value,\n hooks,\n ...(matcher === undefined ? {} : { matcher }),\n };\n}\n\nfunction parseClaudeHookHandler(\n value: unknown,\n hookEventName: string,\n): ClaudeHookHandler {\n if (!isRecord(value) || typeof value.type !== 'string') {\n throw new Error(\n `Claude Code hook handler \"${hookEventName}\" must be an object with a string type.`,\n );\n }\n\n return {\n ...value,\n type: value.type,\n };\n}\n\nfunction parseGeminiHookMatcherGroup(\n value: unknown,\n hookEventName: string,\n): GeminiHookMatcherGroup {\n if (!isRecord(value)) {\n throw new Error(\n `Gemini hook matcher group \"${hookEventName}\" must be an object.`,\n );\n }\n\n if (!Array.isArray(value.hooks)) {\n throw new Error(\n `Gemini matcher group \"${hookEventName}\" must include a hooks array.`,\n );\n }\n\n const hooks = value.hooks.map((handler) =>\n parseGeminiHookHandler(handler, hookEventName),\n );\n const matcher =\n value.matcher === undefined\n ? undefined\n : typeof value.matcher === 'string'\n ? value.matcher\n : (() => {\n throw new Error(\n `Gemini matcher \"${hookEventName}\" must be a string when present.`,\n );\n })();\n\n return {\n ...value,\n hooks,\n ...(matcher === undefined ? {} : { matcher }),\n };\n}\n\nfunction parseGeminiHookHandler(\n value: unknown,\n hookEventName: string,\n): GeminiHookHandler {\n if (!isRecord(value) || typeof value.type !== 'string') {\n throw new Error(\n `Gemini hook handler \"${hookEventName}\" must be an object with a string type.`,\n );\n }\n\n return {\n ...value,\n type: value.type,\n };\n}\n\nfunction parseCopilotHookHandler(\n value: unknown,\n hookEventName: string,\n): CopilotHookHandler {\n if (!isRecord(value) || typeof value.type !== 'string') {\n throw new Error(\n `Copilot hook handler \"${hookEventName}\" must be an object with a string type.`,\n );\n }\n\n return {\n ...value,\n type: value.type,\n };\n}\n\nfunction renderColoredDiff(\n filePath: string,\n currentContent: string | null,\n nextContent: string,\n): string {\n const currentLines =\n currentContent === null ? [] : stripTrailingNewline(currentContent).split('\\n');\n const nextLines = stripTrailingNewline(nextContent).split('\\n');\n\n return [\n `${ANSI_CYAN}--- ${filePath} (current)${ANSI_RESET}`,\n `${ANSI_CYAN}+++ ${filePath} (proposed)${ANSI_RESET}`,\n ...(currentLines.length === 0\n ? [`${ANSI_RED}-(file does not exist)${ANSI_RESET}`]\n : currentLines.map((line) => `${ANSI_RED}-${line}${ANSI_RESET}`)),\n ...(nextLines.length === 0\n ? [`${ANSI_GREEN}+(empty file)${ANSI_RESET}`]\n : nextLines.map((line) => `${ANSI_GREEN}+${line}${ANSI_RESET}`)),\n ].join('\\n');\n}\n\nfunction stripTrailingNewline(value: string): string {\n return value.endsWith('\\n') ? value.slice(0, -1) : value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function isBinaryAvailable(binaryName: string): Promise<boolean> {\n const lookupCommand = process.platform === 'win32' ? 'where' : 'which';\n\n try {\n await execFile(lookupCommand, [binaryName], {\n encoding: 'utf8',\n });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readOptionalFile(path: string): Promise<string | null> {\n try {\n return await readFile(path, 'utf8');\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\nasync function restoreBackupOrRemove(path: string): Promise<void> {\n const backupPath = `${path}.bak`;\n\n if (await fileExists(backupPath)) {\n await copyFile(backupPath, path);\n await rm(backupPath, { force: true });\n return;\n }\n\n await rm(path, { force: true });\n}\n\nfunction buildAiderNotificationCommand(options: SetupCliOptions): string {\n const cliArgs = [process.execPath, resolveCurrentCliEntryPath(), 'aider-notify'];\n\n if (options.config) {\n cliArgs.push('--config', options.config);\n }\n\n return cliArgs.map((argument) => JSON.stringify(argument)).join(' ');\n}\n\nfunction resolveCurrentCliEntryPath(): string {\n const cliEntryPath = process.argv[1];\n\n if (!cliEntryPath || cliEntryPath.trim().length === 0) {\n throw new Error('Unable to resolve the current AISnitch CLI entry path.');\n }\n\n return cliEntryPath;\n}\n\nfunction upsertYamlScalar(\n content: string,\n aliases: readonly string[],\n nextEntry: {\n readonly key: string;\n readonly value: string;\n },\n): string {\n const lines = content.replace(/\\r\\n/gu, '\\n').split('\\n');\n const matcher = new RegExp(\n `^\\\\s*#?\\\\s*(?:${aliases.map(escapeForRegExp).join('|')})\\\\s*:`,\n 'u',\n );\n const nextLines: string[] = [];\n let replaced = false;\n\n for (const line of lines) {\n if (matcher.test(line)) {\n if (!replaced) {\n nextLines.push(`${nextEntry.key}: ${nextEntry.value}`);\n replaced = true;\n }\n\n continue;\n }\n\n nextLines.push(line);\n }\n\n if (!replaced) {\n if (nextLines.length > 0 && nextLines.at(-1)?.trim().length !== 0) {\n nextLines.push('');\n }\n\n nextLines.push(`${nextEntry.key}: ${nextEntry.value}`);\n }\n\n return nextLines.join('\\n');\n}\n\nfunction escapeForRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, '\\\\$&');\n}\n\nasync function setAdapterEnabled(\n toolName: SetupToolName,\n enabled: boolean,\n options: SetupCliOptions,\n): Promise<void> {\n const configOptions = toConfigPathOptions(options);\n const config = await loadConfig(configOptions);\n const currentAdapters = config.adapters;\n\n const nextAdapters: AISnitchConfig['adapters'] = {\n ...currentAdapters,\n [toolName]: {\n enabled,\n } satisfies AdapterConfig,\n };\n\n await saveConfig(\n {\n ...config,\n adapters: nextAdapters,\n },\n configOptions,\n );\n}\n\nfunction toConfigPathOptions(options: SetupCliOptions): ConfigPathOptions {\n return options.config ? { configPath: options.config } : {};\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 { execFile as execFileCallback, spawn as spawnChildProcess } from 'node:child_process';\nimport { closeSync, openSync } from 'node:fs';\nimport { mkdtemp, rename, rm, writeFile } from 'node:fs/promises';\nimport { createConnection } from 'node:net';\nimport { tmpdir } from 'node:os';\nimport { basename, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nimport { GenericPTYSession } from '../adapters/generic-pty.js';\nimport {\n AISnitchEventTypeSchema,\n ToolNameSchema,\n type AISnitchEvent,\n type AISnitchConfig,\n type AISnitchEventType,\n type ToolName,\n} from '../core/index.js';\nimport {\n ConfigSchema,\n LOG_LEVELS,\n Pipeline,\n setLoggerLevel,\n type ConfigPathOptions,\n type HealthSnapshot,\n} from '../core/index.js';\nimport {\n attachEventBusMonitor,\n renderAttachedTui,\n renderForegroundTui,\n type MonitorCloseHandler,\n type MonitorOutput,\n} from '../tui/index.js';\nimport {\n TUI_VIEW_MODES,\n type TuiInitialFilters,\n type TuiViewMode,\n} from '../tui/types.js';\nimport {\n cleanupStaleDaemonFiles,\n ensureLaunchAgentDir,\n getDaemonLogPath,\n getDaemonLogSize,\n getEffectiveCliConfigPath,\n getLaunchAgentPath,\n isDaemonRunning,\n isProcessRunning,\n readDaemonState,\n readPid,\n removeDaemonState,\n removePid,\n writeDaemonState,\n writePid,\n type DaemonPathOptions,\n} from './pid.js';\nimport {\n ensureConfigDir,\n getAISnitchHomePath,\n loadConfig,\n} from '../core/config/index.js';\nimport {\n runSetupCommand,\n type SetupCliOptions,\n type SetupOutput,\n type SetupToolName,\n} from './commands/setup.js';\nimport {\n runMockScenario,\n type MockCommandOptions,\n type MockToolSelection,\n} from './commands/mock.js';\n\n/**\n * @file src/cli/runtime.ts\n * @description Runtime command implementations for foreground mode, daemon mode, status inspection, and launchd integration.\n * @functions\n * → createCliRuntime\n * → parsePortOption\n * → parseLogLevelOption\n * → buildLaunchAgentPlist\n * @exports CliOutput, CommonCliOptions, AttachCliOptions, StartCliOptions, MockCliOptions, createCliRuntime, parsePortOption, parseLogLevelOption, parseToolFilterOption, parseEventTypeFilterOption, parseTuiViewModeOption, buildLaunchAgentPlist\n * @see ./pid.ts\n * @see ../tui/live-monitor.ts\n * @see ../core/engine/pipeline.ts\n */\n\nconst execFile = promisify(execFileCallback);\n\nconst DAEMON_READY_TIMEOUT_MS = 4_000;\nconst DAEMON_READY_POLL_INTERVAL_MS = 100;\nconst DAEMON_STOP_TIMEOUT_MS = 4_000;\nconst DAEMON_LOG_MAX_BYTES = 5 * 1024 * 1024;\nconst LAUNCH_AGENT_LABEL = 'com.aisnitch.daemon';\n\n/**\n * Shared CLI output abstraction for commands and monitor rendering.\n */\nexport type CliOutput = MonitorOutput;\n\n/**\n * Shared config override supported by all runtime commands.\n */\nexport interface CommonCliOptions {\n readonly config?: string;\n}\n\n/**\n * TUI filter options accepted by foreground and attach commands.\n */\nexport interface AttachCliOptions extends CommonCliOptions {\n readonly tool?: ToolName;\n readonly type?: AISnitchEventType;\n readonly view?: TuiViewMode;\n}\n\n/**\n * Options accepted by `aisnitch start`.\n */\nexport interface StartCliOptions extends AttachCliOptions {\n readonly daemon?: boolean;\n readonly httpPort?: number;\n readonly logLevel?: AISnitchConfig['logLevel'];\n readonly mock?: MockToolSelection;\n readonly mockDuration?: number;\n readonly mockLoop?: boolean;\n readonly mockSpeed?: number;\n readonly wsPort?: number;\n}\n\n/**\n * Options accepted by `aisnitch mock`.\n */\nexport interface MockCliOptions extends CommonCliOptions, MockCommandOptions {}\n\n/**\n * Options accepted by `aisnitch wrap`.\n */\nexport interface WrapCliOptions extends CommonCliOptions {\n readonly cwd?: string;\n}\n\n/**\n * Stable runtime command interface consumed by the commander program wiring.\n */\nexport interface CliRuntime {\n readonly adapters: (options: CommonCliOptions) => Promise<void>;\n readonly aiderNotify: (options: CommonCliOptions) => Promise<void>;\n readonly attach: (options: AttachCliOptions) => Promise<void>;\n readonly install: (options: CommonCliOptions) => Promise<void>;\n readonly mock: (\n selection: MockToolSelection,\n options: MockCliOptions,\n ) => Promise<void>;\n readonly runDaemonProcess: (options: StartCliOptions) => Promise<void>;\n readonly setup: (\n toolName: SetupToolName,\n options: SetupCliOptions,\n ) => Promise<void>;\n readonly start: (options: StartCliOptions) => Promise<void>;\n readonly status: (options: CommonCliOptions) => Promise<void>;\n readonly stop: (options: CommonCliOptions) => Promise<void>;\n readonly uninstall: (options: CommonCliOptions) => Promise<void>;\n readonly wrap: (\n command: string,\n args: readonly string[],\n options: WrapCliOptions,\n ) => Promise<void>;\n}\n\n/**\n * LaunchAgent plist generation inputs.\n */\nexport interface LaunchAgentPlistOptions {\n readonly cliEntryPath: string;\n readonly configPath?: string;\n readonly logFilePath: string;\n readonly nodeExecutablePath: string;\n}\n\ninterface CliRuntimeDependencies {\n readonly execFile?: (\n file: string,\n args: readonly string[],\n ) => Promise<{ readonly stdout: string; readonly stderr: string }>;\n readonly fetch?: typeof globalThis.fetch;\n readonly output?: CliOutput;\n readonly sleep?: (ms: number) => Promise<void>;\n readonly spawn?: typeof spawnChildProcess;\n}\n\ninterface StatusSnapshot {\n readonly configuredAdapters: readonly ToolName[];\n readonly daemonPid: number | null;\n readonly health: HealthSnapshot | null;\n readonly httpPort: number;\n readonly logFilePath: string;\n readonly running: boolean;\n readonly socketPath: string | null;\n readonly wsPort: number;\n}\n\ninterface SocketEventPublisher {\n readonly close: () => Promise<void>;\n readonly publish: (event: AISnitchEvent) => Promise<boolean>;\n}\n\n/**\n * 📖 The CLI runtime keeps command-side orchestration separate from commander\n * parsing so tests can exercise the logic without shelling out to a subprocess.\n */\nexport function createCliRuntime(\n dependencies: CliRuntimeDependencies = {},\n): CliRuntime {\n const output = dependencies.output ?? createProcessOutput();\n const fetchImplementation = dependencies.fetch ?? globalThis.fetch;\n const spawnImplementation = dependencies.spawn ?? spawnChildProcess;\n const execFileImplementation =\n dependencies.execFile ??\n (async (file, args) => {\n return await execFile(file, [...args], {\n encoding: 'utf8',\n });\n });\n const sleep =\n dependencies.sleep ??\n (async (ms) => {\n await new Promise<void>((resolve) => {\n setTimeout(resolve, ms).unref();\n });\n });\n\n async function loadEffectiveConfig(\n options: StartCliOptions | CommonCliOptions,\n ): Promise<{\n readonly config: AISnitchConfig;\n readonly pathOptions: ConfigPathOptions;\n }> {\n const pathOptions = toPathOptions(options);\n const baseConfig = await loadConfig(pathOptions);\n const config = ConfigSchema.parse({\n ...baseConfig,\n ...(isStartCliOptions(options)\n ? {\n httpPort: options.httpPort ?? baseConfig.httpPort,\n logLevel: options.logLevel ?? baseConfig.logLevel,\n wsPort: options.wsPort ?? baseConfig.wsPort,\n }\n : {}),\n });\n\n return {\n config,\n pathOptions,\n };\n }\n\n async function fetchHealth(\n httpPort: number,\n ): Promise<HealthSnapshot | null> {\n try {\n const response = await fetchImplementation(\n `http://127.0.0.1:${httpPort}/health`,\n );\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as HealthSnapshot;\n } catch {\n return null;\n }\n }\n\n async function ensureDaemonNotRunning(\n options: CommonCliOptions,\n ): Promise<void> {\n const pathOptions = toPathOptions(options);\n\n await cleanupStaleDaemonFiles(pathOptions);\n\n if (await isDaemonRunning(pathOptions)) {\n throw new Error(\n 'AISnitch daemon is already running. Use `aisnitch attach` or `aisnitch stop` first.',\n );\n }\n }\n\n async function rotateDaemonLogIfNeeded(\n pathOptions: DaemonPathOptions,\n ): Promise<void> {\n const logFilePath = getDaemonLogPath(pathOptions);\n const backupPath = `${logFilePath}.1`;\n const logSize = await getDaemonLogSize(pathOptions);\n\n if (logSize < DAEMON_LOG_MAX_BYTES) {\n return;\n }\n\n await rm(backupPath, { force: true });\n await rename(logFilePath, backupPath);\n }\n\n async function waitForDaemonReady(\n pathOptions: DaemonPathOptions,\n ): Promise<StatusSnapshot> {\n const deadline = Date.now() + DAEMON_READY_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n const daemonState = await readDaemonState(pathOptions);\n\n if (daemonState && isProcessRunning(daemonState.pid)) {\n const health = await fetchHealth(daemonState.httpPort);\n\n if (health !== null) {\n return {\n configuredAdapters: [],\n daemonPid: daemonState.pid,\n health,\n httpPort: daemonState.httpPort,\n logFilePath: daemonState.logFilePath,\n running: true,\n socketPath: daemonState.socketPath,\n wsPort: daemonState.wsPort,\n };\n }\n }\n\n await sleep(DAEMON_READY_POLL_INTERVAL_MS);\n }\n\n throw new Error(\n `AISnitch daemon did not become ready in time. Check ${getDaemonLogPath(\n pathOptions,\n )}.`,\n );\n }\n\n async function waitForProcessExit(pid: number): Promise<boolean> {\n const deadline = Date.now() + DAEMON_STOP_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n if (!isProcessRunning(pid)) {\n return true;\n }\n\n await sleep(DAEMON_READY_POLL_INTERVAL_MS);\n }\n\n return !isProcessRunning(pid);\n }\n\n function startMockEmitter(\n pipeline: Pipeline,\n options: StartCliOptions,\n ): void {\n if (!options.mock) {\n return;\n }\n\n const speed = options.mockSpeed ?? 1;\n const durationSeconds = options.mockDuration ?? 60;\n const loop = options.mockLoop ?? false;\n\n output.stdout(\n `Starting mock scenario ${options.mock} (${speed}x, ${durationSeconds}s${loop ? ', loop' : ''}).\\n`,\n );\n\n void runMockScenario({\n durationSeconds,\n loop,\n publishEvent: async (event) => {\n return await pipeline.publishEvent(event);\n },\n selection: options.mock,\n speed,\n }).then((result) => {\n output.stdout(\n `Mock scenario ${options.mock} published ${result.publishedEvents} events across ${result.loopCount} loop(s).\\n`,\n );\n }).catch((error: unknown) => {\n output.stderr(\n `Mock scenario failed: ${error instanceof Error ? error.message : 'unknown error'}\\n`,\n );\n });\n }\n\n async function runPipelineHeadless(\n options: StartCliOptions,\n daemonMode: boolean,\n ): Promise<never> {\n const { config, pathOptions } = await loadEffectiveConfig(options);\n\n setLoggerLevel(getForegroundSafeLogLevel(config.logLevel, daemonMode));\n\n const pipeline = new Pipeline();\n const status = await pipeline.start({\n config,\n ...pathOptions,\n });\n\n startMockEmitter(pipeline, options);\n\n if (daemonMode) {\n const daemonPathOptions = toPathOptions(options);\n\n await writePid(process.pid, daemonPathOptions);\n await writeDaemonState(\n {\n configPath: getEffectiveCliConfigPath(daemonPathOptions),\n httpPort: status.httpPort ?? config.httpPort,\n logFilePath: getDaemonLogPath(daemonPathOptions),\n pid: process.pid,\n socketPath: status.socketPath,\n startedAt: new Date().toISOString(),\n wsPort: status.wsPort ?? config.wsPort,\n },\n daemonPathOptions,\n );\n }\n\n let shuttingDown = false;\n\n const shutdown = async (signal: string, exitCode = 0): Promise<void> => {\n if (shuttingDown) {\n return;\n }\n\n shuttingDown = true;\n\n try {\n await pipeline.stop();\n } finally {\n if (daemonMode) {\n const daemonPathOptions = toPathOptions(options);\n\n await Promise.all([\n removePid(daemonPathOptions),\n removeDaemonState(daemonPathOptions),\n ]);\n }\n }\n\n if (!daemonMode) {\n output.stdout(`AISnitch stopped after ${signal}.\\n`);\n }\n\n process.exit(exitCode);\n };\n\n if (daemonMode) {\n process.once('SIGTERM', () => {\n void shutdown('SIGTERM');\n });\n process.once('SIGINT', () => {\n void shutdown('SIGINT');\n });\n process.once('uncaughtException', (error) => {\n output.stderr(\n `AISnitch daemon crashed: ${\n error instanceof Error ? error.message : 'unknown exception'\n }\\n`,\n );\n void shutdown('uncaughtException', 1);\n });\n process.once('unhandledRejection', (reason) => {\n output.stderr(\n `AISnitch daemon rejected a promise: ${\n reason instanceof Error ? reason.message : 'unknown rejection'\n }\\n`,\n );\n void shutdown('unhandledRejection', 1);\n });\n\n return await new Promise<never>(() => undefined);\n }\n\n process.once('SIGTERM', () => {\n void shutdown('SIGTERM');\n });\n process.once('SIGINT', () => {\n void shutdown('SIGINT');\n });\n\n await renderForegroundTui({\n configuredAdapters: getEnabledAdapters(config),\n eventBus: pipeline.getEventBus(),\n initialFilters: toInitialTuiFilters(options),\n onQuit: () => {\n void shutdown('tui-exit');\n },\n status,\n });\n\n return await new Promise<never>(() => undefined);\n }\n\n async function start(options: StartCliOptions): Promise<void> {\n if (options.daemon) {\n await ensureDaemonNotRunning(options);\n\n const daemonPathOptions = toPathOptions(options);\n\n await ensureConfigDir(daemonPathOptions);\n await rotateDaemonLogIfNeeded(daemonPathOptions);\n\n const daemonLogPath = getDaemonLogPath(daemonPathOptions);\n const stdoutFd = openSync(daemonLogPath, 'w');\n const stderrFd = openSync(daemonLogPath, 'a');\n const cliEntryPath = resolveCliEntryPath();\n const daemonArgs = [cliEntryPath, 'daemon-run', ...toDaemonArgv(options)];\n const child = spawnImplementation(process.execPath, daemonArgs, {\n detached: true,\n env: {\n ...process.env,\n AISNITCH_DAEMON: '1',\n },\n stdio: ['ignore', stdoutFd, stderrFd],\n });\n\n child.unref();\n closeSync(stdoutFd);\n closeSync(stderrFd);\n\n if (child.pid === undefined) {\n throw new Error('Failed to obtain the AISnitch daemon PID.');\n }\n\n const snapshot = await waitForDaemonReady(daemonPathOptions);\n\n output.stdout(\n `AISnitch daemon started (PID: ${child.pid}) on ws://${'127.0.0.1'}:${snapshot.wsPort}\\n`,\n );\n\n return;\n }\n\n await ensureDaemonNotRunning(options);\n await runPipelineHeadless(options, false);\n }\n\n async function runDaemonProcess(options: StartCliOptions): Promise<void> {\n await ensureDaemonNotRunning(options);\n await runPipelineHeadless(options, true);\n }\n\n async function stop(options: CommonCliOptions): Promise<void> {\n const pathOptions = toPathOptions(options);\n\n const pid = await readPid(pathOptions);\n\n if (pid === null) {\n output.stdout('AISnitch daemon is not running.\\n');\n return;\n }\n\n if (!isProcessRunning(pid)) {\n await cleanupStaleDaemonFiles(pathOptions);\n output.stdout('Removed stale AISnitch daemon state.\\n');\n return;\n }\n\n process.kill(pid, 'SIGTERM');\n\n if (!(await waitForProcessExit(pid))) {\n throw new Error(`AISnitch daemon PID ${pid} did not stop in time.`);\n }\n\n await Promise.all([\n removePid(pathOptions),\n removeDaemonState(pathOptions),\n ]);\n\n output.stdout(`AISnitch daemon stopped (PID: ${pid}).\\n`);\n }\n\n async function status(options: CommonCliOptions): Promise<void> {\n const snapshot = await getStatusSnapshot(options);\n const enabledAdapters =\n snapshot.configuredAdapters.length > 0\n ? snapshot.configuredAdapters.join(', ')\n : 'none';\n\n output.stdout(`AISnitch daemon: ${snapshot.running ? 'running' : 'stopped'}\\n`);\n output.stdout(`PID: ${snapshot.daemonPid ?? 'none'}\\n`);\n output.stdout(`WebSocket port: ${snapshot.wsPort}\\n`);\n output.stdout(`HTTP port: ${snapshot.httpPort}\\n`);\n output.stdout(`Socket path: ${snapshot.socketPath ?? 'none'}\\n`);\n output.stdout(`Configured adapters: ${enabledAdapters}\\n`);\n output.stdout(`Daemon log: ${snapshot.logFilePath}\\n`);\n\n if (snapshot.health) {\n output.stdout(`Consumers: ${snapshot.health.consumers}\\n`);\n output.stdout(`Events: ${snapshot.health.events}\\n`);\n output.stdout(`Dropped events: ${snapshot.health.droppedEvents}\\n`);\n output.stdout(`Uptime: ${snapshot.health.uptime}ms\\n`);\n } else {\n output.stdout('Health endpoint: unavailable\\n');\n }\n }\n\n async function adapters(options: CommonCliOptions): Promise<void> {\n const { config } = await loadEffectiveConfig(options);\n const tools = ToolNameSchema.options.filter(\n (toolName): toolName is ToolName => toolName !== 'unknown',\n );\n\n for (const toolName of tools) {\n const enabled = config.adapters[toolName]?.enabled === true;\n\n output.stdout(\n `${toolName}: ${enabled ? 'enabled' : 'disabled'} | runtime=stopped\\n`,\n );\n }\n }\n\n async function attach(options: AttachCliOptions): Promise<void> {\n const snapshot = await getStatusSnapshot(options);\n\n if (!snapshot.running || snapshot.daemonPid === null) {\n throw new Error('AISnitch daemon is not running. Start it with `aisnitch start --daemon` first.');\n }\n\n await renderAttachedTui({\n configuredAdapters: snapshot.configuredAdapters,\n initialFilters: toInitialTuiFilters(options),\n status: {\n consumerCount: (snapshot.health?.consumers ?? 0) + 1,\n eventCount: snapshot.health?.events ?? 0,\n uptimeMs: snapshot.health?.uptime ?? 0,\n },\n wsUrl: `ws://127.0.0.1:${snapshot.wsPort}`,\n });\n }\n\n async function mock(\n selection: MockToolSelection,\n options: MockCliOptions,\n ): Promise<void> {\n const pathOptions = toPathOptions(options);\n const daemonState = await readDaemonState(pathOptions);\n const daemonPid = await readPid(pathOptions);\n const daemonAvailable =\n daemonState !== null &&\n daemonPid !== null &&\n isProcessRunning(daemonPid) &&\n daemonState.socketPath !== null;\n\n if (daemonAvailable) {\n const socketPublisher = await createSocketEventPublisher(\n daemonState.socketPath ?? joinSocketPath(pathOptions),\n );\n\n try {\n output.stdout(\n `Streaming mock scenario ${selection} into the running AISnitch daemon.\\n`,\n );\n\n const result = await runMockScenario({\n durationSeconds: options.duration ?? 60,\n loop: options.loop ?? false,\n publishEvent: async (event) => {\n return await socketPublisher.publish(event);\n },\n selection,\n speed: options.speed ?? 1,\n });\n\n output.stdout(\n `Published ${result.publishedEvents} mock events across ${result.loopCount} loop(s).\\n`,\n );\n } finally {\n await socketPublisher.close();\n }\n\n return;\n }\n\n const { config } = await loadEffectiveConfig(options);\n\n setLoggerLevel(getForegroundSafeLogLevel(config.logLevel, false));\n\n const ephemeralHomeDirectory = await mkdtemp(join(tmpdir(), 'aisnitch-mock-'));\n const ephemeralPipeline = new Pipeline();\n const status = await ephemeralPipeline.start({\n config: {\n ...config,\n adapters: {},\n },\n homeDirectory: ephemeralHomeDirectory,\n ...pathOptions,\n });\n const monitorClose = attachEventBusMonitor(ephemeralPipeline.getEventBus(), {\n stderr: (text) => {\n output.stderr(prefixMonitorText(text));\n },\n stdout: (text) => {\n output.stderr(prefixMonitorText(text));\n },\n });\n\n output.stdout(\n `AISnitch mock started an ephemeral local pipeline on ws://127.0.0.1:${status.wsPort}\\n`,\n );\n\n try {\n const result = await runMockScenario({\n durationSeconds: options.duration ?? 60,\n loop: options.loop ?? false,\n publishEvent: async (event) => {\n return await ephemeralPipeline.publishEvent(event);\n },\n selection,\n speed: options.speed ?? 1,\n });\n\n output.stdout(\n `Published ${result.publishedEvents} mock events across ${result.loopCount} loop(s).\\n`,\n );\n } finally {\n await Promise.resolve(monitorClose());\n await ephemeralPipeline.stop();\n await rm(ephemeralHomeDirectory, { force: true, recursive: true });\n }\n }\n\n async function install(options: CommonCliOptions): Promise<void> {\n if (process.platform !== 'darwin') {\n throw new Error('LaunchAgent install is currently supported on macOS only.');\n }\n\n const daemonPathOptions = toPathOptions(options);\n const launchAgentPath = getLaunchAgentPath(daemonPathOptions);\n const domainTarget = `gui/${getCurrentUid()}`;\n const plistContents = buildLaunchAgentPlist({\n cliEntryPath: resolveCliEntryPath(),\n configPath: options.config,\n logFilePath: getDaemonLogPath(daemonPathOptions),\n nodeExecutablePath: process.execPath,\n });\n\n await ensureConfigDir(daemonPathOptions);\n await ensureLaunchAgentDir(daemonPathOptions);\n\n try {\n await execFileImplementation('launchctl', ['bootout', domainTarget, launchAgentPath]);\n } catch {\n // Ignore bootout errors when the service is not loaded yet.\n }\n\n await writeFile(launchAgentPath, plistContents, 'utf8');\n await execFileImplementation('launchctl', ['bootstrap', domainTarget, launchAgentPath]);\n\n output.stdout(`AISnitch LaunchAgent installed at ${launchAgentPath}\\n`);\n }\n\n async function wrap(\n command: string,\n args: readonly string[],\n options: WrapCliOptions,\n ): Promise<void> {\n const executionCwd = options.cwd ?? process.cwd();\n const pathOptions = toPathOptions(options);\n const daemonState = await readDaemonState(pathOptions);\n const daemonPid = await readPid(pathOptions);\n const daemonAvailable =\n daemonState !== null &&\n daemonPid !== null &&\n isProcessRunning(daemonPid) &&\n daemonState.socketPath !== null;\n let ephemeralPipeline: Pipeline | null = null;\n let ephemeralHomeDirectory: string | null = null;\n let monitorClose: MonitorCloseHandler | null = null;\n let socketPublisher: SocketEventPublisher | null = null;\n let wrappedExitCode!: number;\n\n if (daemonAvailable) {\n socketPublisher = await createSocketEventPublisher(\n daemonState.socketPath ?? joinSocketPath(pathOptions),\n );\n } else {\n const { config } = await loadEffectiveConfig(options);\n\n setLoggerLevel(getForegroundSafeLogLevel(config.logLevel, false));\n ephemeralHomeDirectory = await mkdtemp(join(tmpdir(), 'aisnitch-wrap-'));\n ephemeralPipeline = new Pipeline();\n await ephemeralPipeline.start({\n config: {\n ...config,\n adapters: {},\n },\n homeDirectory: ephemeralHomeDirectory,\n ...pathOptions,\n });\n monitorClose = attachEventBusMonitor(ephemeralPipeline.getEventBus(), {\n stderr: (text) => {\n output.stderr(prefixMonitorText(text));\n },\n stdout: (text) => {\n output.stderr(prefixMonitorText(text));\n },\n });\n\n output.stderr(\n 'AISnitch wrap is using an ephemeral local monitor because no daemon is running.\\n',\n );\n }\n\n try {\n const ptySession = new GenericPTYSession({\n args,\n command,\n cwd: executionCwd,\n env: process.env,\n publishEvent: async (event, context) => {\n if (socketPublisher !== null) {\n return await socketPublisher.publish(event);\n }\n\n if (ephemeralPipeline !== null) {\n return await ephemeralPipeline.publishEvent(event, context);\n }\n\n return false;\n },\n stdin: process.stdin,\n stdout: process.stdout,\n });\n wrappedExitCode = await ptySession.run();\n\n if (wrappedExitCode !== 0) {\n process.exitCode = wrappedExitCode;\n }\n } finally {\n if (monitorClose !== null) {\n await Promise.resolve(monitorClose());\n }\n\n if (socketPublisher !== null) {\n await socketPublisher.close();\n }\n\n if (ephemeralPipeline !== null) {\n await ephemeralPipeline.stop();\n }\n\n if (ephemeralHomeDirectory !== null) {\n await rm(ephemeralHomeDirectory, { force: true, recursive: true });\n }\n }\n\n process.exit(wrappedExitCode);\n }\n\n async function aiderNotify(options: CommonCliOptions): Promise<void> {\n const { config } = await loadEffectiveConfig(options);\n\n try {\n await fetchImplementation(`http://127.0.0.1:${config.httpPort}/hooks/aider`, {\n body: JSON.stringify({\n cwd: process.cwd(),\n data: {\n cwd: process.cwd(),\n raw: {\n argv: process.argv.slice(2),\n source: 'notifications-command',\n },\n },\n pid: process.ppid > 1 ? process.ppid : undefined,\n source: 'aisnitch://adapters/aider/notifications-command',\n transcriptPath: join(process.cwd(), '.aider.chat.history.md'),\n type: 'agent.idle',\n }),\n headers: {\n 'content-type': 'application/json',\n },\n method: 'POST',\n });\n } catch {\n // Aider notifications must stay fire-and-forget, even when AISnitch is offline.\n }\n }\n\n async function uninstall(options: CommonCliOptions): Promise<void> {\n if (process.platform !== 'darwin') {\n throw new Error('LaunchAgent uninstall is currently supported on macOS only.');\n }\n\n const daemonPathOptions = toPathOptions(options);\n const launchAgentPath = getLaunchAgentPath(daemonPathOptions);\n const domainTarget = `gui/${getCurrentUid()}`;\n\n try {\n await execFileImplementation('launchctl', ['bootout', domainTarget, launchAgentPath]);\n } catch {\n // Ignore bootout errors when the agent was not loaded.\n }\n\n await rm(launchAgentPath, { force: true });\n\n output.stdout(`AISnitch LaunchAgent removed from ${launchAgentPath}\\n`);\n }\n\n async function getStatusSnapshot(\n options: CommonCliOptions,\n ): Promise<StatusSnapshot> {\n const { config, pathOptions } = await loadEffectiveConfig(options);\n const daemonState = await readDaemonState(pathOptions);\n const daemonPid = await readPid(pathOptions);\n const running =\n daemonPid !== null &&\n isProcessRunning(daemonPid) &&\n daemonState !== null;\n const health =\n running && daemonState !== null\n ? await fetchHealth(daemonState.httpPort)\n : null;\n\n return {\n configuredAdapters: getEnabledAdapters(config),\n daemonPid,\n health,\n httpPort: daemonState?.httpPort ?? config.httpPort,\n logFilePath: getDaemonLogPath(pathOptions),\n running,\n socketPath: daemonState?.socketPath ?? joinSocketPath(pathOptions),\n wsPort: daemonState?.wsPort ?? config.wsPort,\n };\n }\n\n async function setup(\n toolName: SetupToolName,\n options: SetupCliOptions,\n ): Promise<void> {\n await runSetupCommand(toolName, options, {\n output: output as SetupOutput,\n });\n }\n\n return {\n adapters,\n aiderNotify,\n attach,\n install,\n mock,\n runDaemonProcess,\n setup,\n start,\n status,\n stop,\n uninstall,\n wrap,\n };\n}\n\n/**\n * Parses and validates a port option.\n */\nexport function parsePortOption(rawValue: string): number {\n const parsedPort = Number.parseInt(rawValue, 10);\n\n if (\n !Number.isInteger(parsedPort) ||\n parsedPort < 1024 ||\n parsedPort > 65535\n ) {\n throw new Error(`Invalid port: ${rawValue}`);\n }\n\n return parsedPort;\n}\n\n/**\n * Parses and validates a log level option.\n */\nexport function parseLogLevelOption(\n rawValue: string,\n): AISnitchConfig['logLevel'] {\n if (!LOG_LEVELS.includes(rawValue as AISnitchConfig['logLevel'])) {\n throw new Error(`Invalid log level: ${rawValue}`);\n }\n\n return rawValue as AISnitchConfig['logLevel'];\n}\n\n/**\n * Parses and validates a CLI tool filter.\n */\nexport function parseToolFilterOption(rawValue: string): ToolName {\n const parsedTool = ToolNameSchema.safeParse(rawValue);\n\n if (!parsedTool.success || parsedTool.data === 'unknown') {\n throw new Error(`Invalid tool filter: ${rawValue}`);\n }\n\n return parsedTool.data;\n}\n\n/**\n * Parses and validates a CLI event-type filter.\n */\nexport function parseEventTypeFilterOption(\n rawValue: string,\n): AISnitchEventType {\n const parsedEventType = AISnitchEventTypeSchema.safeParse(rawValue);\n\n if (!parsedEventType.success) {\n throw new Error(`Invalid event type filter: ${rawValue}`);\n }\n\n return parsedEventType.data;\n}\n\n/**\n * Parses and validates the initial TUI body view.\n */\nexport function parseTuiViewModeOption(rawValue: string): TuiViewMode {\n if (\n TUI_VIEW_MODES.includes(rawValue as TuiViewMode)\n ) {\n return rawValue as TuiViewMode;\n }\n\n throw new Error(`Invalid TUI view: ${rawValue}`);\n}\n\n/**\n * Builds the LaunchAgent plist used by `aisnitch install`.\n */\nexport function buildLaunchAgentPlist(\n options: LaunchAgentPlistOptions,\n): string {\n const configArgs =\n options.configPath && options.configPath.length > 0\n ? `<string>--config</string>\\n <string>${escapeXml(options.configPath)}</string>\\n `\n : '';\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${LAUNCH_AGENT_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${escapeXml(options.nodeExecutablePath)}</string>\n <string>${escapeXml(options.cliEntryPath)}</string>\n <string>start</string>\n <string>--daemon</string>\n ${configArgs.trimEnd()}\n </array>\n <key>KeepAlive</key>\n <true/>\n <key>RunAtLoad</key>\n <true/>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n <key>StandardOutPath</key>\n <string>${escapeXml(options.logFilePath)}</string>\n <key>StandardErrorPath</key>\n <string>${escapeXml(options.logFilePath)}</string>\n</dict>\n</plist>\n`;\n}\n\nfunction createProcessOutput(): CliOutput {\n return {\n stderr: (text) => {\n process.stderr.write(text);\n },\n stdout: (text) => {\n process.stdout.write(text);\n },\n };\n}\n\nasync function createSocketEventPublisher(\n socketPath: string,\n): Promise<SocketEventPublisher> {\n const socket = createConnection(socketPath);\n\n await new Promise<void>((resolve, reject) => {\n socket.once('connect', () => {\n resolve();\n });\n socket.once('error', reject);\n });\n\n return {\n close: async () => {\n if (socket.destroyed) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n socket.end(() => {\n resolve();\n });\n });\n },\n publish: async (event) => {\n if (socket.destroyed) {\n return false;\n }\n\n return await new Promise<boolean>((resolve) => {\n socket.write(`${JSON.stringify(event)}\\n`, (error) => {\n resolve(error === undefined || error === null);\n });\n });\n },\n };\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&apos;');\n}\n\nfunction prefixMonitorText(text: string): string {\n return text\n .split('\\n')\n .map((line) => (line.length > 0 ? `[aisnitch] ${line}` : line))\n .join('\\n');\n}\n\nfunction getEnabledAdapters(config: AISnitchConfig): ToolName[] {\n return Object.entries(config.adapters)\n .filter((entry): entry is [ToolName, { enabled: boolean }] => {\n const [toolName, adapterConfig] = entry;\n\n return (\n ToolNameSchema.safeParse(toolName).success &&\n adapterConfig?.enabled === true\n );\n })\n .map(([toolName]) => toolName);\n}\n\nfunction isStartCliOptions(\n options: StartCliOptions | CommonCliOptions,\n): options is StartCliOptions {\n return (\n 'daemon' in options ||\n 'httpPort' in options ||\n 'logLevel' in options ||\n 'wsPort' in options\n );\n}\n\nfunction joinSocketPath(pathOptions: ConfigPathOptions): string {\n return `${getAISnitchHomePath(pathOptions)}/aisnitch.sock`;\n}\n\nfunction resolveCliEntryPath(): string {\n const cliEntryPath = process.argv[1];\n\n if (!cliEntryPath || basename(cliEntryPath).length === 0) {\n throw new Error('Unable to resolve the AISnitch CLI entry path.');\n }\n\n return cliEntryPath;\n}\n\nfunction getForegroundSafeLogLevel(\n configuredLevel: AISnitchConfig['logLevel'],\n daemonMode: boolean,\n): AISnitchConfig['logLevel'] {\n if (daemonMode || configuredLevel !== 'info') {\n return configuredLevel;\n }\n\n /**\n * 📖 The Ink UI is the primary foreground surface now, so the default\n * info-level startup chatter only makes the screen dirtier without helping\n * the operator. Warnings and errors still pass through.\n */\n return 'warn';\n}\n\nfunction getCurrentUid(): number {\n if (typeof process.getuid !== 'function') {\n throw new Error('Unable to resolve the current user id for LaunchAgent installation.');\n }\n\n return process.getuid();\n}\n\nfunction toDaemonArgv(options: StartCliOptions): string[] {\n const args: string[] = [];\n\n if (options.config) {\n args.push('--config', options.config);\n }\n\n if (options.wsPort !== undefined) {\n args.push('--ws-port', String(options.wsPort));\n }\n\n if (options.httpPort !== undefined) {\n args.push('--http-port', String(options.httpPort));\n }\n\n if (options.logLevel !== undefined) {\n args.push('--log-level', options.logLevel);\n }\n\n if (options.mock !== undefined) {\n args.push('--mock', options.mock);\n }\n\n if (options.mockSpeed !== undefined) {\n args.push('--mock-speed', String(options.mockSpeed));\n }\n\n if (options.mockLoop) {\n args.push('--mock-loop');\n }\n\n if (options.mockDuration !== undefined) {\n args.push('--mock-duration', String(options.mockDuration));\n }\n\n return args;\n}\n\nfunction toInitialTuiFilters(\n options: AttachCliOptions,\n): TuiInitialFilters | undefined {\n if (\n options.tool === undefined &&\n options.type === undefined &&\n options.view === undefined\n ) {\n return undefined;\n }\n\n return {\n tool: options.tool,\n type: options.type,\n view: options.view,\n };\n}\n\nfunction toPathOptions(options: CommonCliOptions): ConfigPathOptions {\n return options.config\n ? { configPath: options.config, env: process.env }\n : { env: process.env };\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","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 { 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 { 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 { 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 { 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","/**\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 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","import { constants } from 'node:fs';\nimport { mkdir, readFile, rm, stat, writeFile, access } from 'node:fs/promises';\nimport { createConnection } from 'node:net';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nimport { z } from 'zod';\n\nimport {\n ensureConfigDir,\n getAISnitchHomePath,\n getConfigPath,\n type ConfigPathOptions,\n} from '../core/config/index.js';\n\n/**\n * @file src/cli/pid.ts\n * @description PID, daemon state, and filesystem path helpers for the AISnitch CLI runtime.\n * @functions\n * → getPidFilePath\n * → getDaemonStatePath\n * → getDaemonLogPath\n * → getLaunchAgentPath\n * → writePid\n * → readPid\n * → removePid\n * → writeDaemonState\n * → readDaemonState\n * → removeDaemonState\n * → isProcessRunning\n * → isDaemonRunning\n * → cleanupStaleDaemonFiles\n * @exports DaemonState, DaemonPathOptions, getPidFilePath, getDaemonStatePath, getDaemonLogPath, getLaunchAgentPath, writePid, readPid, removePid, writeDaemonState, readDaemonState, removeDaemonState, isProcessRunning, isDaemonRunning, cleanupStaleDaemonFiles\n * @see ../core/config/loader.ts\n */\n\nconst DaemonStateSchema = z.strictObject({\n pid: z.number().int().positive(),\n wsPort: z.number().int().min(1024).max(65535),\n httpPort: z.number().int().min(1024).max(65535),\n socketPath: z.string().min(1).nullable(),\n startedAt: z.string().min(1),\n configPath: z.string().min(1),\n logFilePath: z.string().min(1),\n});\n\n/**\n * Shared path options used by CLI state files.\n */\nexport interface DaemonPathOptions extends ConfigPathOptions {\n readonly launchAgentHomeDirectory?: string;\n}\n\n/**\n * Serialized daemon runtime metadata persisted next to the PID file.\n */\nexport type DaemonState = z.infer<typeof DaemonStateSchema>;\n\nfunction getDefaultSocketPath(options: DaemonPathOptions): string {\n if (process.platform === 'win32') {\n return '\\\\\\\\.\\\\pipe\\\\aisnitch.sock';\n }\n\n return join(getAISnitchHomePath(options), 'aisnitch.sock');\n}\n\n/**\n * 📖 CLI startup can be reached after crashes or forced exits, so stale UDS\n * paths must be scrubbed before we decide the daemon state is truly clean.\n */\nasync function cleanupSocketPathIfStale(socketPath: string): Promise<boolean> {\n if (process.platform === 'win32') {\n return false;\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 false;\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.end();\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 return false;\n }\n\n await rm(socketPath, { force: true });\n\n return true;\n}\n\n/**\n * 📖 PID and daemon metadata live next to the config by design so overrides via\n * `--config` keep all runtime state inside one predictable directory.\n */\nexport function getPidFilePath(options: DaemonPathOptions = {}): string {\n return join(getAISnitchHomePath(options), 'aisnitch.pid');\n}\n\n/**\n * Returns the daemon metadata JSON path.\n */\nexport function getDaemonStatePath(options: DaemonPathOptions = {}): string {\n return join(getAISnitchHomePath(options), 'daemon-state.json');\n}\n\n/**\n * Returns the rotating daemon log path.\n */\nexport function getDaemonLogPath(options: DaemonPathOptions = {}): string {\n return join(getAISnitchHomePath(options), 'daemon.log');\n}\n\n/**\n * Returns the per-user LaunchAgent plist path.\n */\nexport function getLaunchAgentPath(options: DaemonPathOptions = {}): string {\n return join(\n options.launchAgentHomeDirectory ?? homedir(),\n 'Library',\n 'LaunchAgents',\n 'com.aisnitch.daemon.plist',\n );\n}\n\n/**\n * Persists the daemon PID.\n */\nexport async function writePid(\n pid: number,\n options: DaemonPathOptions = {},\n): Promise<string> {\n await ensureConfigDir(options);\n\n const pidFilePath = getPidFilePath(options);\n await writeFile(pidFilePath, `${pid}\\n`, 'utf8');\n\n return pidFilePath;\n}\n\n/**\n * Reads the daemon PID if present.\n */\nexport async function readPid(\n options: DaemonPathOptions = {},\n): Promise<number | null> {\n try {\n const rawPid = await readFile(getPidFilePath(options), 'utf8');\n const parsedPid = Number.parseInt(rawPid.trim(), 10);\n\n if (!Number.isInteger(parsedPid) || parsedPid <= 0) {\n throw new Error('Invalid PID file contents.');\n }\n\n return parsedPid;\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\n/**\n * Removes the PID file if it exists.\n */\nexport async function removePid(\n options: DaemonPathOptions = {},\n): Promise<void> {\n await rm(getPidFilePath(options), { force: true });\n}\n\n/**\n * Persists daemon runtime metadata after a successful startup.\n */\nexport async function writeDaemonState(\n state: DaemonState,\n options: DaemonPathOptions = {},\n): Promise<string> {\n await ensureConfigDir(options);\n\n const daemonStatePath = getDaemonStatePath(options);\n const validatedState = DaemonStateSchema.parse(state);\n\n await writeFile(\n daemonStatePath,\n `${JSON.stringify(validatedState, null, 2)}\\n`,\n 'utf8',\n );\n\n return daemonStatePath;\n}\n\n/**\n * Reads the daemon metadata JSON if present.\n */\nexport async function readDaemonState(\n options: DaemonPathOptions = {},\n): Promise<DaemonState | null> {\n try {\n const rawJson = await readFile(getDaemonStatePath(options), 'utf8');\n const parsedJson: unknown = JSON.parse(rawJson);\n\n return DaemonStateSchema.parse(parsedJson);\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\n/**\n * Removes the daemon metadata file if it exists.\n */\nexport async function removeDaemonState(\n options: DaemonPathOptions = {},\n): Promise<void> {\n await rm(getDaemonStatePath(options), { force: true });\n}\n\n/**\n * Returns whether the PID currently exists for the same user.\n */\nexport function isProcessRunning(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\n/**\n * Returns whether the persisted daemon PID still points to a live process.\n */\nexport async function isDaemonRunning(\n options: DaemonPathOptions = {},\n): Promise<boolean> {\n const pid = await readPid(options);\n\n return pid !== null && isProcessRunning(pid);\n}\n\n/**\n * Removes stale PID and daemon metadata when the recorded process no longer exists.\n */\nexport async function cleanupStaleDaemonFiles(\n options: DaemonPathOptions = {},\n): Promise<boolean> {\n const pid = await readPid(options);\n const daemonState = await readDaemonState(options);\n const socketPath = daemonState?.socketPath ?? getDefaultSocketPath(options);\n\n if (pid === null) {\n return await cleanupSocketPathIfStale(socketPath);\n }\n\n if (isProcessRunning(pid)) {\n return false;\n }\n\n await cleanupSocketPathIfStale(socketPath);\n\n await Promise.all([\n removePid(options),\n removeDaemonState(options),\n ]);\n\n return true;\n}\n\n/**\n * Ensures the parent directory of the LaunchAgent plist exists.\n */\nexport async function ensureLaunchAgentDir(\n options: DaemonPathOptions = {},\n): Promise<string> {\n const launchAgentPath = getLaunchAgentPath(options);\n const directoryPath = dirname(launchAgentPath);\n\n await mkdir(directoryPath, { recursive: true });\n\n return directoryPath;\n}\n\n/**\n * Checks whether the daemon log file already exceeds the rotation threshold.\n */\nexport async function getDaemonLogSize(\n options: DaemonPathOptions = {},\n): Promise<number> {\n try {\n const logStats = await stat(getDaemonLogPath(options));\n\n return logStats.size;\n } catch (error: unknown) {\n if (\n error instanceof Error &&\n 'code' in error &&\n error.code === 'ENOENT'\n ) {\n return 0;\n }\n\n throw error;\n }\n}\n\n/**\n * Returns the effective config path used by the CLI runtime.\n */\nexport function getEffectiveCliConfigPath(\n options: DaemonPathOptions = {},\n): string {\n return getConfigPath(options);\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["import_commander","isUuid","uuidVersion","uuidv7","resolve","import_promises","import_node_os","import_node_path","import_zod","execFileCallback","JSON5","import_node_child_process","import_node_fs","import_promises","import_node_net","import_node_os","import_node_path","import_node_util","import_node_path","import_node_child_process","import_node_path","import_node_util","pino","execFile","execFileCallback","pidCwd","import_node_path","spawnPty","resolve","stripAnsi","resolve","import_node_events","resolve","import_promises","import_node_fs","import_node_net","import_node_events","resolve","import_node_path","import_zod","import_node_child_process","import_promises","import_node_path","import_node_util","import_pid_cwd","import_node_os","import_zod","execFile","execFileCallback","pidCwd","escapeForRegExp","import_node_child_process","import_promises","import_node_path","import_node_util","import_chokidar","execFile","execFileCallback","isRecord","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_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","import_jsx_runtime","WebSocket","import_node_fs","import_promises","import_node_net","import_node_os","import_node_path","import_zod","resolve","execFile","execFileCallback","spawnChildProcess","resolve","status"]}