@rulemetric/cli 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-5ZOLDIZQ.js → chunk-BCIUSUEV.js} +5 -5
- package/dist/{chunk-LJ5OT5XN.js → chunk-CROYS75W.js} +4 -4
- package/dist/{chunk-AOIY5RT6.js → chunk-CXWY5XKD.js} +15 -15
- package/dist/{chunk-K3BFZ7KG.js → chunk-E3BIT53W.js} +1 -1
- package/dist/chunk-E3BIT53W.js.map +7 -0
- package/dist/{chunk-46LMTDRE.js → chunk-ER5DPPHB.js} +2 -2
- package/dist/{chunk-4QGATD5Y.js → chunk-F5N6CLJJ.js} +1 -1
- package/dist/{chunk-4QGATD5Y.js.map → chunk-F5N6CLJJ.js.map} +2 -2
- package/dist/{chunk-7XDWLJJP.js → chunk-H3C6EGR2.js} +5 -5
- package/dist/{chunk-IVOCDHWA.js → chunk-IPOO4IGF.js} +3 -3
- package/dist/{chunk-YQFCUKNI.js → chunk-QNSVCSHG.js} +373 -414
- package/dist/chunk-QNSVCSHG.js.map +7 -0
- package/dist/{chunk-PHIAFGQ2.js → chunk-T76YQCKX.js} +6 -6
- package/dist/{chunk-IKEI4KNV.js → chunk-VCG4Q53B.js} +3 -3
- package/dist/{chunk-DUR54APY.js → chunk-WLFX4PYR.js} +6 -6
- package/dist/{chunk-FUS5C4SB.js → chunk-Y4BJXXYV.js} +2 -2
- package/dist/commands/auth/create-key.js +3 -1
- package/dist/commands/auth/create-key.js.map +2 -2
- package/dist/commands/evals/agent.js +18 -21
- package/dist/commands/evals/agent.js.map +4 -4
- package/dist/commands/research/backfill.js +3 -3
- package/dist/commands/research/tail-transcript.js +3 -3
- package/dist/commands/service/install.js +5 -0
- package/dist/commands/service/install.js.map +2 -2
- package/dist/dashboard/Dashboard.js +13 -13
- package/dist/dashboard/data.js +2 -2
- package/dist/dashboard/launcher/LauncherOverlay.js +3 -3
- package/dist/{dist-NEECHU47.js → dist-UNYP5PJR.js} +2 -2
- package/dist/lib/agent-loop.js +14 -14
- package/dist/lib/handlers/cron-suggest-instructions.js +3 -3
- package/dist/lib/handlers/process-announcement.js +3 -3
- package/dist/lib/handlers/process-changelog.js +3 -3
- package/dist/lib/handlers/process-launch.js +3 -3
- package/dist/lib/handlers/process-run-cleanup.js +4 -4
- package/dist/lib/handlers/process-session-goal.js +2 -2
- package/dist/lib/manual-tasks.js +6 -6
- package/dist/lib/worktree.js +2 -2
- package/oclif.manifest.json +1 -40
- package/package.json +7 -7
- package/dist/chunk-K3BFZ7KG.js.map +0 -7
- package/dist/chunk-YQFCUKNI.js.map +0 -7
- package/dist/commands/signals/report.js +0 -43
- package/dist/commands/signals/report.js.map +0 -7
- package/dist/lib/handlers/cron-close-stale-sessions.js +0 -19
- package/dist/lib/handlers/cron-close-stale-sessions.js.map +0 -7
- package/dist/lib/handlers/cron-data-integrity-audit.js +0 -22
- package/dist/lib/handlers/cron-data-integrity-audit.js.map +0 -7
- package/dist/lib/provider-aggregator.js +0 -59
- package/dist/lib/provider-aggregator.js.map +0 -7
- /package/dist/{chunk-5ZOLDIZQ.js.map → chunk-BCIUSUEV.js.map} +0 -0
- /package/dist/{chunk-LJ5OT5XN.js.map → chunk-CROYS75W.js.map} +0 -0
- /package/dist/{chunk-AOIY5RT6.js.map → chunk-CXWY5XKD.js.map} +0 -0
- /package/dist/{chunk-46LMTDRE.js.map → chunk-ER5DPPHB.js.map} +0 -0
- /package/dist/{chunk-7XDWLJJP.js.map → chunk-H3C6EGR2.js.map} +0 -0
- /package/dist/{chunk-IVOCDHWA.js.map → chunk-IPOO4IGF.js.map} +0 -0
- /package/dist/{chunk-PHIAFGQ2.js.map → chunk-T76YQCKX.js.map} +0 -0
- /package/dist/{chunk-IKEI4KNV.js.map → chunk-VCG4Q53B.js.map} +0 -0
- /package/dist/{chunk-DUR54APY.js.map → chunk-WLFX4PYR.js.map} +0 -0
- /package/dist/{chunk-FUS5C4SB.js.map → chunk-Y4BJXXYV.js.map} +0 -0
- /package/dist/{dist-NEECHU47.js.map → dist-UNYP5PJR.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../packages/session/src/types.ts", "../../../packages/session/src/adapters/claude-code.ts", "../../../packages/session/src/adapters/cursor.ts", "../../../packages/session/src/adapters/vscode-copilot.ts", "../../../packages/session/src/adapters/copilot-agent.ts", "../../../packages/session/src/adapters/rulemetric-mcp.ts", "../../../packages/session/src/adapters/codex.ts", "../../../packages/session/src/registry.ts", "../../../packages/session/src/analyzer.ts", "../../../packages/session/src/providers/claude-code.ts", "../../../packages/session/src/providers/codex.ts", "../../../packages/session/src/providers/copilot.ts", "../../../packages/session/src/providers/pi.ts", "../../../packages/session/src/providers/index.ts", "../../../packages/session/src/launchers/claude-code.ts", "../../../packages/session/src/terminal/tmux.ts", "../../../packages/session/src/launchers/codex.ts", "../../../packages/session/src/launchers/aider.ts", "../../../packages/session/src/launchers/generic.ts", "../../../packages/session/src/launchers/index.ts", "../../../packages/session/src/launchers/worktree-path.ts"],
|
|
4
|
-
"sourcesContent": ["export const SESSION_TOOLS = ['claude_code', 'cursor', 'vscode_copilot', 'copilot_agent', 'rulemetric_mcp', 'codex', 'pi', 'opencode', 'antigravity'] as const;\nexport type SessionTool = (typeof SESSION_TOOLS)[number];\n\nexport const SESSION_EVENT_TYPES = [\n 'user_message',\n 'assistant_message',\n 'tool_call',\n 'tool_result',\n 'thinking',\n 'error',\n] as const;\nexport type SessionEventType = (typeof SESSION_EVENT_TYPES)[number];\n\nexport interface TokenUsage {\n input: number;\n output: number;\n cacheRead?: number;\n cacheWrite?: number;\n}\n\nexport interface SessionEvent {\n sequence: number;\n eventType: SessionEventType;\n content: string | null;\n toolName: string | null;\n toolInput: Record<string, unknown> | null;\n toolOutput: Record<string, unknown> | null;\n tokenUsage: TokenUsage | null;\n timestamp: string;\n metadata: Record<string, unknown>;\n // Optional model attribution per event (set by the codex adapter from\n // session_meta/turn_context; carried across incremental appends).\n model?: string | null;\n}\n\nexport interface ParsedSession {\n tool: SessionTool;\n projectPath: string | null;\n gitBranch: string | null;\n startedAt: string;\n endedAt: string | null;\n events: SessionEvent[];\n metadata: Record<string, unknown>;\n}\n\nexport interface SessionAdapter {\n tool: SessionTool;\n parse(input: string): ParsedSession;\n}\n\nexport interface Deviation {\n eventSequence: number;\n instructionId: string;\n description: string;\n severity: 'low' | 'medium' | 'high';\n}\n\nexport interface InstructionSuggestion {\n instructionId: string;\n currentContent: string;\n suggestedContent: string;\n rationale: string;\n confidence: number;\n}\n\nexport interface SessionAnalysis {\n adherenceScore: number;\n deviations: Deviation[];\n suggestions: InstructionSuggestion[];\n summary: string;\n analyzedAt: string;\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface ClaudeCodeRecord {\n type: string;\n uuid?: string;\n parentUuid?: string | null;\n sessionId?: string;\n requestId?: string;\n timestamp?: string;\n cwd?: string;\n gitBranch?: string;\n version?: string;\n userType?: string;\n slug?: string;\n message?: {\n role: string;\n model?: string;\n stop_reason?: string;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n service_tier?: string;\n speed?: string;\n inference_geo?: string;\n server_tool_use?: Record<string, number>;\n cache_creation?: Record<string, number>;\n };\n content: string | Array<{ type: string; text?: string; thinking?: string; id?: string; name?: string; input?: Record<string, unknown>; tool_use_id?: string; content?: string }>;\n };\n toolUseMessages?: unknown[];\n}\n\nexport class ClaudeCodeAdapter implements SessionAdapter {\n tool = 'claude_code' as const;\n\n parse(input: string): ParsedSession {\n const lines = input.split('\\n').filter((line) => line.trim());\n const records: ClaudeCodeRecord[] = [];\n\n for (const line of lines) {\n try {\n records.push(JSON.parse(line) as ClaudeCodeRecord);\n } catch {\n // Skip malformed lines\n }\n }\n\n const messageRecords = records.filter(\n (r) => r.type === 'user' || r.type === 'assistant',\n );\n\n let projectPath: string | null = null;\n let gitBranch: string | null = null;\n const metadata: Record<string, unknown> = {};\n\n // Extract project info from first user message\n const firstUser = records.find((r) => r.type === 'user');\n if (firstUser) {\n projectPath = firstUser.cwd ?? null;\n gitBranch = firstUser.gitBranch ?? null;\n if (firstUser.version) metadata.claudeCodeVersion = firstUser.version;\n if (firstUser.sessionId) metadata.sessionId = firstUser.sessionId;\n }\n\n // Extract model from first assistant message\n const firstAssistant = records.find((r) => r.type === 'assistant');\n if (firstAssistant?.message?.model) metadata.model = firstAssistant.message.model;\n\n const events: SessionEvent[] = [];\n let sequence = 0;\n\n for (const record of messageRecords) {\n const timestamp = record.timestamp ?? new Date().toISOString();\n\n if (record.type === 'user') {\n const messageContent = record.message?.content;\n\n if (typeof messageContent === 'string') {\n events.push({\n sequence: sequence++,\n eventType: 'user_message',\n content: messageContent,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: {},\n });\n } else if (Array.isArray(messageContent)) {\n for (const block of messageContent) {\n if (block.type === 'tool_result') {\n events.push({\n sequence: sequence++,\n eventType: 'tool_result',\n content: typeof block.content === 'string' ? block.content : JSON.stringify(block.content),\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: { toolUseId: block.tool_use_id },\n });\n }\n }\n }\n } else if (record.type === 'assistant') {\n const contentBlocks = Array.isArray(record.message?.content)\n ? record.message.content\n : [];\n\n // Extract token usage from the API response\n const usage = record.message?.usage;\n const tokenUsage = usage\n ? {\n input: usage.input_tokens ?? 0,\n output: usage.output_tokens ?? 0,\n cacheRead: usage.cache_read_input_tokens ?? 0,\n cacheWrite: usage.cache_creation_input_tokens ?? 0,\n }\n : null;\n\n // Build metadata with model info and extra usage details\n const assistantMeta: Record<string, unknown> = {};\n if (record.message?.model) assistantMeta.model = record.message.model;\n if (record.message?.stop_reason) assistantMeta.stopReason = record.message.stop_reason;\n if (record.requestId) assistantMeta.requestId = record.requestId;\n if (usage?.service_tier) assistantMeta.serviceTier = usage.service_tier;\n if (usage?.speed) assistantMeta.speed = usage.speed;\n if (usage?.cache_creation) assistantMeta.cacheCreationDetail = usage.cache_creation;\n if (usage?.server_tool_use) assistantMeta.serverToolUse = usage.server_tool_use;\n\n for (const block of contentBlocks) {\n if (block.type === 'text') {\n events.push({\n sequence: sequence++,\n eventType: 'assistant_message',\n content: block.text ?? '',\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage,\n timestamp,\n metadata: assistantMeta,\n });\n } else if (block.type === 'thinking') {\n events.push({\n sequence: sequence++,\n eventType: 'thinking',\n content: block.thinking ?? '',\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage,\n timestamp,\n metadata: assistantMeta,\n });\n } else if (block.type === 'tool_use') {\n events.push({\n sequence: sequence++,\n eventType: 'tool_call',\n content: null,\n toolName: block.name ?? 'unknown',\n toolInput: block.input ?? null,\n toolOutput: null,\n tokenUsage,\n timestamp,\n metadata: { ...assistantMeta, toolUseId: block.id },\n });\n }\n }\n }\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'claude_code',\n projectPath,\n gitBranch,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata,\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface CursorBubble {\n type: number; // 1 = user, 2 = assistant\n text: string;\n createdAt?: string;\n}\n\ninterface CursorComposer {\n composerId: string;\n conversationId?: string;\n createdAt?: string;\n conversation?: CursorBubble[];\n}\n\ninterface CursorComposerData {\n allComposers: Record<string, CursorComposer>;\n}\n\nexport class CursorAdapter implements SessionAdapter {\n tool = 'cursor' as const;\n\n /**\n * Parse from a SQLite database file path.\n * Reads `composer.composerData` from the ItemTable.\n */\n parse(dbPath: string): ParsedSession {\n // Dynamic import to avoid bundling better-sqlite3 when not needed\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const Database = require('better-sqlite3');\n const db = new Database(dbPath, { readonly: true });\n\n try {\n const row = db.prepare(\n \"SELECT value FROM ItemTable WHERE key = 'composer.composerData'\",\n ).get() as { value: string } | undefined;\n\n if (!row) {\n return this.emptySession();\n }\n\n return this.parseComposerJson(row.value);\n } finally {\n db.close();\n }\n }\n\n /**\n * Parse from raw composer data JSON (for testing without SQLite).\n */\n parseComposerJson(json: string): ParsedSession {\n let data: CursorComposerData;\n try {\n data = JSON.parse(json) as CursorComposerData;\n } catch {\n return this.emptySession();\n }\n\n const composers = Object.values(data.allComposers ?? {});\n if (composers.length === 0) {\n return this.emptySession();\n }\n\n // Take the most recent composer conversation\n const composer = composers.sort((a, b) => {\n const aTime = a.createdAt ? new Date(a.createdAt).getTime() : 0;\n const bTime = b.createdAt ? new Date(b.createdAt).getTime() : 0;\n return bTime - aTime;\n })[0];\n\n const bubbles = composer.conversation ?? [];\n const events: SessionEvent[] = [];\n\n for (let i = 0; i < bubbles.length; i++) {\n const bubble = bubbles[i];\n const timestamp = bubble.createdAt ?? new Date().toISOString();\n\n events.push({\n sequence: i,\n eventType: bubble.type === 1 ? 'user_message' : 'assistant_message',\n content: bubble.text,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: {},\n });\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'cursor',\n projectPath: null,\n gitBranch: null,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata: { composerId: composer.composerId },\n };\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'cursor',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface CopilotRequest {\n message: string;\n timestamp?: number;\n response?: {\n message: string;\n timestamp?: number;\n };\n}\n\ninterface CopilotSession {\n requesterUsername?: string;\n requests?: CopilotRequest[];\n customTitle?: string;\n}\n\nexport class VSCodeCopilotAdapter implements SessionAdapter {\n tool = 'vscode_copilot' as const;\n\n parse(input: string): ParsedSession {\n let data: CopilotSession;\n try {\n data = JSON.parse(input) as CopilotSession;\n } catch {\n return this.emptySession();\n }\n\n const requests = data.requests ?? [];\n const events: SessionEvent[] = [];\n let sequence = 0;\n\n for (const req of requests) {\n const userTimestamp = req.timestamp\n ? new Date(req.timestamp).toISOString()\n : new Date().toISOString();\n\n events.push({\n sequence: sequence++,\n eventType: 'user_message',\n content: req.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: userTimestamp,\n metadata: {},\n });\n\n if (req.response) {\n const assistantTimestamp = req.response.timestamp\n ? new Date(req.response.timestamp).toISOString()\n : userTimestamp;\n\n events.push({\n sequence: sequence++,\n eventType: 'assistant_message',\n content: req.response.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: assistantTimestamp,\n metadata: {},\n });\n }\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'vscode_copilot',\n projectPath: null,\n gitBranch: null,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata: {\n ...(data.requesterUsername && { username: data.requesterUsername }),\n ...(data.customTitle && { title: data.customTitle }),\n },\n };\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'vscode_copilot',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface CopilotAgentToolCall {\n name?: string;\n input?: Record<string, unknown>;\n output?: Record<string, unknown>;\n timestamp?: number;\n}\n\ninterface CopilotAgentRequest {\n message: string;\n timestamp?: number;\n agentMode?: boolean;\n toolCalls?: CopilotAgentToolCall[];\n response?: {\n message: string;\n timestamp?: number;\n };\n}\n\ninterface CopilotAgentSession {\n requesterUsername?: string;\n requests?: CopilotAgentRequest[];\n customTitle?: string;\n agentMode?: boolean;\n}\n\nexport class CopilotAgentAdapter implements SessionAdapter {\n tool = 'copilot_agent' as const;\n\n parse(input: string): ParsedSession {\n let data: CopilotAgentSession;\n try {\n data = JSON.parse(input) as CopilotAgentSession;\n } catch {\n return this.emptySession();\n }\n\n const requests = data.requests ?? [];\n const events: SessionEvent[] = [];\n let sequence = 0;\n\n for (const req of requests) {\n const userTimestamp = req.timestamp\n ? new Date(req.timestamp).toISOString()\n : new Date().toISOString();\n\n events.push({\n sequence: sequence++,\n eventType: 'user_message',\n content: req.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: userTimestamp,\n metadata: {},\n });\n\n // Emit tool_call events for each tool call\n if (req.toolCalls) {\n for (const tc of req.toolCalls) {\n const toolTimestamp = tc.timestamp\n ? new Date(tc.timestamp).toISOString()\n : userTimestamp;\n\n events.push({\n sequence: sequence++,\n eventType: 'tool_call',\n content: null,\n toolName: tc.name ?? 'unknown',\n toolInput: tc.input ?? null,\n toolOutput: tc.output ?? null,\n tokenUsage: null,\n timestamp: toolTimestamp,\n metadata: {},\n });\n }\n }\n\n if (req.response) {\n const assistantTimestamp = req.response.timestamp\n ? new Date(req.response.timestamp).toISOString()\n : userTimestamp;\n\n events.push({\n sequence: sequence++,\n eventType: 'assistant_message',\n content: req.response.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: assistantTimestamp,\n metadata: {},\n });\n }\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'copilot_agent',\n projectPath: null,\n gitBranch: null,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata: {\n ...(data.requesterUsername && { username: data.requesterUsername }),\n ...(data.customTitle && { title: data.customTitle }),\n ...(data.agentMode != null && { agentMode: data.agentMode }),\n },\n };\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'copilot_agent',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface RuleMetricMcpEvent {\n sequence?: number;\n eventType?: string;\n content?: string | null;\n toolName?: string | null;\n toolInput?: Record<string, unknown> | null;\n toolOutput?: Record<string, unknown> | null;\n tokenUsage?: { input: number; output: number; cacheRead?: number; cacheWrite?: number } | null;\n timestamp?: string;\n metadata?: Record<string, unknown>;\n}\n\ninterface RuleMetricMcpSession {\n events?: RuleMetricMcpEvent[];\n projectPath?: string;\n gitBranch?: string;\n startedAt?: string;\n endedAt?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport class RuleMetricMcpAdapter implements SessionAdapter {\n tool = 'rulemetric_mcp' as const;\n\n parse(input: string): ParsedSession {\n let data: RuleMetricMcpSession;\n try {\n data = JSON.parse(input) as RuleMetricMcpSession;\n } catch {\n return this.emptySession();\n }\n\n const rawEvents = data.events ?? [];\n const events: SessionEvent[] = rawEvents.map((e, i) => ({\n sequence: e.sequence ?? i,\n eventType: this.normalizeEventType(e.eventType),\n content: e.content ?? null,\n toolName: e.toolName ?? null,\n toolInput: e.toolInput ?? null,\n toolOutput: e.toolOutput ?? null,\n tokenUsage: e.tokenUsage ?? null,\n timestamp: e.timestamp ?? new Date().toISOString(),\n metadata: e.metadata ?? {},\n }));\n\n const now = new Date().toISOString();\n\n return {\n tool: 'rulemetric_mcp',\n projectPath: data.projectPath ?? null,\n gitBranch: data.gitBranch ?? null,\n startedAt: data.startedAt ?? events[0]?.timestamp ?? now,\n endedAt: data.endedAt ?? events[events.length - 1]?.timestamp ?? null,\n events,\n metadata: data.metadata ?? {},\n };\n }\n\n private normalizeEventType(type?: string): SessionEvent['eventType'] {\n const valid = ['user_message', 'assistant_message', 'tool_call', 'tool_result', 'thinking', 'error'];\n if (type && valid.includes(type)) return type as SessionEvent['eventType'];\n return 'assistant_message';\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'rulemetric_mcp',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { ParsedSession, SessionAdapter, SessionEvent, TokenUsage } from '../types.js';\n\ninterface CodexContentBlock {\n type?: string;\n text?: string;\n}\n\ninterface CodexTokenUsage {\n input_tokens?: number;\n cached_input_tokens?: number;\n output_tokens?: number;\n reasoning_output_tokens?: number;\n total_tokens?: number;\n}\n\ninterface CodexEntry {\n timestamp?: string;\n type?: string;\n payload?: {\n type?: string;\n role?: string;\n cwd?: string;\n git_branch?: string;\n session_id?: string;\n id?: string;\n originator?: string;\n cli_version?: string;\n source?: string;\n model?: string;\n model_provider?: string;\n name?: string;\n call_id?: string;\n arguments?: string;\n output?: string;\n content?: CodexContentBlock[];\n info?: {\n model?: string;\n model_name?: string;\n last_token_usage?: CodexTokenUsage;\n total_token_usage?: CodexTokenUsage;\n };\n };\n}\n\nfunction safeJsonParse(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction textFromBlocks(blocks: CodexContentBlock[] | undefined, wanted: string[]): string {\n if (!Array.isArray(blocks)) return '';\n return blocks\n .filter((b) => b.type && wanted.includes(b.type))\n .map((b) => b.text ?? '')\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction tokenUsageFromCodex(raw: CodexTokenUsage | undefined): TokenUsage | null {\n if (!raw) return null;\n const cacheRead = raw.cached_input_tokens ?? 0;\n const input = Math.max(0, (raw.input_tokens ?? 0) - cacheRead);\n const output = (raw.output_tokens ?? 0) + (raw.reasoning_output_tokens ?? 0);\n if (input === 0 && output === 0 && cacheRead === 0) return null;\n return { input, output, cacheRead, cacheWrite: 0 };\n}\n\nfunction normalizeTimestamp(ts: string | undefined): string {\n if (!ts) return new Date().toISOString();\n const d = new Date(ts);\n return Number.isFinite(d.getTime()) ? d.toISOString() : new Date().toISOString();\n}\n\n/**\n * Resumable parser state. Carried across incremental (`parseAppend`) calls so a\n * tail-only parse produces byte-identical events to a single full parse:\n * - `sequence` \u2014 absolute event index; continues across appends.\n * - `model` \u2014 last seen model (set by session_meta/turn_context near\n * the file head); later events inherit it.\n * - `prevCumulativeTotal` \u2014 token_count dedup watermark (skip unchanged totals).\n * - `callNames` \u2014 call_id \u2192 tool name, so a tool_result whose tool_call\n * landed in an earlier append still resolves its name.\n * Plain JSON (callNames is a Record, not a Map) so the server can persist it in\n * `session.metadata` between appends.\n */\nexport interface CodexParseState {\n sequence: number;\n model: string | null;\n prevCumulativeTotal: number;\n callNames: Record<string, string>;\n}\n\nexport function freshCodexState(): CodexParseState {\n return { sequence: 0, model: null, prevCumulativeTotal: 0, callNames: {} };\n}\n\nexport class CodexAdapter implements SessionAdapter {\n tool = 'codex' as const;\n\n parse(input: string): ParsedSession {\n const state = freshCodexState();\n const { events, projectPath, gitBranch, metadata } = this.parseLines(input, state);\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n return {\n tool: 'codex',\n projectPath,\n gitBranch,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata,\n };\n }\n\n /**\n * Incrementally parse a tail of new JSONL lines, resuming from `prior` state.\n * Returns the new events (sequences continue from prior.sequence) and the\n * updated state to carry into the next append. `prior` is not mutated.\n */\n parseAppend(input: string, prior: CodexParseState): { events: SessionEvent[]; state: CodexParseState } {\n const state: CodexParseState = { ...prior, callNames: { ...prior.callNames } };\n const { events } = this.parseLines(input, state);\n return { events, state };\n }\n\n private parseLines(\n input: string,\n state: CodexParseState,\n ): {\n events: SessionEvent[];\n projectPath: string | null;\n gitBranch: string | null;\n sessionId: string | null;\n metadata: Record<string, unknown>;\n } {\n const lines = input.split('\\n').filter((line) => line.trim());\n const events: SessionEvent[] = [];\n const metadata: Record<string, unknown> = {};\n const callNames = state.callNames;\n let projectPath: string | null = null;\n let gitBranch: string | null = null;\n let sessionId: string | null = null;\n\n for (const line of lines) {\n let entry: CodexEntry;\n try {\n entry = JSON.parse(line) as CodexEntry;\n } catch {\n continue;\n }\n\n const payload = entry.payload;\n if (!payload) continue;\n const timestamp = normalizeTimestamp(entry.timestamp);\n\n if (entry.type === 'session_meta') {\n sessionId = payload.session_id ?? payload.id ?? sessionId;\n projectPath = payload.cwd ?? projectPath;\n if (payload.git_branch) gitBranch = payload.git_branch;\n if (payload.model) state.model = payload.model;\n metadata.sessionId = sessionId;\n metadata.codexSessionId = sessionId;\n metadata.originator = payload.originator;\n metadata.source = payload.source;\n metadata.modelProvider = payload.model_provider;\n metadata.codexCliVersion = payload.cli_version;\n continue;\n }\n\n if (entry.type === 'turn_context') {\n projectPath = payload.cwd ?? projectPath;\n if (payload.model) {\n state.model = payload.model;\n metadata.model = payload.model;\n }\n continue;\n }\n\n if (entry.type === 'response_item' && payload.type === 'message') {\n if (payload.role === 'user') {\n const content = textFromBlocks(payload.content, ['input_text']);\n if (!content) continue;\n events.push({\n sequence: state.sequence++,\n eventType: 'user_message',\n content,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: {},\n });\n } else if (payload.role === 'assistant') {\n const content = textFromBlocks(payload.content, ['output_text']);\n if (!content) continue;\n events.push({\n sequence: state.sequence++,\n eventType: 'assistant_message',\n content,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n model: state.model,\n timestamp,\n metadata: state.model ? { model: state.model } : {},\n });\n }\n continue;\n }\n\n if (entry.type === 'response_item' && payload.type === 'function_call') {\n const toolName = payload.name ?? 'unknown';\n if (payload.call_id) callNames[payload.call_id] = toolName;\n const args = typeof payload.arguments === 'string' ? safeJsonParse(payload.arguments) : {};\n events.push({\n sequence: state.sequence++,\n eventType: 'tool_call',\n content: null,\n toolName,\n toolInput: args && typeof args === 'object' && !Array.isArray(args) ? args as Record<string, unknown> : { arguments: args },\n toolOutput: null,\n tokenUsage: null,\n model: state.model,\n timestamp,\n metadata: { callId: payload.call_id },\n });\n continue;\n }\n\n if (entry.type === 'response_item' && payload.type === 'function_call_output') {\n const toolName = payload.call_id ? callNames[payload.call_id] ?? null : null;\n events.push({\n sequence: state.sequence++,\n eventType: 'tool_result',\n content: payload.output ?? null,\n toolName,\n toolInput: null,\n toolOutput: payload.output == null ? null : { output: payload.output },\n tokenUsage: null,\n model: state.model,\n timestamp,\n metadata: { callId: payload.call_id },\n });\n continue;\n }\n\n if (entry.type === 'event_msg' && payload.type === 'token_count') {\n const info = payload.info;\n const cumulativeTotal = info?.total_token_usage?.total_tokens ?? 0;\n if (cumulativeTotal > 0 && cumulativeTotal === state.prevCumulativeTotal) continue;\n if (cumulativeTotal > 0) state.prevCumulativeTotal = cumulativeTotal;\n const usage = tokenUsageFromCodex(info?.last_token_usage ?? info?.total_token_usage);\n if (!usage) continue;\n const eventModel = info?.model ?? info?.model_name ?? state.model;\n events.push({\n sequence: state.sequence++,\n eventType: 'assistant_message',\n content: null,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: usage,\n model: eventModel ?? null,\n timestamp,\n metadata: {\n codexEventType: 'token_count',\n ...(eventModel ? { model: eventModel } : {}),\n reasoningOutputTokens: info?.last_token_usage?.reasoning_output_tokens ?? 0,\n },\n });\n }\n }\n\n return { events, projectPath, gitBranch, sessionId, metadata };\n }\n}\n", "import type { SessionAdapter, SessionTool } from './types.js';\nimport { ClaudeCodeAdapter } from './adapters/claude-code.js';\nimport { CursorAdapter } from './adapters/cursor.js';\nimport { VSCodeCopilotAdapter } from './adapters/vscode-copilot.js';\nimport { CopilotAgentAdapter } from './adapters/copilot-agent.js';\nimport { RuleMetricMcpAdapter } from './adapters/rulemetric-mcp.js';\nimport { CodexAdapter } from './adapters/codex.js';\n\nconst adapters: Record<string, () => SessionAdapter> = {\n claude_code: () => new ClaudeCodeAdapter(),\n cursor: () => new CursorAdapter(),\n vscode_copilot: () => new VSCodeCopilotAdapter(),\n copilot_agent: () => new CopilotAgentAdapter(),\n rulemetric_mcp: () => new RuleMetricMcpAdapter(),\n codex: () => new CodexAdapter(),\n};\n\nexport function getAdapter(tool: SessionTool): SessionAdapter {\n const factory = adapters[tool];\n if (!factory) {\n throw new Error(`Unknown session tool: ${tool}`);\n }\n return factory();\n}\n\nexport function detectTool(input: string): SessionTool | null {\n const trimmed = input.trim();\n\n if (trimmed.startsWith('{')) {\n // Try single-line JSON first (JSONL first line), then full multi-line JSON\n const firstLine = trimmed.split('\\n')[0];\n let parsed: Record<string, unknown> | null = null;\n\n try {\n parsed = JSON.parse(firstLine);\n } catch {\n // First line wasn't complete JSON (pretty-printed) \u2014 try full content\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n // Not valid JSON \u2014 fall through to JSONL detection\n }\n }\n\n if (parsed) {\n // Claude Code JSONL: has type field with user/assistant\n if (parsed.type === 'user' || parsed.type === 'assistant') {\n return 'claude_code';\n }\n\n // RuleMetric MCP: has top-level events array without other format markers\n if (Array.isArray(parsed.events) && !parsed.requests && !parsed.allComposers) {\n return 'rulemetric_mcp';\n }\n\n // Copilot Agent: has requests array with toolCalls or agentMode flag\n if (Array.isArray(parsed.requests)) {\n const hasToolCalls = parsed.requests.some(\n (r: Record<string, unknown>) => Array.isArray(r.toolCalls),\n );\n if (hasToolCalls || parsed.agentMode) {\n return 'copilot_agent';\n }\n return 'vscode_copilot';\n }\n\n // Cursor: has allComposers key\n if (parsed.allComposers) {\n return 'cursor';\n }\n }\n\n // JSONL detection: multiple lines, each valid JSON\n if (!parsed) {\n try {\n const lines = trimmed.split('\\n').filter((l) => l.trim());\n if (lines.length > 1) {\n const first = JSON.parse(lines[0]);\n if (first.type === 'user' || first.type === 'assistant') {\n return 'claude_code';\n }\n }\n } catch {\n // Not JSONL either\n }\n }\n }\n\n return null;\n}\n", "import type { SessionEvent, SessionAnalysis } from './types.js';\n\ninterface InstructionContext {\n id: string;\n name: string;\n content: string;\n}\n\nexport function buildAnalysisPrompt(\n events: SessionEvent[],\n instructions: InstructionContext[],\n): string {\n const instructionSection = instructions.length > 0\n ? instructions.map((i) => `### ${i.name} (ID: ${i.id})\\n\\n${i.content}`).join('\\n\\n---\\n\\n')\n : 'No instructions were linked to this session.';\n\n const eventSummary = events.map((e) => {\n const prefix = `[${e.sequence}] ${e.eventType}`;\n if (e.eventType === 'tool_call') {\n return `${prefix}: ${e.toolName}(${JSON.stringify(e.toolInput)})`;\n }\n if (e.eventType === 'tool_result') {\n const preview = e.content?.slice(0, 200) ?? '';\n return `${prefix}: ${preview}${e.content && e.content.length > 200 ? '...' : ''}`;\n }\n const preview = e.content?.slice(0, 300) ?? '';\n return `${prefix}: ${preview}${e.content && e.content.length > 300 ? '...' : ''}`;\n }).join('\\n');\n\n return `You are analyzing an AI coding session to evaluate how well the agent followed its instructions and to suggest improvements.\n\n## Active Instructions\n\n${instructionSection}\n\n## Session Transcript\n\n${eventSummary}\n\n## Analysis Tasks\n\n1. **Adherence Score** (0-100): Rate how well the agent followed each active instruction. 100 = perfect adherence.\n2. **Deviations**: List specific events where the agent deviated from instructions. Each deviation needs:\n - eventSequence: the event number\n - instructionId: which instruction was violated\n - description: what went wrong\n - severity: \"low\", \"medium\", or \"high\"\n3. **Suggestions**: For each gap or deviation, propose a specific edit to the instruction. Each suggestion needs:\n - instructionId: which instruction to improve\n - currentContent: the relevant excerpt from the instruction\n - suggestedContent: your proposed replacement text\n - rationale: why this change would help\n - confidence: 0-100 how confident you are this would improve outcomes\n4. **Summary**: One paragraph summarizing the session quality.\n\nReturn your response as JSON matching this schema:\n{\n \"adherenceScore\": <number 0-100>,\n \"deviations\": [{ \"eventSequence\": <number>, \"instructionId\": \"<string>\", \"description\": \"<string>\", \"severity\": \"<low|medium|high>\" }],\n \"suggestions\": [{ \"instructionId\": \"<string>\", \"currentContent\": \"<string>\", \"suggestedContent\": \"<string>\", \"rationale\": \"<string>\", \"confidence\": <number 0-100> }],\n \"summary\": \"<string>\"\n}\n\nReturn valid JSON only.`;\n}\n\nexport function parseAnalysisResponse(response: string): SessionAnalysis | null {\n try {\n // Extract JSON from response (may be wrapped in markdown fences)\n const jsonMatch = response.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) return null;\n\n const parsed = JSON.parse(jsonMatch[0]);\n\n // Validate required fields\n if (\n typeof parsed.adherenceScore !== 'number' ||\n !Array.isArray(parsed.deviations) ||\n !Array.isArray(parsed.suggestions) ||\n typeof parsed.summary !== 'string'\n ) {\n return null;\n }\n\n return {\n adherenceScore: parsed.adherenceScore,\n deviations: parsed.deviations,\n suggestions: parsed.suggestions,\n summary: parsed.summary,\n analyzedAt: new Date().toISOString(),\n };\n } catch {\n return null;\n }\n}\n", "import { readdir, stat } from 'fs/promises';\nimport { basename, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst shortNames: Record<string, string> = {\n 'claude-opus-4-7': 'Opus 4.7',\n 'claude-opus-4-6': 'Opus 4.6',\n 'claude-opus-4-5': 'Opus 4.5',\n 'claude-opus-4-1': 'Opus 4.1',\n 'claude-opus-4': 'Opus 4',\n 'claude-sonnet-4-6': 'Sonnet 4.6',\n 'claude-sonnet-4-5': 'Sonnet 4.5',\n 'claude-sonnet-4': 'Sonnet 4',\n 'claude-3-7-sonnet': 'Sonnet 3.7',\n 'claude-3-5-sonnet': 'Sonnet 3.5',\n 'claude-haiku-4-5': 'Haiku 4.5',\n 'claude-3-5-haiku': 'Haiku 3.5',\n};\n\nfunction getClaudeDir(): string {\n return process.env['CLAUDE_CONFIG_DIR'] || join(homedir(), '.claude');\n}\n\nfunction getProjectsDir(): string {\n return join(getClaudeDir(), 'projects');\n}\n\nfunction getDesktopSessionsDir(): string {\n if (process.platform === 'darwin') return join(homedir(), 'Library', 'Application Support', 'Claude', 'local-agent-mode-sessions');\n if (process.platform === 'win32') return join(homedir(), 'AppData', 'Roaming', 'Claude', 'local-agent-mode-sessions');\n return join(homedir(), '.config', 'Claude', 'local-agent-mode-sessions');\n}\n\nasync function findDesktopProjectDirs(base: string): Promise<string[]> {\n const results: string[] = [];\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > 8) return;\n const entries = await readdir(dir).catch(() => []);\n for (const entry of entries) {\n if (entry === 'node_modules' || entry === '.git') continue;\n const full = join(dir, entry);\n const s = await stat(full).catch(() => null);\n if (!s?.isDirectory()) continue;\n if (entry === 'projects') {\n const projectDirs = await readdir(full).catch(() => []);\n for (const pd of projectDirs) {\n const pdFull = join(full, pd);\n const pdStat = await stat(pdFull).catch(() => null);\n if (pdStat?.isDirectory()) results.push(pdFull);\n }\n } else {\n await walk(full, depth + 1);\n }\n }\n }\n await walk(base, 0);\n return results;\n}\n\nexport const claudeCode: Provider = {\n name: 'claude',\n displayName: 'Claude Code',\n\n modelDisplayName(model: string): string {\n const canonical = model.replace(/@.*$/, '').replace(/-\\d{8}$/, '');\n for (const [key, name] of Object.entries(shortNames)) {\n if (canonical.startsWith(key)) return name;\n }\n return canonical;\n },\n\n toolDisplayName(rawTool: string): string {\n return rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n const sources: SessionSource[] = [];\n\n const projectsDir = getProjectsDir();\n try {\n const entries = await readdir(projectsDir);\n for (const dirName of entries) {\n const dirPath = join(projectsDir, dirName);\n const dirStat = await stat(dirPath).catch(() => null);\n if (dirStat?.isDirectory()) {\n sources.push({ path: dirPath, project: dirName, provider: 'claude' });\n }\n }\n } catch { /* projects dir may not exist */ }\n\n const desktopDirs = await findDesktopProjectDirs(getDesktopSessionsDir());\n for (const dirPath of desktopDirs) {\n sources.push({ path: dirPath, project: basename(dirPath), provider: 'claude' });\n }\n\n return sources;\n },\n\n createSessionParser(): SessionParser {\n // Claude Code sessions are parsed via the existing ClaudeCodeAdapter.\n // This provider handles discovery; parsing is done by the adapter.\n return {\n async *parse() { /* no-op \u2014 use ClaudeCodeAdapter for full parsing */ },\n };\n },\n};\n", "import { readdir, readFile, stat } from 'fs/promises';\nimport { basename, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-5.3-codex': 'GPT-5.3 Codex',\n 'gpt-5.4-mini': 'GPT-5.4 Mini',\n 'gpt-5.4': 'GPT-5.4',\n 'gpt-5': 'GPT-5',\n 'gpt-4o-mini': 'GPT-4o Mini',\n 'gpt-4o': 'GPT-4o',\n};\n\nconst toolNameMap: Record<string, string> = {\n exec_command: 'Bash',\n read_file: 'Read',\n write_file: 'Edit',\n apply_diff: 'Edit',\n apply_patch: 'Edit',\n spawn_agent: 'Agent',\n close_agent: 'Agent',\n wait_agent: 'Agent',\n read_dir: 'Glob',\n};\n\ntype CodexEntry = {\n type: string;\n timestamp?: string;\n payload?: {\n type?: string;\n role?: string;\n cwd?: string;\n model_provider?: string;\n originator?: string;\n session_id?: string;\n model?: string;\n name?: string;\n content?: Array<{ type?: string; text?: string }>;\n info?: {\n model?: string;\n model_name?: string;\n last_token_usage?: CodexTokenUsage;\n total_token_usage?: CodexTokenUsage;\n };\n };\n};\n\ntype CodexTokenUsage = {\n input_tokens?: number;\n cached_input_tokens?: number;\n output_tokens?: number;\n reasoning_output_tokens?: number;\n total_tokens?: number;\n};\n\nfunction getCodexDir(): string {\n return process.env['CODEX_HOME'] ?? join(homedir(), '.codex');\n}\n\nfunction sanitizeProject(cwd: string): string {\n return cwd.replace(/^\\//, '').replace(/\\//g, '-');\n}\n\nasync function readFirstLine(filePath: string): Promise<CodexEntry | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const line = content.split('\\n')[0];\n if (!line?.trim()) return null;\n return JSON.parse(line) as CodexEntry;\n } catch {\n return null;\n }\n}\n\nasync function isValidCodexSession(filePath: string): Promise<{ valid: boolean; meta?: CodexEntry }> {\n const entry = await readFirstLine(filePath);\n if (!entry) return { valid: false };\n const valid = entry.type === 'session_meta' &&\n typeof entry.payload?.originator === 'string' &&\n entry.payload.originator.toLowerCase().startsWith('codex');\n return { valid, meta: valid ? entry : undefined };\n}\n\nasync function discoverSessionsInDir(codexDir: string): Promise<SessionSource[]> {\n const sessionsDir = join(codexDir, 'sessions');\n const sources: SessionSource[] = [];\n\n let years: string[];\n try {\n years = await readdir(sessionsDir);\n } catch {\n return sources;\n }\n\n for (const year of years) {\n if (!/^\\d{4}$/.test(year)) continue;\n const yearDir = join(sessionsDir, year);\n const months = await readdir(yearDir).catch(() => [] as string[]);\n\n for (const month of months) {\n if (!/^\\d{2}$/.test(month)) continue;\n const monthDir = join(yearDir, month);\n const days = await readdir(monthDir).catch(() => [] as string[]);\n\n for (const day of days) {\n if (!/^\\d{2}$/.test(day)) continue;\n const dayDir = join(monthDir, day);\n const files = await readdir(dayDir).catch(() => [] as string[]);\n\n for (const file of files) {\n if (!file.startsWith('rollout-') || !file.endsWith('.jsonl')) continue;\n const filePath = join(dayDir, file);\n const s = await stat(filePath).catch(() => null);\n if (!s?.isFile()) continue;\n\n const { valid, meta } = await isValidCodexSession(filePath);\n if (!valid || !meta) continue;\n\n const cwd = meta.payload?.cwd ?? 'unknown';\n sources.push({ path: filePath, project: sanitizeProject(cwd), provider: 'codex' });\n }\n }\n }\n }\n\n return sources;\n}\n\nfunction resolveModel(info: CodexEntry['payload'], sessionModel?: string): string {\n return info?.info?.model\n ?? info?.info?.model_name\n ?? sessionModel\n ?? 'gpt-5';\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n let content: string;\n try {\n content = await readFile(source.path, 'utf-8');\n } catch {\n return;\n }\n\n const lines = content.split('\\n').filter(l => l.trim());\n let sessionModel: string | undefined;\n let sessionId = '';\n let prevCumulativeTotal = 0;\n let prevInput = 0;\n let prevCached = 0;\n let prevOutput = 0;\n let prevReasoning = 0;\n let pendingTools: string[] = [];\n let pendingUserMessage = '';\n\n for (const line of lines) {\n let entry: CodexEntry;\n try {\n entry = JSON.parse(line) as CodexEntry;\n } catch {\n continue;\n }\n\n if (entry.type === 'session_meta') {\n sessionId = entry.payload?.session_id ?? basename(source.path, '.jsonl');\n sessionModel = entry.payload?.model;\n continue;\n }\n\n if (entry.type === 'response_item' && entry.payload?.type === 'function_call') {\n const rawName = entry.payload.name ?? '';\n pendingTools.push(toolNameMap[rawName] ?? rawName);\n continue;\n }\n\n if (entry.type === 'response_item' && entry.payload?.type === 'message' && entry.payload?.role === 'user') {\n const texts = (entry.payload.content ?? [])\n .filter(c => c.type === 'input_text')\n .map(c => c.text ?? '')\n .filter(Boolean);\n if (texts.length > 0) pendingUserMessage = texts.join(' ');\n continue;\n }\n\n if (entry.type === 'event_msg' && entry.payload?.type === 'token_count') {\n const info = entry.payload.info;\n if (!info) continue;\n\n const cumulativeTotal = info.total_token_usage?.total_tokens ?? 0;\n if (cumulativeTotal > 0 && cumulativeTotal === prevCumulativeTotal) continue;\n prevCumulativeTotal = cumulativeTotal;\n\n const last = info.last_token_usage;\n let inputTokens = 0;\n let cachedInputTokens = 0;\n let outputTokens = 0;\n let reasoningTokens = 0;\n\n if (last) {\n inputTokens = last.input_tokens ?? 0;\n cachedInputTokens = last.cached_input_tokens ?? 0;\n outputTokens = last.output_tokens ?? 0;\n reasoningTokens = last.reasoning_output_tokens ?? 0;\n } else if (cumulativeTotal > 0) {\n const total = info.total_token_usage;\n if (!total) continue;\n inputTokens = (total.input_tokens ?? 0) - prevInput;\n cachedInputTokens = (total.cached_input_tokens ?? 0) - prevCached;\n outputTokens = (total.output_tokens ?? 0) - prevOutput;\n reasoningTokens = (total.reasoning_output_tokens ?? 0) - prevReasoning;\n }\n\n if (!last) {\n const total = info.total_token_usage;\n if (total) {\n prevInput = total.input_tokens ?? 0;\n prevCached = total.cached_input_tokens ?? 0;\n prevOutput = total.output_tokens ?? 0;\n prevReasoning = total.reasoning_output_tokens ?? 0;\n }\n }\n\n const totalTokens = inputTokens + cachedInputTokens + outputTokens + reasoningTokens;\n if (totalTokens === 0) continue;\n\n // OpenAI includes cached tokens inside input_tokens; normalize to non-cached only\n const uncachedInputTokens = Math.max(0, inputTokens - cachedInputTokens);\n\n const model = resolveModel(entry.payload, sessionModel);\n const timestamp = entry.timestamp ?? '';\n const dedupKey = `codex:${source.path}:${timestamp}:${cumulativeTotal}`;\n\n if (seenKeys.has(dedupKey)) continue;\n seenKeys.add(dedupKey);\n\n yield {\n provider: 'codex',\n model,\n inputTokens: uncachedInputTokens,\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: cachedInputTokens,\n cachedInputTokens,\n reasoningTokens,\n costUSD: 0, // Cost calculated downstream\n tools: pendingTools,\n bashCommands: [],\n timestamp,\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n };\n\n pendingTools = [];\n pendingUserMessage = '';\n }\n }\n },\n };\n}\n\nexport const codex: Provider = {\n name: 'codex',\n displayName: 'Codex',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of Object.entries(modelDisplayNames)) {\n if (model.startsWith(key)) return name;\n }\n return model;\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(getCodexDir());\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys);\n },\n};\n", "import { readdir, readFile, stat } from 'fs/promises';\nimport { basename, dirname, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-4.1-nano': 'GPT-4.1 Nano',\n 'gpt-4.1-mini': 'GPT-4.1 Mini',\n 'gpt-4.1': 'GPT-4.1',\n 'gpt-4o-mini': 'GPT-4o Mini',\n 'gpt-4o': 'GPT-4o',\n 'gpt-5-mini': 'GPT-5 Mini',\n 'gpt-5': 'GPT-5',\n 'claude-sonnet-4-5': 'Sonnet 4.5',\n 'claude-sonnet-4': 'Sonnet 4',\n 'claude-3-7-sonnet': 'Sonnet 3.7',\n 'claude-3-5-sonnet': 'Sonnet 3.5',\n 'o4-mini': 'o4-mini',\n 'o3': 'o3',\n};\n\nconst toolNameMap: Record<string, string> = {\n bash: 'Bash',\n read_file: 'Read',\n write_file: 'Edit',\n edit_file: 'Edit',\n create_file: 'Write',\n delete_file: 'Delete',\n search_files: 'Grep',\n find_files: 'Glob',\n list_directory: 'LS',\n web_search: 'WebSearch',\n fetch_webpage: 'WebFetch',\n github_repo: 'GitHub',\n};\n\nconst modelDisplayEntries = Object.entries(modelDisplayNames).sort((a, b) => b[0].length - a[0].length);\n\ntype ToolRequest = {\n name?: string;\n toolCallId?: string;\n type?: string;\n};\n\ntype CopilotEvent =\n | { type: 'session.model_change'; timestamp?: string; data: { newModel: string } }\n | { type: 'user.message'; timestamp?: string; data: { content: string } }\n | { type: 'assistant.message'; timestamp?: string; data: { messageId: string; outputTokens: number; toolRequests?: ToolRequest[] } };\n\nfunction getCopilotSessionStateDir(): string {\n return join(homedir(), '.copilot', 'session-state');\n}\n\nfunction parseCwd(yaml: string): string | null {\n const match = yaml.match(/^cwd:\\s*(.+)$/m);\n if (!match?.[1]) return null;\n return match[1].replace(/\\s*#.*$/, '').replace(/^['\"]|['\"]$/g, '').trim() || null;\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n let content: string;\n try {\n content = await readFile(source.path, 'utf-8');\n } catch {\n return;\n }\n\n const sessionId = basename(dirname(source.path));\n const lines = content.split('\\n').filter(l => l.trim());\n let currentModel = '';\n let pendingUserMessage = '';\n\n for (const line of lines) {\n let event: CopilotEvent;\n try {\n event = JSON.parse(line) as CopilotEvent;\n } catch {\n continue;\n }\n\n if (event.type === 'session.model_change') {\n currentModel = event.data.newModel ?? currentModel;\n continue;\n }\n\n if (event.type === 'user.message') {\n pendingUserMessage = event.data.content ?? '';\n continue;\n }\n\n if (event.type === 'assistant.message') {\n const { messageId, outputTokens, toolRequests = [] } = event.data;\n if (outputTokens === 0) continue;\n if (!currentModel) continue;\n\n const dedupKey = `copilot:${sessionId}:${messageId}`;\n if (seenKeys.has(dedupKey)) continue;\n seenKeys.add(dedupKey);\n\n const tools = toolRequests\n .map(t => t.name ?? '')\n .filter(Boolean)\n .map(n => toolNameMap[n] ?? n);\n\n yield {\n provider: 'copilot',\n model: currentModel,\n inputTokens: 0, // Copilot only logs outputTokens\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: 0,\n cachedInputTokens: 0,\n reasoningTokens: 0,\n costUSD: 0,\n tools,\n bashCommands: [],\n timestamp: event.timestamp ?? '',\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n };\n\n pendingUserMessage = '';\n }\n }\n },\n };\n}\n\nasync function discoverSessionsInDir(sessionStateDir: string): Promise<SessionSource[]> {\n const sources: SessionSource[] = [];\n\n let sessionDirs: string[];\n try {\n sessionDirs = await readdir(sessionStateDir);\n } catch {\n return sources;\n }\n\n for (const sessionId of sessionDirs) {\n const eventsPath = join(sessionStateDir, sessionId, 'events.jsonl');\n const s = await stat(eventsPath).catch(() => null);\n if (!s?.isFile()) continue;\n\n let project = sessionId;\n try {\n const yaml = await readFile(join(sessionStateDir, sessionId, 'workspace.yaml'), 'utf-8');\n const cwd = parseCwd(yaml);\n if (cwd) project = basename(cwd);\n } catch { /* no workspace.yaml */ }\n\n sources.push({ path: eventsPath, project, provider: 'copilot' });\n }\n\n return sources;\n}\n\nexport const copilot: Provider = {\n name: 'copilot',\n displayName: 'GitHub Copilot',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of modelDisplayEntries) {\n if (model === key || model.startsWith(key + '-')) return name;\n }\n return model;\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(getCopilotSessionStateDir());\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys);\n },\n};\n", "import { readdir, readFile, stat } from 'fs/promises';\nimport { basename, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-5.4': 'GPT-5.4',\n 'gpt-5.4-mini': 'GPT-5.4 Mini',\n 'gpt-5': 'GPT-5',\n 'gpt-4o': 'GPT-4o',\n 'gpt-4o-mini': 'GPT-4o Mini',\n};\n\nconst toolNameMap: Record<string, string> = {\n bash: 'Bash',\n read: 'Read',\n edit: 'Edit',\n write: 'Write',\n glob: 'Glob',\n grep: 'Grep',\n task: 'Agent',\n dispatch_agent: 'Agent',\n fetch: 'WebFetch',\n search: 'WebSearch',\n todo: 'TodoWrite',\n patch: 'Patch',\n};\n\nconst modelDisplayEntries = Object.entries(modelDisplayNames).sort((a, b) => b[0].length - a[0].length);\n\ntype PiEntry = {\n type: string;\n id?: string;\n timestamp?: string;\n cwd?: string;\n message?: {\n role?: string;\n content?: Array<{ type?: string; text?: string; name?: string; arguments?: Record<string, unknown> }>;\n model?: string;\n responseId?: string;\n usage?: {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n };\n };\n};\n\nfunction getPiSessionsDir(): string {\n return join(homedir(), '.pi', 'agent', 'sessions');\n}\n\nasync function readFirstEntry(filePath: string): Promise<PiEntry | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const line = content.split('\\n')[0];\n if (!line?.trim()) return null;\n return JSON.parse(line) as PiEntry;\n } catch {\n return null;\n }\n}\n\nfunction extractBashCommands(cmd: string): string[] {\n return cmd.split(/[;&|]+/).map(s => s.trim().split(/\\s+/)[0]).filter(Boolean);\n}\n\nasync function discoverSessionsInDir(sessionsDir: string): Promise<SessionSource[]> {\n const sources: SessionSource[] = [];\n\n let projectDirs: string[];\n try {\n projectDirs = await readdir(sessionsDir);\n } catch {\n return sources;\n }\n\n for (const dirName of projectDirs) {\n const dirPath = join(sessionsDir, dirName);\n const dirStat = await stat(dirPath).catch(() => null);\n if (!dirStat?.isDirectory()) continue;\n\n let files: string[];\n try {\n files = await readdir(dirPath);\n } catch {\n continue;\n }\n\n for (const file of files) {\n if (!file.endsWith('.jsonl')) continue;\n const filePath = join(dirPath, file);\n const fileStat = await stat(filePath).catch(() => null);\n if (!fileStat?.isFile()) continue;\n\n const first = await readFirstEntry(filePath);\n if (!first || first.type !== 'session') continue;\n\n const cwd = first.cwd ?? dirName;\n sources.push({ path: filePath, project: basename(cwd), provider: 'pi' });\n }\n }\n\n return sources;\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n let content: string;\n try {\n content = await readFile(source.path, 'utf-8');\n } catch {\n return;\n }\n\n const lines = content.split('\\n').filter(l => l.trim());\n let sessionId = basename(source.path, '.jsonl');\n let pendingUserMessage = '';\n\n for (const [lineIdx, line] of lines.entries()) {\n let entry: PiEntry;\n try {\n entry = JSON.parse(line) as PiEntry;\n } catch {\n continue;\n }\n\n if (entry.type === 'session') {\n sessionId = entry.id ?? sessionId;\n continue;\n }\n\n if (entry.type !== 'message') continue;\n\n const msg = entry.message;\n if (!msg) continue;\n\n if (msg.role === 'user') {\n const texts = (msg.content ?? [])\n .filter(c => c.type === 'text')\n .map(c => c.text ?? '')\n .filter(Boolean);\n if (texts.length > 0) pendingUserMessage = texts.join(' ');\n continue;\n }\n\n if (msg.role !== 'assistant' || !msg.usage) continue;\n\n const { input, output, cacheRead, cacheWrite } = msg.usage;\n if (input === 0 && output === 0) continue;\n\n const model = msg.model ?? 'gpt-5';\n const responseId = msg.responseId ?? '';\n const dedupKey = `pi:${source.path}:${responseId || entry.id || entry.timestamp || String(lineIdx)}`;\n\n if (seenKeys.has(dedupKey)) continue;\n seenKeys.add(dedupKey);\n\n const toolCalls = (msg.content ?? []).filter(c => c.type === 'toolCall' && c.name);\n const tools = toolCalls.map(c => toolNameMap[c.name!] ?? c.name!);\n const bashCommands = toolCalls\n .filter(c => c.name === 'bash')\n .flatMap(c => {\n const cmd = c.arguments?.['command'];\n return typeof cmd === 'string' ? extractBashCommands(cmd) : [];\n });\n\n const timestamp = entry.timestamp ?? '';\n\n yield {\n provider: 'pi',\n model,\n inputTokens: input,\n outputTokens: output,\n cacheCreationInputTokens: cacheWrite,\n cacheReadInputTokens: cacheRead,\n cachedInputTokens: cacheRead,\n reasoningTokens: 0,\n costUSD: 0,\n tools,\n bashCommands,\n timestamp,\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n };\n\n pendingUserMessage = '';\n }\n },\n };\n}\n\nexport const pi: Provider = {\n name: 'pi',\n displayName: 'Pi',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of modelDisplayEntries) {\n if (model.startsWith(key)) return name;\n }\n return model;\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(getPiSessionsDir());\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys);\n },\n};\n", "import { claudeCode } from './claude-code.js';\nimport { codex } from './codex.js';\nimport { copilot } from './copilot.js';\nimport { pi } from './pi.js';\nimport type { Provider, SessionSource } from './types.js';\n\nexport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\n// Core providers (no native dependencies)\nconst coreProviders: Provider[] = [claudeCode, codex, copilot, pi];\n\n// Optional providers (require better-sqlite3, lazy-loaded)\nlet cursorProvider: Provider | null = null;\nlet cursorLoadAttempted = false;\n\nasync function loadCursor(): Promise<Provider | null> {\n if (cursorLoadAttempted) return cursorProvider;\n cursorLoadAttempted = true;\n try {\n const { cursor } = await import('./cursor.js');\n cursorProvider = cursor;\n return cursor;\n } catch {\n return null;\n }\n}\n\nlet opencodeProvider: Provider | null = null;\nlet opencodeLoadAttempted = false;\n\nasync function loadOpenCode(): Promise<Provider | null> {\n if (opencodeLoadAttempted) return opencodeProvider;\n opencodeLoadAttempted = true;\n try {\n const { opencode } = await import('./opencode.js');\n opencodeProvider = opencode;\n return opencode;\n } catch {\n return null;\n }\n}\n\nexport async function getAllProviders(): Promise<Provider[]> {\n const [cursor, opencode] = await Promise.all([loadCursor(), loadOpenCode()]);\n const all = [...coreProviders];\n if (cursor) all.push(cursor);\n if (opencode) all.push(opencode);\n return all;\n}\n\nexport async function discoverAllSessions(providerFilter?: string): Promise<SessionSource[]> {\n const allProviders = await getAllProviders();\n const filtered = providerFilter && providerFilter !== 'all'\n ? allProviders.filter(p => p.name === providerFilter)\n : allProviders;\n const all: SessionSource[] = [];\n for (const provider of filtered) {\n const sessions = await provider.discoverSessions();\n all.push(...sessions);\n }\n return all;\n}\n\nexport async function getProvider(name: string): Promise<Provider | undefined> {\n if (name === 'cursor') return (await loadCursor()) ?? undefined;\n if (name === 'opencode') return (await loadOpenCode()) ?? undefined;\n return coreProviders.find(p => p.name === name);\n}\n", "import { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport { writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\nimport {\n buildTmuxAttachCommand,\n buildTmuxLaunchArgs,\n buildTmuxSendKeysArgs,\n isTmuxAvailable,\n runTmux,\n sanitizeTmuxName,\n type TmuxRunResult,\n} from '../terminal/tmux.js';\n\ninterface ClaudeCodeLauncherOptions {\n tmuxAvailable?: () => Promise<boolean>;\n runTmux?: (args: string[]) => Promise<TmuxRunResult>;\n}\n\ntype TmuxFallbackReason = NonNullable<LaunchResult['fallbackReason']>;\n\n// Mirror the API's `z.string().uuid()` contract (8-4-4-4-12 hex). runId is a\n// server-minted uuid today and the generic launch-jobs route strips it via\n// Zod, so this is NOT client-reachable \u2014 it's defense-in-depth so a future\n// relaxation of that boundary can't turn the Terminal.app `.command` script\n// into shell command-substitution RCE (e.g. a runId of `$(touch /tmp/x)`).\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Validate a caller-supplied runId at the launcher boundary. Returns the runId\n * only if it's a well-formed uuid; otherwise returns undefined (and logs a\n * warning) so NONE of the three injection paths stamp an untrusted value.\n */\nexport function validateRunId(runId: string | undefined): string | undefined {\n if (runId === undefined) return undefined;\n if (UUID_RE.test(runId)) return runId;\n console.warn(\n `[claude-code-launcher] dropping non-uuid runId (RULEMETRIC_RUN_ID not injected): ${JSON.stringify(runId)}`,\n );\n return undefined;\n}\n\n/**\n * Single-quote a string for safe inclusion in a POSIX shell script. Single\n * quotes suppress ALL expansion (command substitution, parameter expansion,\n * backticks); the `'\\''` trick closes the quote, emits an escaped literal\n * quote, then reopens \u2014 the only escape single-quoting needs.\n */\nexport function shellSingleQuote(s: string): string {\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n}\n\nexport class ClaudeCodeLauncher implements ToolLauncher {\n tool = 'claude_code' as const;\n\n constructor(private readonly options: ClaudeCodeLauncherOptions = {}) {}\n\n capabilities: LaunchCapabilities = {\n headless: true,\n interactive: true,\n remoteSpawn: true,\n };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n\n // Validate the runId ONCE at the launcher boundary so all three injection\n // paths (headless env, tmux argv, Terminal.app .command) only ever see a\n // well-formed uuid. A non-uuid value is dropped (see validateRunId).\n const safeConfig: LaunchConfig = { ...config, runId: validateRunId(config.runId) };\n\n if (safeConfig.mode === 'headless') {\n return this.launchHeadless(safeConfig, sessionId);\n }\n return this.launchInteractive(safeConfig, sessionId);\n }\n\n private async launchHeadless(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const args = ['-p', config.prompt ?? '', '--output-format', 'json'];\n if (config.systemPrompt) args.push('--system-prompt', config.systemPrompt);\n if (config.model) args.push('--model', config.model);\n\n // Remove CLAUDECODE flag so spawned claude doesn't think it's a nested session.\n // Remove HTTPS_PROXY so headless runs bypass the capture proxy \u2014 these are\n // infrastructure calls, not user sessions.\n const env = { ...process.env };\n delete env.CLAUDECODE;\n delete env.HTTPS_PROXY;\n // Task 3.1: stamp the run id so the spawned session's hook forwards it.\n // NOTE: RULEMETRIC_RUN_ID is effectively a no-op on the headless path today\n // \u2014 headless runs delete HTTPS_PROXY above to bypass the capture proxy/hook,\n // and runs always use mode:'interactive'. Kept for forward-compat. runId is\n // already validated as a uuid at the launch() boundary.\n if (config.runId) env.RULEMETRIC_RUN_ID = config.runId;\n\n return new Promise((resolve) => {\n const proc = spawn('claude', args, {\n cwd: config.projectPath,\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n const timer = config.timeout\n ? setTimeout(() => { proc.kill('SIGTERM'); }, config.timeout)\n : null;\n\n proc.on('close', (code) => {\n if (timer) clearTimeout(timer);\n let output = stdout;\n try {\n const parsed = JSON.parse(stdout);\n output = parsed.result ?? parsed.content ?? stdout;\n } catch { /* raw text */ }\n\n resolve({\n sessionId,\n pid: proc.pid,\n exitCode: code,\n output,\n error: code !== 0 ? stderr : undefined,\n });\n });\n\n proc.on('error', (err) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, error: `Failed to spawn claude: ${err.message}` });\n });\n });\n }\n\n private async launchInteractive(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const tmuxAvailableCheck = this.options.tmuxAvailable ?? isTmuxAvailable;\n if (await tmuxAvailableCheck().catch(() => false)) {\n return this.launchInteractiveTmux(config, sessionId);\n }\n return this.launchInteractiveTerminal(config, sessionId, 'tmux_not_found');\n }\n\n private async launchInteractiveTmux(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const run = this.options.runTmux ?? runTmux;\n const target = sanitizeTmuxName(`claude-${config.resumeSessionId ?? sessionId}`);\n const launchResult = await run(buildTmuxLaunchArgs({\n sessionName: target,\n projectPath: config.projectPath,\n resumeSessionId: config.resumeSessionId,\n model: config.model,\n // Task 3.1: inject the run id into the spawned session's env so its\n // session-start hook forwards it to POST /api/sessions (stamps run_id).\n runId: config.runId,\n }));\n\n if (launchResult.code !== 0) {\n return this.launchInteractiveTerminal(\n config,\n sessionId,\n 'tmux_launch_failed',\n `tmux new-session exited ${launchResult.code}: ${launchResult.stderr.trim() || 'no stderr'}`,\n );\n }\n\n const attachResult = await this.openTerminalAttach(target, sessionId);\n\n if (config.prompt) {\n const sendResult = await run(buildTmuxSendKeysArgs(target, config.prompt));\n if (sendResult.code !== 0) {\n return {\n sessionId,\n liveSendAvailable: false,\n fallbackReason: 'tmux_launch_failed',\n error: `tmux send-keys exited ${sendResult.code}: ${sendResult.stderr.trim() || 'no stderr'}`,\n };\n }\n const enterResult = await run(buildTmuxSendKeysArgs(target, 'Enter', { literal: false }));\n if (enterResult.code !== 0) {\n return {\n sessionId,\n liveSendAvailable: false,\n fallbackReason: 'tmux_launch_failed',\n error: `tmux send Enter exited ${enterResult.code}: ${enterResult.stderr.trim() || 'no stderr'}`,\n };\n }\n }\n\n return {\n sessionId,\n pid: attachResult.pid,\n liveSendAvailable: true,\n ...(attachResult.error ? { error: attachResult.error } : {}),\n terminalTarget: {\n kind: 'tmux',\n target,\n attachCommand: buildTmuxAttachCommand(target),\n live: true,\n },\n };\n }\n\n private async openTerminalAttach(\n target: string,\n sessionId: string,\n ): Promise<{ pid?: number; error?: string }> {\n const scriptPath = join(tmpdir(), `rulemetric-attach-${sessionId}.command`);\n const scriptBody =\n '#!/bin/zsh\\n' +\n 'rm -- \"$0\"\\n' +\n `${buildTmuxAttachCommand(target)}\\n`;\n await writeFile(scriptPath, scriptBody, { mode: 0o755 });\n\n return new Promise((resolve) => {\n const proc = spawn('open', ['-a', 'Terminal', scriptPath], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stderr = '';\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({ pid: proc.pid });\n } else {\n resolve({\n pid: proc.pid,\n error: `open attach exited ${code}: ${stderr.trim() || 'no stderr'}`,\n });\n }\n });\n proc.on('error', (err) => {\n resolve({ error: `Failed to spawn open attach: ${err.message}` });\n });\n });\n }\n\n private async launchInteractiveTerminal(\n config: LaunchConfig,\n sessionId: string,\n fallbackReason: TmuxFallbackReason,\n fallbackDetail?: string,\n ): Promise<LaunchResult> {\n // Build the claude command that runs INSIDE the new Terminal window. We\n // bake it into a .command script (next step) so the user sees a single\n // self-contained file in their tmpdir instead of a long inline AppleScript.\n const parts = ['claude'];\n if (config.resumeSessionId) {\n parts.push('--resume', config.resumeSessionId);\n } else if (config.prompt) {\n parts.push('-p', JSON.stringify(config.prompt));\n }\n if (config.model) parts.push('--model', config.model);\n const cmd = parts.join(' ');\n\n // Write a self-deleting .command script, then ask LaunchServices (via\n // `open -a Terminal`) to hand it to Terminal.app.\n //\n // History: this used to call `osascript \"tell Terminal to do script ...\"`.\n // That path goes through the macOS TCC AppleEvents bucket, which silently\n // denies launchd-spawned processes (the worker is launched via\n // `com.rulemetric.worker.plist`) \u2014 leaving the user with a \"completed\"\n // launch row and no Terminal window. See:\n // docs/incidents/2026-05-24-launcher-tcc-silent-failure.md.\n //\n // `open -a Terminal foo.command` goes through LaunchServices instead,\n // which is exempt from the AppleEvents bucket AND surfaces a real exit\n // code we can propagate to the mirror row.\n const scriptPath = join(tmpdir(), `rulemetric-launch-${sessionId}.command`);\n // The script self-deletes its own file (`rm -- \"$0\"`) BEFORE handing off\n // to claude so we don't leak temp files even if the user kills the window\n // mid-session. `cd ... || exit` ensures we don't silently launch claude\n // in $HOME when the project path is gone.\n // Task 3.1: export the run id (when present) into the script's shell so\n // the spawned claude \u2014 and its session-start hook \u2014 see RULEMETRIC_RUN_ID.\n // SINGLE-quote the value (not JSON/double-quote): double quotes still allow\n // `$(...)` / backtick command-substitution, so a value like `$(touch /tmp/x)`\n // would EXECUTE when the .command runs. Single quotes suppress all\n // expansion. config.runId is already uuid-validated at the launch()\n // boundary; the quoting is a second layer so the script is robust\n // regardless of value.\n const runIdExport = config.runId\n ? `export RULEMETRIC_RUN_ID=${shellSingleQuote(config.runId)}\\n`\n : '';\n const scriptBody =\n '#!/bin/zsh\\n' +\n 'rm -- \"$0\"\\n' +\n `cd ${JSON.stringify(config.projectPath)} || exit\\n` +\n runIdExport +\n `${cmd}\\n`;\n await writeFile(scriptPath, scriptBody, { mode: 0o755 });\n\n // Note: NOT detached / NOT unref'd. `open` returns once LaunchServices has\n // accepted the request (~10s of ms), so we CAN await its close + propagate\n // the exit code without coupling the Terminal window's lifetime to the\n // worker. Terminal.app is its own process and survives the worker exiting.\n return new Promise((resolve) => {\n const proc = spawn('open', ['-a', 'Terminal', scriptPath], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stderr = '';\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({\n sessionId,\n pid: proc.pid,\n liveSendAvailable: false,\n fallbackReason,\n ...(fallbackDetail ? { error: fallbackDetail } : {}),\n });\n } else {\n const tail = stderr.trim() || 'no stderr';\n resolve({\n sessionId,\n pid: proc.pid,\n liveSendAvailable: false,\n fallbackReason,\n error: fallbackDetail\n ? `${fallbackDetail}; open exited ${code}: ${tail}`\n : `open exited ${code}: ${tail}`,\n });\n }\n });\n proc.on('error', (err) => {\n resolve({\n sessionId,\n liveSendAvailable: false,\n fallbackReason,\n error: `Failed to spawn open: ${err.message}`,\n });\n });\n });\n }\n}\n", "import { spawn } from 'node:child_process';\n\nexport interface TmuxLaunchArgsInput {\n sessionName: string;\n projectPath: string;\n resumeSessionId?: string;\n model?: string;\n /**\n * Multi-session-run id (Task 3.1). When set, the launched `claude` command\n * is prefixed with `env RULEMETRIC_RUN_ID=<id>` so the value reaches ONLY\n * the spawned session's process (not the tmux server env), where the\n * session-start hook forwards it to POST /api/sessions.\n */\n runId?: string;\n}\n\nexport interface TmuxSendKeysOptions {\n literal?: boolean;\n}\n\nexport function sanitizeTmuxName(input: string): string {\n const cleaned = input\n .trim()\n .replace(/[^A-Za-z0-9_.-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80);\n return `rm-${cleaned || 'session'}`;\n}\n\nexport function buildTmuxLaunchArgs(input: TmuxLaunchArgsInput): string[] {\n // Prefix with `env RULEMETRIC_RUN_ID=<id>` so the var is scoped to the\n // spawned claude process only \u2014 tmux passes argv straight to exec, so this\n // never leaks into the tmux server's environment.\n const claudeArgs = input.runId\n ? ['env', `RULEMETRIC_RUN_ID=${input.runId}`, 'claude']\n : ['claude'];\n if (input.resumeSessionId) {\n claudeArgs.push('--resume', input.resumeSessionId);\n }\n if (input.model) {\n claudeArgs.push('--model', input.model);\n }\n\n return [\n 'new-session',\n '-d',\n '-s',\n input.sessionName,\n '-c',\n input.projectPath,\n '--',\n ...claudeArgs,\n ];\n}\n\nexport function buildTmuxSendKeysArgs(\n target: string,\n message: string,\n options: TmuxSendKeysOptions = {},\n): string[] {\n if (options.literal === false) {\n return ['send-keys', '-t', target, message];\n }\n return ['send-keys', '-t', target, '-l', '--', message];\n}\n\nexport function buildTmuxHasSessionArgs(target: string): string[] {\n return ['has-session', '-t', target];\n}\n\nexport function buildTmuxAttachCommand(target: string): string {\n return `tmux attach -t ${target}`;\n}\n\nexport interface TmuxRunResult {\n code: number | null;\n stderr: string;\n}\n\n// Homebrew installs tmux to /opt/homebrew/bin (Apple Silicon) or\n// /usr/local/bin (Intel). The launchd worker runs with a minimal PATH that\n// omits /opt/homebrew/bin, so a bare spawn('tmux') fails with ENOENT under\n// launchd even though it works in an interactive shell. Augment PATH at the\n// spawn boundary so live-send/launch work in the real (launchd) worker\n// environment \u2014 verified 2026-06-09 when every terminal target flipped to\n// `missing` because the worker couldn't resolve tmux.\nexport function tmuxSpawnEnv(): NodeJS.ProcessEnv {\n const extraDirs = ['/opt/homebrew/bin', '/usr/local/bin'];\n const parts = (process.env.PATH ?? '').split(':').filter(Boolean);\n const missing = extraDirs.filter((d) => !parts.includes(d));\n if (missing.length === 0) return process.env;\n return { ...process.env, PATH: [...parts, ...missing].join(':') };\n}\n\nexport function runTmux(args: string[]): Promise<TmuxRunResult> {\n return new Promise((resolve) => {\n const proc = spawn('tmux', args, {\n stdio: ['ignore', 'ignore', 'pipe'],\n env: tmuxSpawnEnv(),\n });\n let stderr = '';\n proc.stderr.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n proc.on('close', (code) => resolve({ code, stderr }));\n proc.on('error', (err) => resolve({ code: null, stderr: err.message }));\n });\n}\n\nexport async function isTmuxAvailable(): Promise<boolean> {\n const result = await runTmux(['-V']);\n return result.code === 0;\n}\n", "// codex.ts \u2014 OpenAI's Codex CLI (codex -q \"prompt\")\nimport { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\n\nexport class CodexLauncher implements ToolLauncher {\n tool = 'codex' as const;\n capabilities: LaunchCapabilities = { headless: true, interactive: true, remoteSpawn: true };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n if (config.mode === 'headless') {\n return this.launchHeadless(config, sessionId);\n }\n return this.launchInteractive(config, sessionId);\n }\n\n private launchHeadless(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const args = ['-q', config.prompt ?? ''];\n if (config.model) args.push('--model', config.model);\n\n return new Promise((resolve) => {\n const proc = spawn('codex', args, {\n cwd: config.projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n const timer = config.timeout\n ? setTimeout(() => { proc.kill('SIGTERM'); }, config.timeout)\n : null;\n\n proc.on('close', (code) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, pid: proc.pid, exitCode: code, output: stdout, error: code !== 0 ? stderr : undefined });\n });\n\n proc.on('error', (err) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, error: `Failed to spawn codex: ${err.message}` });\n });\n });\n }\n\n private launchInteractive(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const parts = ['codex'];\n if (config.prompt) parts.push(JSON.stringify(config.prompt));\n const script = `cd ${JSON.stringify(config.projectPath)} && ${parts.join(' ')}`;\n const proc = spawn('osascript', ['-e', `tell application \"Terminal\" to do script ${JSON.stringify(script)}`], {\n stdio: 'ignore',\n detached: true,\n });\n proc.unref();\n return Promise.resolve({ sessionId, pid: proc.pid });\n }\n}\n", "// aider.ts \u2014 Aider CLI (aider --message \"prompt\" for headless)\nimport { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\n\nexport class AiderLauncher implements ToolLauncher {\n tool = 'aider' as const;\n capabilities: LaunchCapabilities = { headless: true, interactive: true, remoteSpawn: true };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n if (config.mode === 'headless') {\n return this.launchHeadless(config, sessionId);\n }\n return this.launchInteractive(config, sessionId);\n }\n\n private launchHeadless(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const args = ['--message', config.prompt ?? '', '--yes'];\n if (config.model) args.push('--model', config.model);\n\n return new Promise((resolve) => {\n const proc = spawn('aider', args, {\n cwd: config.projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n const timer = config.timeout\n ? setTimeout(() => { proc.kill('SIGTERM'); }, config.timeout)\n : null;\n\n proc.on('close', (code) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, pid: proc.pid, exitCode: code, output: stdout, error: code !== 0 ? stderr : undefined });\n });\n\n proc.on('error', (err) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, error: `Failed to spawn aider: ${err.message}` });\n });\n });\n }\n\n private launchInteractive(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const parts = ['aider'];\n if (config.model) parts.push('--model', config.model);\n const script = `cd ${JSON.stringify(config.projectPath)} && ${parts.join(' ')}`;\n const proc = spawn('osascript', ['-e', `tell application \"Terminal\" to do script ${JSON.stringify(script)}`], {\n stdio: 'ignore',\n detached: true,\n });\n proc.unref();\n return Promise.resolve({ sessionId, pid: proc.pid });\n }\n}\n", "// generic.ts \u2014 opens a terminal in the project directory (fallback for unknown tools)\nimport { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\n\nexport class GenericLauncher implements ToolLauncher {\n constructor(public tool: string) {}\n\n capabilities: LaunchCapabilities = { headless: false, interactive: true, remoteSpawn: false };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n if (config.mode === 'headless') {\n return { sessionId, error: `${this.tool} does not support headless mode` };\n }\n\n // Just open a terminal in the project directory\n const script = `cd ${JSON.stringify(config.projectPath)} && echo \"Session ${sessionId} \u2014 tool: ${this.tool}\" && exec $SHELL`;\n const proc = spawn('osascript', ['-e', `tell application \"Terminal\" to do script ${JSON.stringify(script)}`], {\n stdio: 'ignore',\n detached: true,\n });\n proc.unref();\n return { sessionId, pid: proc.pid };\n }\n}\n", "import type { ToolLauncher } from './types.js';\nimport { ClaudeCodeLauncher } from './claude-code.js';\nimport { CodexLauncher } from './codex.js';\nimport { AiderLauncher } from './aider.js';\nimport { GenericLauncher } from './generic.js';\n\nexport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\nexport { ClaudeCodeLauncher } from './claude-code.js';\nexport { CodexLauncher } from './codex.js';\nexport { AiderLauncher } from './aider.js';\nexport { GenericLauncher } from './generic.js';\n\nconst launchers: Record<string, () => ToolLauncher> = {\n claude_code: () => new ClaudeCodeLauncher(),\n codex: () => new CodexLauncher(),\n aider: () => new AiderLauncher(),\n};\n\nexport function getLauncher(tool: string): ToolLauncher {\n const factory = launchers[tool];\n return factory ? factory() : new GenericLauncher(tool);\n}\n\nexport function getAvailableLaunchers(): Array<{ tool: string; capabilities: ToolLauncher['capabilities'] }> {\n return Object.entries(launchers).map(([tool, factory]) => ({\n tool,\n capabilities: factory().capabilities,\n }));\n}\n", "import path from 'node:path';\n\n/**\n * Shared, pure worktree-path math used by BOTH the worker's `ensureWorktree`\n * (apps/cli/src/lib/worktree.ts, which actually creates the worktree) and the\n * API's run reconcile fallback (apps/api/src/routes/runs.ts, which must derive\n * the same path to match captured sessions). It lives here, in the cross-app\n * `@rulemetric/session` package, so neither side duplicates the sanitizer \u2014\n * a drift between the two would silently break session\u2192run attribution.\n *\n * NOTE: this returns a `path.resolve`-only absolute path. The worker\n * additionally `realpath`-resolves it after creation (macOS `/var` \u2192\n * `/private/var`, etc.), so the persisted `launch_jobs.result.worktreePath` is\n * the authoritative join key. This derivation is a best-effort fallback for\n * the window before a job persists its result, and is exact only when the\n * repo root contains no symlinks.\n */\n\n/** Turn an arbitrary branch name into a filesystem-safe single path segment. */\nexport function sanitizeBranch(branch: string): string {\n return (\n branch\n // collapse any run of non-safe chars into a single dash\n .replace(/[^a-zA-Z0-9._-]+/g, '-')\n // trim leading/trailing dashes/dots so we never produce `.` or `-foo`\n .replace(/^[-.]+|[-.]+$/g, '') || 'worktree'\n );\n}\n\n/**\n * Compute the default worktree path for a (repoRoot, branch) pair: a SIBLING of\n * `repoRoot` at `<repoRoot>/../.rulemetric-worktrees/<sanitized-branch>`. Never\n * inside `repoRoot` (a nested worktree would be tracked by the parent repo).\n */\nexport function worktreePathFor(options: {\n repoRoot: string;\n branch: string;\n basePath?: string;\n}): string {\n return path.resolve(\n options.basePath ??\n path.join(options.repoRoot, '..', '.rulemetric-worktrees', sanitizeBranch(options.branch)),\n );\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["export const SESSION_TOOLS = ['claude_code', 'cursor', 'vscode_copilot', 'copilot_agent', 'rulemetric_mcp', 'codex', 'pi', 'opencode', 'antigravity'] as const;\nexport type SessionTool = (typeof SESSION_TOOLS)[number];\n\nexport const SESSION_EVENT_TYPES = [\n 'user_message',\n 'assistant_message',\n 'tool_call',\n 'tool_result',\n 'thinking',\n 'error',\n] as const;\nexport type SessionEventType = (typeof SESSION_EVENT_TYPES)[number];\n\nexport interface TokenUsage {\n input: number;\n output: number;\n cacheRead?: number;\n cacheWrite?: number;\n}\n\nexport interface SessionEvent {\n sequence: number;\n eventType: SessionEventType;\n content: string | null;\n toolName: string | null;\n toolInput: Record<string, unknown> | null;\n toolOutput: Record<string, unknown> | null;\n tokenUsage: TokenUsage | null;\n timestamp: string;\n metadata: Record<string, unknown>;\n // Optional model attribution per event (set by the codex adapter from\n // session_meta/turn_context; carried across incremental appends).\n model?: string | null;\n}\n\nexport interface ParsedSession {\n tool: SessionTool;\n projectPath: string | null;\n gitBranch: string | null;\n startedAt: string;\n endedAt: string | null;\n events: SessionEvent[];\n metadata: Record<string, unknown>;\n}\n\nexport interface SessionAdapter {\n tool: SessionTool;\n parse(input: string): ParsedSession;\n}\n\nexport interface Deviation {\n eventSequence: number;\n instructionId: string;\n description: string;\n severity: 'low' | 'medium' | 'high';\n}\n\nexport interface InstructionSuggestion {\n instructionId: string;\n currentContent: string;\n suggestedContent: string;\n rationale: string;\n confidence: number;\n}\n\nexport interface SessionAnalysis {\n adherenceScore: number;\n deviations: Deviation[];\n suggestions: InstructionSuggestion[];\n summary: string;\n analyzedAt: string;\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface ClaudeCodeRecord {\n type: string;\n uuid?: string;\n parentUuid?: string | null;\n sessionId?: string;\n requestId?: string;\n timestamp?: string;\n cwd?: string;\n gitBranch?: string;\n version?: string;\n userType?: string;\n slug?: string;\n message?: {\n role: string;\n model?: string;\n stop_reason?: string;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n service_tier?: string;\n speed?: string;\n inference_geo?: string;\n server_tool_use?: Record<string, number>;\n cache_creation?: Record<string, number>;\n };\n content: string | Array<{ type: string; text?: string; thinking?: string; id?: string; name?: string; input?: Record<string, unknown>; tool_use_id?: string; content?: string }>;\n };\n toolUseMessages?: unknown[];\n}\n\nexport class ClaudeCodeAdapter implements SessionAdapter {\n tool = 'claude_code' as const;\n\n parse(input: string): ParsedSession {\n const lines = input.split('\\n').filter((line) => line.trim());\n const records: ClaudeCodeRecord[] = [];\n\n for (const line of lines) {\n try {\n records.push(JSON.parse(line) as ClaudeCodeRecord);\n } catch {\n // Skip malformed lines\n }\n }\n\n const messageRecords = records.filter(\n (r) => r.type === 'user' || r.type === 'assistant',\n );\n\n let projectPath: string | null = null;\n let gitBranch: string | null = null;\n const metadata: Record<string, unknown> = {};\n\n // Extract project info from first user message\n const firstUser = records.find((r) => r.type === 'user');\n if (firstUser) {\n projectPath = firstUser.cwd ?? null;\n gitBranch = firstUser.gitBranch ?? null;\n if (firstUser.version) metadata.claudeCodeVersion = firstUser.version;\n if (firstUser.sessionId) metadata.sessionId = firstUser.sessionId;\n }\n\n // Extract model from first assistant message\n const firstAssistant = records.find((r) => r.type === 'assistant');\n if (firstAssistant?.message?.model) metadata.model = firstAssistant.message.model;\n\n const events: SessionEvent[] = [];\n let sequence = 0;\n\n for (const record of messageRecords) {\n const timestamp = record.timestamp ?? new Date().toISOString();\n\n if (record.type === 'user') {\n const messageContent = record.message?.content;\n\n if (typeof messageContent === 'string') {\n events.push({\n sequence: sequence++,\n eventType: 'user_message',\n content: messageContent,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: {},\n });\n } else if (Array.isArray(messageContent)) {\n for (const block of messageContent) {\n if (block.type === 'tool_result') {\n events.push({\n sequence: sequence++,\n eventType: 'tool_result',\n content: typeof block.content === 'string' ? block.content : JSON.stringify(block.content),\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: { toolUseId: block.tool_use_id },\n });\n }\n }\n }\n } else if (record.type === 'assistant') {\n const contentBlocks = Array.isArray(record.message?.content)\n ? record.message.content\n : [];\n\n // Extract token usage from the API response\n const usage = record.message?.usage;\n const tokenUsage = usage\n ? {\n input: usage.input_tokens ?? 0,\n output: usage.output_tokens ?? 0,\n cacheRead: usage.cache_read_input_tokens ?? 0,\n cacheWrite: usage.cache_creation_input_tokens ?? 0,\n }\n : null;\n\n // Build metadata with model info and extra usage details\n const assistantMeta: Record<string, unknown> = {};\n if (record.message?.model) assistantMeta.model = record.message.model;\n if (record.message?.stop_reason) assistantMeta.stopReason = record.message.stop_reason;\n if (record.requestId) assistantMeta.requestId = record.requestId;\n if (usage?.service_tier) assistantMeta.serviceTier = usage.service_tier;\n if (usage?.speed) assistantMeta.speed = usage.speed;\n if (usage?.cache_creation) assistantMeta.cacheCreationDetail = usage.cache_creation;\n if (usage?.server_tool_use) assistantMeta.serverToolUse = usage.server_tool_use;\n\n for (const block of contentBlocks) {\n if (block.type === 'text') {\n events.push({\n sequence: sequence++,\n eventType: 'assistant_message',\n content: block.text ?? '',\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage,\n timestamp,\n metadata: assistantMeta,\n });\n } else if (block.type === 'thinking') {\n events.push({\n sequence: sequence++,\n eventType: 'thinking',\n content: block.thinking ?? '',\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage,\n timestamp,\n metadata: assistantMeta,\n });\n } else if (block.type === 'tool_use') {\n events.push({\n sequence: sequence++,\n eventType: 'tool_call',\n content: null,\n toolName: block.name ?? 'unknown',\n toolInput: block.input ?? null,\n toolOutput: null,\n tokenUsage,\n timestamp,\n metadata: { ...assistantMeta, toolUseId: block.id },\n });\n }\n }\n }\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'claude_code',\n projectPath,\n gitBranch,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata,\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface CursorBubble {\n type: number; // 1 = user, 2 = assistant\n text: string;\n createdAt?: string;\n}\n\ninterface CursorComposer {\n composerId: string;\n conversationId?: string;\n createdAt?: string;\n conversation?: CursorBubble[];\n}\n\ninterface CursorComposerData {\n allComposers: Record<string, CursorComposer>;\n}\n\nexport class CursorAdapter implements SessionAdapter {\n tool = 'cursor' as const;\n\n /**\n * Parse from a SQLite database file path.\n * Reads `composer.composerData` from the ItemTable.\n */\n parse(dbPath: string): ParsedSession {\n // Dynamic import to avoid bundling better-sqlite3 when not needed\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const Database = require('better-sqlite3');\n const db = new Database(dbPath, { readonly: true });\n\n try {\n const row = db.prepare(\n \"SELECT value FROM ItemTable WHERE key = 'composer.composerData'\",\n ).get() as { value: string } | undefined;\n\n if (!row) {\n return this.emptySession();\n }\n\n return this.parseComposerJson(row.value);\n } finally {\n db.close();\n }\n }\n\n /**\n * Parse from raw composer data JSON (for testing without SQLite).\n */\n parseComposerJson(json: string): ParsedSession {\n let data: CursorComposerData;\n try {\n data = JSON.parse(json) as CursorComposerData;\n } catch {\n return this.emptySession();\n }\n\n const composers = Object.values(data.allComposers ?? {});\n if (composers.length === 0) {\n return this.emptySession();\n }\n\n // Take the most recent composer conversation\n const composer = composers.sort((a, b) => {\n const aTime = a.createdAt ? new Date(a.createdAt).getTime() : 0;\n const bTime = b.createdAt ? new Date(b.createdAt).getTime() : 0;\n return bTime - aTime;\n })[0];\n\n const bubbles = composer.conversation ?? [];\n const events: SessionEvent[] = [];\n\n for (let i = 0; i < bubbles.length; i++) {\n const bubble = bubbles[i];\n const timestamp = bubble.createdAt ?? new Date().toISOString();\n\n events.push({\n sequence: i,\n eventType: bubble.type === 1 ? 'user_message' : 'assistant_message',\n content: bubble.text,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: {},\n });\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'cursor',\n projectPath: null,\n gitBranch: null,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata: { composerId: composer.composerId },\n };\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'cursor',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface CopilotRequest {\n message: string;\n timestamp?: number;\n response?: {\n message: string;\n timestamp?: number;\n };\n}\n\ninterface CopilotSession {\n requesterUsername?: string;\n requests?: CopilotRequest[];\n customTitle?: string;\n}\n\nexport class VSCodeCopilotAdapter implements SessionAdapter {\n tool = 'vscode_copilot' as const;\n\n parse(input: string): ParsedSession {\n let data: CopilotSession;\n try {\n data = JSON.parse(input) as CopilotSession;\n } catch {\n return this.emptySession();\n }\n\n const requests = data.requests ?? [];\n const events: SessionEvent[] = [];\n let sequence = 0;\n\n for (const req of requests) {\n const userTimestamp = req.timestamp\n ? new Date(req.timestamp).toISOString()\n : new Date().toISOString();\n\n events.push({\n sequence: sequence++,\n eventType: 'user_message',\n content: req.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: userTimestamp,\n metadata: {},\n });\n\n if (req.response) {\n const assistantTimestamp = req.response.timestamp\n ? new Date(req.response.timestamp).toISOString()\n : userTimestamp;\n\n events.push({\n sequence: sequence++,\n eventType: 'assistant_message',\n content: req.response.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: assistantTimestamp,\n metadata: {},\n });\n }\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'vscode_copilot',\n projectPath: null,\n gitBranch: null,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata: {\n ...(data.requesterUsername && { username: data.requesterUsername }),\n ...(data.customTitle && { title: data.customTitle }),\n },\n };\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'vscode_copilot',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface CopilotAgentToolCall {\n name?: string;\n input?: Record<string, unknown>;\n output?: Record<string, unknown>;\n timestamp?: number;\n}\n\ninterface CopilotAgentRequest {\n message: string;\n timestamp?: number;\n agentMode?: boolean;\n toolCalls?: CopilotAgentToolCall[];\n response?: {\n message: string;\n timestamp?: number;\n };\n}\n\ninterface CopilotAgentSession {\n requesterUsername?: string;\n requests?: CopilotAgentRequest[];\n customTitle?: string;\n agentMode?: boolean;\n}\n\nexport class CopilotAgentAdapter implements SessionAdapter {\n tool = 'copilot_agent' as const;\n\n parse(input: string): ParsedSession {\n let data: CopilotAgentSession;\n try {\n data = JSON.parse(input) as CopilotAgentSession;\n } catch {\n return this.emptySession();\n }\n\n const requests = data.requests ?? [];\n const events: SessionEvent[] = [];\n let sequence = 0;\n\n for (const req of requests) {\n const userTimestamp = req.timestamp\n ? new Date(req.timestamp).toISOString()\n : new Date().toISOString();\n\n events.push({\n sequence: sequence++,\n eventType: 'user_message',\n content: req.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: userTimestamp,\n metadata: {},\n });\n\n // Emit tool_call events for each tool call\n if (req.toolCalls) {\n for (const tc of req.toolCalls) {\n const toolTimestamp = tc.timestamp\n ? new Date(tc.timestamp).toISOString()\n : userTimestamp;\n\n events.push({\n sequence: sequence++,\n eventType: 'tool_call',\n content: null,\n toolName: tc.name ?? 'unknown',\n toolInput: tc.input ?? null,\n toolOutput: tc.output ?? null,\n tokenUsage: null,\n timestamp: toolTimestamp,\n metadata: {},\n });\n }\n }\n\n if (req.response) {\n const assistantTimestamp = req.response.timestamp\n ? new Date(req.response.timestamp).toISOString()\n : userTimestamp;\n\n events.push({\n sequence: sequence++,\n eventType: 'assistant_message',\n content: req.response.message,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp: assistantTimestamp,\n metadata: {},\n });\n }\n }\n\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n\n return {\n tool: 'copilot_agent',\n projectPath: null,\n gitBranch: null,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata: {\n ...(data.requesterUsername && { username: data.requesterUsername }),\n ...(data.customTitle && { title: data.customTitle }),\n ...(data.agentMode != null && { agentMode: data.agentMode }),\n },\n };\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'copilot_agent',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { SessionAdapter, SessionEvent, ParsedSession } from '../types.js';\n\ninterface RuleMetricMcpEvent {\n sequence?: number;\n eventType?: string;\n content?: string | null;\n toolName?: string | null;\n toolInput?: Record<string, unknown> | null;\n toolOutput?: Record<string, unknown> | null;\n tokenUsage?: { input: number; output: number; cacheRead?: number; cacheWrite?: number } | null;\n timestamp?: string;\n metadata?: Record<string, unknown>;\n}\n\ninterface RuleMetricMcpSession {\n events?: RuleMetricMcpEvent[];\n projectPath?: string;\n gitBranch?: string;\n startedAt?: string;\n endedAt?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport class RuleMetricMcpAdapter implements SessionAdapter {\n tool = 'rulemetric_mcp' as const;\n\n parse(input: string): ParsedSession {\n let data: RuleMetricMcpSession;\n try {\n data = JSON.parse(input) as RuleMetricMcpSession;\n } catch {\n return this.emptySession();\n }\n\n const rawEvents = data.events ?? [];\n const events: SessionEvent[] = rawEvents.map((e, i) => ({\n sequence: e.sequence ?? i,\n eventType: this.normalizeEventType(e.eventType),\n content: e.content ?? null,\n toolName: e.toolName ?? null,\n toolInput: e.toolInput ?? null,\n toolOutput: e.toolOutput ?? null,\n tokenUsage: e.tokenUsage ?? null,\n timestamp: e.timestamp ?? new Date().toISOString(),\n metadata: e.metadata ?? {},\n }));\n\n const now = new Date().toISOString();\n\n return {\n tool: 'rulemetric_mcp',\n projectPath: data.projectPath ?? null,\n gitBranch: data.gitBranch ?? null,\n startedAt: data.startedAt ?? events[0]?.timestamp ?? now,\n endedAt: data.endedAt ?? events[events.length - 1]?.timestamp ?? null,\n events,\n metadata: data.metadata ?? {},\n };\n }\n\n private normalizeEventType(type?: string): SessionEvent['eventType'] {\n const valid = ['user_message', 'assistant_message', 'tool_call', 'tool_result', 'thinking', 'error'];\n if (type && valid.includes(type)) return type as SessionEvent['eventType'];\n return 'assistant_message';\n }\n\n private emptySession(): ParsedSession {\n return {\n tool: 'rulemetric_mcp',\n projectPath: null,\n gitBranch: null,\n startedAt: new Date().toISOString(),\n endedAt: null,\n events: [],\n metadata: {},\n };\n }\n}\n", "import type { ParsedSession, SessionAdapter, SessionEvent, TokenUsage } from '../types.js';\n\ninterface CodexContentBlock {\n type?: string;\n text?: string;\n}\n\ninterface CodexTokenUsage {\n input_tokens?: number;\n cached_input_tokens?: number;\n output_tokens?: number;\n reasoning_output_tokens?: number;\n total_tokens?: number;\n}\n\ninterface CodexEntry {\n timestamp?: string;\n type?: string;\n payload?: {\n type?: string;\n role?: string;\n cwd?: string;\n git_branch?: string;\n session_id?: string;\n id?: string;\n originator?: string;\n cli_version?: string;\n source?: string;\n model?: string;\n model_provider?: string;\n name?: string;\n call_id?: string;\n arguments?: string;\n output?: string;\n content?: CodexContentBlock[];\n info?: {\n model?: string;\n model_name?: string;\n last_token_usage?: CodexTokenUsage;\n total_token_usage?: CodexTokenUsage;\n };\n };\n}\n\nfunction safeJsonParse(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction textFromBlocks(blocks: CodexContentBlock[] | undefined, wanted: string[]): string {\n if (!Array.isArray(blocks)) return '';\n return blocks\n .filter((b) => b.type && wanted.includes(b.type))\n .map((b) => b.text ?? '')\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction tokenUsageFromCodex(raw: CodexTokenUsage | undefined): TokenUsage | null {\n if (!raw) return null;\n const cacheRead = raw.cached_input_tokens ?? 0;\n const input = Math.max(0, (raw.input_tokens ?? 0) - cacheRead);\n const output = (raw.output_tokens ?? 0) + (raw.reasoning_output_tokens ?? 0);\n if (input === 0 && output === 0 && cacheRead === 0) return null;\n return { input, output, cacheRead, cacheWrite: 0 };\n}\n\nfunction normalizeTimestamp(ts: string | undefined): string {\n if (!ts) return new Date().toISOString();\n const d = new Date(ts);\n return Number.isFinite(d.getTime()) ? d.toISOString() : new Date().toISOString();\n}\n\n/**\n * Resumable parser state. Carried across incremental (`parseAppend`) calls so a\n * tail-only parse produces byte-identical events to a single full parse:\n * - `sequence` \u2014 absolute event index; continues across appends.\n * - `model` \u2014 last seen model (set by session_meta/turn_context near\n * the file head); later events inherit it.\n * - `prevCumulativeTotal` \u2014 token_count dedup watermark (skip unchanged totals).\n * - `callNames` \u2014 call_id \u2192 tool name, so a tool_result whose tool_call\n * landed in an earlier append still resolves its name.\n * Plain JSON (callNames is a Record, not a Map) so the server can persist it in\n * `session.metadata` between appends.\n */\nexport interface CodexParseState {\n sequence: number;\n model: string | null;\n prevCumulativeTotal: number;\n callNames: Record<string, string>;\n}\n\nexport function freshCodexState(): CodexParseState {\n return { sequence: 0, model: null, prevCumulativeTotal: 0, callNames: {} };\n}\n\nexport class CodexAdapter implements SessionAdapter {\n tool = 'codex' as const;\n\n parse(input: string): ParsedSession {\n const state = freshCodexState();\n const { events, projectPath, gitBranch, metadata } = this.parseLines(input, state);\n const timestamps = events.map((e) => e.timestamp).sort();\n const now = new Date().toISOString();\n return {\n tool: 'codex',\n projectPath,\n gitBranch,\n startedAt: timestamps[0] ?? now,\n endedAt: timestamps[timestamps.length - 1] ?? null,\n events,\n metadata,\n };\n }\n\n /**\n * Incrementally parse a tail of new JSONL lines, resuming from `prior` state.\n * Returns the new events (sequences continue from prior.sequence) and the\n * updated state to carry into the next append. `prior` is not mutated.\n */\n parseAppend(input: string, prior: CodexParseState): { events: SessionEvent[]; state: CodexParseState } {\n const state: CodexParseState = { ...prior, callNames: { ...prior.callNames } };\n const { events } = this.parseLines(input, state);\n return { events, state };\n }\n\n private parseLines(\n input: string,\n state: CodexParseState,\n ): {\n events: SessionEvent[];\n projectPath: string | null;\n gitBranch: string | null;\n sessionId: string | null;\n metadata: Record<string, unknown>;\n } {\n const lines = input.split('\\n').filter((line) => line.trim());\n const events: SessionEvent[] = [];\n const metadata: Record<string, unknown> = {};\n const callNames = state.callNames;\n let projectPath: string | null = null;\n let gitBranch: string | null = null;\n let sessionId: string | null = null;\n\n for (const line of lines) {\n let entry: CodexEntry;\n try {\n entry = JSON.parse(line) as CodexEntry;\n } catch {\n continue;\n }\n\n const payload = entry.payload;\n if (!payload) continue;\n const timestamp = normalizeTimestamp(entry.timestamp);\n\n if (entry.type === 'session_meta') {\n sessionId = payload.session_id ?? payload.id ?? sessionId;\n projectPath = payload.cwd ?? projectPath;\n if (payload.git_branch) gitBranch = payload.git_branch;\n if (payload.model) state.model = payload.model;\n metadata.sessionId = sessionId;\n metadata.codexSessionId = sessionId;\n metadata.originator = payload.originator;\n metadata.source = payload.source;\n metadata.modelProvider = payload.model_provider;\n metadata.codexCliVersion = payload.cli_version;\n continue;\n }\n\n if (entry.type === 'turn_context') {\n projectPath = payload.cwd ?? projectPath;\n if (payload.model) {\n state.model = payload.model;\n metadata.model = payload.model;\n }\n continue;\n }\n\n if (entry.type === 'response_item' && payload.type === 'message') {\n if (payload.role === 'user') {\n const content = textFromBlocks(payload.content, ['input_text']);\n if (!content) continue;\n events.push({\n sequence: state.sequence++,\n eventType: 'user_message',\n content,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n timestamp,\n metadata: {},\n });\n } else if (payload.role === 'assistant') {\n const content = textFromBlocks(payload.content, ['output_text']);\n if (!content) continue;\n events.push({\n sequence: state.sequence++,\n eventType: 'assistant_message',\n content,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: null,\n model: state.model,\n timestamp,\n metadata: state.model ? { model: state.model } : {},\n });\n }\n continue;\n }\n\n if (entry.type === 'response_item' && payload.type === 'function_call') {\n const toolName = payload.name ?? 'unknown';\n if (payload.call_id) callNames[payload.call_id] = toolName;\n const args = typeof payload.arguments === 'string' ? safeJsonParse(payload.arguments) : {};\n events.push({\n sequence: state.sequence++,\n eventType: 'tool_call',\n content: null,\n toolName,\n toolInput: args && typeof args === 'object' && !Array.isArray(args) ? args as Record<string, unknown> : { arguments: args },\n toolOutput: null,\n tokenUsage: null,\n model: state.model,\n timestamp,\n metadata: { callId: payload.call_id },\n });\n continue;\n }\n\n if (entry.type === 'response_item' && payload.type === 'function_call_output') {\n const toolName = payload.call_id ? callNames[payload.call_id] ?? null : null;\n events.push({\n sequence: state.sequence++,\n eventType: 'tool_result',\n content: payload.output ?? null,\n toolName,\n toolInput: null,\n toolOutput: payload.output == null ? null : { output: payload.output },\n tokenUsage: null,\n model: state.model,\n timestamp,\n metadata: { callId: payload.call_id },\n });\n continue;\n }\n\n if (entry.type === 'event_msg' && payload.type === 'token_count') {\n const info = payload.info;\n const cumulativeTotal = info?.total_token_usage?.total_tokens ?? 0;\n if (cumulativeTotal > 0 && cumulativeTotal === state.prevCumulativeTotal) continue;\n if (cumulativeTotal > 0) state.prevCumulativeTotal = cumulativeTotal;\n const usage = tokenUsageFromCodex(info?.last_token_usage ?? info?.total_token_usage);\n if (!usage) continue;\n const eventModel = info?.model ?? info?.model_name ?? state.model;\n events.push({\n sequence: state.sequence++,\n eventType: 'assistant_message',\n content: null,\n toolName: null,\n toolInput: null,\n toolOutput: null,\n tokenUsage: usage,\n model: eventModel ?? null,\n timestamp,\n metadata: {\n codexEventType: 'token_count',\n ...(eventModel ? { model: eventModel } : {}),\n reasoningOutputTokens: info?.last_token_usage?.reasoning_output_tokens ?? 0,\n },\n });\n }\n }\n\n return { events, projectPath, gitBranch, sessionId, metadata };\n }\n}\n", "import type { SessionAdapter, SessionTool } from './types.js';\nimport { ClaudeCodeAdapter } from './adapters/claude-code.js';\nimport { CursorAdapter } from './adapters/cursor.js';\nimport { VSCodeCopilotAdapter } from './adapters/vscode-copilot.js';\nimport { CopilotAgentAdapter } from './adapters/copilot-agent.js';\nimport { RuleMetricMcpAdapter } from './adapters/rulemetric-mcp.js';\nimport { CodexAdapter } from './adapters/codex.js';\n\nconst adapters: Record<string, () => SessionAdapter> = {\n claude_code: () => new ClaudeCodeAdapter(),\n cursor: () => new CursorAdapter(),\n vscode_copilot: () => new VSCodeCopilotAdapter(),\n copilot_agent: () => new CopilotAgentAdapter(),\n rulemetric_mcp: () => new RuleMetricMcpAdapter(),\n codex: () => new CodexAdapter(),\n};\n\nexport function getAdapter(tool: SessionTool): SessionAdapter {\n const factory = adapters[tool];\n if (!factory) {\n throw new Error(`Unknown session tool: ${tool}`);\n }\n return factory();\n}\n\nexport function detectTool(input: string): SessionTool | null {\n const trimmed = input.trim();\n\n if (trimmed.startsWith('{')) {\n // Try single-line JSON first (JSONL first line), then full multi-line JSON\n const firstLine = trimmed.split('\\n')[0];\n let parsed: Record<string, unknown> | null = null;\n\n try {\n parsed = JSON.parse(firstLine);\n } catch {\n // First line wasn't complete JSON (pretty-printed) \u2014 try full content\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n // Not valid JSON \u2014 fall through to JSONL detection\n }\n }\n\n if (parsed) {\n // Claude Code JSONL: has type field with user/assistant\n if (parsed.type === 'user' || parsed.type === 'assistant') {\n return 'claude_code';\n }\n\n // RuleMetric MCP: has top-level events array without other format markers\n if (Array.isArray(parsed.events) && !parsed.requests && !parsed.allComposers) {\n return 'rulemetric_mcp';\n }\n\n // Copilot Agent: has requests array with toolCalls or agentMode flag\n if (Array.isArray(parsed.requests)) {\n const hasToolCalls = parsed.requests.some(\n (r: Record<string, unknown>) => Array.isArray(r.toolCalls),\n );\n if (hasToolCalls || parsed.agentMode) {\n return 'copilot_agent';\n }\n return 'vscode_copilot';\n }\n\n // Cursor: has allComposers key\n if (parsed.allComposers) {\n return 'cursor';\n }\n }\n\n // JSONL detection: multiple lines, each valid JSON\n if (!parsed) {\n try {\n const lines = trimmed.split('\\n').filter((l) => l.trim());\n if (lines.length > 1) {\n const first = JSON.parse(lines[0]);\n if (first.type === 'user' || first.type === 'assistant') {\n return 'claude_code';\n }\n }\n } catch {\n // Not JSONL either\n }\n }\n }\n\n return null;\n}\n", "import type { SessionEvent, SessionAnalysis } from './types.js';\n\ninterface InstructionContext {\n id: string;\n name: string;\n content: string;\n}\n\nexport function buildAnalysisPrompt(\n events: SessionEvent[],\n instructions: InstructionContext[],\n): string {\n const instructionSection = instructions.length > 0\n ? instructions.map((i) => `### ${i.name} (ID: ${i.id})\\n\\n${i.content}`).join('\\n\\n---\\n\\n')\n : 'No instructions were linked to this session.';\n\n const eventSummary = events.map((e) => {\n const prefix = `[${e.sequence}] ${e.eventType}`;\n if (e.eventType === 'tool_call') {\n return `${prefix}: ${e.toolName}(${JSON.stringify(e.toolInput)})`;\n }\n if (e.eventType === 'tool_result') {\n const preview = e.content?.slice(0, 200) ?? '';\n return `${prefix}: ${preview}${e.content && e.content.length > 200 ? '...' : ''}`;\n }\n const preview = e.content?.slice(0, 300) ?? '';\n return `${prefix}: ${preview}${e.content && e.content.length > 300 ? '...' : ''}`;\n }).join('\\n');\n\n return `You are analyzing an AI coding session to evaluate how well the agent followed its instructions and to suggest improvements.\n\n## Active Instructions\n\n${instructionSection}\n\n## Session Transcript\n\n${eventSummary}\n\n## Analysis Tasks\n\n1. **Adherence Score** (0-100): Rate how well the agent followed each active instruction. 100 = perfect adherence.\n2. **Deviations**: List specific events where the agent deviated from instructions. Each deviation needs:\n - eventSequence: the event number\n - instructionId: which instruction was violated\n - description: what went wrong\n - severity: \"low\", \"medium\", or \"high\"\n3. **Suggestions**: For each gap or deviation, propose a specific edit to the instruction. Each suggestion needs:\n - instructionId: which instruction to improve\n - currentContent: the relevant excerpt from the instruction\n - suggestedContent: your proposed replacement text\n - rationale: why this change would help\n - confidence: 0-100 how confident you are this would improve outcomes\n4. **Summary**: One paragraph summarizing the session quality.\n\nReturn your response as JSON matching this schema:\n{\n \"adherenceScore\": <number 0-100>,\n \"deviations\": [{ \"eventSequence\": <number>, \"instructionId\": \"<string>\", \"description\": \"<string>\", \"severity\": \"<low|medium|high>\" }],\n \"suggestions\": [{ \"instructionId\": \"<string>\", \"currentContent\": \"<string>\", \"suggestedContent\": \"<string>\", \"rationale\": \"<string>\", \"confidence\": <number 0-100> }],\n \"summary\": \"<string>\"\n}\n\nReturn valid JSON only.`;\n}\n\nexport function parseAnalysisResponse(response: string): SessionAnalysis | null {\n try {\n // Extract JSON from response (may be wrapped in markdown fences)\n const jsonMatch = response.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) return null;\n\n const parsed = JSON.parse(jsonMatch[0]);\n\n // Validate required fields\n if (\n typeof parsed.adherenceScore !== 'number' ||\n !Array.isArray(parsed.deviations) ||\n !Array.isArray(parsed.suggestions) ||\n typeof parsed.summary !== 'string'\n ) {\n return null;\n }\n\n return {\n adherenceScore: parsed.adherenceScore,\n deviations: parsed.deviations,\n suggestions: parsed.suggestions,\n summary: parsed.summary,\n analyzedAt: new Date().toISOString(),\n };\n } catch {\n return null;\n }\n}\n", "import { readdir, stat } from 'fs/promises';\nimport { basename, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst shortNames: Record<string, string> = {\n 'claude-opus-4-7': 'Opus 4.7',\n 'claude-opus-4-6': 'Opus 4.6',\n 'claude-opus-4-5': 'Opus 4.5',\n 'claude-opus-4-1': 'Opus 4.1',\n 'claude-opus-4': 'Opus 4',\n 'claude-sonnet-4-6': 'Sonnet 4.6',\n 'claude-sonnet-4-5': 'Sonnet 4.5',\n 'claude-sonnet-4': 'Sonnet 4',\n 'claude-3-7-sonnet': 'Sonnet 3.7',\n 'claude-3-5-sonnet': 'Sonnet 3.5',\n 'claude-haiku-4-5': 'Haiku 4.5',\n 'claude-3-5-haiku': 'Haiku 3.5',\n};\n\nfunction getClaudeDir(): string {\n return process.env['CLAUDE_CONFIG_DIR'] || join(homedir(), '.claude');\n}\n\nfunction getProjectsDir(): string {\n return join(getClaudeDir(), 'projects');\n}\n\nfunction getDesktopSessionsDir(): string {\n if (process.platform === 'darwin') return join(homedir(), 'Library', 'Application Support', 'Claude', 'local-agent-mode-sessions');\n if (process.platform === 'win32') return join(homedir(), 'AppData', 'Roaming', 'Claude', 'local-agent-mode-sessions');\n return join(homedir(), '.config', 'Claude', 'local-agent-mode-sessions');\n}\n\nasync function findDesktopProjectDirs(base: string): Promise<string[]> {\n const results: string[] = [];\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > 8) return;\n const entries = await readdir(dir).catch(() => []);\n for (const entry of entries) {\n if (entry === 'node_modules' || entry === '.git') continue;\n const full = join(dir, entry);\n const s = await stat(full).catch(() => null);\n if (!s?.isDirectory()) continue;\n if (entry === 'projects') {\n const projectDirs = await readdir(full).catch(() => []);\n for (const pd of projectDirs) {\n const pdFull = join(full, pd);\n const pdStat = await stat(pdFull).catch(() => null);\n if (pdStat?.isDirectory()) results.push(pdFull);\n }\n } else {\n await walk(full, depth + 1);\n }\n }\n }\n await walk(base, 0);\n return results;\n}\n\nexport const claudeCode: Provider = {\n name: 'claude',\n displayName: 'Claude Code',\n\n modelDisplayName(model: string): string {\n const canonical = model.replace(/@.*$/, '').replace(/-\\d{8}$/, '');\n for (const [key, name] of Object.entries(shortNames)) {\n if (canonical.startsWith(key)) return name;\n }\n return canonical;\n },\n\n toolDisplayName(rawTool: string): string {\n return rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n const sources: SessionSource[] = [];\n\n const projectsDir = getProjectsDir();\n try {\n const entries = await readdir(projectsDir);\n for (const dirName of entries) {\n const dirPath = join(projectsDir, dirName);\n const dirStat = await stat(dirPath).catch(() => null);\n if (dirStat?.isDirectory()) {\n sources.push({ path: dirPath, project: dirName, provider: 'claude' });\n }\n }\n } catch { /* projects dir may not exist */ }\n\n const desktopDirs = await findDesktopProjectDirs(getDesktopSessionsDir());\n for (const dirPath of desktopDirs) {\n sources.push({ path: dirPath, project: basename(dirPath), provider: 'claude' });\n }\n\n return sources;\n },\n\n createSessionParser(): SessionParser {\n // Claude Code sessions are parsed via the existing ClaudeCodeAdapter.\n // This provider handles discovery; parsing is done by the adapter.\n return {\n async *parse() { /* no-op \u2014 use ClaudeCodeAdapter for full parsing */ },\n };\n },\n};\n", "import { readdir, readFile, stat } from 'fs/promises';\nimport { basename, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-5.3-codex': 'GPT-5.3 Codex',\n 'gpt-5.4-mini': 'GPT-5.4 Mini',\n 'gpt-5.4': 'GPT-5.4',\n 'gpt-5': 'GPT-5',\n 'gpt-4o-mini': 'GPT-4o Mini',\n 'gpt-4o': 'GPT-4o',\n};\n\nconst toolNameMap: Record<string, string> = {\n exec_command: 'Bash',\n read_file: 'Read',\n write_file: 'Edit',\n apply_diff: 'Edit',\n apply_patch: 'Edit',\n spawn_agent: 'Agent',\n close_agent: 'Agent',\n wait_agent: 'Agent',\n read_dir: 'Glob',\n};\n\ntype CodexEntry = {\n type: string;\n timestamp?: string;\n payload?: {\n type?: string;\n role?: string;\n cwd?: string;\n model_provider?: string;\n originator?: string;\n session_id?: string;\n model?: string;\n name?: string;\n content?: Array<{ type?: string; text?: string }>;\n info?: {\n model?: string;\n model_name?: string;\n last_token_usage?: CodexTokenUsage;\n total_token_usage?: CodexTokenUsage;\n };\n };\n};\n\ntype CodexTokenUsage = {\n input_tokens?: number;\n cached_input_tokens?: number;\n output_tokens?: number;\n reasoning_output_tokens?: number;\n total_tokens?: number;\n};\n\nfunction getCodexDir(): string {\n return process.env['CODEX_HOME'] ?? join(homedir(), '.codex');\n}\n\nfunction sanitizeProject(cwd: string): string {\n return cwd.replace(/^\\//, '').replace(/\\//g, '-');\n}\n\nasync function readFirstLine(filePath: string): Promise<CodexEntry | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const line = content.split('\\n')[0];\n if (!line?.trim()) return null;\n return JSON.parse(line) as CodexEntry;\n } catch {\n return null;\n }\n}\n\nasync function isValidCodexSession(filePath: string): Promise<{ valid: boolean; meta?: CodexEntry }> {\n const entry = await readFirstLine(filePath);\n if (!entry) return { valid: false };\n const valid = entry.type === 'session_meta' &&\n typeof entry.payload?.originator === 'string' &&\n entry.payload.originator.toLowerCase().startsWith('codex');\n return { valid, meta: valid ? entry : undefined };\n}\n\nasync function discoverSessionsInDir(codexDir: string): Promise<SessionSource[]> {\n const sessionsDir = join(codexDir, 'sessions');\n const sources: SessionSource[] = [];\n\n let years: string[];\n try {\n years = await readdir(sessionsDir);\n } catch {\n return sources;\n }\n\n for (const year of years) {\n if (!/^\\d{4}$/.test(year)) continue;\n const yearDir = join(sessionsDir, year);\n const months = await readdir(yearDir).catch(() => [] as string[]);\n\n for (const month of months) {\n if (!/^\\d{2}$/.test(month)) continue;\n const monthDir = join(yearDir, month);\n const days = await readdir(monthDir).catch(() => [] as string[]);\n\n for (const day of days) {\n if (!/^\\d{2}$/.test(day)) continue;\n const dayDir = join(monthDir, day);\n const files = await readdir(dayDir).catch(() => [] as string[]);\n\n for (const file of files) {\n if (!file.startsWith('rollout-') || !file.endsWith('.jsonl')) continue;\n const filePath = join(dayDir, file);\n const s = await stat(filePath).catch(() => null);\n if (!s?.isFile()) continue;\n\n const { valid, meta } = await isValidCodexSession(filePath);\n if (!valid || !meta) continue;\n\n const cwd = meta.payload?.cwd ?? 'unknown';\n sources.push({ path: filePath, project: sanitizeProject(cwd), provider: 'codex' });\n }\n }\n }\n }\n\n return sources;\n}\n\nfunction resolveModel(info: CodexEntry['payload'], sessionModel?: string): string {\n return info?.info?.model\n ?? info?.info?.model_name\n ?? sessionModel\n ?? 'gpt-5';\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n let content: string;\n try {\n content = await readFile(source.path, 'utf-8');\n } catch {\n return;\n }\n\n const lines = content.split('\\n').filter(l => l.trim());\n let sessionModel: string | undefined;\n let sessionId = '';\n let prevCumulativeTotal = 0;\n let prevInput = 0;\n let prevCached = 0;\n let prevOutput = 0;\n let prevReasoning = 0;\n let pendingTools: string[] = [];\n let pendingUserMessage = '';\n\n for (const line of lines) {\n let entry: CodexEntry;\n try {\n entry = JSON.parse(line) as CodexEntry;\n } catch {\n continue;\n }\n\n if (entry.type === 'session_meta') {\n sessionId = entry.payload?.session_id ?? basename(source.path, '.jsonl');\n sessionModel = entry.payload?.model;\n continue;\n }\n\n if (entry.type === 'response_item' && entry.payload?.type === 'function_call') {\n const rawName = entry.payload.name ?? '';\n pendingTools.push(toolNameMap[rawName] ?? rawName);\n continue;\n }\n\n if (entry.type === 'response_item' && entry.payload?.type === 'message' && entry.payload?.role === 'user') {\n const texts = (entry.payload.content ?? [])\n .filter(c => c.type === 'input_text')\n .map(c => c.text ?? '')\n .filter(Boolean);\n if (texts.length > 0) pendingUserMessage = texts.join(' ');\n continue;\n }\n\n if (entry.type === 'event_msg' && entry.payload?.type === 'token_count') {\n const info = entry.payload.info;\n if (!info) continue;\n\n const cumulativeTotal = info.total_token_usage?.total_tokens ?? 0;\n if (cumulativeTotal > 0 && cumulativeTotal === prevCumulativeTotal) continue;\n prevCumulativeTotal = cumulativeTotal;\n\n const last = info.last_token_usage;\n let inputTokens = 0;\n let cachedInputTokens = 0;\n let outputTokens = 0;\n let reasoningTokens = 0;\n\n if (last) {\n inputTokens = last.input_tokens ?? 0;\n cachedInputTokens = last.cached_input_tokens ?? 0;\n outputTokens = last.output_tokens ?? 0;\n reasoningTokens = last.reasoning_output_tokens ?? 0;\n } else if (cumulativeTotal > 0) {\n const total = info.total_token_usage;\n if (!total) continue;\n inputTokens = (total.input_tokens ?? 0) - prevInput;\n cachedInputTokens = (total.cached_input_tokens ?? 0) - prevCached;\n outputTokens = (total.output_tokens ?? 0) - prevOutput;\n reasoningTokens = (total.reasoning_output_tokens ?? 0) - prevReasoning;\n }\n\n if (!last) {\n const total = info.total_token_usage;\n if (total) {\n prevInput = total.input_tokens ?? 0;\n prevCached = total.cached_input_tokens ?? 0;\n prevOutput = total.output_tokens ?? 0;\n prevReasoning = total.reasoning_output_tokens ?? 0;\n }\n }\n\n const totalTokens = inputTokens + cachedInputTokens + outputTokens + reasoningTokens;\n if (totalTokens === 0) continue;\n\n // OpenAI includes cached tokens inside input_tokens; normalize to non-cached only\n const uncachedInputTokens = Math.max(0, inputTokens - cachedInputTokens);\n\n const model = resolveModel(entry.payload, sessionModel);\n const timestamp = entry.timestamp ?? '';\n const dedupKey = `codex:${source.path}:${timestamp}:${cumulativeTotal}`;\n\n if (seenKeys.has(dedupKey)) continue;\n seenKeys.add(dedupKey);\n\n yield {\n provider: 'codex',\n model,\n inputTokens: uncachedInputTokens,\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: cachedInputTokens,\n cachedInputTokens,\n reasoningTokens,\n costUSD: 0, // Cost calculated downstream\n tools: pendingTools,\n bashCommands: [],\n timestamp,\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n };\n\n pendingTools = [];\n pendingUserMessage = '';\n }\n }\n },\n };\n}\n\nexport const codex: Provider = {\n name: 'codex',\n displayName: 'Codex',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of Object.entries(modelDisplayNames)) {\n if (model.startsWith(key)) return name;\n }\n return model;\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(getCodexDir());\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys);\n },\n};\n", "import { readdir, readFile, stat } from 'fs/promises';\nimport { basename, dirname, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-4.1-nano': 'GPT-4.1 Nano',\n 'gpt-4.1-mini': 'GPT-4.1 Mini',\n 'gpt-4.1': 'GPT-4.1',\n 'gpt-4o-mini': 'GPT-4o Mini',\n 'gpt-4o': 'GPT-4o',\n 'gpt-5-mini': 'GPT-5 Mini',\n 'gpt-5': 'GPT-5',\n 'claude-sonnet-4-5': 'Sonnet 4.5',\n 'claude-sonnet-4': 'Sonnet 4',\n 'claude-3-7-sonnet': 'Sonnet 3.7',\n 'claude-3-5-sonnet': 'Sonnet 3.5',\n 'o4-mini': 'o4-mini',\n 'o3': 'o3',\n};\n\nconst toolNameMap: Record<string, string> = {\n bash: 'Bash',\n read_file: 'Read',\n write_file: 'Edit',\n edit_file: 'Edit',\n create_file: 'Write',\n delete_file: 'Delete',\n search_files: 'Grep',\n find_files: 'Glob',\n list_directory: 'LS',\n web_search: 'WebSearch',\n fetch_webpage: 'WebFetch',\n github_repo: 'GitHub',\n};\n\nconst modelDisplayEntries = Object.entries(modelDisplayNames).sort((a, b) => b[0].length - a[0].length);\n\ntype ToolRequest = {\n name?: string;\n toolCallId?: string;\n type?: string;\n};\n\ntype CopilotEvent =\n | { type: 'session.model_change'; timestamp?: string; data: { newModel: string } }\n | { type: 'user.message'; timestamp?: string; data: { content: string } }\n | { type: 'assistant.message'; timestamp?: string; data: { messageId: string; outputTokens: number; toolRequests?: ToolRequest[] } };\n\nfunction getCopilotSessionStateDir(): string {\n return join(homedir(), '.copilot', 'session-state');\n}\n\nfunction parseCwd(yaml: string): string | null {\n const match = yaml.match(/^cwd:\\s*(.+)$/m);\n if (!match?.[1]) return null;\n return match[1].replace(/\\s*#.*$/, '').replace(/^['\"]|['\"]$/g, '').trim() || null;\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n let content: string;\n try {\n content = await readFile(source.path, 'utf-8');\n } catch {\n return;\n }\n\n const sessionId = basename(dirname(source.path));\n const lines = content.split('\\n').filter(l => l.trim());\n let currentModel = '';\n let pendingUserMessage = '';\n\n for (const line of lines) {\n let event: CopilotEvent;\n try {\n event = JSON.parse(line) as CopilotEvent;\n } catch {\n continue;\n }\n\n if (event.type === 'session.model_change') {\n currentModel = event.data.newModel ?? currentModel;\n continue;\n }\n\n if (event.type === 'user.message') {\n pendingUserMessage = event.data.content ?? '';\n continue;\n }\n\n if (event.type === 'assistant.message') {\n const { messageId, outputTokens, toolRequests = [] } = event.data;\n if (outputTokens === 0) continue;\n if (!currentModel) continue;\n\n const dedupKey = `copilot:${sessionId}:${messageId}`;\n if (seenKeys.has(dedupKey)) continue;\n seenKeys.add(dedupKey);\n\n const tools = toolRequests\n .map(t => t.name ?? '')\n .filter(Boolean)\n .map(n => toolNameMap[n] ?? n);\n\n yield {\n provider: 'copilot',\n model: currentModel,\n inputTokens: 0, // Copilot only logs outputTokens\n outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: 0,\n cachedInputTokens: 0,\n reasoningTokens: 0,\n costUSD: 0,\n tools,\n bashCommands: [],\n timestamp: event.timestamp ?? '',\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n };\n\n pendingUserMessage = '';\n }\n }\n },\n };\n}\n\nasync function discoverSessionsInDir(sessionStateDir: string): Promise<SessionSource[]> {\n const sources: SessionSource[] = [];\n\n let sessionDirs: string[];\n try {\n sessionDirs = await readdir(sessionStateDir);\n } catch {\n return sources;\n }\n\n for (const sessionId of sessionDirs) {\n const eventsPath = join(sessionStateDir, sessionId, 'events.jsonl');\n const s = await stat(eventsPath).catch(() => null);\n if (!s?.isFile()) continue;\n\n let project = sessionId;\n try {\n const yaml = await readFile(join(sessionStateDir, sessionId, 'workspace.yaml'), 'utf-8');\n const cwd = parseCwd(yaml);\n if (cwd) project = basename(cwd);\n } catch { /* no workspace.yaml */ }\n\n sources.push({ path: eventsPath, project, provider: 'copilot' });\n }\n\n return sources;\n}\n\nexport const copilot: Provider = {\n name: 'copilot',\n displayName: 'GitHub Copilot',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of modelDisplayEntries) {\n if (model === key || model.startsWith(key + '-')) return name;\n }\n return model;\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(getCopilotSessionStateDir());\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys);\n },\n};\n", "import { readdir, readFile, stat } from 'fs/promises';\nimport { basename, join } from 'path';\nimport { homedir } from 'os';\n\nimport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\nconst modelDisplayNames: Record<string, string> = {\n 'gpt-5.4': 'GPT-5.4',\n 'gpt-5.4-mini': 'GPT-5.4 Mini',\n 'gpt-5': 'GPT-5',\n 'gpt-4o': 'GPT-4o',\n 'gpt-4o-mini': 'GPT-4o Mini',\n};\n\nconst toolNameMap: Record<string, string> = {\n bash: 'Bash',\n read: 'Read',\n edit: 'Edit',\n write: 'Write',\n glob: 'Glob',\n grep: 'Grep',\n task: 'Agent',\n dispatch_agent: 'Agent',\n fetch: 'WebFetch',\n search: 'WebSearch',\n todo: 'TodoWrite',\n patch: 'Patch',\n};\n\nconst modelDisplayEntries = Object.entries(modelDisplayNames).sort((a, b) => b[0].length - a[0].length);\n\ntype PiEntry = {\n type: string;\n id?: string;\n timestamp?: string;\n cwd?: string;\n message?: {\n role?: string;\n content?: Array<{ type?: string; text?: string; name?: string; arguments?: Record<string, unknown> }>;\n model?: string;\n responseId?: string;\n usage?: {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n };\n };\n};\n\nfunction getPiSessionsDir(): string {\n return join(homedir(), '.pi', 'agent', 'sessions');\n}\n\nasync function readFirstEntry(filePath: string): Promise<PiEntry | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const line = content.split('\\n')[0];\n if (!line?.trim()) return null;\n return JSON.parse(line) as PiEntry;\n } catch {\n return null;\n }\n}\n\nfunction extractBashCommands(cmd: string): string[] {\n return cmd.split(/[;&|]+/).map(s => s.trim().split(/\\s+/)[0]).filter(Boolean);\n}\n\nasync function discoverSessionsInDir(sessionsDir: string): Promise<SessionSource[]> {\n const sources: SessionSource[] = [];\n\n let projectDirs: string[];\n try {\n projectDirs = await readdir(sessionsDir);\n } catch {\n return sources;\n }\n\n for (const dirName of projectDirs) {\n const dirPath = join(sessionsDir, dirName);\n const dirStat = await stat(dirPath).catch(() => null);\n if (!dirStat?.isDirectory()) continue;\n\n let files: string[];\n try {\n files = await readdir(dirPath);\n } catch {\n continue;\n }\n\n for (const file of files) {\n if (!file.endsWith('.jsonl')) continue;\n const filePath = join(dirPath, file);\n const fileStat = await stat(filePath).catch(() => null);\n if (!fileStat?.isFile()) continue;\n\n const first = await readFirstEntry(filePath);\n if (!first || first.type !== 'session') continue;\n\n const cwd = first.cwd ?? dirName;\n sources.push({ path: filePath, project: basename(cwd), provider: 'pi' });\n }\n }\n\n return sources;\n}\n\nfunction createParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return {\n async *parse(): AsyncGenerator<ParsedProviderCall> {\n let content: string;\n try {\n content = await readFile(source.path, 'utf-8');\n } catch {\n return;\n }\n\n const lines = content.split('\\n').filter(l => l.trim());\n let sessionId = basename(source.path, '.jsonl');\n let pendingUserMessage = '';\n\n for (const [lineIdx, line] of lines.entries()) {\n let entry: PiEntry;\n try {\n entry = JSON.parse(line) as PiEntry;\n } catch {\n continue;\n }\n\n if (entry.type === 'session') {\n sessionId = entry.id ?? sessionId;\n continue;\n }\n\n if (entry.type !== 'message') continue;\n\n const msg = entry.message;\n if (!msg) continue;\n\n if (msg.role === 'user') {\n const texts = (msg.content ?? [])\n .filter(c => c.type === 'text')\n .map(c => c.text ?? '')\n .filter(Boolean);\n if (texts.length > 0) pendingUserMessage = texts.join(' ');\n continue;\n }\n\n if (msg.role !== 'assistant' || !msg.usage) continue;\n\n const { input, output, cacheRead, cacheWrite } = msg.usage;\n if (input === 0 && output === 0) continue;\n\n const model = msg.model ?? 'gpt-5';\n const responseId = msg.responseId ?? '';\n const dedupKey = `pi:${source.path}:${responseId || entry.id || entry.timestamp || String(lineIdx)}`;\n\n if (seenKeys.has(dedupKey)) continue;\n seenKeys.add(dedupKey);\n\n const toolCalls = (msg.content ?? []).filter(c => c.type === 'toolCall' && c.name);\n const tools = toolCalls.map(c => toolNameMap[c.name!] ?? c.name!);\n const bashCommands = toolCalls\n .filter(c => c.name === 'bash')\n .flatMap(c => {\n const cmd = c.arguments?.['command'];\n return typeof cmd === 'string' ? extractBashCommands(cmd) : [];\n });\n\n const timestamp = entry.timestamp ?? '';\n\n yield {\n provider: 'pi',\n model,\n inputTokens: input,\n outputTokens: output,\n cacheCreationInputTokens: cacheWrite,\n cacheReadInputTokens: cacheRead,\n cachedInputTokens: cacheRead,\n reasoningTokens: 0,\n costUSD: 0,\n tools,\n bashCommands,\n timestamp,\n speed: 'standard',\n deduplicationKey: dedupKey,\n userMessage: pendingUserMessage,\n sessionId,\n };\n\n pendingUserMessage = '';\n }\n },\n };\n}\n\nexport const pi: Provider = {\n name: 'pi',\n displayName: 'Pi',\n\n modelDisplayName(model: string): string {\n for (const [key, name] of modelDisplayEntries) {\n if (model.startsWith(key)) return name;\n }\n return model;\n },\n\n toolDisplayName(rawTool: string): string {\n return toolNameMap[rawTool] ?? rawTool;\n },\n\n async discoverSessions(): Promise<SessionSource[]> {\n return discoverSessionsInDir(getPiSessionsDir());\n },\n\n createSessionParser(source: SessionSource, seenKeys: Set<string>): SessionParser {\n return createParser(source, seenKeys);\n },\n};\n", "import { claudeCode } from './claude-code.js';\nimport { codex } from './codex.js';\nimport { copilot } from './copilot.js';\nimport { pi } from './pi.js';\nimport type { Provider, SessionSource } from './types.js';\n\nexport type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js';\n\n// Core providers (no native dependencies)\nconst coreProviders: Provider[] = [claudeCode, codex, copilot, pi];\n\n// Optional providers (require better-sqlite3, lazy-loaded)\nlet cursorProvider: Provider | null = null;\nlet cursorLoadAttempted = false;\n\nasync function loadCursor(): Promise<Provider | null> {\n if (cursorLoadAttempted) return cursorProvider;\n cursorLoadAttempted = true;\n try {\n const { cursor } = await import('./cursor.js');\n cursorProvider = cursor;\n return cursor;\n } catch {\n return null;\n }\n}\n\nlet opencodeProvider: Provider | null = null;\nlet opencodeLoadAttempted = false;\n\nasync function loadOpenCode(): Promise<Provider | null> {\n if (opencodeLoadAttempted) return opencodeProvider;\n opencodeLoadAttempted = true;\n try {\n const { opencode } = await import('./opencode.js');\n opencodeProvider = opencode;\n return opencode;\n } catch {\n return null;\n }\n}\n\nexport async function getAllProviders(): Promise<Provider[]> {\n const [cursor, opencode] = await Promise.all([loadCursor(), loadOpenCode()]);\n const all = [...coreProviders];\n if (cursor) all.push(cursor);\n if (opencode) all.push(opencode);\n return all;\n}\n\nexport async function discoverAllSessions(providerFilter?: string): Promise<SessionSource[]> {\n const allProviders = await getAllProviders();\n const filtered = providerFilter && providerFilter !== 'all'\n ? allProviders.filter(p => p.name === providerFilter)\n : allProviders;\n const all: SessionSource[] = [];\n for (const provider of filtered) {\n const sessions = await provider.discoverSessions();\n all.push(...sessions);\n }\n return all;\n}\n\nexport async function getProvider(name: string): Promise<Provider | undefined> {\n if (name === 'cursor') return (await loadCursor()) ?? undefined;\n if (name === 'opencode') return (await loadOpenCode()) ?? undefined;\n return coreProviders.find(p => p.name === name);\n}\n", "import { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport { writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\nimport {\n buildTmuxAttachCommand,\n buildTmuxLaunchArgs,\n buildTmuxSendKeysArgs,\n isTmuxAvailable,\n runTmux,\n sanitizeTmuxName,\n type TmuxRunResult,\n} from '../terminal/tmux.js';\n\ninterface ClaudeCodeLauncherOptions {\n tmuxAvailable?: () => Promise<boolean>;\n runTmux?: (args: string[]) => Promise<TmuxRunResult>;\n}\n\ntype TmuxFallbackReason = NonNullable<LaunchResult['fallbackReason']>;\n\n// Mirror the API's `z.string().uuid()` contract (8-4-4-4-12 hex). runId is a\n// server-minted uuid today and the generic launch-jobs route strips it via\n// Zod, so this is NOT client-reachable \u2014 it's defense-in-depth so a future\n// relaxation of that boundary can't turn the Terminal.app `.command` script\n// into shell command-substitution RCE (e.g. a runId of `$(touch /tmp/x)`).\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Validate a caller-supplied runId at the launcher boundary. Returns the runId\n * only if it's a well-formed uuid; otherwise returns undefined (and logs a\n * warning) so NONE of the three injection paths stamp an untrusted value.\n */\nexport function validateRunId(runId: string | undefined): string | undefined {\n if (runId === undefined) return undefined;\n if (UUID_RE.test(runId)) return runId;\n console.warn(\n `[claude-code-launcher] dropping non-uuid runId (RULEMETRIC_RUN_ID not injected): ${JSON.stringify(runId)}`,\n );\n return undefined;\n}\n\n/**\n * Single-quote a string for safe inclusion in a POSIX shell script. Single\n * quotes suppress ALL expansion (command substitution, parameter expansion,\n * backticks); the `'\\''` trick closes the quote, emits an escaped literal\n * quote, then reopens \u2014 the only escape single-quoting needs.\n */\nexport function shellSingleQuote(s: string): string {\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n}\n\nexport class ClaudeCodeLauncher implements ToolLauncher {\n tool = 'claude_code' as const;\n\n constructor(private readonly options: ClaudeCodeLauncherOptions = {}) {}\n\n capabilities: LaunchCapabilities = {\n headless: true,\n interactive: true,\n remoteSpawn: true,\n };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n\n // Validate the runId ONCE at the launcher boundary so all three injection\n // paths (headless env, tmux argv, Terminal.app .command) only ever see a\n // well-formed uuid. A non-uuid value is dropped (see validateRunId).\n const safeConfig: LaunchConfig = { ...config, runId: validateRunId(config.runId) };\n\n if (safeConfig.mode === 'headless') {\n return this.launchHeadless(safeConfig, sessionId);\n }\n return this.launchInteractive(safeConfig, sessionId);\n }\n\n private async launchHeadless(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const args = ['-p', config.prompt ?? '', '--output-format', 'json'];\n if (config.systemPrompt) args.push('--system-prompt', config.systemPrompt);\n if (config.model) args.push('--model', config.model);\n\n // Remove CLAUDECODE flag so spawned claude doesn't think it's a nested session.\n // Remove HTTPS_PROXY so headless runs bypass the capture proxy \u2014 these are\n // infrastructure calls, not user sessions.\n const env = { ...process.env };\n delete env.CLAUDECODE;\n delete env.HTTPS_PROXY;\n // Task 3.1: stamp the run id so the spawned session's hook forwards it.\n // NOTE: RULEMETRIC_RUN_ID is effectively a no-op on the headless path today\n // \u2014 headless runs delete HTTPS_PROXY above to bypass the capture proxy/hook,\n // and runs always use mode:'interactive'. Kept for forward-compat. runId is\n // already validated as a uuid at the launch() boundary.\n if (config.runId) env.RULEMETRIC_RUN_ID = config.runId;\n\n return new Promise((resolve) => {\n const proc = spawn('claude', args, {\n cwd: config.projectPath,\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n const timer = config.timeout\n ? setTimeout(() => { proc.kill('SIGTERM'); }, config.timeout)\n : null;\n\n proc.on('close', (code) => {\n if (timer) clearTimeout(timer);\n let output = stdout;\n try {\n const parsed = JSON.parse(stdout);\n output = parsed.result ?? parsed.content ?? stdout;\n } catch { /* raw text */ }\n\n resolve({\n sessionId,\n pid: proc.pid,\n exitCode: code,\n output,\n error: code !== 0 ? stderr : undefined,\n });\n });\n\n proc.on('error', (err) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, error: `Failed to spawn claude: ${err.message}` });\n });\n });\n }\n\n private async launchInteractive(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const tmuxAvailableCheck = this.options.tmuxAvailable ?? isTmuxAvailable;\n if (await tmuxAvailableCheck().catch(() => false)) {\n return this.launchInteractiveTmux(config, sessionId);\n }\n return this.launchInteractiveTerminal(config, sessionId, 'tmux_not_found');\n }\n\n private async launchInteractiveTmux(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const run = this.options.runTmux ?? runTmux;\n const target = sanitizeTmuxName(`claude-${config.resumeSessionId ?? sessionId}`);\n const launchResult = await run(buildTmuxLaunchArgs({\n sessionName: target,\n projectPath: config.projectPath,\n resumeSessionId: config.resumeSessionId,\n model: config.model,\n // Task 3.1: inject the run id into the spawned session's env so its\n // session-start hook forwards it to POST /api/sessions (stamps run_id).\n runId: config.runId,\n }));\n\n if (launchResult.code !== 0) {\n return this.launchInteractiveTerminal(\n config,\n sessionId,\n 'tmux_launch_failed',\n `tmux new-session exited ${launchResult.code}: ${launchResult.stderr.trim() || 'no stderr'}`,\n );\n }\n\n const attachResult = await this.openTerminalAttach(target, sessionId);\n\n if (config.prompt) {\n const sendResult = await run(buildTmuxSendKeysArgs(target, config.prompt));\n if (sendResult.code !== 0) {\n return {\n sessionId,\n liveSendAvailable: false,\n fallbackReason: 'tmux_launch_failed',\n error: `tmux send-keys exited ${sendResult.code}: ${sendResult.stderr.trim() || 'no stderr'}`,\n };\n }\n const enterResult = await run(buildTmuxSendKeysArgs(target, 'Enter', { literal: false }));\n if (enterResult.code !== 0) {\n return {\n sessionId,\n liveSendAvailable: false,\n fallbackReason: 'tmux_launch_failed',\n error: `tmux send Enter exited ${enterResult.code}: ${enterResult.stderr.trim() || 'no stderr'}`,\n };\n }\n }\n\n return {\n sessionId,\n pid: attachResult.pid,\n liveSendAvailable: true,\n ...(attachResult.error ? { error: attachResult.error } : {}),\n terminalTarget: {\n kind: 'tmux',\n target,\n attachCommand: buildTmuxAttachCommand(target),\n live: true,\n },\n };\n }\n\n private async openTerminalAttach(\n target: string,\n sessionId: string,\n ): Promise<{ pid?: number; error?: string }> {\n const scriptPath = join(tmpdir(), `rulemetric-attach-${sessionId}.command`);\n const scriptBody =\n '#!/bin/zsh\\n' +\n 'rm -- \"$0\"\\n' +\n `${buildTmuxAttachCommand(target)}\\n`;\n await writeFile(scriptPath, scriptBody, { mode: 0o755 });\n\n return new Promise((resolve) => {\n const proc = spawn('open', ['-a', 'Terminal', scriptPath], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stderr = '';\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({ pid: proc.pid });\n } else {\n resolve({\n pid: proc.pid,\n error: `open attach exited ${code}: ${stderr.trim() || 'no stderr'}`,\n });\n }\n });\n proc.on('error', (err) => {\n resolve({ error: `Failed to spawn open attach: ${err.message}` });\n });\n });\n }\n\n private async launchInteractiveTerminal(\n config: LaunchConfig,\n sessionId: string,\n fallbackReason: TmuxFallbackReason,\n fallbackDetail?: string,\n ): Promise<LaunchResult> {\n // Build the claude command that runs INSIDE the new Terminal window. We\n // bake it into a .command script (next step) so the user sees a single\n // self-contained file in their tmpdir instead of a long inline AppleScript.\n const parts = ['claude'];\n if (config.resumeSessionId) {\n parts.push('--resume', config.resumeSessionId);\n } else if (config.prompt) {\n parts.push('-p', JSON.stringify(config.prompt));\n }\n if (config.model) parts.push('--model', config.model);\n const cmd = parts.join(' ');\n\n // Write a self-deleting .command script, then ask LaunchServices (via\n // `open -a Terminal`) to hand it to Terminal.app.\n //\n // History: this used to call `osascript \"tell Terminal to do script ...\"`.\n // That path goes through the macOS TCC AppleEvents bucket, which silently\n // denies launchd-spawned processes (the worker is launched via\n // `com.rulemetric.worker.plist`) \u2014 leaving the user with a \"completed\"\n // launch row and no Terminal window. See:\n // docs/incidents/2026-05-24-launcher-tcc-silent-failure.md.\n //\n // `open -a Terminal foo.command` goes through LaunchServices instead,\n // which is exempt from the AppleEvents bucket AND surfaces a real exit\n // code we can propagate to the mirror row.\n const scriptPath = join(tmpdir(), `rulemetric-launch-${sessionId}.command`);\n // The script self-deletes its own file (`rm -- \"$0\"`) BEFORE handing off\n // to claude so we don't leak temp files even if the user kills the window\n // mid-session. `cd ... || exit` ensures we don't silently launch claude\n // in $HOME when the project path is gone.\n // Task 3.1: export the run id (when present) into the script's shell so\n // the spawned claude \u2014 and its session-start hook \u2014 see RULEMETRIC_RUN_ID.\n // SINGLE-quote the value (not JSON/double-quote): double quotes still allow\n // `$(...)` / backtick command-substitution, so a value like `$(touch /tmp/x)`\n // would EXECUTE when the .command runs. Single quotes suppress all\n // expansion. config.runId is already uuid-validated at the launch()\n // boundary; the quoting is a second layer so the script is robust\n // regardless of value.\n const runIdExport = config.runId\n ? `export RULEMETRIC_RUN_ID=${shellSingleQuote(config.runId)}\\n`\n : '';\n const scriptBody =\n '#!/bin/zsh\\n' +\n 'rm -- \"$0\"\\n' +\n `cd ${JSON.stringify(config.projectPath)} || exit\\n` +\n runIdExport +\n `${cmd}\\n`;\n await writeFile(scriptPath, scriptBody, { mode: 0o755 });\n\n // Note: NOT detached / NOT unref'd. `open` returns once LaunchServices has\n // accepted the request (~10s of ms), so we CAN await its close + propagate\n // the exit code without coupling the Terminal window's lifetime to the\n // worker. Terminal.app is its own process and survives the worker exiting.\n return new Promise((resolve) => {\n const proc = spawn('open', ['-a', 'Terminal', scriptPath], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stderr = '';\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({\n sessionId,\n pid: proc.pid,\n liveSendAvailable: false,\n fallbackReason,\n ...(fallbackDetail ? { error: fallbackDetail } : {}),\n });\n } else {\n const tail = stderr.trim() || 'no stderr';\n resolve({\n sessionId,\n pid: proc.pid,\n liveSendAvailable: false,\n fallbackReason,\n error: fallbackDetail\n ? `${fallbackDetail}; open exited ${code}: ${tail}`\n : `open exited ${code}: ${tail}`,\n });\n }\n });\n proc.on('error', (err) => {\n resolve({\n sessionId,\n liveSendAvailable: false,\n fallbackReason,\n error: `Failed to spawn open: ${err.message}`,\n });\n });\n });\n }\n}\n", "import { spawn } from 'node:child_process';\n\nexport interface TmuxLaunchArgsInput {\n sessionName: string;\n projectPath: string;\n resumeSessionId?: string;\n model?: string;\n /**\n * Multi-session-run id (Task 3.1). When set, the launched `claude` command\n * is prefixed with `env RULEMETRIC_RUN_ID=<id>` so the value reaches ONLY\n * the spawned session's process (not the tmux server env), where the\n * session-start hook forwards it to POST /api/sessions.\n */\n runId?: string;\n}\n\nexport interface TmuxSendKeysOptions {\n literal?: boolean;\n}\n\nexport function sanitizeTmuxName(input: string): string {\n const cleaned = input\n .trim()\n .replace(/[^A-Za-z0-9_.-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80);\n return `rm-${cleaned || 'session'}`;\n}\n\nexport function buildTmuxLaunchArgs(input: TmuxLaunchArgsInput): string[] {\n // Prefix with `env RULEMETRIC_RUN_ID=<id>` so the var is scoped to the\n // spawned claude process only \u2014 tmux passes argv straight to exec, so this\n // never leaks into the tmux server's environment.\n const claudeArgs = input.runId\n ? ['env', `RULEMETRIC_RUN_ID=${input.runId}`, 'claude']\n : ['claude'];\n if (input.resumeSessionId) {\n claudeArgs.push('--resume', input.resumeSessionId);\n }\n if (input.model) {\n claudeArgs.push('--model', input.model);\n }\n\n return [\n 'new-session',\n '-d',\n '-s',\n input.sessionName,\n '-c',\n input.projectPath,\n '--',\n ...claudeArgs,\n ];\n}\n\nexport function buildTmuxSendKeysArgs(\n target: string,\n message: string,\n options: TmuxSendKeysOptions = {},\n): string[] {\n if (options.literal === false) {\n return ['send-keys', '-t', target, message];\n }\n return ['send-keys', '-t', target, '-l', '--', message];\n}\n\nexport function buildTmuxHasSessionArgs(target: string): string[] {\n return ['has-session', '-t', target];\n}\n\nexport function buildTmuxAttachCommand(target: string): string {\n return `tmux attach -t ${target}`;\n}\n\nexport interface TmuxRunResult {\n code: number | null;\n stderr: string;\n}\n\n// Homebrew installs tmux to /opt/homebrew/bin (Apple Silicon) or\n// /usr/local/bin (Intel). The launchd worker runs with a minimal PATH that\n// omits /opt/homebrew/bin, so a bare spawn('tmux') fails with ENOENT under\n// launchd even though it works in an interactive shell. Augment PATH at the\n// spawn boundary so live-send/launch work in the real (launchd) worker\n// environment \u2014 verified 2026-06-09 when every terminal target flipped to\n// `missing` because the worker couldn't resolve tmux.\nexport function tmuxSpawnEnv(): NodeJS.ProcessEnv {\n const extraDirs = ['/opt/homebrew/bin', '/usr/local/bin'];\n const parts = (process.env.PATH ?? '').split(':').filter(Boolean);\n const missing = extraDirs.filter((d) => !parts.includes(d));\n if (missing.length === 0) return process.env;\n return { ...process.env, PATH: [...parts, ...missing].join(':') };\n}\n\nexport function runTmux(args: string[]): Promise<TmuxRunResult> {\n return new Promise((resolve) => {\n const proc = spawn('tmux', args, {\n stdio: ['ignore', 'ignore', 'pipe'],\n env: tmuxSpawnEnv(),\n });\n let stderr = '';\n proc.stderr.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n proc.on('close', (code) => resolve({ code, stderr }));\n proc.on('error', (err) => resolve({ code: null, stderr: err.message }));\n });\n}\n\nexport async function isTmuxAvailable(): Promise<boolean> {\n const result = await runTmux(['-V']);\n return result.code === 0;\n}\n", "// codex.ts \u2014 OpenAI's Codex CLI (codex -q \"prompt\")\nimport { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\n\nexport class CodexLauncher implements ToolLauncher {\n tool = 'codex' as const;\n capabilities: LaunchCapabilities = { headless: true, interactive: true, remoteSpawn: true };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n if (config.mode === 'headless') {\n return this.launchHeadless(config, sessionId);\n }\n return this.launchInteractive(config, sessionId);\n }\n\n private launchHeadless(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const args = ['-q', config.prompt ?? ''];\n if (config.model) args.push('--model', config.model);\n\n return new Promise((resolve) => {\n const proc = spawn('codex', args, {\n cwd: config.projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n const timer = config.timeout\n ? setTimeout(() => { proc.kill('SIGTERM'); }, config.timeout)\n : null;\n\n proc.on('close', (code) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, pid: proc.pid, exitCode: code, output: stdout, error: code !== 0 ? stderr : undefined });\n });\n\n proc.on('error', (err) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, error: `Failed to spawn codex: ${err.message}` });\n });\n });\n }\n\n private launchInteractive(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const parts = ['codex'];\n if (config.prompt) parts.push(JSON.stringify(config.prompt));\n const script = `cd ${JSON.stringify(config.projectPath)} && ${parts.join(' ')}`;\n const proc = spawn('osascript', ['-e', `tell application \"Terminal\" to do script ${JSON.stringify(script)}`], {\n stdio: 'ignore',\n detached: true,\n });\n proc.unref();\n return Promise.resolve({ sessionId, pid: proc.pid });\n }\n}\n", "// aider.ts \u2014 Aider CLI (aider --message \"prompt\" for headless)\nimport { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\n\nexport class AiderLauncher implements ToolLauncher {\n tool = 'aider' as const;\n capabilities: LaunchCapabilities = { headless: true, interactive: true, remoteSpawn: true };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n if (config.mode === 'headless') {\n return this.launchHeadless(config, sessionId);\n }\n return this.launchInteractive(config, sessionId);\n }\n\n private launchHeadless(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const args = ['--message', config.prompt ?? '', '--yes'];\n if (config.model) args.push('--model', config.model);\n\n return new Promise((resolve) => {\n const proc = spawn('aider', args, {\n cwd: config.projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n proc.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\n proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\n\n const timer = config.timeout\n ? setTimeout(() => { proc.kill('SIGTERM'); }, config.timeout)\n : null;\n\n proc.on('close', (code) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, pid: proc.pid, exitCode: code, output: stdout, error: code !== 0 ? stderr : undefined });\n });\n\n proc.on('error', (err) => {\n if (timer) clearTimeout(timer);\n resolve({ sessionId, error: `Failed to spawn aider: ${err.message}` });\n });\n });\n }\n\n private launchInteractive(config: LaunchConfig, sessionId: string): Promise<LaunchResult> {\n const parts = ['aider'];\n if (config.model) parts.push('--model', config.model);\n const script = `cd ${JSON.stringify(config.projectPath)} && ${parts.join(' ')}`;\n const proc = spawn('osascript', ['-e', `tell application \"Terminal\" to do script ${JSON.stringify(script)}`], {\n stdio: 'ignore',\n detached: true,\n });\n proc.unref();\n return Promise.resolve({ sessionId, pid: proc.pid });\n }\n}\n", "// generic.ts \u2014 opens a terminal in the project directory (fallback for unknown tools)\nimport { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\n\nexport class GenericLauncher implements ToolLauncher {\n constructor(public tool: string) {}\n\n capabilities: LaunchCapabilities = { headless: false, interactive: true, remoteSpawn: false };\n\n async launch(config: LaunchConfig): Promise<LaunchResult> {\n const sessionId = randomUUID();\n if (config.mode === 'headless') {\n return { sessionId, error: `${this.tool} does not support headless mode` };\n }\n\n // Just open a terminal in the project directory\n const script = `cd ${JSON.stringify(config.projectPath)} && echo \"Session ${sessionId} \u2014 tool: ${this.tool}\" && exec $SHELL`;\n const proc = spawn('osascript', ['-e', `tell application \"Terminal\" to do script ${JSON.stringify(script)}`], {\n stdio: 'ignore',\n detached: true,\n });\n proc.unref();\n return { sessionId, pid: proc.pid };\n }\n}\n", "import type { ToolLauncher } from './types.js';\nimport { ClaudeCodeLauncher } from './claude-code.js';\nimport { CodexLauncher } from './codex.js';\nimport { AiderLauncher } from './aider.js';\nimport { GenericLauncher } from './generic.js';\n\nexport type { ToolLauncher, LaunchConfig, LaunchResult, LaunchCapabilities } from './types.js';\n\nconst launchers: Record<string, () => ToolLauncher> = {\n claude_code: () => new ClaudeCodeLauncher(),\n codex: () => new CodexLauncher(),\n aider: () => new AiderLauncher(),\n};\n\nexport function getLauncher(tool: string): ToolLauncher {\n const factory = launchers[tool];\n return factory ? factory() : new GenericLauncher(tool);\n}\n\nexport function getAvailableLaunchers(): Array<{ tool: string; capabilities: ToolLauncher['capabilities'] }> {\n return Object.entries(launchers).map(([tool, factory]) => ({\n tool,\n capabilities: factory().capabilities,\n }));\n}\n", "import path from 'node:path';\n\n/**\n * Shared, pure worktree-path math used by BOTH the worker's `ensureWorktree`\n * (apps/cli/src/lib/worktree.ts, which actually creates the worktree) and the\n * API's run reconcile fallback (apps/api/src/routes/runs.ts, which must derive\n * the same path to match captured sessions). It lives here, in the cross-app\n * `@rulemetric/session` package, so neither side duplicates the sanitizer \u2014\n * a drift between the two would silently break session\u2192run attribution.\n *\n * NOTE: this returns a `path.resolve`-only absolute path. The worker\n * additionally `realpath`-resolves it after creation (macOS `/var` \u2192\n * `/private/var`, etc.), so the persisted `launch_jobs.result.worktreePath` is\n * the authoritative join key. This derivation is a best-effort fallback for\n * the window before a job persists its result, and is exact only when the\n * repo root contains no symlinks.\n */\n\n/** Turn an arbitrary branch name into a filesystem-safe single path segment. */\nexport function sanitizeBranch(branch: string): string {\n return (\n branch\n // collapse any run of non-safe chars into a single dash\n .replace(/[^a-zA-Z0-9._-]+/g, '-')\n // trim leading/trailing dashes/dots so we never produce `.` or `-foo`\n .replace(/^[-.]+|[-.]+$/g, '') || 'worktree'\n );\n}\n\n/**\n * Compute the default worktree path for a (repoRoot, branch) pair: a SIBLING of\n * `repoRoot` at `<repoRoot>/../.rulemetric-worktrees/<sanitized-branch>`. Never\n * inside `repoRoot` (a nested worktree would be tracked by the parent repo).\n */\nexport function worktreePathFor(options: {\n repoRoot: string;\n branch: string;\n basePath?: string;\n}): string {\n return path.resolve(\n options.basePath ??\n path.join(options.repoRoot, '..', '.rulemetric-worktrees', sanitizeBranch(options.branch)),\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["preview", "readdir", "stat", "basename", "join", "homedir", "readdir", "readFile", "stat", "basename", "join", "homedir", "modelDisplayNames", "toolNameMap", "createParser", "discoverSessionsInDir", "readdir", "readFile", "stat", "basename", "join", "homedir", "modelDisplayNames", "toolNameMap", "modelDisplayEntries", "discoverSessionsInDir", "createParser", "spawn", "join", "spawn", "join", "spawn", "randomUUID", "spawn", "randomUUID", "spawn", "randomUUID"]
|
|
7
7
|
}
|