@ai-matrx/coding-sessions 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/engine/index.cjs +54 -10
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.js +54 -10
- package/dist/engine/index.js.map +1 -1
- package/dist/{index-29t7n472.d.cts → index-Bbe11HoB.d.cts} +30 -3
- package/dist/{index-29t7n472.d.ts → index-Bbe11HoB.d.ts} +30 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +34 -5
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +15 -1
- package/dist/react/index.d.ts +15 -1
- package/dist/react/index.js +34 -5
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +44 -9
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +44 -9
- package/dist/server/index.js.map +1 -1
- package/dist/sessions/index.cjs +26 -1
- package/dist/sessions/index.cjs.map +1 -1
- package/dist/sessions/index.d.cts +13 -5
- package/dist/sessions/index.d.ts +13 -5
- package/dist/sessions/index.js +26 -1
- package/dist/sessions/index.js.map +1 -1
- package/dist/{titles-eCnA5sY7.d.cts → titles-DjxUb0ji.d.cts} +8 -1
- package/dist/{titles-eCnA5sY7.d.ts → titles-DjxUb0ji.d.ts} +8 -1
- package/dist/ui/assets/index-BqzTnRFe.css +2 -0
- package/dist/ui/assets/{index-SuRr0-D2.js → index-U98AY8r-.js} +17 -17
- package/dist/ui/index.html +2 -2
- package/package.json +3 -3
- package/dist/ui/assets/index-BqpVx_My.css +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/engine/index.ts","../../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.28_tsx@4.23.15_typescript@6.0.3_yaml@2.9.1/node_modules/tsup/assets/cjs_shims.js","../../src/engine/raw-backup.ts","../../src/engine/agent-attach.ts","../../src/normalize/agent-block.ts","../../src/engine/agents.ts","../../src/normalize/claude.ts","../../src/normalize/codex.ts","../../src/normalize/lines.ts","../../src/types.ts","../../src/provider-health.ts","../../src/engine/binaries.ts","../../src/engine/clean-env.ts","../../src/engine/files.ts","../../src/sessions/titles.ts","../../src/engine/activity.ts","../../src/engine/preferences.ts","../../src/engine/search.ts","../../src/sessions/hints.ts","../../src/engine/title-hints.ts","../../src/engine/store.ts","../../src/engine/user-defaults.ts"],"sourcesContent":["/**\n * `@ai-matrx/coding-sessions/engine` — drive the user's own Claude Code and\n * Codex on their own subscription logins, through Paperclip's MIT driver\n * packages, with every fix the 2026-09-27 spike found built in:\n *\n * - each run's driver lives in a forked worker with an ALLOWLISTED\n * environment (`clean-env.ts`), so a host running inside a Claude Code\n * session never leaks `CLAUDE_CODE_*` / `ANTHROPIC_BASE_URL` into the CLI;\n * - Claude runs on the CLI engine with the user's text as the whole prompt;\n * - no Paperclip skill is mounted and no skill-list prompt is appended\n * (`paperclipRuntimeSkills: []`), and a shim strips `PAPERCLIP_*` and\n * Paperclip's `--add-dir` before exec'ing the real CLI;\n * - Codex runs against the user's real `~/.codex`, so sessions appear in\n * their own history and no copy of their login is ever made;\n * - the driver's scratch state goes to this package's data dir, never\n * `~/.paperclip`, and its auth-cache vend is switched off;\n * - stop kills the CLI's process group (the driver ignores `signal`) and the\n * run is recorded as stopped even when Codex exits 0;\n * - a resume the driver would silently replace with a FRESH session is\n * refused and reported, and the driver may never delete the user's own\n * session files.\n */\n\nimport { execFile, fork, type ChildProcess } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport { createRawBackupScheduler, type RawBackupSink } from \"./raw-backup\";\nimport {\n AGENT_REMOVED_BLOCK,\n agentArgsFor,\n codexCompactionDroppedAgent,\n renderFallbackBlock,\n sessionAgentRecord,\n writeAgentAttachment,\n} from \"./agent-attach\";\nimport { createAgentConnection, type CodingSessionsAgentsOptions } from \"./agents\";\n\nexport type { CodingSessionsAgentsOptions } from \"./agents\";\nexport { DEFAULT_SERVER_URL, DEFAULT_SUPABASE_URL } from \"./agents\";\nimport type { McpHttpReply } from \"@ai-matrx/agents/portable/mcp\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexStreamNormalizer } from \"../normalize/codex\";\nimport { createLineSplitter } from \"../normalize/lines\";\nimport {\n PROVIDER_LABEL,\n isTerminalRunStatus,\n type Billing,\n type CodingEvent,\n type CodingProvider,\n type CodingSession,\n type CodingSessionsApi,\n type DiscoveredSession,\n type ProviderStatus,\n type RecentFolder,\n type RunRecord,\n type RunStatus,\n type RunUsage,\n type SendResult,\n type SessionHistory,\n type StartInput,\n type TakeoverInput,\n type TranscriptItem,\n} from \"../types\";\nimport {\n classifyProviderError,\n describeProblem,\n problemFromQuota,\n problemStillApplies,\n} from \"../provider-health\";\nimport type { ModelOption, OpenTarget, ProviderBinary, ProviderProblem, QuotaWindow } from \"../types\";\nimport { chatKey } from \"../types\";\nimport { resolveBinary } from \"./binaries\";\nimport { buildCleanEnv } from \"./clean-env\";\nimport {\n defaultProviderHomes,\n discoverLocalSessions,\n findSessionFile,\n readSessionFile,\n sessionActivity,\n type ProviderHomes,\n} from \"./files\";\nimport { PreferenceStore } from \"./preferences\";\nimport { searchLocalChats } from \"./search\";\nimport { overlayHint, unavailableFromHints, type TitleHints } from \"./title-hints\";\nimport { titleHintKey } from \"../sessions/hints\";\nimport { RunIndex, type Identity } from \"./store\";\nimport { EFFORT_LEVELS, userDefaults } from \"./user-defaults\";\n\nexport { buildCleanEnv, isAllowedEnvName } from \"./clean-env\";\n/** Largest transcript Full Download hands to a page in one message (the file stays on disk). */\nexport const RAW_TRANSCRIPT_MAX_BYTES = 200 * 1_048_576;\n\nexport { createRawBackupScheduler, createAiMatrxRawBackupSink } from \"./raw-backup\";\nexport type { RawBackupPolicy, RawBackupSink } from \"./raw-backup\";\nexport { codexHome, discoverLocalSessions, findSessionFile, readSessionFile, defaultProviderHomes, sessionActivity } from \"./files\";\nexport { describeActivity, findDrivingProcess, endsWithOpenToolCall, listProcesses } from \"./activity\";\nexport type { CodexHome, ProviderHomes } from \"./files\";\nexport { createTitleHintsStore, titleHintKey, type TitleHint, type TitleHints } from \"../sessions/hints\";\nexport { searchLocalChats, snippetAround } from \"./search\";\nexport { claudeDefaults, codexDefaults, EFFORT_LEVELS } from \"./user-defaults\";\nexport { PreferenceStore } from \"./preferences\";\n\nexport interface CodingSessionsEngineOptions {\n /** Where the run index and the driver's scratch state live. Default `~/.matrx/coding-sessions`. */\n dataDir?: string | undefined;\n /** The environment the clean one is built FROM. Default `process.env`. */\n hostEnv?: NodeJS.ProcessEnv | undefined;\n /** Explicit CLI paths; default: found on the clean PATH. */\n commands?: Partial<Record<CodingProvider, string>> | undefined;\n /** Where the providers keep their sessions. Default: the user's own homes. */\n homes?: ProviderHomes | undefined;\n /** Ask the drivers for usage windows during `providers()` (Codex). Default true. */\n quota?: boolean | undefined;\n /**\n * Where an opted-in owner's full transcripts are backed up (the host's AI\n * Matrx sign-in). Absent → nothing is ever uploaded. The sink's policy is\n * asked before every upload; with backup off not one byte leaves.\n */\n rawBackup?: RawBackupSink | undefined;\n /** Receives raw provider stdout per run — used to capture test fixtures. */\n onRawOutput?: ((runId: string, provider: CodingProvider, chunk: string) => void) | undefined;\n /**\n * The AI Matrx connection that loads the person's agents into sessions:\n * `credentials` (a `CredentialsPort`, read fresh per call) plus the\n * organization. Absent → the agent picker shows signed out; plain sessions\n * are unaffected.\n */\n agents?: CodingSessionsAgentsOptions | undefined;\n /**\n * What the coding apps' own records say each chat is called (and archived / scheduled / file\n * gone), from the owner of the apps' index — Matrx 2's core. Never waited for; absent → titles\n * come from the transcripts alone (the standalone host).\n */\n titleHints?: TitleHints | undefined;\n}\n\nexport interface CodingSessionsEngine extends CodingSessionsApi {\n subscribe(listener: (event: CodingEvent) => void): () => void;\n /** Stop every live run and wait for the index to be written. */\n dispose(): Promise<void>;\n readonly dataDir: string;\n /** The host serves agent tools at `<baseUrl>/mcp/<secret>`; null stops serving. */\n setMcpBaseUrl(baseUrl: string | null): void;\n /** One MCP POST for a session's agent tools; null = no session owns `secret`. */\n handleMcp(secret: string, body: unknown): Promise<McpHttpReply | null>;\n}\n\ninterface WorkerMessage {\n kind: string;\n [key: string]: unknown;\n}\n\ninterface LiveRun {\n run: RunRecord;\n child: ChildProcess;\n pgid: number | null;\n stopRequested: boolean;\n killTimer: NodeJS.Timeout | null;\n stderrTail: string;\n refusals: string[];\n /** The provider file's size when this run began (history reads stop there). */\n fileOffset: number | null;\n /** Items this run produced, for a history read that lands mid-run. */\n items: { seq: number; item: TranscriptItem }[];\n}\n\nfunction moduleDir(): string {\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\nfunction resolveWorkerPath(): string {\n const dir = moduleDir();\n // This module is bundled into BOTH dist/engine and dist/server, so the\n // worker is either beside it or in the sibling engine directory.\n for (const candidate of [\n path.join(dir, \"worker.js\"),\n path.join(dir, \"worker.ts\"),\n path.join(dir, \"..\", \"engine\", \"worker.js\"),\n path.join(dir, \"..\", \"engine\", \"worker.ts\"),\n ]) {\n if (existsSync(candidate)) return candidate;\n }\n throw new Error(`[coding-sessions] The driver worker is missing next to ${dir}.`);\n}\n\n/**\n * The shim must be EXECUTABLE, and npm does not preserve the executable bit of\n * a non-`bin` file in a tarball (the packed-tarball canary caught exactly\n * that). So the engine installs its own copy into its data dir, mode 0755,\n * rewriting it only when the packaged source changed.\n */\nasync function installShim(dataDir: string): Promise<string> {\n const source = path.resolve(moduleDir(), \"..\", \"..\", \"bin\", \"cli-shim.sh\");\n if (!existsSync(source)) throw new Error(`[coding-sessions] The CLI shim is missing at ${source}.`);\n const body = await fs.readFile(source, \"utf8\");\n const target = path.join(dataDir, \"bin\", \"cli-shim.sh\");\n const current = await fs.readFile(target, \"utf8\").catch(() => null);\n if (current !== body) {\n await fs.mkdir(path.dirname(target), { recursive: true });\n await fs.writeFile(target, body, { mode: 0o755 });\n }\n await fs.chmod(target, 0o755);\n return target;\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction titleFrom(prompt: string): string {\n const flat = prompt.replace(/\\s+/g, \" \").trim();\n return flat.length > 80 ? `${flat.slice(0, 79)}…` : flat || \"New session\";\n}\n\nfunction capitalize(value: string | null | undefined): string | null {\n if (!value) return null;\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n\nfunction asUsage(value: unknown): RunUsage | null {\n if (typeof value !== \"object\" || value === null) return null;\n const v = value as Record<string, unknown>;\n const n = (x: unknown) => (typeof x === \"number\" && Number.isFinite(x) ? x : 0);\n return {\n inputTokens: n(v.inputTokens),\n outputTokens: n(v.outputTokens),\n cachedInputTokens: n(v.cachedInputTokens),\n };\n}\n\nfunction asBilling(value: unknown): Billing | null {\n if (value === \"subscription\" || value === \"api\") return value;\n if (typeof value === \"string\") return \"unknown\";\n return null;\n}\n\n/**\n * The status the screen shows: what the provider's own auth check says, then\n * — for a provider that looks ready — any usage limit or expired sign-in a run\n * reported (until a run succeeds) or a full quota window.\n */\nexport function describeProviderStatus(\n provider: CodingProvider,\n probe: Record<string, unknown> | undefined,\n lastProblem: ProviderProblem | null = null,\n quota: QuotaWindow[] = [],\n): ProviderStatus {\n const base = describeAuthStatus(provider, probe);\n const withQuota = { ...base, quota };\n if (!base.installed || !base.loggedIn) return { ...withQuota, ready: false, lastProblem };\n const current =\n (lastProblem && problemStillApplies(lastProblem) ? lastProblem : null) ?? problemFromQuota(quota);\n if (!current) return { ...withQuota, ready: true, lastProblem: null };\n const words = describeProblem(provider, current);\n return { ...withQuota, ready: false, lastProblem: current, problem: words.problem, fix: words.fix };\n}\n\nfunction describeAuthStatus(\n provider: CodingProvider,\n probe: Record<string, unknown> | undefined,\n): ProviderStatus {\n const label = PROVIDER_LABEL[provider];\n const installed = probe?.installed === true;\n const binary = (probe?.binary ?? null) as ProviderBinary | null;\n const version = binary?.version ?? (typeof probe?.version === \"string\" ? probe.version : null);\n const base: ProviderStatus = {\n provider,\n label,\n installed,\n version,\n binary,\n loggedIn: false,\n billing: \"unknown\",\n plan: null,\n account: null,\n problem: null,\n fix: null,\n ready: false,\n lastProblem: null,\n quota: [],\n };\n if (!installed) {\n return {\n ...base,\n problem: `${label} isn't installed on this computer.`,\n fix:\n provider === \"claude\"\n ? \"Install Claude Code from claude.com/code and sign in once, then check again.\"\n : \"Install Codex from openai.com/codex and sign in once, then check again.\",\n };\n }\n const auth = (probe?.auth ?? null) as Record<string, unknown> | null;\n if (provider === \"claude\") {\n if (!auth || auth.loggedIn !== true) {\n return {\n ...base,\n problem: \"Claude Code is installed but not signed in.\",\n fix: \"Open Claude Code once and sign in with your Claude account, then check again.\",\n };\n }\n const subscription = auth.authMethod === \"claude.ai\";\n return {\n ...base,\n loggedIn: true,\n billing: subscription ? \"subscription\" : \"api\",\n plan: subscription ? capitalize(typeof auth.subscriptionType === \"string\" ? auth.subscriptionType : null) : null,\n };\n }\n if (!auth || auth.loggedIn !== true) {\n return {\n ...base,\n problem: \"Codex is installed but not signed in.\",\n fix: \"Open Codex once and sign in with your ChatGPT account, then check again.\",\n };\n }\n const apiKey = auth.apiKey === true;\n return {\n ...base,\n loggedIn: true,\n billing: apiKey ? \"api\" : \"subscription\",\n plan: capitalize(typeof auth.planType === \"string\" ? auth.planType : null),\n account: typeof auth.email === \"string\" ? auth.email : null,\n };\n}\n\nexport async function createCodingSessionsEngine(\n options: CodingSessionsEngineOptions = {},\n): Promise<CodingSessionsEngine> {\n const dataDir = options.dataDir ?? path.join(os.homedir(), \".matrx\", \"coding-sessions\");\n const stateDir = path.join(dataDir, \"paperclip-state\");\n const homes = options.homes ?? defaultProviderHomes();\n const index = new RunIndex(dataDir);\n await index.load();\n const preferences = new PreferenceStore(dataDir);\n await preferences.load();\n await fs.mkdir(stateDir, { recursive: true });\n const identity: Identity = await index.identity();\n const agents = createAgentConnection(options.agents, dataDir);\n const backups = options.rawBackup\n ? createRawBackupScheduler({\n sink: options.rawBackup,\n findFile: (provider, providerSessionId) => findSessionFile(provider, providerSessionId, homes),\n onError: (error) => console.warn(\"[coding-sessions] raw transcript backup failed:\", error),\n })\n : null;\n /** Last `updatedAt` seen per discovered chat — a change is a turn that ended elsewhere. */\n const discoveredSeen = new Map<string, string>();\n\n // Last usage-limit / sign-in failure per provider, remembered across restarts.\n const healthFile = path.join(dataDir, \"provider-health.json\");\n let health: Partial<Record<CodingProvider, ProviderProblem>> = {};\n try {\n health = JSON.parse(await fs.readFile(healthFile, \"utf8\")) as typeof health;\n } catch {\n health = {};\n }\n const saveHealth = () =>\n fs.writeFile(healthFile, JSON.stringify(health), { mode: 0o600 }).catch(() => undefined);\n function noteRunOutcome(provider: CodingProvider, status: RunStatus, texts: string[]): void {\n if (status === \"completed\") {\n if (health[provider]) {\n delete health[provider];\n void saveHealth();\n }\n return;\n }\n if (status !== \"failed\") return;\n for (const text of texts) {\n const problem = classifyProviderError(text);\n if (problem) {\n health[provider] = problem;\n void saveHealth();\n return;\n }\n }\n }\n\n const workerEnv = buildCleanEnv(options.hostEnv ?? process.env, {\n // The driver's scratch state (prompt bundle, per-run MCP config) lives in\n // OUR data dir; nothing is ever written under ~/.paperclip.\n PAPERCLIP_HOME: stateDir,\n // The Codex driver otherwise \"vends\" cached copies of the user's login.\n PAPERCLIP_CODEX_AUTH_CACHE: \"0\",\n // Marks the forked process as a driver worker (see worker.ts).\n MATRX_CODING_SESSIONS_WORKER: \"1\",\n });\n // THE CLI EACH RUN USES: the newest copy on this computer (desktop app,\n // PATH, npm global), re-checked every few minutes so an app update is\n // picked up without a restart. A host-set command always wins.\n const binaryHome = options.hostEnv?.HOME ?? os.homedir();\n const binaryCache = new Map<CodingProvider, { at: number; value: Promise<ProviderBinary | null> }>();\n function binaryFor(provider: CodingProvider, fresh = false): Promise<ProviderBinary | null> {\n const cached = binaryCache.get(provider);\n if (cached && !fresh && Date.now() - cached.at < 5 * 60_000) return cached.value;\n const forced = options.commands?.[provider];\n const value = resolveBinary(provider, {\n env: workerEnv,\n home: binaryHome,\n forced,\n // A forced command needs no discovery to run; the status check still\n // looks, so it can say when a newer copy exists.\n discover: !forced || fresh,\n }).catch(() => (forced ? { path: forced, version: null, source: \"configured\" as const, sourceLabel: \"set by host\", newer: null } : null));\n if (!forced || !fresh) binaryCache.set(provider, { at: Date.now(), value });\n return value;\n }\n const commandFor = async (provider: CodingProvider): Promise<string | null> => (await binaryFor(provider))?.path ?? null;\n\n const workerPath = resolveWorkerPath();\n const shimPath = await installShim(dataDir);\n const listeners = new Set<(event: CodingEvent) => void>();\n const live = new Map<string, LiveRun>();\n const seqBySession = new Map<string, number>();\n\n function emit(event: CodingEvent): void {\n for (const listener of listeners) {\n try {\n listener(event);\n } catch {\n /* one bad listener never starves the rest */\n }\n }\n }\n const titleHints = options.titleHints;\n const hintsNow = () => titleHints?.current() ?? null;\n const unsubscribeHints = titleHints?.subscribe(() => emit({ type: \"titles\" })) ?? null;\n /** A session the engine drives shows the app's title once the app has one. */\n const withHintTitle = (session: CodingSession): CodingSession => {\n const hint = session.providerSessionId ? hintsNow()?.get(titleHintKey(session.provider, session.providerSessionId)) : undefined;\n return hint ? { ...session, title: hint.title } : session;\n };\n\n\n function saveSession(session: CodingSession): CodingSession {\n index.putSession(session);\n emit({ type: \"session\", session });\n return session;\n }\n\n function saveRun(run: RunRecord): RunRecord {\n index.putRun(run);\n emit({ type: \"run\", run });\n if (backups && isTerminalRunStatus(run.status)) {\n const providerSessionId = index.session(run.sessionId)?.providerSessionId;\n if (providerSessionId) void backups.notify(run.provider, providerSessionId);\n }\n return run;\n }\n\n function emitItem(liveRun: LiveRun, item: TranscriptItem): void {\n const sessionId = liveRun.run.sessionId;\n const seq = (seqBySession.get(sessionId) ?? 0) + 1;\n seqBySession.set(sessionId, seq);\n liveRun.items.push({ seq, item });\n emit({ type: \"item\", sessionId, runId: liveRun.run.runId, seq, item });\n }\n\n // A run the index says is live, with no process behind it, died with the\n // previous host. Say so rather than showing it spinning forever.\n for (const run of index.allRuns()) {\n if (!isTerminalRunStatus(run.status)) {\n index.putRun({\n ...run,\n status: \"failed\",\n endedAt: run.endedAt ?? nowIso(),\n error: \"The app closed while this run was in progress, so it did not finish.\",\n });\n const session = index.session(run.sessionId);\n if (session && session.lastRunId === run.runId) {\n index.putSession({ ...session, lastRunStatus: \"failed\" });\n }\n }\n }\n\n function forkWorker(): ChildProcess {\n return fork(workerPath, [], {\n env: workerEnv,\n cwd: dataDir,\n stdio: [\"ignore\", \"pipe\", \"pipe\", \"ipc\"],\n serialization: \"json\",\n });\n }\n\n function ourPids(): Set<number> {\n const pids = new Set<number>();\n for (const liveRun of live.values()) {\n if (liveRun.pgid !== null) pids.add(liveRun.pgid);\n if (liveRun.child.pid !== undefined) pids.add(liveRun.child.pid);\n }\n return pids;\n }\n\n function activeRunFor(sessionId: string): LiveRun | null {\n for (const liveRun of live.values()) if (liveRun.run.sessionId === sessionId) return liveRun;\n return null;\n }\n\n async function startRun(session: CodingSession, prompt: string): Promise<RunRecord> {\n const provider = session.provider;\n const realCommand = await commandFor(provider);\n const runId = randomUUID();\n // No model picked: the person's OWN default. The Claude driver would\n // otherwise force its built-in model over the one they chose in Claude\n // Code; Codex already falls back to its own config when none is passed.\n const model =\n session.model ?? (provider === \"claude\" ? ((await userDefaults(provider, session.cwd)).model ?? null) : null);\n const run: RunRecord = {\n runId,\n sessionId: session.id,\n provider,\n cwd: session.cwd,\n prompt,\n model,\n status: \"starting\",\n startedAt: nowIso(),\n endedAt: null,\n error: null,\n usage: null,\n costUsd: null,\n billing: null,\n };\n saveRun(run);\n saveSession({\n ...session,\n lastRunId: runId,\n lastRunStatus: \"starting\",\n updatedAt: run.startedAt,\n });\n\n if (!realCommand) {\n const failed = saveRun({\n ...run,\n status: \"failed\",\n endedAt: nowIso(),\n error: `${PROVIDER_LABEL[provider]} isn't installed on this computer.`,\n });\n const current = index.session(session.id);\n if (current) saveSession({ ...current, lastRunStatus: \"failed\" });\n return failed;\n }\n\n let fileOffset: number | null = null;\n if (session.providerSessionId) {\n const file = await findSessionFile(provider, session.providerSessionId, homes);\n if (file) fileOffset = (await fs.stat(file).catch(() => null))?.size ?? null;\n }\n\n // THE AGENT, when the session has one: the SAME pinned bundle every turn,\n // loaded through the CLI's own slots (agent-attach.ts).\n let agentArgs: string[] = [];\n // What the CLI is sent: the person's words, behind a delimited agent block\n // when Codex must be TOLD (a takeover, a switch, a compaction that dropped\n // it) — Codex ignores developer_instructions on a resumed chat.\n let cliPrompt = prompt;\n let delivered: Partial<CodingSession> | null = null;\n if (!session.agent && session.agentRemovedDue) {\n cliPrompt = `${AGENT_REMOVED_BLOCK}${prompt}`;\n delivered = { agentRemovedDue: false };\n }\n if (session.agent) {\n const bundle = await agents.readSessionBundle(session.id);\n if (!bundle) {\n const failed = saveRun({\n ...run,\n status: \"failed\",\n endedAt: nowIso(),\n error: `The agent ${session.agent.name} could not be loaded on this computer anymore. Start a new session to load it again.`,\n });\n const current = index.session(session.id);\n if (current) saveSession({ ...current, lastRunStatus: \"failed\" });\n return failed;\n }\n const attachment = await writeAgentAttachment(agents.sessionDir(session.id), bundle, {\n mcpUrl: await agents.mcpUrlFor(session.id),\n });\n agentArgs = agentArgsFor(provider, attachment, { resuming: session.providerSessionId !== null });\n if (session.agent.blockDue) {\n cliPrompt = `${renderFallbackBlock(bundle, path.join(attachment.dir, \"skills\"), { replaces: session.agent.replaces })}${prompt}`;\n }\n delivered = { agent: { ...session.agent, blockDue: false, deliveredAt: run.startedAt } };\n }\n\n const child = forkWorker();\n const liveRun: LiveRun = {\n run,\n child,\n pgid: null,\n stopRequested: false,\n killTimer: null,\n stderrTail: \"\",\n refusals: [],\n fileOffset,\n items: [],\n };\n live.set(runId, liveRun);\n emitItem(liveRun, { kind: \"user\", id: `run-${runId}`, text: prompt, at: run.startedAt });\n if (delivered) {\n const current = index.session(session.id);\n if (current) saveSession({ ...current, ...delivered });\n }\n\n const splitter = createLineSplitter();\n const claude = provider === \"claude\" ? createClaudeNormalizer() : null;\n const codex = provider === \"codex\" ? createCodexStreamNormalizer(runId.slice(0, 8)) : null;\n let knownProviderSession = session.providerSessionId;\n\n const consume = (values: unknown[]) => {\n for (const value of values) {\n const items = claude ? claude.push(value) : codex ? codex.push(value) : [];\n const sid = claude?.sessionId ?? codex?.sessionId ?? null;\n if (sid && sid !== knownProviderSession) {\n knownProviderSession = sid;\n const current = index.session(session.id);\n if (current) {\n saveSession({ ...current, providerSessionId: sid });\n // A rename made before the provider id was known follows the chat to its lasting key.\n if (preferences.rekey(chatKey(current.provider, null, current.id), chatKey(current.provider, sid))) {\n emit({ type: \"preferences\", preferences: preferences.all() });\n }\n }\n }\n for (const item of items) emitItem(liveRun, item);\n }\n };\n\n const settle = (patch: Partial<RunRecord>) => {\n if (liveRun.killTimer) clearTimeout(liveRun.killTimer);\n live.delete(runId);\n const final = saveRun({ ...liveRun.run, ...patch, endedAt: nowIso() });\n liveRun.run = final;\n noteRunOutcome(provider, final.status, [\n final.error ?? \"\",\n ...liveRun.items.flatMap((entry) => (entry.item.kind === \"error\" ? [entry.item.text] : [])),\n ]);\n const current = index.session(session.id);\n if (current) {\n const [next, ...rest] = current.queued;\n saveSession({ ...current, lastRunStatus: final.status, updatedAt: final.endedAt ?? nowIso() });\n if (next !== undefined) {\n const updated = index.session(session.id);\n if (updated) {\n const trimmed = saveSession({ ...updated, queued: rest });\n void startRun(trimmed, next);\n }\n }\n }\n void pruneDriverScratch();\n if (provider === \"codex\" && final.status === \"completed\") void checkCompaction(session.id);\n };\n\n let settled = false;\n child.on(\"message\", (raw) => {\n const message = raw as WorkerMessage;\n switch (message.kind) {\n case \"log\": {\n const chunk = String(message.chunk ?? \"\");\n if (message.stream === \"stdout\") {\n options.onRawOutput?.(runId, provider, chunk);\n const { values } = splitter.push(chunk);\n consume(values);\n } else {\n liveRun.stderrTail = (liveRun.stderrTail + chunk).slice(-4000);\n }\n return;\n }\n case \"spawn\": {\n const pgid =\n typeof message.processGroupId === \"number\"\n ? message.processGroupId\n : typeof message.pid === \"number\"\n ? message.pid\n : null;\n liveRun.pgid = pgid;\n if (liveRun.stopRequested) {\n killGroup(liveRun);\n return;\n }\n liveRun.run = saveRun({ ...liveRun.run, status: \"running\" });\n const current = index.session(session.id);\n if (current) saveSession({ ...current, lastRunStatus: \"running\" });\n return;\n }\n case \"refused\": {\n liveRun.refusals.push(`${String(message.op)}: ${String(message.target)}`);\n if (message.op === \"config-guard\") {\n emitItem(liveRun, {\n kind: \"notice\",\n id: \"config-guard\",\n level: \"warning\",\n text: \"The Codex driver has changed, so this run could not stop it from rewriting your ~/.codex/config.toml. Its contents are kept; update AI Matrx to restore the protection.\",\n });\n return;\n }\n if (message.op === \"delete\" || message.op === \"remove\") {\n emitItem(liveRun, {\n kind: \"notice\",\n id: `refused-${liveRun.refusals.length}`,\n level: \"warning\",\n text: \"The driver tried to delete part of your saved chat history. That was blocked; your history is untouched.\",\n });\n }\n return;\n }\n case \"result\": {\n consume(splitter.flush().values);\n settled = true;\n const result = (message.result ?? {}) as Record<string, unknown>;\n const usage = asUsage(result.usage);\n const billing = asBilling(result.billingType);\n const costUsd = typeof result.costUsd === \"number\" ? result.costUsd : null;\n if (liveRun.stopRequested) {\n // Codex exits 0 when its process group is killed; the host knows\n // better — the person pressed Stop.\n settle({ status: \"stopped\", usage, billing, costUsd, error: null });\n return;\n }\n if (message.refusedFreshSession === true) {\n settle({\n status: \"failed\",\n usage,\n billing,\n costUsd,\n error:\n `${PROVIDER_LABEL[provider]} could not reopen this chat, and would have started a new, empty one instead. ` +\n \"Nothing was sent. The chat may have been deleted or moved on this computer.\",\n });\n return;\n }\n const exitCode = typeof result.exitCode === \"number\" ? result.exitCode : null;\n const errorMessage = typeof result.errorMessage === \"string\" ? result.errorMessage : null;\n if (exitCode === 0 && !errorMessage && result.timedOut !== true) {\n settle({ status: \"completed\", usage, billing, costUsd, error: null });\n } else {\n const tail = liveRun.stderrTail.trim().split(\"\\n\").slice(-6).join(\"\\n\");\n settle({\n status: \"failed\",\n usage,\n billing,\n costUsd,\n error:\n errorMessage ??\n (tail || `${PROVIDER_LABEL[provider]} exited with code ${exitCode ?? \"unknown\"}.`),\n });\n }\n return;\n }\n case \"fatal\": {\n settled = true;\n settle({\n status: liveRun.stopRequested ? \"stopped\" : \"failed\",\n error: liveRun.stopRequested ? null : String(message.message ?? \"The driver failed.\"),\n });\n return;\n }\n default:\n return;\n }\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n liveRun.stderrTail = (liveRun.stderrTail + chunk.toString(\"utf8\")).slice(-4000);\n });\n child.on(\"exit\", (code, signal) => {\n if (settled) return;\n settled = true;\n settle({\n status: liveRun.stopRequested ? \"stopped\" : \"failed\",\n error: liveRun.stopRequested\n ? null\n : `The driver process ended unexpectedly (${signal ?? `code ${code ?? \"unknown\"}`}). ${liveRun.stderrTail.trim().split(\"\\n\").slice(-3).join(\" \")}`.trim(),\n });\n });\n\n child.send({\n kind: \"run\",\n provider,\n runId,\n cwd: session.cwd,\n prompt: cliPrompt,\n model,\n effort: session.effort ?? null,\n resumeSessionId: session.providerSessionId,\n shimPath,\n realCommand,\n identity,\n agentArgs,\n });\n return run;\n }\n\n /** After a Codex turn: if a compaction dropped the agent, tell it again next turn. */\n async function checkCompaction(sessionId: string): Promise<void> {\n const session = index.session(sessionId);\n if (!session?.agent || session.agent.blockDue || !session.providerSessionId) return;\n const file = await findSessionFile(\"codex\", session.providerSessionId, homes);\n if (!file || !(await codexCompactionDroppedAgent(file, session.agent.deliveredAt ?? null))) return;\n const current = index.session(sessionId);\n if (current?.agent) {\n saveSession({ ...current, agent: { ...current.agent, blockDue: true } });\n }\n }\n\n /** Load an agent for a session and record it (refuses, in plain words, when signed out). */\n async function attachAgent(\n sessionId: string,\n selection: import(\"../types\").AgentSelection,\n options: { blockDue: boolean; replaces?: string | null },\n ): Promise<import(\"../types\").SessionAgent> {\n const bundle = await agents.loadBundle(selection);\n await agents.saveSessionBundle(sessionId, bundle);\n return {\n ...sessionAgentRecord(bundle, {\n toolsServed: (await agents.mcpUrlFor(sessionId)) !== null,\n variables: selection.variables ?? {},\n }),\n blockDue: options.blockDue,\n deliveredAt: null,\n replaces: options.replaces ?? null,\n };\n }\n\n function killGroup(liveRun: LiveRun): void {\n const target = liveRun.pgid;\n if (target === null) return;\n try {\n process.kill(-target, \"SIGTERM\");\n } catch {\n /* already gone */\n }\n liveRun.killTimer = setTimeout(() => {\n try {\n process.kill(-target, \"SIGKILL\");\n } catch {\n /* already gone */\n }\n }, 3000);\n }\n\n async function pruneDriverScratch(): Promise<void> {\n // The Claude driver writes a per-run MCP config under its state dir; it is\n // empty (no Paperclip MCP servers) and never read again.\n const runsDir = path.join(\n stateDir,\n \"instances\",\n \"default\",\n \"companies\",\n identity.companyId,\n \"agents\",\n identity.agentId,\n \"claude-runtime\",\n \"runs\",\n );\n const entries = await fs.readdir(runsDir).catch(() => [] as string[]);\n await Promise.all(\n entries\n .filter((name) => !live.has(name))\n .map((name) => fs.rm(path.join(runsDir, name), { recursive: true, force: true }).catch(() => undefined)),\n );\n }\n\n async function probe(): Promise<Record<string, Record<string, unknown>>> {\n const [claudeBinary, codexBinary] = await Promise.all([binaryFor(\"claude\", true), binaryFor(\"codex\", true)]);\n return new Promise((resolve) => {\n const child = forkWorker();\n let answered = false;\n const timer = setTimeout(() => {\n if (answered) return;\n answered = true;\n child.kill(\"SIGKILL\");\n resolve({});\n }, 20000);\n child.on(\"message\", (raw) => {\n const message = raw as WorkerMessage;\n if (message.kind === \"probe-result\" && !answered) {\n answered = true;\n clearTimeout(timer);\n resolve({\n claude: { ...((message.claude ?? {}) as Record<string, unknown>), binary: claudeBinary },\n codex: { ...((message.codex ?? {}) as Record<string, unknown>), binary: codexBinary },\n });\n }\n });\n child.on(\"exit\", () => {\n if (answered) return;\n answered = true;\n clearTimeout(timer);\n resolve({});\n });\n child.send({\n kind: \"probe\",\n commands: { claude: claudeBinary?.path ?? null, codex: codexBinary?.path ?? null },\n quota: options.quota !== false,\n });\n });\n }\n\n function newSession(input: {\n provider: CodingProvider;\n cwd: string;\n title: string;\n model: string | null;\n effort?: string | null;\n origin: CodingSession[\"origin\"];\n providerSessionId: string | null;\n }): CodingSession {\n const at = nowIso();\n return {\n id: randomUUID(),\n provider: input.provider,\n providerSessionId: input.providerSessionId,\n cwd: input.cwd,\n title: input.title,\n model: input.model,\n effort: input.effort ?? null,\n origin: input.origin,\n createdAt: at,\n updatedAt: at,\n lastRunId: null,\n lastRunStatus: null,\n queued: [],\n };\n }\n\n function resolveFolder(raw: string): string | null {\n const trimmed = raw.trim();\n if (!trimmed) return null;\n return path.resolve(trimmed.replace(/^~(?=$|\\/)/, os.homedir()));\n }\n\n async function checkFolder(raw: string): Promise<import(\"../types\").FolderCheck> {\n const target = resolveFolder(raw);\n if (!target) return { path: \"\", exists: false, isDirectory: false };\n const stat = await fs.stat(target).catch(() => null);\n return { path: target, exists: stat !== null, isDirectory: stat?.isDirectory() === true };\n }\n\n async function assertFolder(cwd: string): Promise<string> {\n const resolved = path.resolve(cwd.replace(/^~(?=$|\\/)/, os.homedir()));\n const stat = await fs.stat(resolved).catch(() => null);\n if (!stat?.isDirectory()) {\n throw new Error(`The folder ${resolved} doesn't exist on this computer.`);\n }\n return resolved;\n }\n\n const engine: CodingSessionsEngine = {\n dataDir,\n\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n\n async providers() {\n const result = await probe();\n return Promise.all(\n ([\"claude\", \"codex\"] as const).map(async (provider) => {\n const probeResult = result[provider];\n const quota = Array.isArray(probeResult?.quota) ? (probeResult.quota as QuotaWindow[]) : [];\n const status = describeProviderStatus(provider, probeResult, health[provider] ?? null, quota);\n const models = Array.isArray(probeResult?.models) ? (probeResult.models as ModelOption[]) : [];\n const mine = await userDefaults(provider, null);\n // With no model of their own, Claude runs on the driver's built-in\n // default; Codex omits the flag and uses the CLI's own.\n const driverDefault =\n provider === \"claude\" && typeof probeResult?.driverDefaultModel === \"string\"\n ? probeResult.driverDefaultModel\n : null;\n return {\n ...status,\n models,\n efforts: EFFORT_LEVELS[provider],\n defaultModel: mine.model\n ? { id: mine.model, source: \"settings\" as const }\n : driverDefault\n ? { id: driverDefault, source: \"driver\" as const }\n : null,\n defaultEffort: mine.effort,\n };\n }),\n );\n },\n\n async discoverSessions(opts) {\n const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids() });\n const hints = hintsNow();\n const found = read.map((chat) => overlayHint(chat, hints, titleHints !== undefined));\n if (backups) {\n for (const chat of found) {\n const key = `${chat.provider}:${chat.providerSessionId}`;\n const previous = discoveredSeen.get(key);\n discoveredSeen.set(key, chat.updatedAt);\n // Only a CHANGE since this engine last looked — never a first-sight\n // sweep of someone's whole history.\n if (previous !== undefined && previous !== chat.updatedAt) {\n void backups.notify(chat.provider, chat.providerSessionId);\n }\n }\n }\n const limit = opts?.limit ?? 60;\n const oldest = found.length >= limit ? (found[found.length - 1]?.updatedAt ?? \"\") : \"\";\n const gone = unavailableFromHints(hints, new Set(found.map((c) => titleHintKey(c.provider, c.providerSessionId)))).filter(\n (c) => c.updatedAt >= oldest,\n );\n return gone.length ? [...found, ...gone].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, limit) : found;\n },\n\n async recentFolders(): Promise<RecentFolder[]> {\n const seen = new Map<string, string>();\n for (const session of index.sessions()) {\n if (!seen.has(session.cwd)) seen.set(session.cwd, session.updatedAt);\n }\n const discovered: DiscoveredSession[] = await discoverLocalSessions({ limit: 80, homes });\n for (const d of discovered) {\n if (d.cwd && !seen.has(d.cwd)) seen.set(d.cwd, d.updatedAt);\n }\n const folders = [...seen.entries()]\n .sort((a, b) => b[1].localeCompare(a[1]))\n .slice(0, 12);\n return Promise.all(\n folders.map(async ([folder, lastUsedAt]) => ({\n path: folder,\n lastUsedAt,\n exists: (await fs.stat(folder).catch(() => null))?.isDirectory() === true,\n })),\n );\n },\n\n async listSessions() {\n return index.sessions().map(withHintTitle);\n },\n\n async listRuns(sessionId) {\n const session = index.session(sessionId);\n return session ? index.runs(session.id) : [];\n },\n\n async history(sessionId, options): Promise<SessionHistory> {\n const session = index.session(sessionId);\n if (!session) {\n return { items: [], truncated: false, unavailable: \"This session is not in the list anymore.\", seq: 0 };\n }\n const active = activeRunFor(session.id);\n let base: SessionHistory = { items: [], truncated: false, unavailable: null, seq: 0 };\n if (session.providerSessionId) {\n const file = await findSessionFile(session.provider, session.providerSessionId, homes);\n if (file) {\n const endOffset = active ? (active.fileOffset ?? 0) : undefined;\n base = await readSessionFile(session.provider, file, endOffset, options?.maxBytes);\n } else if (!active) {\n base = {\n items: [],\n truncated: false,\n unavailable: `${PROVIDER_LABEL[session.provider]} has no saved transcript for this chat on this computer.`,\n seq: 0,\n };\n }\n }\n // Taken synchronously right before answering, so a live item is either\n // in this answer (seq ≤ answer.seq) or arrives after it.\n const liveItems = active ? active.items : [];\n return {\n ...base,\n items: [...base.items, ...liveItems.map((entry) => entry.item)],\n seq: seqBySession.get(session.id) ?? 0,\n };\n },\n\n async checkFolder(raw) {\n return checkFolder(raw);\n },\n\n async createFolder(raw) {\n const target = resolveFolder(raw);\n if (!target) throw new Error(\"Type a folder path first.\");\n await fs.mkdir(target, { recursive: true });\n return checkFolder(target);\n },\n\n async sessionActivity(provider, providerSessionId) {\n // A session WE are driving is not \"live elsewhere\".\n for (const liveRun of live.values()) {\n const session = index.session(liveRun.run.sessionId);\n if (session?.providerSessionId === providerSessionId) return null;\n }\n // Our own finished runs wrote the file too; those writes are not evidence.\n let ownWritesUntilMs: number | undefined;\n const ours = index.session(providerSessionId);\n if (ours) {\n for (const run of index.runs(ours.id)) {\n const ended = run.endedAt ? Date.parse(run.endedAt) + 5000 : undefined;\n if (ended !== undefined && (ownWritesUntilMs === undefined || ended > ownWritesUntilMs)) ownWritesUntilMs = ended;\n }\n }\n return sessionActivity(provider, providerSessionId, { homes, excludePids: ourPids(), ownWritesUntilMs });\n },\n\n async readTranscript(provider, providerSessionId, options) {\n const file = await findSessionFile(provider, providerSessionId, homes);\n if (!file) {\n return {\n items: [],\n truncated: false,\n unavailable: `${PROVIDER_LABEL[provider]} has no saved transcript for this chat on this computer.`,\n seq: 0,\n };\n }\n return readSessionFile(provider, file, undefined, options?.maxBytes);\n },\n\n async readRawTranscript(provider, providerSessionId) {\n const file = await findSessionFile(provider, providerSessionId, homes);\n if (!file) {\n return {\n available: false,\n reason: `${PROVIDER_LABEL[provider]} has no saved transcript for this chat on this computer.`,\n };\n }\n const stat = await fs.stat(file);\n if (stat.size > RAW_TRANSCRIPT_MAX_BYTES) {\n return {\n available: false,\n reason: `This transcript is ${formatFileSize(stat.size)}, larger than the ${formatFileSize(RAW_TRANSCRIPT_MAX_BYTES)} this page can hand over. It is at ${file}.`,\n };\n }\n const content = await fs.readFile(file, \"utf8\");\n return { available: true, fileName: path.basename(file), bytes: stat.size, content };\n },\n\n async start(input: StartInput): Promise<SendResult> {\n const prompt = input.prompt.trim();\n if (!prompt) throw new Error(\"Type what you want done before starting.\");\n const cwd = await assertFolder(input.cwd);\n const draft = newSession({\n provider: input.provider,\n cwd,\n title: titleFrom(prompt),\n model: input.model?.trim() || null,\n effort: input.effort?.trim() || null,\n origin: \"started\",\n providerSessionId: null,\n });\n // The agent is loaded BEFORE the session is saved, so a refusal (signed\n // out, not shared, gone) leaves nothing half-made in the list. A NEW\n // session loads it natively (Codex: developer_instructions), no block.\n if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: false });\n const session = saveSession(draft);\n const run = await startRun(session, prompt);\n return { session: index.session(session.id) ?? session, run, queued: false };\n },\n\n async takeover(input: TakeoverInput) {\n const existing = index.session(input.providerSessionId);\n if (existing) {\n if (!input.agent) return existing;\n return engine.setAgent(existing.id, input.agent);\n }\n const cwd = await assertFolder(input.cwd);\n const draft = newSession({\n provider: input.provider,\n cwd,\n title: input.title?.trim() || \"Taken-over chat\",\n model: null,\n origin: \"takeover\",\n providerSessionId: input.providerSessionId,\n });\n // \"Continue with agent\": Claude reads it every turn; Codex ignores\n // developer_instructions on a resumed chat, so it is TOLD in the next prompt.\n if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: input.provider === \"codex\" });\n return saveSession(draft);\n },\n\n async setAgent(sessionId, selection) {\n const session = index.session(String(sessionId ?? \"\"));\n if (!session) throw new Error(\"This session is not in the list anymore.\");\n if (!selection) {\n // A chat that ever followed an agent is TOLD it is gone, on both CLIs —\n // measured live: Claude, simply no longer given the instructions, kept\n // ending replies the way its earlier replies did.\n const told = session.agent?.deliveredAt != null;\n return saveSession({ ...session, agent: null, agentRemovedDue: told });\n }\n // A change mid-chat is TOLD in the next prompt, on both CLIs, naming the\n // agent it replaces (Claude also takes it natively every turn; Codex\n // only this way). Measured live: told only through the system prompt, a\n // model kept the rule its own earlier replies repeated.\n const previous = session.agent && session.agent.deliveredAt != null ? session.agent : null;\n const started = session.providerSessionId !== null;\n const agent = await attachAgent(session.id, selection, {\n blockDue: started,\n replaces: previous ? `${previous.name}${previous.versionNumber !== null ? ` v${previous.versionNumber}` : \"\"}` : null,\n });\n return saveSession({ ...session, agent, agentRemovedDue: false });\n },\n\n async send(sessionId, rawPrompt): Promise<SendResult> {\n const prompt = rawPrompt.trim();\n if (!prompt) throw new Error(\"Type a message before sending.\");\n const session = index.session(sessionId);\n if (!session) throw new Error(\"This session is not in the list anymore.\");\n if (activeRunFor(session.id)) {\n const queued = saveSession({ ...session, queued: [...session.queued, prompt] });\n return { session: queued, run: null, queued: true };\n }\n if (!session.providerSessionId && session.lastRunId) {\n // The first run never reported a session id (it failed before the\n // provider started a chat), so there is nothing to continue.\n const run = await startRun(session, prompt);\n return { session: index.session(session.id) ?? session, run, queued: false };\n }\n const run = await startRun(session, prompt);\n return { session: index.session(session.id) ?? session, run, queued: false };\n },\n\n async stop(runId) {\n const liveRun = live.get(runId);\n if (!liveRun) return index.run(runId);\n liveRun.stopRequested = true;\n if (liveRun.pgid !== null) {\n killGroup(liveRun);\n } else {\n // Not spawned yet: the worker is still preparing. End it; the CLI\n // never started.\n liveRun.child.kill(\"SIGTERM\");\n }\n return liveRun.run;\n },\n\n async chatPreferences() {\n return preferences.all();\n },\n\n async setChatPreference(key, patch) {\n const all = preferences.set(key, patch ?? {});\n emit({ type: \"preferences\", preferences: all });\n return all;\n },\n\n async searchChats(query, opts) {\n const result = await searchLocalChats(String(query ?? \"\"), { homes, cursor: opts?.cursor, limit: opts?.limit });\n const hints = hintsNow();\n return { ...result, hits: result.hits.map((hit) => ({ ...hit, title: hints?.get(titleHintKey(hit.provider, hit.providerSessionId))?.title ?? hit.title })) };\n },\n\n async openFolder(raw, target) {\n const folder = await assertFolder(String(raw ?? \"\"));\n await openFolderIn(folder, target);\n },\n\n async setSessionOptions(sessionId, opts) {\n const session = index.session(sessionId);\n if (!session) throw new Error(\"This session is not in the list anymore.\");\n const next = { ...session };\n if (opts && \"model\" in opts) next.model = typeof opts.model === \"string\" && opts.model.trim() ? opts.model.trim() : null;\n if (opts && \"effort\" in opts) next.effort = typeof opts.effort === \"string\" && opts.effort.trim() ? opts.effort.trim() : null;\n return saveSession(next);\n },\n\n async agentAccess() {\n return agents.access();\n },\n\n async agentCatalogRpc(request) {\n return agents.catalogRpc(request);\n },\n\n async agentDetails(agentId) {\n return agents.details(String(agentId ?? \"\"));\n },\n\n setMcpBaseUrl(baseUrl) {\n agents.setMcpBaseUrl(baseUrl);\n },\n\n async handleMcp(secret, body) {\n return agents.handleMcp(secret, body);\n },\n\n async dispose() {\n unsubscribeHints?.();\n for (const liveRun of live.values()) {\n liveRun.stopRequested = true;\n if (liveRun.pgid !== null) killGroup(liveRun);\n else liveRun.child.kill(\"SIGTERM\");\n }\n const deadline = Date.now() + 5000;\n while (live.size > 0 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n await index.flush();\n await preferences.flush();\n },\n };\n\n return engine;\n}\n\nconst OPEN_APP: Record<Exclude<OpenTarget, \"finder\">, { app: string; label: string }> = {\n vscode: { app: \"Visual Studio Code\", label: \"VS Code\" },\n cursor: { app: \"Cursor\", label: \"Cursor\" },\n terminal: { app: \"Terminal\", label: \"Terminal\" },\n};\n\n/** Open a folder in Finder or an app (macOS `open`; Finder-only elsewhere). */\nfunction openFolderIn(folder: string, target: OpenTarget): Promise<void> {\n const mac = process.platform === \"darwin\";\n let command: string;\n let args: string[];\n if (target === \"finder\") {\n command = mac ? \"open\" : process.platform === \"win32\" ? \"explorer\" : \"xdg-open\";\n args = [folder];\n } else {\n const app = OPEN_APP[target];\n if (!app) return Promise.reject(new Error(\"That app can't open folders from here.\"));\n if (!mac) return Promise.reject(new Error(`Opening ${app.label} from here works on a Mac only.`));\n command = \"open\";\n args = [\"-a\", app.app, folder];\n }\n return new Promise((resolve, reject) => {\n execFile(command, args, { timeout: 10_000 }, (error) => {\n if (!error) return resolve();\n const label = target === \"finder\" ? \"the folder\" : (OPEN_APP[target]?.label ?? target);\n reject(\n new Error(\n target === \"finder\"\n ? `Couldn't open ${label}: ${error.message}`\n : `${label} isn't installed on this computer, or it couldn't open this folder.`,\n ),\n );\n });\n });\n}\n\nexport type { RunStatus };\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","/**\n * AUTOMATIC RAW BACKUP — the engine uploads a chat's full provider file after\n * its runs end, but ONLY when the owner opted in.\n *\n * The cloud keeps a coding chat's text and tool names; the full transcript is\n * the provider's own file on this computer. When the Feature Knob\n * `coding_session_bridge.raw_transcript_backup` resolves on for the owner, the\n * host's sink uploads that file through the server's one door.\n *\n * Guarantees (proven in `raw-backup.test.ts`):\n * - the sink's policy is asked FIRST; with `enabled: false` the file is not\n * even read for upload and nothing is sent;\n * - at most one upload per chat per `debounceSeconds`, plus one trailing upload\n * so the final state is always backed up;\n * - an unchanged file (by SHA-256, including the server's stored one) is never\n * sent twice.\n *\n * The engine holds no cloud credentials: a host that can reach AI Matrx passes\n * a sink (`createAiMatrxRawBackupSink`); without one nothing is ever uploaded.\n */\n\nimport { createHash } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\n\nimport type { CodingProvider } from \"../types\";\n\nexport interface RawBackupPolicy {\n enabled: boolean;\n debounceSeconds: number;\n backupSha256?: string | null;\n}\n\nexport interface RawBackupSink {\n policy(provider: CodingProvider, providerSessionId: string): Promise<RawBackupPolicy>;\n upload(provider: CodingProvider, providerSessionId: string, content: Buffer): Promise<void>;\n}\n\ninterface ChatState {\n lastUploadAt: number | null;\n lastSha: string | null;\n trailing: Promise<void> | null;\n}\n\nexport interface RawBackupScheduler {\n notify(provider: CodingProvider, providerSessionId: string): Promise<void>;\n idle(): Promise<void>;\n}\n\nexport function createRawBackupScheduler(options: {\n sink: RawBackupSink;\n findFile: (provider: CodingProvider, providerSessionId: string) => Promise<string | null>;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n onError?: (error: unknown) => void;\n}): RawBackupScheduler {\n const now = options.now ?? (() => Date.now());\n const sleep = options.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const chats = new Map<string, ChatState>();\n\n async function uploadNow(state: ChatState, provider: CodingProvider, id: string, policy: RawBackupPolicy) {\n const file = await options.findFile(provider, id);\n if (!file) return;\n const content = await fs.readFile(file);\n const sha = createHash(\"sha256\").update(content).digest(\"hex\");\n if (sha === state.lastSha || sha === policy.backupSha256) {\n state.lastSha = sha;\n return;\n }\n await options.sink.upload(provider, id, content);\n state.lastUploadAt = now();\n state.lastSha = sha;\n }\n\n async function notify(provider: CodingProvider, providerSessionId: string): Promise<void> {\n const key = `${provider}:${providerSessionId}`;\n const state = chats.get(key) ?? { lastUploadAt: null, lastSha: null, trailing: null };\n chats.set(key, state);\n if (state.trailing) return; // the trailing upload carries this change\n try {\n const policy = await options.sink.policy(provider, providerSessionId);\n if (!policy.enabled) return;\n const windowMs = Math.max(1, policy.debounceSeconds) * 1000;\n const elapsed = state.lastUploadAt === null ? Infinity : now() - state.lastUploadAt;\n if (elapsed >= windowMs) {\n await uploadNow(state, provider, providerSessionId, policy);\n return;\n }\n state.trailing = (async () => {\n try {\n await sleep(windowMs - elapsed);\n const again = await options.sink.policy(provider, providerSessionId);\n if (again.enabled) await uploadNow(state, provider, providerSessionId, again);\n } catch (error) {\n options.onError?.(error);\n } finally {\n state.trailing = null;\n }\n })();\n } catch (error) {\n options.onError?.(error);\n }\n }\n\n return {\n notify,\n async idle() {\n await Promise.all([...chats.values()].map((s) => s.trailing).filter(Boolean));\n },\n };\n}\n\nconst SERVER_PROVIDER: Record<CodingProvider, string> = { claude: \"claude_code\", codex: \"codex\" };\n\n/**\n * The sink a host with an AI Matrx sign-in passes to the engine: the server's\n * backup-policy answer, then its one upload door.\n */\nexport function createAiMatrxRawBackupSink(options: {\n baseUrl: string;\n accessToken: () => Promise<string | null>;\n organizationId?: () => Promise<string | null>;\n fetch?: typeof fetch;\n}): RawBackupSink {\n const doFetch = options.fetch ?? fetch;\n async function headers(extra: Record<string, string> = {}): Promise<Record<string, string> | null> {\n const token = await options.accessToken();\n if (!token) return null;\n const org = options.organizationId ? await options.organizationId() : null;\n return { Authorization: `Bearer ${token}`, ...(org ? { \"X-Organization-Id\": org } : {}), ...extra };\n }\n const base = options.baseUrl.replace(/\\/$/, \"\");\n return {\n async policy(provider, providerSessionId) {\n const auth = await headers();\n if (!auth) return { enabled: false, debounceSeconds: 0 };\n const query = new URLSearchParams({ provider: SERVER_PROVIDER[provider], provider_session_id: providerSessionId });\n const response = await doFetch(`${base}/coding-sessions/raw-transcripts/backup-policy?${query}`, { headers: auth });\n if (!response.ok) throw new Error(`backup policy answered HTTP ${response.status}`);\n const body = (await response.json()) as { enabled?: boolean; debounce_seconds?: number; backup_sha256?: string | null };\n return {\n enabled: body.enabled === true,\n debounceSeconds: Number(body.debounce_seconds ?? 0),\n backupSha256: body.backup_sha256 ?? null,\n };\n },\n async upload(provider, providerSessionId, content) {\n const auth = await headers({ \"Content-Type\": \"application/x-ndjson\" });\n if (!auth) return;\n const query = new URLSearchParams({ provider: SERVER_PROVIDER[provider], provider_session_id: providerSessionId });\n const response = await doFetch(`${base}/coding-sessions/raw-transcripts/backup?${query}`, {\n method: \"POST\",\n headers: auth,\n body: new Uint8Array(content),\n });\n if (!response.ok) throw new Error(`backup upload answered HTTP ${response.status}`);\n },\n };\n}\n","/**\n * AGENT ATTACH — loading an AI Matrx agent into the person's own Claude Code or\n * Codex, through each CLI's own slots and nothing else.\n *\n * Design of record: matrx-desktop/design/agents-in-sessions/DESIGN.md (slot\n * table proven live on Claude Code 2.1.283 and codex-cli 0.157.1).\n *\n * Per session we write ONE directory under this package's data dir:\n *\n * <dir>/instructions.md the agent's instructions (+ included skills)\n * <dir>/plugin/.claude-plugin/plugin.json a temporary Claude plugin …\n * <dir>/plugin/skills/<slug>/SKILL.md … carrying the listed skills\n * <dir>/skills/<slug>/SKILL.md the same files, read by Codex by absolute path\n * <dir>/mcp.json Claude's MCP config → our host's /mcp/<secret>\n *\n * and pass it through the drivers' `extraArgs` only:\n *\n * Claude --append-system-prompt-file <instructions> --system-prompt-snapshot off\n * --plugin-dir <plugin> --mcp-config <mcp.json> (every turn)\n * Codex -c developer_instructions=<instructions + skills list> (new session only —\n * it survives resume)\n * -c mcp_servers.matrx-agent.url=… default_tools_approval_mode=\"approve\"\n *\n * 🚨 NEVER: `--system-prompt`, `--agent`, `--strict-mcp-config`, `--bare`, `--add-dir`\n * (our shim strips it), `model_instructions_file`, CLAUDE.md / AGENTS.md,\n * `~/.codex/skills`, settings files or profiles — the person's own setup is\n * never touched, and the Paperclip drivers' own instruction/skill/MCP options\n * are never used. The access token NEVER enters these files, the args or the\n * CLI's environment: the CLI only ever sees a 127.0.0.1 URL.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { JsonValue, PortableAgentBundle } from \"@ai-matrx/agents/portable\";\n\nimport type { CodingProvider, SessionAgent, SessionAgentPart } from \"../types\";\n\n/** The MCP server name both CLIs see. Never `matrx` (the person's own plugin). */\nexport const AGENT_MCP_SERVER_NAME = \"matrx-agent\";\n/** The temporary Claude plugin's name: skills read `matrx-agent:<slug>`. */\nexport const AGENT_PLUGIN_NAME = \"matrx-agent\";\n\n/** Codex's developer instructions end with this: a later block may replace them. */\nexport const CODEX_REPLACEMENT_CLAUSE =\n \"If a later message in this chat begins with an <ai_matrx_agent> block, that block replaces these AI Matrx agent instructions from then on; an <ai_matrx_agent_removed> block withdraws them.\";\n\nexport interface AgentAttachment {\n dir: string;\n instructionsFile: string;\n pluginDir: string;\n /** Present only when the agent has server tools and the host serves MCP. */\n mcpConfigFile: string | null;\n mcpUrl: string | null;\n /** The instructions text (what Codex receives as developer_instructions). */\n codexInstructions: string;\n}\n\nfunction escapeAttr(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\");\n}\n\nfunction versionWords(bundle: PortableAgentBundle): string {\n return bundle.version_number !== null ? String(bundle.version_number) : \"latest\";\n}\n\n/**\n * The instructions both CLIs receive: the agent's text plus included skills in\n * full. `claudeSkills` names the listed skills as the agent's own — Claude lists\n * plugin skills by itself, but measured live (2026-10-02, Haiku): with readable\n * names alone it loaded the skill in 5 of 5 fresh chats yet answered \"I don't\n * have access\" in a chat several turns long; told which skills are its own, it\n * loads them there too. (Names are readable at the source — `assign_names` in\n * aidream — so no listing is needed to stop an id being read as content.)\n */\nexport function renderAgentInstructions(bundle: PortableAgentBundle, options: { claudeSkills?: boolean } = {}): string {\n const included = bundle.skills.filter((skill) => skill.tier === \"included\");\n const listed = bundle.skills.filter((skill) => skill.tier === \"listed\");\n // The agent's own words come LAST, so its standing rules (the line every\n // reply must end with, say) are the most recent thing the model read\n // (observed: with the skill list after them, Haiku dropped such a rule on\n // two turns of one live run).\n const parts = [`<ai_matrx_agent name=\"${escapeAttr(bundle.name)}\" version=\"${versionWords(bundle)}\">`];\n if (included.length > 0) {\n parts.push(\n \"## Skills (always in effect)\",\n ...included.map((skill) => `### ${skill.label}\\n\\n${skill.body.trim()}`),\n );\n }\n if (options.claudeSkills && listed.length > 0) {\n parts.push(\n [\n \"## Your skills\",\n \"When a request matches one of these, load it with your Skill tool and follow it before answering:\",\n ...listed.map((skill) => `- ${AGENT_PLUGIN_NAME}:${skill.slug} — ${skill.description || skill.label}`),\n ].join(\"\\n\"),\n );\n }\n if (included.length > 0 || (options.claudeSkills && listed.length > 0)) parts.push(\"## Your instructions\");\n parts.push(bundle.instructions.trim());\n parts.push(\"</ai_matrx_agent>\");\n return `${parts.filter(Boolean).join(\"\\n\\n\")}\\n`;\n}\n\n/** Codex's own `<skills_instructions>` list, pointing at our files by absolute path. */\nexport function renderCodexSkillsList(bundle: PortableAgentBundle, skillsRoot: string): string {\n const listed = bundle.skills.filter((skill) => skill.tier === \"listed\");\n if (listed.length === 0) return \"\";\n const lines = [\n \"<skills_instructions>\",\n \"## AI Matrx agent skills\",\n \"A skill is a set of instructions stored in a `SKILL.md` file. Each entry has a name, a description and the absolute path of its file. When a task matches a skill's description, read that file and follow it.\",\n \"### Available skills\",\n ...listed.map(\n (skill) =>\n `- ${skill.slug}: ${skill.description || skill.label} (file: ${path.join(skillsRoot, skill.slug, \"SKILL.md\")})`,\n ),\n \"</skills_instructions>\",\n ];\n return lines.join(\"\\n\");\n}\n\n/**\n * THE FALLBACK: the agent as a delimited block at the start of a first prompt,\n * for a CLI slot that cannot carry it (a Codex takeover ignores\n * developer_instructions). Listed skills are named, with their files' paths.\n */\nexport function renderFallbackBlock(\n bundle: PortableAgentBundle,\n skillsRoot: string,\n options: { replaces?: string | null | undefined } = {},\n): string {\n const skills = renderCodexSkillsList(bundle, skillsRoot);\n // The block arrives mid-chat (a takeover, a switch, an update, after a\n // compaction), so it says plainly that it is the agent from now on — and,\n // on a switch, WHICH earlier agent it replaces: measured live, a model kept\n // following the older rule its own earlier replies repeated when told only\n // through the system prompt.\n const lead = options.replaces\n ? `These instructions REPLACE the earlier AI Matrx agent \"${options.replaces}\" from this message on. Where they differ from anything said before — including how earlier replies ended — follow these.`\n : \"The instructions below are your AI Matrx agent for this chat from now on; they replace any AI Matrx agent instructions given earlier.\";\n const body = renderAgentInstructions(bundle)\n .trim()\n .replace(/^(<ai_matrx_agent [^>]*>)/, `$1\\n\\n${lead}`);\n return skills ? `${body}\\n\\n${skills}\\n\\n` : `${body}\\n\\n`;\n}\n\n/**\n * A TOML basic string. JSON escapes are TOML escapes, except two JSON leaves\n * raw or emits that TOML refuses: DEL (must be escaped) and lone surrogates\n * (not Unicode scalar values — replaced).\n */\nexport function tomlString(value: string): string {\n const scalar = value.replace(/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/g, \"�\");\n return JSON.stringify(scalar).replace(/\\u007f/g, \"\\\\u007f\");\n}\n\n/** Write (or rewrite — idempotent) one session's agent directory. */\nexport async function writeAgentAttachment(\n dir: string,\n bundle: PortableAgentBundle,\n options: { mcpUrl: string | null },\n): Promise<AgentAttachment> {\n const pluginDir = path.join(dir, \"plugin\");\n const skillsRoot = path.join(dir, \"skills\");\n await fs.mkdir(path.join(pluginDir, \".claude-plugin\"), { recursive: true, mode: 0o700 });\n await fs.mkdir(skillsRoot, { recursive: true, mode: 0o700 });\n\n const instructions = renderAgentInstructions(bundle);\n const instructionsFile = path.join(dir, \"instructions.md\");\n await fs.writeFile(instructionsFile, renderAgentInstructions(bundle, { claudeSkills: true }), { mode: 0o600 });\n\n await fs.writeFile(\n path.join(pluginDir, \".claude-plugin\", \"plugin.json\"),\n `${JSON.stringify(\n {\n name: AGENT_PLUGIN_NAME,\n description: `Skills of the AI Matrx agent \"${bundle.name}\"`,\n version: versionWords(bundle) === \"latest\" ? \"1.0.0\" : `${versionWords(bundle)}.0.0`,\n },\n null,\n 2,\n )}\\n`,\n { mode: 0o600 },\n );\n // Listed skills only: an included skill's body is already in the instructions.\n const listed = bundle.skills.filter((skill) => skill.tier === \"listed\");\n const wanted = new Set(listed.map((skill) => skill.slug));\n for (const root of [path.join(pluginDir, \"skills\"), skillsRoot]) {\n await fs.mkdir(root, { recursive: true, mode: 0o700 });\n for (const existing of await fs.readdir(root).catch(() => [] as string[])) {\n if (!wanted.has(existing)) await fs.rm(path.join(root, existing), { recursive: true, force: true });\n }\n for (const skill of listed) {\n const skillDir = path.join(root, skill.slug);\n await fs.mkdir(skillDir, { recursive: true, mode: 0o700 });\n await fs.writeFile(path.join(skillDir, \"SKILL.md\"), skill.content, { mode: 0o600 });\n }\n }\n\n let mcpConfigFile: string | null = null;\n const mcpUrl = options.mcpUrl && bundle.tools.length > 0 ? options.mcpUrl : null;\n const mcpPath = path.join(dir, \"mcp.json\");\n if (mcpUrl) {\n mcpConfigFile = mcpPath;\n await fs.writeFile(\n mcpPath,\n `${JSON.stringify({ mcpServers: { [AGENT_MCP_SERVER_NAME]: { type: \"http\", url: mcpUrl } } }, null, 2)}\\n`,\n { mode: 0o600 },\n );\n } else {\n await fs.rm(mcpPath, { force: true });\n }\n\n const skillsList = renderCodexSkillsList(bundle, skillsRoot);\n return {\n dir,\n instructionsFile,\n pluginDir,\n mcpConfigFile,\n mcpUrl,\n // Same order as Claude's: the skills list first, the agent's words last —\n // then the one sentence that lets a later block replace them. Codex ranks\n // developer instructions above a user message, so without this permission\n // a mid-chat switch or update is ignored (measured live: the v2 block was\n // delivered and Codex kept ending with v1's line).\n codexInstructions: `${skillsList ? `${skillsList}\\n\\n` : \"\"}${instructions}\\n${CODEX_REPLACEMENT_CLAUSE}\\n`,\n };\n}\n\n/** The `extraArgs` that load the agent into one run. */\nexport function agentArgsFor(\n provider: CodingProvider,\n attachment: AgentAttachment,\n options: { resuming: boolean },\n): string[] {\n if (provider === \"claude\") {\n const args = [\n // Every turn: without snapshot off, a resumed Claude drops appended instructions.\n \"--append-system-prompt-file\",\n attachment.instructionsFile,\n \"--system-prompt-snapshot\",\n \"off\",\n \"--plugin-dir\",\n attachment.pluginDir,\n ];\n // Never --strict-mcp-config: the person's own MCP servers stay loaded.\n if (attachment.mcpConfigFile) args.push(\"--mcp-config\", attachment.mcpConfigFile);\n return args;\n }\n const args: string[] = [];\n // Codex keeps developer_instructions in the session it starts; on resume the\n // flag is ignored, so it is sent only when the session is new.\n if (!options.resuming) args.push(\"-c\", `developer_instructions=${tomlString(attachment.codexInstructions)}`);\n if (attachment.mcpUrl) {\n const key = `mcp_servers.${AGENT_MCP_SERVER_NAME}`;\n args.push(\n \"-c\",\n `${key}.url=${tomlString(attachment.mcpUrl)}`,\n \"-c\",\n `${key}.default_tools_approval_mode=\"approve\"`,\n );\n }\n return args;\n}\n\n/** What the session records about its agent: identity, and what each part loaded. */\nexport function sessionAgentRecord(\n bundle: PortableAgentBundle,\n options: { toolsServed: boolean; variables?: Record<string, JsonValue> | undefined },\n): SessionAgent {\n const unavailable = bundle.unavailable.map((u) => ({ kind: u.kind, name: u.name, reason: u.reason }));\n const missingSkills = unavailable.filter((u) => u.kind === \"skill\").length;\n const missingTools = unavailable.filter((u) => u.kind === \"tool\").length;\n if (!options.toolsServed && bundle.tools.length > 0) {\n for (const tool of bundle.tools) {\n unavailable.push({ kind: \"tool\", name: tool.canonical_name, reason: \"Tools need the coding sessions host\" });\n }\n }\n const toolsLoaded = options.toolsServed ? bundle.tools.length : 0;\n const loaded: SessionAgentPart[] = [\n { part: \"instructions\", loaded: bundle.instructions.trim() ? 1 : 0, total: 1 },\n { part: \"skills\", loaded: bundle.skills.length, total: bundle.skills.length + missingSkills },\n { part: \"tools\", loaded: toolsLoaded, total: bundle.tools.length + missingTools },\n ];\n return {\n agentId: bundle.agent_id,\n versionId: bundle.version_id,\n versionNumber: bundle.version_number,\n name: bundle.name,\n definitionHash: bundle.definition_hash,\n loaded,\n unavailable,\n skills: bundle.skills.map((skill) => skill.label),\n tools: options.toolsServed ? bundle.tools.map((tool) => tool.canonical_name) : [],\n ...(options.variables ? { variables: options.variables } : {}),\n };\n}\n\nimport { AGENT_BLOCK_MARKER } from \"../normalize/agent-block\";\n\nexport { AGENT_BLOCK_MARKER };\n\n/** What Codex is told when the person removes the agent from a chat. */\nexport const AGENT_REMOVED_BLOCK =\n \"<ai_matrx_agent_removed>The AI Matrx agent instructions given earlier in this chat no longer apply — including any rule about how replies end. Answer normally from this message on.</ai_matrx_agent_removed>\\n\\n\";\n\nexport { stripAgentBlock } from \"../normalize/agent-block\";\n\n\n/**\n * Did a Codex compaction, after `sinceIso`, drop the agent? Codex records each\n * compaction in the rollout as `{\"type\":\"compacted\",\"payload\":{\"replacement_history\":[…]}}`\n * — the history the model keeps. When the LATEST such record is newer than the\n * last delivery and no longer carries our marker, the agent must be told again.\n */\nexport async function codexCompactionDroppedAgent(rolloutFile: string, sinceIso: string | null): Promise<boolean> {\n const text = await fs.readFile(rolloutFile, \"utf8\").catch(() => \"\");\n if (!text.includes('\"type\":\"compacted\"')) return false;\n let latest: { timestamp?: string; payload?: { replacement_history?: unknown } } | null = null;\n for (const line of text.split(\"\\n\")) {\n if (!line.includes('\"type\":\"compacted\"')) continue;\n try {\n const entry = JSON.parse(line) as { type?: string; timestamp?: string; payload?: { replacement_history?: unknown } };\n if (entry.type === \"compacted\") latest = entry;\n } catch {\n /* a torn last line: ignore */\n }\n }\n if (!latest) return false;\n if (sinceIso && latest.timestamp && latest.timestamp <= sinceIso) return false;\n return !JSON.stringify(latest.payload?.replacement_history ?? \"\").includes(AGENT_BLOCK_MARKER.trim());\n}\n","/**\n * The delimited AI Matrx agent block a coding session puts in front of a\n * person's message when a CLI must be TOLD about the agent (a Codex takeover,\n * an agent switch, after a compaction). Pure: the transcript strips it so the\n * screen shows what the person wrote, not how the CLI was told.\n */\n\n/** The marker every agent text we hand a CLI starts with. */\nexport const AGENT_BLOCK_MARKER = \"<ai_matrx_agent \";\n\n/**\n * Remove a leading agent block from a user message, so the transcript shows\n * what the PERSON wrote (the block is how the CLI was told, not their words).\n */\nexport function stripAgentBlock(text: string): string {\n const removed = text.match(/^<ai_matrx_agent_removed>[\\s\\S]*?<\\/ai_matrx_agent_removed>\\s*/);\n if (removed) return text.slice(removed[0].length);\n if (!text.startsWith(AGENT_BLOCK_MARKER)) return text;\n const end = text.indexOf(\"</ai_matrx_agent>\");\n if (end < 0) return text;\n let rest = text.slice(end + \"</ai_matrx_agent>\".length);\n // The Codex skills list rides after the block.\n const skills = rest.match(/^\\s*<skills_instructions>[\\s\\S]*?<\\/skills_instructions>/);\n if (skills) rest = rest.slice(skills[0].length);\n return rest.replace(/^\\s+/, \"\");\n}\n","/**\n * THE AI MATRX CONNECTION — what a host needs to load the person's agents into\n * their coding sessions: who they are (a `CredentialsPort`, read fresh on every\n * call), which organization the work runs in, the agent picker's catalogue\n * reads, the portable bundle, and one MCP endpoint per session for the agent's\n * server tools.\n *\n * The token lives only in this process. The browser page asks the host to make\n * each catalogue read (an allowlist of RPCs); the CLI only ever sees a\n * 127.0.0.1 URL carrying a per-session random secret.\n *\n * A host with no credentials (the standalone launchd page today) is a STATE,\n * not an error: `access()` says signed out, the page shows one line, and plain\n * sessions work exactly as before.\n */\n\nimport { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { MatrxTransport } from \"@ai-matrx/agents/matrx\";\nimport type { PortableAgentBundle } from \"@ai-matrx/agents/portable\";\nimport type { AgentToolsMcpHandler, McpHttpReply } from \"@ai-matrx/agents/portable/mcp\";\nimport type { CredentialsPort, MatrxCredential } from \"@ai-matrx/data\";\n\nimport type {\n AgentAccess,\n AgentCatalogRpcRequest,\n AgentCatalogRpcResult,\n AgentDetails,\n AgentSelection,\n} from \"../types\";\n\n/** The host option that connects coding sessions to AI Matrx. */\nexport interface CodingSessionsAgentsOptions {\n /** The person's AI Matrx sign-in. Absent or `get() → null` = signed out. */\n credentials?: CredentialsPort | null | undefined;\n /**\n * The organization agent work runs in: a value, or a getter read per call —\n * sync or async (Matrx 2's `codingSessionsCredentials()` hands an async one).\n */\n organizationId?:\n | string\n | null\n | (() => string | null | undefined | Promise<string | null | undefined>)\n | undefined;\n /** AI Matrx server. Default `https://server.app.matrxserver.com`. */\n serverUrl?: string | undefined;\n /** The platform database URL. Default `https://db.matrxserver.com`. */\n supabaseUrl?: string | undefined;\n /** The database's publishable key (the picker's reads). Default: the platform's. */\n supabaseKey?: string | undefined;\n}\n\nexport const DEFAULT_SERVER_URL = \"https://server.app.matrxserver.com\";\nexport const DEFAULT_SUPABASE_URL = \"https://db.matrxserver.com\";\n/**\n * The platform database's PUBLISHABLE key — meant to ship inside apps (the\n * same value Matrx 2's sign-in uses); row access is decided by the person's\n * token, never by this key. A host on another database passes its own.\n */\nexport const DEFAULT_SUPABASE_KEY = \"sb_publishable_scm0jzEJiFUB5ItiqOx5Fg_8BOjB6oA\";\n\n/** The only catalogue reads the page may ask the host to make. */\nexport const AGENT_CATALOG_RPCS: ReadonlySet<string> = new Set([\n \"agx_get_list_full\",\n \"agx_search\",\n \"agx_resolve_agent_address\",\n \"ues_get_bulk\",\n \"ues_list\",\n \"ues_set\",\n \"ues_touch\",\n]);\n\n/**\n * The agents client loads ONLY when a host connected AI Matrx: a host with no\n * `agents` option (the standalone page) never imports it, so it runs exactly\n * as before — including from workspace source, where these entries are\n * TypeScript the plain Node runtime cannot load.\n */\nconst agentsClient = async () => {\n const [matrx, portable, mcp] = await Promise.all([\n import(\"@ai-matrx/agents/matrx\"),\n import(\"@ai-matrx/agents/portable\"),\n import(\"@ai-matrx/agents/portable/mcp\"),\n ]);\n return { ...matrx, ...portable, ...mcp };\n};\n\nfunction sortedValues(values: Record<string, unknown>): [string, unknown][] {\n return Object.keys(values)\n .sort()\n .map((key) => [key, values[key]]);\n}\n\nconst BUNDLE_CACHE_MS = 24 * 60 * 60 * 1000;\n\nexport const SIGNED_OUT_AGENT_MESSAGE = \"Sign in to AI Matrx to use your agents.\";\n\ninterface SessionAgentMeta {\n mcpSecret: string;\n conversationId: string;\n}\n\nfunction userIdOf(credential: MatrxCredential | null): string | null {\n if (!credential || credential.kind !== \"user\") return null;\n const payload = credential.accessToken.split(\".\")[1];\n if (!payload) return null;\n try {\n const claims = JSON.parse(Buffer.from(payload, \"base64url\").toString(\"utf8\")) as { sub?: unknown };\n return typeof claims.sub === \"string\" ? claims.sub : null;\n } catch {\n return null;\n }\n}\n\nexport interface AgentConnection {\n access(): Promise<AgentAccess>;\n catalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;\n details(agentId: string): Promise<AgentDetails>;\n /** Load the bundle a new session pins (refuses, in plain words, when signed out). */\n loadBundle(selection: AgentSelection): Promise<PortableAgentBundle>;\n saveSessionBundle(sessionId: string, bundle: PortableAgentBundle): Promise<void>;\n readSessionBundle(sessionId: string): Promise<PortableAgentBundle | null>;\n sessionDir(sessionId: string): string;\n /** The MCP URL for a session's tools, or null when no host serves MCP. */\n mcpUrlFor(sessionId: string): Promise<string | null>;\n /** Set by the host once it listens: `http://127.0.0.1:<port>`. */\n setMcpBaseUrl(baseUrl: string | null): void;\n /** Answer one MCP POST for the session that owns `secret`; null = unknown secret. */\n handleMcp(secret: string, body: unknown): Promise<McpHttpReply | null>;\n}\n\nexport function createAgentConnection(\n options: CodingSessionsAgentsOptions | undefined,\n dataDir: string,\n): AgentConnection {\n const credentials = options?.credentials ?? null;\n const serverUrl = (options?.serverUrl ?? DEFAULT_SERVER_URL).replace(/\\/+$/, \"\");\n const supabaseUrl = (options?.supabaseUrl ?? DEFAULT_SUPABASE_URL).replace(/\\/+$/, \"\");\n const supabaseKey = options?.supabaseKey ?? (options?.supabaseUrl ? null : DEFAULT_SUPABASE_KEY);\n const root = path.join(dataDir, \"agents\");\n let mcpBaseUrl: string | null = null;\n const handlers = new Map<string, AgentToolsMcpHandler>();\n const secretToSession = new Map<string, string>();\n\n const organizationId = async (): Promise<string | null> => {\n const raw = typeof options?.organizationId === \"function\" ? await options.organizationId() : options?.organizationId;\n return raw && raw.trim() ? raw.trim() : null;\n };\n\n /** A transport for ONE call: the organization is read now, the token per request. */\n const transport = async (): Promise<MatrxTransport> => {\n const org = await organizationId();\n return (await agentsClient()).createMatrxTransport({\n baseUrl: serverUrl,\n ...(credentials ? { credentials } : {}),\n ...(org ? { organizationId: org } : {}),\n source: \"codingSessionsAgents\",\n });\n };\n\n const cacheDir = path.join(dataDir, \"agents\", \".bundles\");\n /**\n * A built bundle is reused when the SAME definition (by hash) is loaded with\n * the same values on the same surface — versions are immutable, so a hash is\n * an identity. The cache never holds a token, only what the CLI is given.\n */\n const cacheKey = (definitionHash: string, selection: AgentSelection, surface: string): string =>\n createHash(\"sha256\")\n .update(JSON.stringify([definitionHash, sortedValues(selection.variables ?? {}), surface]))\n .digest(\"hex\");\n\n const credential = async (): Promise<MatrxCredential | null> => (credentials ? credentials.get() : null);\n\n const requireSignedIn = async (): Promise<void> => {\n if (!(await credential())) throw new Error(SIGNED_OUT_AGENT_MESSAGE);\n };\n\n const sessionDir = (sessionId: string): string => path.join(root, sessionId.replace(/[^A-Za-z0-9_-]/g, \"_\"));\n\n async function meta(sessionId: string): Promise<SessionAgentMeta> {\n const file = path.join(sessionDir(sessionId), \"session.json\");\n const existing = await fs\n .readFile(file, \"utf8\")\n .then((text) => JSON.parse(text) as SessionAgentMeta)\n .catch(() => null);\n if (existing?.mcpSecret && existing.conversationId) return existing;\n const created: SessionAgentMeta = { mcpSecret: randomBytes(24).toString(\"base64url\"), conversationId: randomUUID() };\n await fs.mkdir(sessionDir(sessionId), { recursive: true, mode: 0o700 });\n await fs.writeFile(file, JSON.stringify(created), { mode: 0o600 });\n return created;\n }\n\n /** A secret this process has not handed out yet (the host restarted mid-session). */\n async function findSessionBySecret(secret: string): Promise<string | null> {\n for (const name of await fs.readdir(root).catch(() => [] as string[])) {\n const found = await fs\n .readFile(path.join(root, name, \"session.json\"), \"utf8\")\n .then((text) => (JSON.parse(text) as SessionAgentMeta).mcpSecret === secret)\n .catch(() => false);\n if (found) {\n secretToSession.set(secret, name);\n return name;\n }\n }\n return null;\n }\n\n async function readSessionBundle(sessionId: string): Promise<PortableAgentBundle | null> {\n return fs\n .readFile(path.join(sessionDir(sessionId), \"bundle.json\"), \"utf8\")\n .then((text) => JSON.parse(text) as PortableAgentBundle)\n .catch(() => null);\n }\n\n return {\n async access() {\n const current = await credential().catch(() => null);\n const userId = userIdOf(current);\n return {\n configured: credentials !== null && supabaseKey !== null,\n signedIn: userId !== null,\n userId,\n organizationId: await organizationId().catch(() => null),\n };\n },\n\n async catalogRpc(request) {\n if (!AGENT_CATALOG_RPCS.has(request.fn)) {\n return { data: null, error: { message: `Not an agent catalogue read: ${request.fn}` } };\n }\n const current = await credential();\n if (!current || current.kind !== \"user\") return { data: null, error: { message: SIGNED_OUT_AGENT_MESSAGE, code: \"signed_out\" } };\n if (!supabaseKey) return { data: null, error: { message: \"This host has no AI Matrx database key.\", code: \"not_configured\" } };\n const query = new URLSearchParams();\n if (request.order) query.set(\"order\", `${request.order.column}.${request.order.ascending === false ? \"desc\" : \"asc\"}`);\n if (request.range) {\n query.set(\"offset\", String(request.range[0]));\n query.set(\"limit\", String(request.range[1] - request.range[0] + 1));\n }\n const headers: Record<string, string> = {\n apikey: supabaseKey,\n Authorization: `Bearer ${current.accessToken}`,\n \"Content-Type\": \"application/json\",\n // Every catalogue RPC lives in `public`; the database's default\n // exposed schema is not `public`, so name it (supabase-js does).\n \"Content-Profile\": \"public\",\n \"Accept-Profile\": \"public\",\n };\n if (request.count) headers.Prefer = `count=${request.count}`;\n const qs = query.toString();\n const response = await fetch(`${supabaseUrl}/rest/v1/rpc/${encodeURIComponent(request.fn)}${qs ? `?${qs}` : \"\"}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(request.args ?? {}),\n });\n const text = await response.text();\n const body: unknown = text ? JSON.parse(text) : null;\n if (!response.ok) {\n const err = (body ?? {}) as { message?: string; code?: string; details?: string | null; hint?: string | null };\n return {\n data: null,\n error: { message: err.message ?? `HTTP ${response.status}`, code: err.code, details: err.details ?? null, hint: err.hint ?? null },\n };\n }\n const range = response.headers.get(\"content-range\");\n const total = range?.split(\"/\")[1];\n return { data: body, error: null, count: total && total !== \"*\" ? Number(total) : null };\n },\n\n async details(agentId) {\n await requireSignedIn();\n // THE LIGHT READ: no skills, no tools — choosing an agent is instant.\n const summary = await (await agentsClient()).fetchPortableAgentSummary(await transport(), agentId);\n return {\n agentId: summary.agent_id,\n name: summary.name,\n variables: summary.variables,\n versions: summary.versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at })),\n latestVersionNumber: summary.version_number,\n latestVersionId: summary.version_id,\n };\n },\n\n async loadBundle(selection) {\n await requireSignedIn();\n const client = await agentsClient();\n // Pin a version: \"Latest\" means the version that is latest NOW.\n const summary = await client.fetchPortableAgentSummary(await transport(), selection.agentId);\n const versionId = selection.versionId ?? summary.version_id;\n const definitionHash = versionId\n ? (summary.versions.find((v) => v.id === versionId)?.definition_hash ?? null)\n : summary.definition_hash;\n const surface = \"matrx-user/code-editor\";\n const file = definitionHash ? path.join(cacheDir, `${cacheKey(definitionHash, selection, surface)}.json`) : null;\n if (file) {\n const cached = await fs\n .readFile(file, \"utf8\")\n .then((text) => JSON.parse(text) as PortableAgentBundle)\n .catch(() => null);\n // A day at most: the platform's tool set can change under the same definition.\n const fresh = await fs\n .stat(file)\n .then((st) => Date.now() - st.mtimeMs < BUNDLE_CACHE_MS)\n .catch(() => false);\n if (cached && fresh && cached.definition_hash === definitionHash) return cached;\n }\n const bundle = await client.fetchPortableAgent(\n await transport(),\n versionId ? { versionId } : { agentId: selection.agentId },\n { variables: selection.variables ?? {}, surface },\n );\n if (file && bundle.definition_hash === definitionHash) {\n await fs.mkdir(cacheDir, { recursive: true, mode: 0o700 });\n await fs.writeFile(file, JSON.stringify(bundle), { mode: 0o600 });\n }\n return bundle;\n },\n\n async saveSessionBundle(sessionId, bundle) {\n await fs.mkdir(sessionDir(sessionId), { recursive: true, mode: 0o700 });\n await fs.writeFile(path.join(sessionDir(sessionId), \"bundle.json\"), JSON.stringify(bundle), { mode: 0o600 });\n await meta(sessionId);\n },\n\n readSessionBundle,\n sessionDir,\n\n async mcpUrlFor(sessionId) {\n if (!mcpBaseUrl) return null;\n const { mcpSecret } = await meta(sessionId);\n secretToSession.set(mcpSecret, sessionId);\n return `${mcpBaseUrl}/mcp/${mcpSecret}`;\n },\n\n setMcpBaseUrl(baseUrl) {\n mcpBaseUrl = baseUrl ? baseUrl.replace(/\\/+$/, \"\") : null;\n },\n\n async handleMcp(secret, body) {\n let handler = handlers.get(secret);\n if (!handler) {\n const sessionId = secretToSession.get(secret) ?? (await findSessionBySecret(secret));\n if (!sessionId) return null;\n const bundle = await readSessionBundle(sessionId);\n if (!bundle) return null;\n const { conversationId } = await meta(sessionId);\n const { createAgentToolsMcpHandler } = await agentsClient();\n handler = createAgentToolsMcpHandler({\n bundle,\n credentials,\n organizationId: () => organizationId(),\n baseUrl: serverUrl,\n conversationId,\n });\n handlers.set(secret, handler);\n }\n return handler.handle(body);\n },\n };\n}\n","/**\n * Claude Code → `TranscriptItem`.\n *\n * ONE normalizer reads both of Claude's shapes, because they are the same\n * shape: `claude --print --output-format stream-json` lines (live) and the\n * entries of the user's own session file `~/.claude/projects/<cwd>/<id>.jsonl`\n * (history) both carry `{ type: \"assistant\" | \"user\", message: { content } }`.\n * The live stream adds `system`/`stream_event`/`result`; the file adds its own\n * bookkeeping entries (titles, attachments, snapshots), which are skipped.\n *\n * Block identity: an assistant message arrives as several lines sharing one\n * `message.id`, one content block per line, in block order — the same order\n * the partial-message `content_block_start.index` counts. So a text block's id\n * is `<message id>:<index>` on both paths, and a streamed draft is replaced by\n * its final text rather than duplicated.\n */\n\nimport type { RunUsage, TranscriptItem } from \"../types\";\nimport { stripAgentBlock } from \"./agent-block\";\n\ntype Json = Record<string, unknown>;\n\nfunction isObject(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction num(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\n/** User-role text Claude Code writes that the person never typed. */\nconst SYNTHETIC_USER_PREFIXES = [\n \"<command-name>\",\n \"<command-message>\",\n \"<command-args>\",\n \"<local-command-stdout>\",\n \"<local-command-stderr>\",\n \"<local-command-caveat>\",\n \"<system-reminder>\",\n \"<bash-input>\",\n \"<bash-stdout>\",\n \"<bash-stderr>\",\n \"<user-memory-input>\",\n \"<task-notification>\",\n \"Caveat: The messages below were generated by the user while running local commands\",\n \"[Request interrupted by user\",\n];\n\nexport function isSyntheticClaudeUserText(text: string): boolean {\n const trimmed = text.trimStart();\n return SYNTHETIC_USER_PREFIXES.some((prefix) => trimmed.startsWith(prefix));\n}\n\nfunction toolResultText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((block) => {\n if (!isObject(block)) return \"\";\n if (block.type === \"text\") return str(block.text) ?? \"\";\n if (block.type === \"image\") return \"[image]\";\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n }\n return content === undefined || content === null ? \"\" : JSON.stringify(content);\n}\n\nexport interface ClaudeNormalizer {\n /** Feed one parsed JSON line; returns the items it produced (often none). */\n push(entry: unknown): TranscriptItem[];\n /** The Claude session id, once a line has carried it. */\n readonly sessionId: string | null;\n}\n\nexport function createClaudeNormalizer(): ClaudeNormalizer {\n let sessionId: string | null = null;\n let streamingMessageId: string | null = null;\n const blockCounters = new Map<string, number>();\n let userCounter = 0;\n let noticeCounter = 0;\n\n function nextBlockIndex(messageId: string): number {\n const index = blockCounters.get(messageId) ?? 0;\n blockCounters.set(messageId, index + 1);\n return index;\n }\n\n function pushAssistant(entry: Json): TranscriptItem[] {\n const message = isObject(entry.message) ? entry.message : null;\n if (!message) return [];\n const messageId = str(message.id) ?? str(entry.uuid) ?? `assistant-${blockCounters.size}`;\n const content = Array.isArray(message.content) ? message.content : [];\n const items: TranscriptItem[] = [];\n for (const block of content) {\n if (!isObject(block)) continue;\n const index = nextBlockIndex(messageId);\n const id = `${messageId}:${index}`;\n if (block.type === \"text\") {\n const text = str(block.text) ?? \"\";\n if (text.length > 0) items.push({ kind: \"text\", id, text });\n } else if (block.type === \"thinking\") {\n // Claude Code writes thinking blocks with an EMPTY text and only a\n // signature unless thinking display is on; an empty aside is noise.\n const text = str(block.thinking) ?? \"\";\n if (text.trim().length > 0) items.push({ kind: \"reasoning\", id, text });\n } else if (block.type === \"tool_use\" || block.type === \"server_tool_use\") {\n items.push({\n kind: \"tool-call\",\n id: str(block.id) ?? id,\n name: str(block.name) ?? \"tool\",\n input: block.input ?? null,\n });\n }\n }\n return items;\n }\n\n function pushUser(entry: Json): TranscriptItem[] {\n if (entry.isMeta === true || entry.isCompactSummary === true) return [];\n const message = isObject(entry.message) ? entry.message : null;\n if (!message) return [];\n const at = str(entry.timestamp);\n const content = message.content;\n if (typeof content === \"string\") {\n if (isSyntheticClaudeUserText(content) || content.trim().length === 0) return [];\n userCounter += 1;\n // The agent block is how the CLI was told, not the person's words.\n return [{ kind: \"user\", id: str(entry.uuid) ?? `user-${userCounter}`, text: stripAgentBlock(content), at }];\n }\n if (!Array.isArray(content)) return [];\n const items: TranscriptItem[] = [];\n const typed: string[] = [];\n for (const block of content) {\n if (!isObject(block)) continue;\n if (block.type === \"tool_result\") {\n items.push({\n kind: \"tool-result\",\n id: str(block.tool_use_id) ?? \"unknown\",\n output: toolResultText(block.content),\n isError: block.is_error === true,\n });\n } else if (block.type === \"text\") {\n const text = str(block.text) ?? \"\";\n if (text.trim().length > 0 && !isSyntheticClaudeUserText(text)) typed.push(text);\n }\n }\n if (typed.length > 0) {\n userCounter += 1;\n items.unshift({\n kind: \"user\",\n id: str(entry.uuid) ?? `user-${userCounter}`,\n text: stripAgentBlock(typed.join(\"\\n\\n\")),\n at,\n });\n }\n return items;\n }\n\n function pushStreamEvent(entry: Json): TranscriptItem[] {\n const event = isObject(entry.event) ? entry.event : null;\n if (!event) return [];\n if (event.type === \"message_start\" && isObject(event.message)) {\n streamingMessageId = str(event.message.id);\n return [];\n }\n if (event.type === \"content_block_delta\" && streamingMessageId !== null) {\n const delta = isObject(event.delta) ? event.delta : null;\n if (delta?.type === \"text_delta\") {\n const text = str(delta.text) ?? \"\";\n if (text.length === 0) return [];\n return [{ kind: \"text-delta\", id: `${streamingMessageId}:${num(event.index)}`, text }];\n }\n }\n return [];\n }\n\n function pushResult(entry: Json): TranscriptItem[] {\n const items: TranscriptItem[] = [];\n const usage = isObject(entry.usage) ? entry.usage : null;\n if (usage) {\n const runUsage: RunUsage = {\n inputTokens: num(usage.input_tokens) + num(usage.cache_creation_input_tokens),\n outputTokens: num(usage.output_tokens),\n cachedInputTokens: num(usage.cache_read_input_tokens),\n };\n const cost = typeof entry.total_cost_usd === \"number\" ? entry.total_cost_usd : null;\n items.push({ kind: \"usage\", usage: runUsage, costUsd: cost });\n }\n if (entry.is_error === true || (typeof entry.subtype === \"string\" && entry.subtype !== \"success\")) {\n const text =\n str(entry.result) ??\n (Array.isArray(entry.errors) ? entry.errors.map(String).join(\"\\n\") : null) ??\n `Claude Code stopped with \"${String(entry.subtype)}\".`;\n noticeCounter += 1;\n items.push({ kind: \"error\", id: `claude-result-${noticeCounter}`, text });\n }\n return items;\n }\n\n return {\n get sessionId() {\n return sessionId;\n },\n push(raw: unknown): TranscriptItem[] {\n if (!isObject(raw)) return [];\n const lineSession = str(raw.session_id) ?? str(raw.sessionId);\n if (lineSession && sessionId === null) sessionId = lineSession;\n if (raw.isSidechain === true) return [];\n switch (raw.type) {\n case \"assistant\":\n return pushAssistant(raw);\n case \"user\":\n return pushUser(raw);\n case \"stream_event\":\n return pushStreamEvent(raw);\n case \"result\":\n return pushResult(raw);\n case \"system\":\n if (raw.subtype === \"compact_boundary\") {\n noticeCounter += 1;\n return [\n {\n kind: \"notice\",\n id: `claude-compact-${noticeCounter}`,\n level: \"info\",\n text: \"Claude Code summarized the earlier part of this conversation to make room.\",\n },\n ];\n }\n return [];\n default:\n return [];\n }\n },\n };\n}\n","/**\n * Codex → `TranscriptItem`, from its two different shapes:\n *\n * - the LIVE stream (`codex exec --json`): `thread.started`, `item.started` /\n * `item.completed` for agent messages, commands, file changes, MCP calls,\n * web searches and plans, then `turn.completed` with usage;\n * - the user's own saved rollout file (`~/.codex/sessions/**\\/rollout-*.jsonl`):\n * `session_meta`, `event_msg` (the person's words, verbatim) and\n * `response_item` (assistant messages, tool calls and their outputs).\n *\n * Codex numbers stream items `item_0, item_1, …` again on every run, so live\n * ids carry a per-run prefix; rollout items carry globally unique call ids.\n */\n\nimport type { RunUsage, TranscriptItem } from \"../types\";\nimport { stripAgentBlock } from \"./agent-block\";\n\ntype Json = Record<string, unknown>;\n\nfunction isObject(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction num(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction codexUsage(usage: Json): RunUsage {\n return {\n inputTokens: num(usage.input_tokens),\n outputTokens: num(usage.output_tokens),\n cachedInputTokens: num(usage.cached_input_tokens),\n };\n}\n\n/** Human names for Codex's item kinds, so a tool card reads like a sentence. */\nfunction toolCall(id: string, item: Json): TranscriptItem | null {\n switch (item.type) {\n case \"command_execution\":\n return { kind: \"tool-call\", id, name: \"Shell\", input: { command: str(item.command) ?? \"\" } };\n case \"file_change\":\n return { kind: \"tool-call\", id, name: \"Edit files\", input: { changes: item.changes ?? [] } };\n case \"mcp_tool_call\": {\n const server = str(item.server) ?? \"mcp\";\n const tool = str(item.tool) ?? \"tool\";\n return { kind: \"tool-call\", id, name: `${server}.${tool}`, input: item.arguments ?? null };\n }\n case \"web_search\":\n return { kind: \"tool-call\", id, name: \"Web search\", input: { query: str(item.query) ?? \"\" } };\n case \"todo_list\":\n return { kind: \"tool-call\", id, name: \"Plan\", input: { items: item.items ?? [] } };\n default:\n return null;\n }\n}\n\nfunction toolResult(id: string, item: Json): TranscriptItem | null {\n switch (item.type) {\n case \"command_execution\": {\n const exit = typeof item.exit_code === \"number\" ? item.exit_code : null;\n const output = str(item.aggregated_output) ?? \"\";\n return {\n kind: \"tool-result\",\n id,\n output: exit !== null && exit !== 0 ? `${output}\\n(exit code ${exit})`.trim() : output,\n isError: (exit !== null && exit !== 0) || item.status === \"failed\",\n };\n }\n case \"file_change\":\n return {\n kind: \"tool-result\",\n id,\n output: item.status === \"failed\" ? \"The file change failed.\" : \"Applied.\",\n isError: item.status === \"failed\",\n };\n case \"mcp_tool_call\": {\n const error = isObject(item.error) ? str(item.error.message) : str(item.error);\n return {\n kind: \"tool-result\",\n id,\n output: error ?? (item.result === undefined ? \"\" : JSON.stringify(item.result)),\n isError: error !== null || item.status === \"failed\",\n };\n }\n case \"web_search\":\n case \"todo_list\":\n return { kind: \"tool-result\", id, output: \"\", isError: false };\n default:\n return null;\n }\n}\n\nexport interface CodexStreamNormalizer {\n push(entry: unknown): TranscriptItem[];\n readonly sessionId: string | null;\n}\n\n/** The live `codex exec --json` stream. `runPrefix` keeps ids unique per run. */\nexport function createCodexStreamNormalizer(runPrefix: string): CodexStreamNormalizer {\n let sessionId: string | null = null;\n const started = new Set<string>();\n let counter = 0;\n\n return {\n get sessionId() {\n return sessionId;\n },\n push(raw: unknown): TranscriptItem[] {\n if (!isObject(raw)) return [];\n switch (raw.type) {\n case \"thread.started\":\n sessionId = str(raw.thread_id) ?? sessionId;\n return [];\n case \"item.started\":\n case \"item.updated\":\n case \"item.completed\": {\n const item = isObject(raw.item) ? raw.item : null;\n if (!item) return [];\n const id = `${runPrefix}:${str(item.id) ?? `item-${counter++}`}`;\n const completed = raw.type === \"item.completed\";\n if (item.type === \"agent_message\") {\n if (!completed) return [];\n const text = str(item.text) ?? \"\";\n return text ? [{ kind: \"text\", id, text }] : [];\n }\n if (item.type === \"reasoning\") {\n if (!completed) return [];\n const text = str(item.text) ?? \"\";\n return text.trim() ? [{ kind: \"reasoning\", id, text }] : [];\n }\n if (item.type === \"error\") {\n if (!completed) return [];\n // An `error` ITEM is a non-fatal warning (the run continues); a\n // fatal failure arrives as `turn.failed` or a top-level `error`.\n return [{ kind: \"notice\", id, level: \"warning\", text: str(item.message) ?? \"Codex warning.\" }];\n }\n const items: TranscriptItem[] = [];\n if (!started.has(id)) {\n const call = toolCall(id, item);\n if (call) {\n started.add(id);\n items.push(call);\n }\n }\n if (completed) {\n const result = toolResult(id, item);\n if (result) items.push(result);\n }\n return items;\n }\n case \"turn.completed\":\n return isObject(raw.usage)\n ? [{ kind: \"usage\", usage: codexUsage(raw.usage), costUsd: null }]\n : [];\n case \"turn.failed\": {\n const error = isObject(raw.error) ? str(raw.error.message) : null;\n counter += 1;\n return [{ kind: \"error\", id: `${runPrefix}:failed-${counter}`, text: error ?? \"Codex reported that the turn failed.\" }];\n }\n case \"error\":\n counter += 1;\n return [{ kind: \"error\", id: `${runPrefix}:error-${counter}`, text: str(raw.message) ?? \"Codex reported an error.\" }];\n default:\n return [];\n }\n },\n };\n}\n\nfunction contentText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .map((block) => (isObject(block) ? (str(block.text) ?? \"\") : \"\"))\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction parseArguments(raw: unknown): unknown {\n if (typeof raw !== \"string\") return raw ?? null;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return raw;\n }\n}\n\nfunction shellName(name: string): string {\n return name === \"shell\" || name === \"exec_command\" || name === \"local_shell\" ? \"Shell\" : name;\n}\n\n/**\n * The Codex app prepends ambient context to what the person typed\n * (`<in-app-browser-context …>…</in-app-browser-context>\\n## My request:\\n…`).\n * It is not their words; a title or a transcript bubble shows only theirs.\n */\nexport function stripCodexInjectedContext(text: string): string {\n let out = text;\n const leading = /^\\s*<([a-z][\\w-]*)(?:\\s[^>]*)?>[\\s\\S]*?<\\/\\1>/i;\n for (let i = 0; i < 8 && leading.test(out); i += 1) out = out.replace(leading, \"\");\n return out.replace(/^\\s*#{1,6}\\s*My request:\\s*/i, \"\").trim() || text.trim();\n}\n\n/** Text of a rollout `item_completed` item's `content` blocks. */\nfunction itemText(content: unknown): string {\n if (!Array.isArray(content)) return \"\";\n return content\n .map((block) => (isObject(block) ? (str(block.text) ?? \"\") : \"\"))\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction commandLine(command: unknown): string {\n if (Array.isArray(command)) {\n // [\"/bin/zsh\", \"-lc\", \"ls -la\"] → \"ls -la\": the shell wrapper is noise.\n const last = command[command.length - 1];\n if (command.length >= 3 && typeof last === \"string\") return last;\n return command.map(String).join(\" \");\n }\n return typeof command === \"string\" ? command : \"\";\n}\n\n/**\n * Current Codex (0.15x) records each turn TWICE in a rollout: the model-level\n * `response_item`s (where a shell command is a JavaScript `exec` snippet) and\n * the app-level `event_msg: item_completed` items the Codex app itself renders\n * (UserMessage, AgentMessage, CommandExecution, FileChange, …). The app-level\n * items read the way a person thinks about the work, so once a file shows it\n * has them, they are the transcript and the response_items are skipped.\n * Older rollouts have only response_items plus `event_msg: user_message`.\n */\nfunction rolloutItem(item: Json, fallbackId: string, at: string | null): TranscriptItem[] {\n const id = str(item.id) ?? fallbackId;\n switch (item.type) {\n case \"UserMessage\": {\n const text = stripCodexInjectedContext(stripAgentBlock(itemText(item.content)));\n return text.trim() ? [{ kind: \"user\", id, text, at }] : [];\n }\n case \"AgentMessage\": {\n const text = itemText(item.content);\n return text ? [{ kind: \"text\", id, text }] : [];\n }\n case \"Reasoning\": {\n const text = Array.isArray(item.summary_text) ? item.summary_text.map(String).join(\"\\n\") : \"\";\n return text.trim() ? [{ kind: \"reasoning\", id, text }] : [];\n }\n case \"CommandExecution\": {\n const exit = typeof item.exit_code === \"number\" ? item.exit_code : null;\n const output = str(item.aggregated_output) ?? str(item.formatted_output) ?? str(item.stdout) ?? \"\";\n const failed = (exit !== null && exit !== 0) || item.status === \"failed\";\n return [\n { kind: \"tool-call\", id, name: \"Shell\", input: { command: commandLine(item.command) } },\n {\n kind: \"tool-result\",\n id,\n output: failed && exit !== null ? `${output}\\n(exit code ${exit})`.trim() : output,\n isError: failed,\n },\n ];\n }\n case \"FileChange\":\n return [\n { kind: \"tool-call\", id, name: \"Edit files\", input: { changes: item.changes ?? null } },\n { kind: \"tool-result\", id, output: item.status === \"failed\" ? \"The file change failed.\" : \"Applied.\", isError: item.status === \"failed\" },\n ];\n case \"McpToolCall\": {\n const name = `${str(item.server) ?? \"mcp\"}.${str(item.tool) ?? \"tool\"}`;\n const error = isObject(item.error) ? str(item.error.message) : str(item.error);\n return [\n { kind: \"tool-call\", id, name, input: item.arguments ?? null },\n {\n kind: \"tool-result\",\n id,\n output: error ?? (item.result === undefined ? \"\" : JSON.stringify(item.result)),\n isError: error !== null || item.status === \"failed\",\n },\n ];\n }\n case \"WebSearch\":\n return [\n { kind: \"tool-call\", id, name: \"Web search\", input: { query: str(item.query) ?? \"\" } },\n { kind: \"tool-result\", id, output: \"\", isError: false },\n ];\n default:\n return [];\n }\n}\n\nexport interface CodexRolloutNormalizer {\n push(entry: unknown): TranscriptItem[];\n readonly sessionId: string | null;\n readonly cwd: string | null;\n}\n\n/** The user's saved rollout file. */\nexport function createCodexRolloutNormalizer(): CodexRolloutNormalizer {\n let sessionId: string | null = null;\n let cwd: string | null = null;\n let counter = 0;\n let appItems = false;\n\n return {\n get sessionId() {\n return sessionId;\n },\n get cwd() {\n return cwd;\n },\n push(raw: unknown): TranscriptItem[] {\n if (!isObject(raw)) return [];\n const payload = isObject(raw.payload) ? raw.payload : null;\n if (!payload) return [];\n const at = str(raw.timestamp);\n counter += 1;\n const fallbackId = `rollout-${typeof raw.ordinal === \"number\" ? raw.ordinal : counter}`;\n if (raw.type === \"session_meta\") {\n sessionId = str(payload.id) ?? sessionId;\n cwd = str(payload.cwd) ?? cwd;\n return [];\n }\n if (raw.type === \"event_msg\") {\n if (payload.type === \"item_completed\" && isObject(payload.item)) {\n appItems = true;\n return rolloutItem(payload.item, fallbackId, at);\n }\n if (payload.type === \"user_message\" && !appItems) {\n const text = stripCodexInjectedContext(stripAgentBlock(str(payload.message) ?? \"\"));\n return text.trim() ? [{ kind: \"user\", id: fallbackId, text, at }] : [];\n }\n return [];\n }\n if (raw.type === \"compacted\") {\n return [\n {\n kind: \"notice\",\n id: fallbackId,\n level: \"info\",\n text: \"Codex summarized the earlier part of this conversation to make room.\",\n },\n ];\n }\n if (raw.type !== \"response_item\" || appItems) return [];\n switch (payload.type) {\n case \"message\": {\n if (payload.role !== \"assistant\") return [];\n const text = contentText(payload.content);\n return text ? [{ kind: \"text\", id: str(payload.id) ?? fallbackId, text }] : [];\n }\n case \"reasoning\": {\n const summary = Array.isArray(payload.summary)\n ? payload.summary.map((part) => (isObject(part) ? (str(part.text) ?? \"\") : \"\")).join(\"\\n\")\n : \"\";\n return summary.trim()\n ? [{ kind: \"reasoning\", id: str(payload.id) ?? fallbackId, text: summary }]\n : [];\n }\n case \"function_call\":\n return [\n {\n kind: \"tool-call\",\n id: str(payload.call_id) ?? fallbackId,\n name: shellName(str(payload.name) ?? \"tool\"),\n input: parseArguments(payload.arguments),\n },\n ];\n case \"custom_tool_call\":\n return [\n {\n kind: \"tool-call\",\n id: str(payload.call_id) ?? fallbackId,\n name: shellName(str(payload.name) ?? \"tool\"),\n input: payload.input ?? null,\n },\n ];\n case \"local_shell_call\": {\n const action = isObject(payload.action) ? payload.action : {};\n return [\n {\n kind: \"tool-call\",\n id: str(payload.call_id) ?? fallbackId,\n name: \"Shell\",\n input: { command: action.command ?? null },\n },\n ];\n }\n case \"web_search_call\":\n return [\n {\n kind: \"tool-call\",\n id: str(payload.id) ?? fallbackId,\n name: \"Web search\",\n input: payload.action ?? null,\n },\n { kind: \"tool-result\", id: str(payload.id) ?? fallbackId, output: \"\", isError: false },\n ];\n case \"function_call_output\":\n case \"custom_tool_call_output\":\n case \"local_shell_call_output\": {\n const output = payload.output;\n const text =\n typeof output === \"string\"\n ? output\n : isObject(output)\n ? (str(output.content) ?? JSON.stringify(output))\n : contentText(output);\n return [\n {\n kind: \"tool-result\",\n id: str(payload.call_id) ?? fallbackId,\n output: text,\n isError: isObject(output) && output.success === false,\n },\n ];\n }\n default:\n return [];\n }\n },\n };\n}\n","/**\n * Stdout arrives in arbitrary chunks; the providers write one JSON object per\n * line. This turns chunks into parsed lines, keeping a partial tail between\n * chunks, and reports (never throws on) a line that is not JSON — the CLIs do\n * print plain-text warnings on stdout now and then.\n */\n\nexport interface LineSplitter {\n push(chunk: string): { values: unknown[]; nonJson: string[] };\n /** Whatever is left when the stream ends. */\n flush(): { values: unknown[]; nonJson: string[] };\n}\n\nfunction parseLines(lines: string[]): { values: unknown[]; nonJson: string[] } {\n const values: unknown[] = [];\n const nonJson: string[] = [];\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n if (!trimmed.startsWith(\"{\")) {\n nonJson.push(trimmed);\n continue;\n }\n try {\n values.push(JSON.parse(trimmed) as unknown);\n } catch {\n nonJson.push(trimmed);\n }\n }\n return { values, nonJson };\n}\n\nexport function createLineSplitter(): LineSplitter {\n let buffer = \"\";\n return {\n push(chunk) {\n buffer += chunk;\n const parts = buffer.split(\"\\n\");\n buffer = parts.pop() ?? \"\";\n return parseLines(parts);\n },\n flush() {\n const rest = buffer;\n buffer = \"\";\n return parseLines([rest]);\n },\n };\n}\n\n/** Parse a whole JSONL text (a fixture, or a provider file read in one go). */\nexport function parseJsonl(text: string): unknown[] {\n return parseLines(text.split(\"\\n\")).values;\n}\n","/**\n * The public contract of `@ai-matrx/coding-sessions`, shared by the engine\n * (Node), the local host (Node) and the UI (browser). Pure types — nothing here\n * touches Node or the DOM, and every value is JSON-serializable because it\n * crosses a transport (WebSocket today, desktop IPC later).\n */\n\nimport type { JsonValue } from \"@ai-matrx/agents/portable\";\n\nimport type { TitleSource } from \"./sessions/titles\";\n\n/** The coding agents this package drives. \"coding session\" is the canonical\n * platform term (chat.coding_session, the Coding Session Bridge). */\nexport type CodingProvider = \"claude\" | \"codex\";\n\nexport const CODING_PROVIDERS: readonly CodingProvider[] = [\"claude\", \"codex\"];\n\nexport const PROVIDER_LABEL: Record<CodingProvider, string> = {\n claude: \"Claude Code\",\n codex: \"Codex\",\n};\n\nexport type Billing = \"subscription\" | \"api\" | \"unknown\";\n\n/** Where the CLI a provider runs came from. */\nexport type BinarySource = \"desktop-app\" | \"path\" | \"npm-global\" | \"configured\";\n\n/** The exact CLI runs use: the newest copy on this computer (or the host's pick). */\nexport interface ProviderBinary {\n path: string;\n version: string | null;\n source: BinarySource;\n /** \"from ChatGPT app\", \"from PATH\", … */\n sourceLabel: string;\n /** A newer copy than the one in use, when one exists. */\n newer: { path: string; version: string; sourceLabel: string } | null;\n}\n\n/** What `providers()` answers for one provider, in plain terms. */\nexport interface ProviderStatus {\n provider: CodingProvider;\n label: string;\n installed: boolean;\n version: string | null;\n loggedIn: boolean;\n billing: Billing;\n /** \"Max\", \"Pro\", \"Plus\", … when the provider reports a plan. */\n plan: string | null;\n /** The signed-in account label, when the provider reports one. */\n account: string | null;\n /** A plain-English sentence for the screen when it is not ready. */\n problem: string | null;\n /** A plain-English fix for `problem`. */\n fix: string | null;\n /** Installed, signed in, and no known usage limit or expired sign-in. */\n ready: boolean;\n /** The last usage-limit or sign-in failure a run reported, until a run succeeds. */\n lastProblem: ProviderProblem | null;\n /** Usage windows, when the provider exposes them (Codex does; see FEATURE.md). */\n quota: QuotaWindow[];\n /** Models the driver knows for this provider (the person may type any other). */\n models?: ModelOption[] | undefined;\n /** Reasoning-effort levels this provider accepts, lowest first. */\n efforts?: string[] | undefined;\n /**\n * The model a run uses when none is picked, and where that comes from: the\n * person's own settings (`~/.claude/settings.json`, `~/.codex/config.toml`)\n * or the driver's built-in default.\n */\n defaultModel?: { id: string; source: \"settings\" | \"driver\" } | null | undefined;\n /** The effort a run uses when none is picked (the person's own settings). */\n defaultEffort?: string | null | undefined;\n /** Which CLI runs use, and its version. */\n binary?: ProviderBinary | null | undefined;\n}\n\nexport interface ModelOption {\n id: string;\n label: string;\n}\n\n/**\n * The person's own organisation of their chats — a rename, a pin, a hide. Kept\n * in this package's data dir, keyed by `chatKey()`; the providers' own files\n * are NEVER touched (a rename here does not rename the chat in Claude Code).\n */\nexport interface ChatPreference {\n /** Shown instead of the chat's own title. */\n title?: string | null | undefined;\n pinned?: boolean | undefined;\n /** Hidden from the lists (still found by search, restorable). */\n hidden?: boolean | undefined;\n updatedAt?: string | undefined;\n}\n\n/** The one key a chat's preference lives under, for ours and discovered alike. */\nexport function chatKey(provider: CodingProvider, providerSessionId: string | null, sessionId?: string | null): string {\n return providerSessionId ? `${provider}:${providerSessionId}` : `session:${sessionId ?? \"\"}`;\n}\n\n/** One chat that matched a search. */\nexport interface ChatSearchHit {\n provider: CodingProvider;\n providerSessionId: string;\n title: string;\n cwd: string | null;\n updatedAt: string;\n /** Where the words were found. */\n where: \"title\" | \"content\";\n /** A short excerpt around the first match in the conversation. */\n snippet: string | null;\n}\n\nexport interface ChatSearchResult {\n query: string;\n hits: ChatSearchHit[];\n /** How many chats were read, newest first, starting from the cursor. */\n scanned: number;\n /** How many chats exist on this computer. */\n total: number;\n /** Pass back to keep searching older chats; null when every chat was read. */\n nextCursor: number | null;\n}\n\n/** Where \"Open folder\" can open a session's folder. */\nexport type OpenTarget = \"finder\" | \"vscode\" | \"cursor\" | \"terminal\";\n\nexport interface ProviderProblem {\n kind: \"usage-limit\" | \"signed-out\";\n /** The provider's own words, verbatim. */\n message: string;\n /** When a usage limit lifts: ISO when parseable, else the provider's phrase. */\n until: string | null;\n at: string;\n}\n\nexport interface QuotaWindow {\n label: string;\n usedPercent: number | null;\n resetsAt: string | null;\n valueLabel: string | null;\n}\n\n/** An existing local Claude Code or Codex chat, found on disk (metadata only). */\nexport interface DiscoveredSession {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string | null;\n /**\n * The chat's own title by the one rule (`./sessions`): the coding app's title when the owner of\n * the apps' index supplied it (title hints), else the transcript's. Never the person's rename —\n * that is applied once, by the screen, from the preferences.\n */\n title: string;\n /** Where `title` came from (`TITLE_PRECEDENCE`). */\n titleSource?: TitleSource | undefined;\n /** The app's title is still on its way (hints not loaded yet); `title` is the transcript's for now. */\n titlePending?: boolean | undefined;\n /** Archived in the app (hidden by default, like Code › Chats). */\n archived?: boolean | undefined;\n /** A scheduled or automated run (hidden by default). */\n scheduled?: boolean | undefined;\n /** The app lists it but its conversation file is gone: why. Shown, cannot be taken over. */\n unavailable?: string | null | undefined;\n updatedAt: string;\n /** Where it was started, when the provider records it (\"cli\", \"vscode\", \"exec\", …). */\n source: string | null;\n /** Set when the chat looks live somewhere else right now (see `ActiveElsewhere`). */\n activeElsewhere: ActiveElsewhere | null;\n}\n\n/**\n * Evidence that a chat is being driven somewhere else RIGHT NOW. Taking it\n * over then puts two agents on one conversation, so the screen warns and asks —\n * it never blocks (validation offers, never blocks).\n */\nexport interface ActiveElsewhere {\n /** How we know, strongest first. */\n reason: \"process\" | \"recent-write\" | \"open-tool-call\";\n /** One plain sentence for the screen. */\n message: string;\n}\n\nexport type RunStatus = \"starting\" | \"running\" | \"completed\" | \"stopped\" | \"failed\";\n\nexport const TERMINAL_RUN_STATUSES: readonly RunStatus[] = [\"completed\", \"stopped\", \"failed\"];\n\nexport function isTerminalRunStatus(status: RunStatus): boolean {\n return TERMINAL_RUN_STATUSES.includes(status);\n}\n\nexport interface RunUsage {\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n}\n\n/** One turn: one prompt sent to one provider process. */\nexport interface RunRecord {\n runId: string;\n /** Our session id (`CodingSession.id`). */\n sessionId: string;\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model: string | null;\n status: RunStatus;\n startedAt: string;\n endedAt: string | null;\n /** The real error, verbatim from the provider or the driver, when failed. */\n error: string | null;\n usage: RunUsage | null;\n costUsd: number | null;\n billing: Billing | null;\n}\n\n/** How a session came to be listed here. */\nexport type SessionOrigin = \"started\" | \"takeover\";\n\n/** A conversation driven from here. Its transcript lives in the provider's own\n * files; this is only the index row. */\nexport interface CodingSession {\n /** Our stable id. */\n id: string;\n provider: CodingProvider;\n /** The provider's own session/thread id — null until the first run reports it. */\n providerSessionId: string | null;\n cwd: string;\n title: string;\n model: string | null;\n /** Reasoning effort for the next run; null = the provider's own default. */\n effort?: string | null | undefined;\n origin: SessionOrigin;\n createdAt: string;\n updatedAt: string;\n /** The live or most recent run. */\n lastRunId: string | null;\n lastRunStatus: RunStatus | null;\n /** Prompts waiting for the active run to finish, oldest first. */\n queued: string[];\n /** The AI Matrx agent loaded into every run of this session, when one was picked. */\n agent?: SessionAgent | null | undefined;\n /** Codex must be told, in the next prompt, that an earlier agent no longer applies. */\n agentRemovedDue?: boolean | undefined;\n}\n\n/**\n * One normalized transcript item — the same shape from Claude and Codex, from\n * a live stream and from a provider's saved session file.\n */\nexport type TranscriptItem =\n | { kind: \"user\"; id: string; text: string; at: string | null }\n | { kind: \"text\"; id: string; text: string }\n | { kind: \"text-delta\"; id: string; text: string }\n | { kind: \"reasoning\"; id: string; text: string }\n | { kind: \"tool-call\"; id: string; name: string; input: unknown }\n | { kind: \"tool-result\"; id: string; output: string; isError: boolean }\n | { kind: \"usage\"; usage: RunUsage; costUsd: number | null }\n | { kind: \"notice\"; id: string; level: \"info\" | \"warning\"; text: string }\n | { kind: \"error\"; id: string; text: string };\n\n/** Everything the engine pushes to a listener. */\nexport type CodingEvent =\n | { type: \"session\"; session: CodingSession }\n | { type: \"run\"; run: RunRecord }\n | { type: \"preferences\"; preferences: Record<string, ChatPreference> }\n /** The apps' titles changed (or finished loading): re-read the discovered chats. */\n | { type: \"titles\" }\n | {\n type: \"item\";\n sessionId: string;\n runId: string;\n /** Monotonic per session; a history read reports the last `seq` it includes. */\n seq: number;\n item: TranscriptItem;\n };\n\n/** A transcript read back from the provider's own file. */\nexport interface SessionHistory {\n items: TranscriptItem[];\n /** True when the file was larger than the read budget and only its end was read. */\n truncated: boolean;\n /** Plain-English reason when history could not be read (never thrown at the UI). */\n unavailable: string | null;\n /** The last live item `seq` this read already contains; apply only newer ones. */\n seq: number;\n}\n\nexport interface StartInput {\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model?: string | null | undefined;\n effort?: string | null | undefined;\n /** An AI Matrx agent to load into the CLI. Needs the host's `agents` credentials. */\n agent?: AgentSelection | null | undefined;\n}\n\n/** Which AI Matrx agent a new session loads, and the person's variable values. */\nexport interface AgentSelection {\n agentId: string;\n /** Pin one saved version; omitted = the latest, pinned at start. */\n versionId?: string | null | undefined;\n variables?: Record<string, JsonValue> | undefined;\n}\n\n/** One part of an agent and whether this session's CLI carries it. */\nexport interface SessionAgentPart {\n part: \"instructions\" | \"skills\" | \"tools\";\n loaded: number;\n total: number;\n}\n\n/**\n * The agent a session runs with. Recorded at start and never drifts: every\n * later turn reloads the SAME bundle (same version, same hash).\n */\nexport interface SessionAgent {\n agentId: string;\n versionId: string | null;\n versionNumber: number | null;\n name: string;\n definitionHash: string;\n loaded: SessionAgentPart[];\n /** What could not be carried, with the reason. */\n unavailable: { kind: string; name: string; reason: string }[];\n /** The skills it carries (labels) and the tools it serves (names) — the agent's own set. */\n skills?: string[] | undefined;\n tools?: string[] | undefined;\n /** The person's variable values, kept so \"Update to vN\" can reuse them. */\n variables?: Record<string, JsonValue> | undefined;\n /**\n * The CLI must be TOLD in the next prompt (a delimited block): a Codex\n * takeover or agent switch (Codex ignores developer_instructions on resume),\n * or a Codex compaction that dropped the block. Cleared once delivered.\n */\n blockDue?: boolean | undefined;\n /** When the block (or native instructions) last reached the CLI. */\n deliveredAt?: string | null | undefined;\n /** The agent this one replaced mid-chat (\"Code Reviewer v1\"), named in the block. */\n replaces?: string | null | undefined;\n}\n\n/** Whether this host can reach AI Matrx as a signed-in person. */\nexport interface AgentAccess {\n signedIn: boolean;\n userId: string | null;\n organizationId: string | null;\n /** True when the host was started with no AI Matrx connection at all. */\n configured: boolean;\n}\n\n/** A catalogue read the picker asks the host to make (PostgREST RPC shape). */\nexport interface AgentCatalogRpcRequest {\n fn: string;\n args?: Record<string, unknown> | undefined;\n count?: \"exact\" | \"planned\" | \"estimated\" | undefined;\n range?: [number, number] | undefined;\n order?: { column: string; ascending?: boolean | undefined } | undefined;\n}\n\nexport interface AgentCatalogRpcResult {\n data: unknown;\n error: {\n message: string;\n code?: string | undefined;\n details?: string | null | undefined;\n hint?: string | null | undefined;\n } | null;\n count?: number | null;\n}\n\n/** What a picker needs about one agent — the LIGHT read (no skills, no tools). */\nexport interface AgentDetails {\n agentId: string;\n name: string;\n /** Variable declarations as authored (camelCase). */\n variables: Record<string, JsonValue>[];\n /** Newest first. */\n versions: { id: string; versionNumber: number; changedAt: string | null }[];\n /** The version \"Latest\" resolves to right now. */\n latestVersionNumber: number | null;\n latestVersionId: string | null;\n}\n\nexport interface TakeoverInput {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string;\n title?: string | undefined;\n /** Continue the chat WITH an AI Matrx agent (\"Continue with agent\"). */\n agent?: AgentSelection | null | undefined;\n}\n\nexport interface SendResult {\n session: CodingSession;\n /** The run that started, or null when the prompt was queued behind a live run. */\n run: RunRecord | null;\n queued: boolean;\n}\n\nexport interface FolderCheck {\n /** The absolute path the check resolved. */\n path: string;\n exists: boolean;\n /** False when something that is NOT a folder sits at the path. */\n isDirectory: boolean;\n}\n\n/** A folder the New session flow offers (from discovered and driven sessions). */\nexport interface RecentFolder {\n path: string;\n lastUsedAt: string;\n exists: boolean;\n}\n\n/**\n * THE ENGINE CONTRACT — what the UI can ask for, independent of transport.\n * The WebSocket host implements it over the wire; a desktop app implements it\n * over IPC; the UI never knows which.\n */\nexport interface CodingSessionsApi {\n providers(): Promise<ProviderStatus[]>;\n discoverSessions(options?: { limit?: number }): Promise<DiscoveredSession[]>;\n recentFolders(): Promise<RecentFolder[]>;\n listSessions(): Promise<CodingSession[]>;\n listRuns(sessionId: string): Promise<RunRecord[]>;\n /** `maxBytes` reads more of a long chat's file (\"Show earlier\"). */\n history(sessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /** Read-only transcript of a chat found on disk, before taking it over. */\n readTranscript(provider: CodingProvider, providerSessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /**\n * FULL DOWNLOAD: the provider's own complete transcript file for this chat,\n * byte for byte (every tool input and output). AI Matrx's cloud keeps only\n * text and tool names, so this computer is the first place the full file\n * lives. `available: false` carries the sentence saying why.\n */\n readRawTranscript(provider: CodingProvider, providerSessionId: string): Promise<RawTranscript>;\n /** Does this folder exist here? `~` is the person's home. */\n checkFolder(path: string): Promise<FolderCheck>;\n /** Create a folder (and any missing parents), then report on it. */\n createFolder(path: string): Promise<FolderCheck>;\n /** Fresh check: is this chat live somewhere else right now? null when not. */\n sessionActivity(provider: CodingProvider, providerSessionId: string): Promise<ActiveElsewhere | null>;\n start(input: StartInput): Promise<SendResult>;\n takeover(input: TakeoverInput): Promise<CodingSession>;\n send(sessionId: string, prompt: string): Promise<SendResult>;\n stop(runId: string): Promise<RunRecord | null>;\n /** The person's renames, pins and hides, by `chatKey()`. */\n chatPreferences(): Promise<Record<string, ChatPreference>>;\n /** Merge a change into one chat's preference; `null` fields clear. Returns them all. */\n setChatPreference(key: string, patch: ChatPreference): Promise<Record<string, ChatPreference>>;\n /** Find chats by title and by what was said in them, newest first, within a time budget. */\n searchChats(query: string, options?: { cursor?: number; limit?: number }): Promise<ChatSearchResult>;\n /** Open a folder in Finder, VS Code, Cursor or Terminal. */\n openFolder(path: string, target: OpenTarget): Promise<void>;\n /** Change the model or effort the NEXT run of a session uses. */\n setSessionOptions(sessionId: string, options: { model?: string | null; effort?: string | null }): Promise<CodingSession>;\n /** Is this host signed in to AI Matrx (so agents can load)? */\n agentAccess(): Promise<AgentAccess>;\n /** One allowlisted agent-catalogue read, made by the host as the signed-in person. */\n agentCatalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;\n /** An agent's variables and saved versions, for the New session form. */\n agentDetails(agentId: string): Promise<AgentDetails>;\n /**\n * Load a different agent into a session from its next message on (or\n * remove it, with `null`). Claude reads it every turn; Codex is told in the\n * next prompt.\n */\n setAgent(sessionId: string, agent: AgentSelection | null): Promise<CodingSession>;\n}\n\nexport type RawTranscript =\n | { available: true; fileName: string; bytes: number; content: string }\n | { available: false; reason: string };\n\nexport interface HistoryOptions {\n /** Read up to this many bytes from the end of the file (default 24 MB). */\n maxBytes?: number | undefined;\n}\n\nexport type CodingSessionsMethod = keyof CodingSessionsApi;\n\n/** The transport the UI talks through (WebSocket, IPC, in-process). */\nexport interface CodingSessionsTransport {\n call<M extends CodingSessionsMethod>(\n method: M,\n ...args: Parameters<CodingSessionsApi[M]>\n ): ReturnType<CodingSessionsApi[M]>;\n subscribe(listener: (event: CodingEvent) => void): () => void;\n /** Connection state, for an honest banner. */\n status(): TransportStatus;\n onStatus(listener: (status: TransportStatus) => void): () => void;\n}\n\nexport type TransportStatus =\n | { state: \"connecting\" }\n | { state: \"open\" }\n | { state: \"closed\"; reason: string };\n","/**\n * USAGE LIMITS AND EXPIRED SIGN-INS, in plain English.\n *\n * A provider can be installed and signed in and still unable to run: the\n * ChatGPT or Claude plan hit its usage limit, or the saved login expired.\n * Runs report that in the provider's own words; this turns those words into\n * a remembered, honest status. Built from the real texts captured on\n * 2026-09-27 (Codex usage limit, Codex refresh failure).\n */\n\nimport { PROVIDER_LABEL, type CodingProvider, type ProviderProblem, type QuotaWindow } from \"./types\";\n\nconst USAGE_LIMIT = [\n /hit your usage limit/i,\n /usage limit (?:reached|exceeded)/i,\n /\\blimit reached\\b/i,\n /you'?ve hit your limit/i,\n /rate limit/i,\n /quota (?:exceeded|exhausted)/i,\n /purchase more credits/i,\n];\n\nconst SIGNED_OUT = [\n /access token could not be refreshed/i,\n /please sign in again/i,\n /(?:not|no longer) (?:logged|signed) in/i,\n /please run \\/login/i,\n /invalid api key/i,\n /oauth token (?:has )?expired/i,\n /authentication_error/i,\n /401 unauthorized/i,\n];\n\n/** \"Oct 4th, 2026 8:34 AM\" → ISO. null when the phrase is not a date. */\nexport function parseLimitDate(phrase: string): string | null {\n const cleaned = phrase.replace(/(\\d{1,2})(st|nd|rd|th)\\b/gi, \"$1\").replace(/[.,]\\s*$/, \"\").trim();\n const ms = Date.parse(cleaned);\n return Number.isNaN(ms) ? null : new Date(ms).toISOString();\n}\n\nfunction limitPhrase(text: string): string | null {\n const match =\n /try again (?:at|after|on) ([^\\n]+?)(?:\\.\\s|\\.$|$)/i.exec(text) ??\n /resets? (?:at |on )?([^\\n∙·|]+?)(?:\\.\\s|\\.$|$|\\s*[∙·|])/i.exec(text);\n return match?.[1]?.trim() ?? null;\n}\n\nexport function classifyProviderError(text: string, at = new Date().toISOString()): ProviderProblem | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n if (SIGNED_OUT.some((re) => re.test(trimmed))) {\n return { kind: \"signed-out\", message: trimmed, until: null, at };\n }\n if (USAGE_LIMIT.some((re) => re.test(trimmed))) {\n const phrase = limitPhrase(trimmed);\n return { kind: \"usage-limit\", message: trimmed, until: phrase ? (parseLimitDate(phrase) ?? phrase) : null, at };\n }\n return null;\n}\n\n/** A usage limit whose reset time has passed no longer applies. */\nexport function problemStillApplies(problem: ProviderProblem, now = Date.now()): boolean {\n if (problem.kind !== \"usage-limit\" || !problem.until) return true;\n const ms = Date.parse(problem.until);\n return Number.isNaN(ms) || ms > now;\n}\n\nexport function formatUntil(until: string | null): string | null {\n if (!until) return null;\n const ms = Date.parse(until);\n if (Number.isNaN(ms)) return until;\n return new Date(ms).toLocaleString(undefined, { month: \"short\", day: \"numeric\", hour: \"numeric\", minute: \"2-digit\" });\n}\n\n/** A full quota window (100% used) is a usage limit even before a run hits it. */\nexport function problemFromQuota(windows: readonly QuotaWindow[], at = new Date().toISOString()): ProviderProblem | null {\n const full = windows.find((w) => typeof w.usedPercent === \"number\" && w.usedPercent >= 100);\n if (!full) return null;\n return {\n kind: \"usage-limit\",\n message: `${full.label} is used up.`,\n until: full.resetsAt,\n at,\n };\n}\n\nexport function describeProblem(provider: CodingProvider, problem: ProviderProblem): { problem: string; fix: string } {\n const label = PROVIDER_LABEL[provider];\n if (problem.kind === \"signed-out\") {\n return {\n problem: `${label} — sign-in expired.`,\n fix: `Open ${label} and sign in again, then check again.`,\n };\n }\n const until = formatUntil(problem.until);\n return {\n problem: until ? `${label} — usage limit reached until ${until}.` : `${label} — usage limit reached.`,\n fix: until\n ? `It lifts on its own then, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`\n : `Wait for it to reset, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`,\n };\n}\n\n/**\n * A run refused because the CHOSEN MODEL is not available — to this account,\n * or to this version of the CLI. It is about the model, not the provider, so\n * the screen offers the model picker rather than a provider-wide warning.\n * Built from the real Codex text captured 2026-10-01\n * (fixtures/codex-model-unsupported.error.txt) and Claude Code's wording.\n */\nconst MODEL_UNAVAILABLE = [\n /model is not supported when using codex/i,\n /\\bmodel[\\s:'\"`][^.\\n]{0,80}\\b(?:not supported|does not exist|not available|not found)\\b/i,\n /\\bmodel_not_found\\b/i,\n /issue with the selected model/i,\n /may not exist or you may not have access to it/i,\n];\n\nexport const MODEL_UNAVAILABLE_LABEL = \"Model not available on this account\";\n\nexport function isModelUnavailable(text: string | null | undefined): boolean {\n const trimmed = (text ?? \"\").trim();\n return trimmed !== \"\" && MODEL_UNAVAILABLE.some((re) => re.test(trimmed));\n}\n\n/** What the screen says for a failed run: a short label for a known class, else the text itself. */\nexport function runErrorLabel(text: string): string {\n return isModelUnavailable(text) ? MODEL_UNAVAILABLE_LABEL : text;\n}\n","/**\n * WHICH `codex` / `claude` RUNS — the newest one on this computer.\n *\n * A person often has several copies: the CLI on PATH (Homebrew, npm, the\n * native installer) and the one bundled inside the desktop app (ChatGPT ships\n * Codex; Claude ships Claude Code). They drift. On 2026-10-01 the PATH Codex\n * was 0.157.1 while ChatGPT's bundled one was 0.159.2, and only the newer one\n * accepted the model the person had configured — the old one answered every\n * run with \"model is not supported\". So every candidate is collected, each\n * one's version read, and the highest wins.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { accessSync, constants as fsConstants, readdirSync, readFileSync, realpathSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport type { BinarySource, CodingProvider, ProviderBinary } from \"../types\";\n\nexport interface BinaryCandidate {\n path: string;\n source: BinarySource;\n version: string | null;\n}\n\nexport interface DiscoveryOptions {\n env: NodeJS.ProcessEnv;\n platform?: NodeJS.Platform;\n home?: string;\n /** Where desktop apps live. Default `/Applications` and `~/Applications`. */\n applications?: string[];\n}\n\nconst SOURCE_LABEL: Record<CodingProvider, Record<BinarySource, string>> = {\n codex: { \"desktop-app\": \"from ChatGPT app\", path: \"from PATH\", \"npm-global\": \"from npm\", configured: \"set by host\" },\n claude: { \"desktop-app\": \"from Claude app\", path: \"from PATH\", \"npm-global\": \"from npm\", configured: \"set by host\" },\n};\n\nexport function sourceLabel(provider: CodingProvider, source: BinarySource): string {\n return SOURCE_LABEL[provider][source];\n}\n\n/** \"codex-cli 0.159.2\" / \"2.1.284 (Claude Code)\" → \"0.159.2\". */\nexport function parseVersion(text: string | null | undefined): string | null {\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)(?:[-.][0-9A-Za-z.]+)?/.exec(text ?? \"\");\n return match ? match[0] : null;\n}\n\n/** Numeric compare of the dotted parts; a pre-release sorts below its release. */\nexport function compareVersions(a: string, b: string): number {\n const [aCore = \"\", aPre] = a.split(\"-\", 2);\n const [bCore = \"\", bPre] = b.split(\"-\", 2);\n const pa = aCore.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n const pb = bCore.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (d !== 0) return d < 0 ? -1 : 1;\n }\n if (aPre && !bPre) return -1;\n if (!aPre && bPre) return 1;\n return 0;\n}\n\n/**\n * The highest version wins. A candidate whose version could not be read ranks\n * below every readable one; ties keep the earlier candidate (desktop app,\n * then PATH order, then npm).\n */\nexport function pickBinary<T extends BinaryCandidate>(candidates: readonly T[]): T | null {\n let best: T | null = null;\n for (const c of candidates) {\n if (!best) {\n best = c;\n continue;\n }\n if (c.version && (!best.version || compareVersions(c.version, best.version) > 0)) best = c;\n }\n return best;\n}\n\nfunction executable(file: string): boolean {\n try {\n accessSync(file, fsConstants.X_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction exeName(name: string, platform: NodeJS.Platform): string[] {\n return platform === \"win32\" ? [`${name}.exe`, `${name}.cmd`, name] : [name];\n}\n\n/** Every executable `name` on PATH, in PATH order (`which -a`). */\nexport function allOnPath(name: string, pathValue: string, platform: NodeJS.Platform = process.platform): string[] {\n const found: string[] = [];\n for (const dir of pathValue.split(path.delimiter)) {\n if (!dir) continue;\n for (const file of exeName(name, platform)) {\n const candidate = path.join(dir, file);\n if (executable(candidate)) {\n found.push(candidate);\n break;\n }\n }\n }\n return found;\n}\n\nfunction desktopAppCandidates(\n provider: CodingProvider,\n platform: NodeJS.Platform,\n home: string,\n applications: string[],\n): string[] {\n if (platform !== \"darwin\") return [];\n if (provider === \"codex\") {\n return applications.map((apps) =>\n path.join(apps, \"ChatGPT.app\", \"Contents\", \"Resources\", \"codex-cli\", \"bin\", \"codex\"),\n );\n }\n // Claude's desktop app keeps each Claude Code it has downloaded in its own\n // version folder.\n const root = path.join(home, \"Library\", \"Application Support\", \"Claude\", \"claude-code\");\n let versions: string[] = [];\n try {\n versions = readdirSync(root);\n } catch {\n return [];\n }\n return versions.map((v) => path.join(root, v, \"claude.app\", \"Contents\", \"MacOS\", \"claude\"));\n}\n\nfunction npmGlobalPrefix(env: NodeJS.ProcessEnv): Promise<string | null> {\n const fromEnv = env.npm_config_prefix ?? env.NPM_CONFIG_PREFIX;\n if (fromEnv) return Promise.resolve(fromEnv);\n const npm = allOnPath(\"npm\", env.PATH ?? \"\")[0];\n if (!npm) return Promise.resolve(null);\n return new Promise((resolve) => {\n const child = execFile(npm, [\"prefix\", \"-g\"], { timeout: 5000, env }, (error, stdout) => {\n resolve(error ? null : String(stdout).trim() || null);\n });\n child.stdin?.end();\n });\n}\n\n/** The version a bundled copy declares on disk, without running it. */\nfunction declaredVersion(provider: CodingProvider, source: BinarySource, file: string): string | null {\n if (source !== \"desktop-app\") return null;\n if (provider === \"codex\") {\n try {\n const pkg = JSON.parse(readFileSync(path.join(path.dirname(path.dirname(file)), \"codex-package.json\"), \"utf8\")) as {\n version?: unknown;\n };\n return typeof pkg.version === \"string\" ? parseVersion(pkg.version) : null;\n } catch {\n return null;\n }\n }\n // …/claude-code/<version>/claude.app/Contents/MacOS/claude\n return parseVersion(path.basename(path.resolve(file, \"..\", \"..\", \"..\", \"..\")));\n}\n\n/** `<cli> --version`, stdin closed (Codex waits on an open one). */\nexport function runVersion(file: string, env: NodeJS.ProcessEnv): Promise<string | null> {\n return new Promise((resolve) => {\n const child = execFile(file, [\"--version\"], { timeout: 8000, env }, (error, stdout) => {\n resolve(error ? null : parseVersion(String(stdout)));\n });\n child.stdin?.end();\n });\n}\n\n/** Every copy of the CLI on this computer, deduplicated by real path. */\nexport async function discoverBinaries(provider: CodingProvider, options: DiscoveryOptions): Promise<BinaryCandidate[]> {\n const platform = options.platform ?? process.platform;\n const home = options.home ?? options.env.HOME ?? os.homedir();\n const listed: { path: string; source: BinarySource }[] = [\n ...desktopAppCandidates(provider, platform, home, options.applications ?? [\"/Applications\", path.join(home, \"Applications\")]).filter(executable).map((p) => ({ path: p, source: \"desktop-app\" as const })),\n ...allOnPath(provider, options.env.PATH ?? \"\", platform).map((p) => ({ path: p, source: \"path\" as const })),\n ];\n const prefix = await npmGlobalPrefix(options.env);\n if (prefix) {\n const dir = platform === \"win32\" ? prefix : path.join(prefix, \"bin\");\n for (const file of exeName(provider, platform)) {\n const candidate = path.join(dir, file);\n if (executable(candidate)) {\n listed.push({ path: candidate, source: \"npm-global\" });\n break;\n }\n }\n }\n const seen = new Set<string>();\n const unique = listed.filter((c) => {\n let real = c.path;\n try {\n real = realpathSync(c.path);\n } catch {\n /* keep the listed path */\n }\n if (seen.has(real)) return false;\n seen.add(real);\n return true;\n });\n return Promise.all(\n unique.map(async (c) => ({\n ...c,\n version: declaredVersion(provider, c.source, c.path) ?? (await runVersion(c.path, options.env)),\n })),\n );\n}\n\n/**\n * The binary runs use. `forced` (the host's `commands` option) always wins,\n * but a newer copy elsewhere is still reported as `newer`.\n */\nexport async function resolveBinary(\n provider: CodingProvider,\n options: DiscoveryOptions & { forced?: string | null | undefined; discover?: boolean },\n): Promise<ProviderBinary | null> {\n const candidates = options.discover === false ? [] : await discoverBinaries(provider, options);\n const best = pickBinary(candidates);\n const inUse: BinaryCandidate | null = options.forced\n ? {\n path: options.forced,\n source: \"configured\",\n version:\n candidates.find((c) => c.path === options.forced)?.version ??\n (options.discover === false ? null : await runVersion(options.forced, options.env)),\n }\n : best;\n if (!inUse) return null;\n const newer =\n best && best.path !== inUse.path && best.version && (!inUse.version || compareVersions(best.version, inUse.version) > 0)\n ? { path: best.path, version: best.version, sourceLabel: sourceLabel(provider, best.source) }\n : null;\n return {\n path: inUse.path,\n version: inUse.version,\n source: inUse.source,\n sourceLabel: sourceLabel(provider, inUse.source),\n newer,\n };\n}\n","/**\n * THE CLEAN ENVIRONMENT — built from an ALLOWLIST, never a denylist.\n *\n * The process that hosts this package is often itself running inside a Claude\n * Code or Codex session. Those sessions export variables (`CLAUDE_CODE_*`,\n * `CLAUDECODE`, `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `CODEX_*`,\n * `OTEL_*`, `GIT_EDITOR`, …) that make a child CLI talk to the wrong endpoint,\n * bill the wrong account, or believe it is a sub-agent. A denylist is always one\n * variable behind the next CLI release; an allowlist cannot be. The spike ran\n * under `env -i` for this reason, and this is that guarantee in code.\n *\n * API keys are deliberately NOT allowed through: the whole point is the user's\n * own subscription login. A host that truly wants API billing passes a key in\n * `extra` on purpose, and `providers()` then reports \"API\" honestly.\n */\n\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n/** Exact names that pass through. */\nconst ALLOWED_NAMES = new Set([\n \"HOME\",\n \"USER\",\n \"LOGNAME\",\n \"SHELL\",\n \"TMPDIR\",\n \"LANG\",\n \"TZ\",\n \"SSH_AUTH_SOCK\",\n \"HTTP_PROXY\",\n \"HTTPS_PROXY\",\n \"NO_PROXY\",\n \"http_proxy\",\n \"https_proxy\",\n \"no_proxy\",\n \"SSL_CERT_FILE\",\n \"NODE_EXTRA_CA_CERTS\",\n]);\n\n/** Prefixes that pass through (locale only). */\nconst ALLOWED_PREFIXES = [\"LC_\"];\n\n/**\n * Where the CLIs are commonly installed. A host launched from a GUI or a\n * launchd agent often has a bare PATH; without these the CLIs look\n * \"not installed\" when they are.\n */\nfunction wellKnownBinDirs(home: string): string[] {\n return [\n path.join(home, \".local\", \"bin\"),\n path.join(home, \".claude\", \"local\"),\n path.join(home, \".npm-global\", \"bin\"),\n path.join(home, \".bun\", \"bin\"),\n path.join(home, \".volta\", \"bin\"),\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\",\n \"/usr/bin\",\n \"/bin\",\n \"/usr/sbin\",\n \"/sbin\",\n ];\n}\n\nexport function isAllowedEnvName(name: string): boolean {\n return ALLOWED_NAMES.has(name) || ALLOWED_PREFIXES.some((prefix) => name.startsWith(prefix));\n}\n\n/**\n * Build the environment for a driver worker (and therefore for the CLI it\n * launches) from the host's environment.\n */\nexport function buildCleanEnv(\n hostEnv: NodeJS.ProcessEnv,\n extra: Record<string, string> = {},\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, value] of Object.entries(hostEnv)) {\n if (typeof value !== \"string\") continue;\n if (isAllowedEnvName(name)) out[name] = value;\n }\n const home = out.HOME ?? os.homedir();\n out.HOME = home;\n const hostPath = (hostEnv.PATH ?? \"\").split(path.delimiter).filter(Boolean);\n const merged: string[] = [];\n for (const dir of [...hostPath, ...wellKnownBinDirs(home)]) {\n if (!merged.includes(dir)) merged.push(dir);\n }\n out.PATH = merged.join(path.delimiter);\n for (const [name, value] of Object.entries(extra)) out[name] = value;\n return out;\n}\n","/**\n * Reading the providers' OWN files — cheaply, and never copying them.\n *\n * A heavy user has tens of gigabytes here (this Mac: 38 GB of Codex rollouts\n * across ~6,800 files, 18 GB of Claude sessions across ~1,900). Discovery\n * therefore stats every file (cheap) but READS only the head and tail of the\n * few newest, and a transcript read is capped with the cap announced.\n */\n\nimport { createReadStream } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexRolloutNormalizer } from \"../normalize/codex\";\nimport { claudeTranscriptTitleSources, resolveSessionTitle } from \"../sessions/titles\";\nimport { parseJsonl } from \"../normalize/lines\";\nimport { describeActivity, listProcesses, type ProcessRow } from \"./activity\";\nimport type {\n ActiveElsewhere,\n CodingProvider,\n DiscoveredSession,\n SessionHistory,\n TranscriptItem,\n} from \"../types\";\n\nexport interface CodexHome {\n /** `<CODEX_HOME>/sessions` (dated folders of rollouts). */\n sessions: string;\n /** `<CODEX_HOME>/archived_sessions` (rollouts Codex archived; flat). */\n archived: string;\n /** `<CODEX_HOME>/session_index.jsonl` (the app's thread names). */\n index: string;\n}\n\nexport interface ProviderHomes {\n claudeProjects: string;\n /** Every Codex home to read (main first). The owner of the apps' index names them (Matrx 2: the Codex source's homes). */\n codex: CodexHome[];\n}\n\nexport function codexHome(dir: string): CodexHome {\n return {\n sessions: path.join(dir, \"sessions\"),\n archived: path.join(dir, \"archived_sessions\"),\n index: path.join(dir, \"session_index.jsonl\"),\n };\n}\n\nexport function defaultProviderHomes(home = os.homedir()): ProviderHomes {\n return {\n claudeProjects: path.join(home, \".claude\", \"projects\"),\n codex: [codexHome(path.join(home, \".codex\"))],\n };\n}\n\ninterface FileCandidate {\n provider: CodingProvider;\n file: string;\n id: string;\n mtimeMs: number;\n size: number;\n /** A Codex rollout in `archived_sessions/` (Codex archived the chat). */\n archived?: boolean;\n}\n\nconst UUIDISH = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\.jsonl$/i;\n\nasync function safeReaddir(dir: string): Promise<import(\"node:fs\").Dirent[]> {\n try {\n return await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nasync function statCandidate(\n provider: CodingProvider,\n file: string,\n): Promise<FileCandidate | null> {\n const match = UUIDISH.exec(file);\n if (!match?.[1]) return null;\n try {\n const stat = await fs.stat(file);\n return { provider, file, id: match[1], mtimeMs: stat.mtimeMs, size: stat.size };\n } catch {\n return null;\n }\n}\n\nasync function claudeCandidates(root: string): Promise<FileCandidate[]> {\n const out: FileCandidate[] = [];\n for (const project of await safeReaddir(root)) {\n if (!project.isDirectory()) continue;\n const dir = path.join(root, project.name);\n const entries = await safeReaddir(dir);\n const stats = await Promise.all(\n entries\n .filter((e) => e.isFile() && e.name.endsWith(\".jsonl\"))\n .map((e) => statCandidate(\"claude\", path.join(dir, e.name))),\n );\n for (const s of stats) if (s) out.push(s);\n }\n return out;\n}\n\nasync function codexTree(root: string): Promise<FileCandidate[]> {\n const out: FileCandidate[] = [];\n for (const year of await safeReaddir(root)) {\n if (!year.isDirectory()) continue;\n for (const month of await safeReaddir(path.join(root, year.name))) {\n if (!month.isDirectory()) continue;\n for (const day of await safeReaddir(path.join(root, year.name, month.name))) {\n if (!day.isDirectory()) continue;\n out.push(...(await codexFlat(path.join(root, year.name, month.name, day.name), false)));\n }\n }\n }\n return out;\n}\n\nasync function codexFlat(dir: string, archived: boolean): Promise<FileCandidate[]> {\n const entries = await safeReaddir(dir);\n const stats = await Promise.all(\n entries\n .filter((e) => e.isFile() && e.name.startsWith(\"rollout-\") && e.name.endsWith(\".jsonl\"))\n .map((e) => statCandidate(\"codex\", path.join(dir, e.name))),\n );\n return stats.filter((s): s is FileCandidate => s !== null).map((s) => (archived ? { ...s, archived: true } : s));\n}\n\n/** Every Codex rollout in every home, archived ones included (marked). */\nasync function codexCandidates(homes: readonly CodexHome[]): Promise<FileCandidate[]> {\n const lists = await Promise.all(homes.flatMap((h) => [codexTree(h.sessions), codexFlat(h.archived, true)]));\n return lists.flat();\n}\n\n/** Read `length` bytes at `start` as UTF-8. */\nasync function readSlice(file: string, start: number, length: number): Promise<string> {\n const handle = await fs.open(file, \"r\");\n try {\n const buffer = Buffer.alloc(length);\n const { bytesRead } = await handle.read(buffer, 0, length, start);\n return buffer.subarray(0, bytesRead).toString(\"utf8\");\n } finally {\n await handle.close();\n }\n}\n\n/** Complete lines only: drop a partial first line (tail reads) and a partial last line. */\nfunction completeLines(text: string, droppedFirst: boolean): string {\n let body = text;\n if (droppedFirst) {\n const nl = body.indexOf(\"\\n\");\n body = nl >= 0 ? body.slice(nl + 1) : \"\";\n }\n const last = body.lastIndexOf(\"\\n\");\n return last >= 0 ? body.slice(0, last) : body;\n}\n\nconst HEAD_BYTES = 256 * 1024;\nconst TAIL_BYTES = 128 * 1024;\n\n\nasync function describeClaude(candidate: FileCandidate): Promise<DiscoveredSession | null> {\n const head = parseJsonl(completeLines(await readSlice(candidate.file, 0, HEAD_BYTES), false));\n const tailStart = Math.max(0, candidate.size - TAIL_BYTES);\n const tail =\n tailStart > 0\n ? parseJsonl(completeLines(await readSlice(candidate.file, tailStart, TAIL_BYTES), true))\n : head;\n\n let cwd: string | null = null;\n let entrypoint: string | null = null;\n for (const entry of head) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (!cwd && typeof e.cwd === \"string\") cwd = e.cwd;\n if (!entrypoint && typeof e.entrypoint === \"string\") entrypoint = e.entrypoint;\n if (cwd && entrypoint) break;\n }\n // The transcript's own title (the one rule, ./sessions); the app's record title, when the\n // owner of the apps' index knows it, is overlaid by the engine (title hints).\n const resolved = resolveSessionTitle(claudeTranscriptTitleSources(head, tailStart > 0 ? tail : []));\n // A file with no conversation in it (a session that only ran start-up hooks)\n // is not a chat anyone can take over.\n if (!resolved) return null;\n return {\n provider: \"claude\",\n providerSessionId: candidate.id,\n cwd,\n title: resolved.title,\n titleSource: resolved.source,\n updatedAt: new Date(candidate.mtimeMs).toISOString(),\n source: entrypoint,\n activeElsewhere: null,\n };\n}\n\n/** Codex's thread names across homes (`session_index.jsonl`, the app's own names; later homes never override). */\nasync function readCodexIndex(files: readonly string[]): Promise<Map<string, string>> {\n const names = new Map<string, string>();\n for (const file of files) for (const [id, name] of await readCodexIndexFile(file)) if (!names.has(id)) names.set(id, name);\n return names;\n}\n\nasync function readCodexIndexFile(file: string): Promise<Map<string, string>> {\n const names = new Map<string, string>();\n let text: string;\n try {\n const stat = await fs.stat(file);\n const budget = 4 * 1024 * 1024;\n text =\n stat.size <= budget\n ? await fs.readFile(file, \"utf8\")\n : completeLines(await readSlice(file, stat.size - budget, budget), true);\n } catch {\n return names;\n }\n for (const entry of parseJsonl(text)) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (typeof e.id === \"string\" && typeof e.thread_name === \"string\" && e.thread_name.trim()) {\n names.set(e.id, e.thread_name);\n }\n }\n return names;\n}\n\nasync function describeCodex(\n candidate: FileCandidate,\n names: Map<string, string>,\n): Promise<DiscoveredSession | null> {\n const head = parseJsonl(completeLines(await readSlice(candidate.file, 0, HEAD_BYTES), false));\n let cwd: string | null = null;\n let source: string | null = null;\n let isSubAgent = false;\n let firstPrompt: string | null = null;\n const normalizer = createCodexRolloutNormalizer();\n for (const entry of head) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (e.type === \"session_meta\" && typeof e.payload === \"object\" && e.payload !== null) {\n const p = e.payload as Record<string, unknown>;\n cwd = typeof p.cwd === \"string\" ? p.cwd : cwd;\n source = typeof p.source === \"string\" ? p.source : typeof p.originator === \"string\" ? p.originator : null;\n if (typeof p.parent_thread_id === \"string\" && p.parent_thread_id) isSubAgent = true;\n if (p.thread_source === \"subagent\" || p.thread_source === \"sub_agent\") isSubAgent = true;\n }\n if (firstPrompt === null) {\n for (const item of normalizer.push(entry)) {\n if (item.kind === \"user\") {\n firstPrompt = item.text;\n break;\n }\n }\n }\n }\n // A sub-agent thread belongs to its parent conversation; taking it over on\n // its own would answer a question nobody in this chat asked.\n if (isSubAgent) return null;\n const resolved = resolveSessionTitle({ app: names.get(candidate.id), \"first-prompt\": firstPrompt });\n if (!resolved) return null;\n return {\n provider: \"codex\",\n providerSessionId: candidate.id,\n cwd,\n title: resolved.title,\n titleSource: resolved.source,\n ...(candidate.archived ? { archived: true } : {}),\n updatedAt: new Date(candidate.mtimeMs).toISOString(),\n source,\n activeElsewhere: null,\n };\n}\n\nexport interface DiscoverOptions {\n limit?: number | undefined;\n homes?: ProviderHomes | undefined;\n /** Processes that are OUR runs (never \"live elsewhere\"). */\n excludePids?: ReadonlySet<number> | undefined;\n}\n\nasync function readTail(file: string, size: number): Promise<unknown[]> {\n const start = Math.max(0, size - TAIL_BYTES);\n return parseJsonl(completeLines(await readSlice(file, start, Math.min(size, TAIL_BYTES)), start > 0));\n}\n\nasync function activityFor(\n candidate: FileCandidate,\n processes: readonly ProcessRow[],\n excludePids: ReadonlySet<number> | undefined,\n ownWritesUntilMs?: number | undefined,\n): Promise<ActiveElsewhere | null> {\n return describeActivity({\n ownWritesUntilMs,\n provider: candidate.provider,\n providerSessionId: candidate.id,\n mtimeMs: candidate.mtimeMs,\n now: Date.now(),\n processes,\n excludePids,\n tail: () => readTail(candidate.file, candidate.size).catch(() => []),\n });\n}\n\n/** Fresh \"is it live elsewhere?\" for one session (the preview and the takeover confirm). */\nexport async function sessionActivity(\n provider: CodingProvider,\n providerSessionId: string,\n options: {\n homes?: ProviderHomes | undefined;\n excludePids?: ReadonlySet<number> | undefined;\n ownWritesUntilMs?: number | undefined;\n } = {},\n): Promise<ActiveElsewhere | null> {\n const file = await findSessionFile(provider, providerSessionId, options.homes);\n const processes = await listProcesses();\n if (!file) {\n return describeActivity({\n provider,\n providerSessionId,\n mtimeMs: 0,\n now: Date.now(),\n processes,\n excludePids: options.excludePids,\n tail: async () => [],\n });\n }\n const candidate = await statCandidate(provider, file);\n if (!candidate) return null;\n return activityFor(candidate, processes, options.excludePids, options.ownWritesUntilMs);\n}\n\n/** Recent existing local Claude Code and Codex chats, newest first (metadata only). */\nexport async function discoverLocalSessions(options: DiscoverOptions = {}): Promise<DiscoveredSession[]> {\n const limit = options.limit ?? 60;\n const homes = options.homes ?? defaultProviderHomes();\n const [claude, codex, names] = await Promise.all([\n claudeCandidates(homes.claudeProjects),\n codexCandidates(homes.codex),\n readCodexIndex(homes.codex.map((h) => h.index)),\n ]);\n const candidates = [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);\n const processes = await listProcesses();\n const out: DiscoveredSession[] = [];\n // Describe in small batches, newest first, until the page is full.\n for (let i = 0; i < candidates.length && out.length < limit; i += 12) {\n const batch = candidates.slice(i, i + 12);\n const described = await Promise.all(\n batch.map(async (c) => {\n const d = await (c.provider === \"claude\" ? describeClaude(c) : describeCodex(c, names)).catch(() => null);\n if (!d) return null;\n return { ...d, activeElsewhere: await activityFor(c, processes, options.excludePids).catch(() => null) };\n }),\n );\n for (const d of described) if (d && out.length < limit) out.push(d);\n }\n return out;\n}\n\n/** Where a provider keeps one session's transcript, or null when it has none on disk. */\nexport async function findSessionFile(\n provider: CodingProvider,\n providerSessionId: string,\n homes: ProviderHomes = defaultProviderHomes(),\n): Promise<string | null> {\n if (!/^[0-9a-f-]{36}$/i.test(providerSessionId)) return null;\n const candidates =\n provider === \"claude\"\n ? await claudeCandidates(homes.claudeProjects)\n : await codexCandidates(homes.codex);\n const hits = candidates.filter((c) => c.id === providerSessionId).sort((a, b) => b.mtimeMs - a.mtimeMs);\n return hits[0]?.file ?? null;\n}\n\nexport const HISTORY_BUDGET = 24 * 1024 * 1024;\n/** \"Show earlier\" never reads more than this at once. */\nexport const MAX_HISTORY_BUDGET = 256 * 1024 * 1024;\n\n/**\n * Read a transcript from the provider's own file, up to `endOffset` bytes (the\n * file's size when a run started, so a live run's lines are not read twice).\n */\nexport async function readSessionFile(\n provider: CodingProvider,\n file: string,\n endOffset?: number | undefined,\n maxBytes: number = HISTORY_BUDGET,\n): Promise<SessionHistory> {\n let size: number;\n try {\n size = (await fs.stat(file)).size;\n } catch {\n return {\n items: [],\n truncated: false,\n unavailable: \"The saved transcript for this chat could not be found on this computer.\",\n seq: 0,\n };\n }\n const end = Math.min(size, endOffset ?? size);\n const start = Math.max(0, end - Math.max(1024 * 1024, Math.min(maxBytes, MAX_HISTORY_BUDGET)));\n const items: TranscriptItem[] = [];\n const normalizer = provider === \"claude\" ? createClaudeNormalizer() : createCodexRolloutNormalizer();\n let droppedFirst = start > 0;\n let carry = \"\";\n await new Promise<void>((resolve, reject) => {\n const stream = createReadStream(file, { start, end: Math.max(start, end - 1), encoding: \"utf8\" });\n stream.on(\"data\", (chunk) => {\n const text = carry + String(chunk);\n const lines = text.split(\"\\n\");\n carry = lines.pop() ?? \"\";\n if (droppedFirst) {\n lines.shift();\n droppedFirst = false;\n }\n for (const value of parseJsonl(lines.join(\"\\n\"))) items.push(...normalizer.push(value));\n });\n stream.on(\"end\", () => {\n for (const value of parseJsonl(carry)) items.push(...normalizer.push(value));\n resolve();\n });\n stream.on(\"error\", reject);\n });\n // Live-only kinds never come from a saved file; usage is per run, not history.\n return {\n items: items.filter((item) => item.kind !== \"usage\" && item.kind !== \"text-delta\"),\n truncated: start > 0,\n unavailable: null,\n seq: 0,\n };\n}\n\n/** Every session file on this computer, newest first (a stat each; nothing read). */\nexport async function listSessionFiles(homes: ProviderHomes = defaultProviderHomes()): Promise<FileCandidate[]> {\n const [claude, codex] = await Promise.all([\n claudeCandidates(homes.claudeProjects),\n codexCandidates(homes.codex),\n ]);\n return [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);\n}\n\n/** Title, folder and time for one file (null for sub-agent and hook-only files). */\nexport async function describeSessionFile(\n candidate: FileCandidate,\n codexNames: Map<string, string>,\n): Promise<DiscoveredSession | null> {\n return (candidate.provider === \"claude\" ? describeClaude(candidate) : describeCodex(candidate, codexNames)).catch(\n () => null,\n );\n}\n\nexport { readCodexIndex };\nexport type { FileCandidate };\n","/**\n * THE ONE TITLE RULE for a coding chat, shared by every reader (Matrx 2's Coding Sessions and\n * Code › Chats, the standalone host, search). Pure: no file access, browser-safe.\n *\n * What a chat is called is what the person sees in the coding app, so the app's own record leads;\n * the CLI's transcript entries fill in for chats the app never listed. The person's rename inside\n * Matrx sits on top and is applied ONCE, by whoever draws the row (never baked into the engine's\n * own `title`). Plan: common-docs/projects/matrx-2/apps-chats.md §12.\n */\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\n\n/** Every title is cut to this (the app tables' rule); the screen truncates further visually. */\nexport const TITLE_MAX = 300;\n/** What a row shows when no source has a title. */\nexport const UNTITLED = \"(untitled)\";\n\n/**\n * The name the AI Matrx coding-session bridge used to stamp on every mirrored Claude Code prompt\n * (`sessionTitle` from its UserPromptSubmit hook; stopped at the source 2026-10-06, still inside\n * old transcripts as `custom-title` / `agent-name` entries). Never a chat's title.\n */\nexport const BRIDGE_PLACEHOLDER = /^AI Matrx · [a-z-]+$/;\n\n/** Where a title came from, strongest first. */\nexport const TITLE_PRECEDENCE = [\n /** The person's rename inside Matrx (Coding Sessions' preference). */\n \"override\",\n /** What the coding app's own sidebar shows: Claude's record `title` (renames included); Codex's thread name; Cursor's name. */\n \"app\",\n /** The title the app last showed, remembered by the claude-accounts engine after the record went away. */\n \"app-remembered\",\n /** Claude Code transcript entries (the last one of each kind that is not the bridge placeholder). */\n \"custom-title\",\n \"ai-title\",\n \"agent-name\",\n \"summary\",\n /** The person's first typed message (Codex: the thread's title / first user message). */\n \"first-prompt\",\n \"last-prompt\",\n] as const;\n\nexport type TitleSource = (typeof TITLE_PRECEDENCE)[number];\n\n/** Whatever each source says; absent, null and blank all mean \"no title here\". */\nexport type TitleSources = Partial<Record<TitleSource, string | null | undefined>>;\n\nexport interface ResolvedTitle {\n title: string;\n source: TitleSource;\n}\n\n/** Transcript-only sources the bridge placeholder can poison. */\nconst STAMPABLE: ReadonlySet<TitleSource> = new Set([\"custom-title\", \"ai-title\", \"agent-name\"]);\n\nexport function isBridgePlaceholder(value: unknown): boolean {\n return typeof value === \"string\" && BRIDGE_PLACEHOLDER.test(value.trim());\n}\n\n/** The first non-empty line, trimmed, cut to `TITLE_MAX` with \"…\"; null when there is none. */\nexport function cleanTitle(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n const line = value\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .find((l) => l.length > 0);\n if (!line) return null;\n return line.length > TITLE_MAX ? `${line.slice(0, TITLE_MAX - 1)}…` : line;\n}\n\n/** The title to show and where it came from: the first source in `TITLE_PRECEDENCE` that has one. */\nexport function resolveSessionTitle(sources: TitleSources): ResolvedTitle | null {\n for (const source of TITLE_PRECEDENCE) {\n const raw = sources[source];\n if (STAMPABLE.has(source) && isBridgePlaceholder(raw)) continue;\n const title = cleanTitle(raw);\n if (title) return { title, source };\n }\n return null;\n}\n\n/**\n * Claude Code's own title entries from transcript lines (already parsed JSON), plus the person's\n * first typed message from `head` (the same normalizer the transcript screen uses). Later entries\n * win within a kind; a bridge placeholder never replaces a real one.\n */\nexport function claudeTranscriptTitleSources(head: Iterable<unknown>, tail: Iterable<unknown> = []): TitleSources {\n const out: TitleSources = {};\n const take = (source: TitleSource, value: unknown) => {\n if (typeof value !== \"string\" || !value.trim()) return;\n if (STAMPABLE.has(source) && isBridgePlaceholder(value)) return;\n out[source] = value;\n };\n const normalizer = createClaudeNormalizer();\n let firstPrompt: string | null = null;\n const scan = (entries: Iterable<unknown>, findPrompt: boolean) => {\n for (const entry of entries) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (e.type === \"custom-title\") take(\"custom-title\", e.customTitle);\n else if (e.type === \"ai-title\") take(\"ai-title\", e.aiTitle);\n else if (e.type === \"agent-name\") take(\"agent-name\", e.agentName);\n else if (e.type === \"summary\") take(\"summary\", e.summary);\n else if (e.type === \"last-prompt\") take(\"last-prompt\", e.lastPrompt);\n else if (findPrompt && firstPrompt === null) {\n for (const item of normalizer.push(entry)) {\n if (item.kind === \"user\" && item.text.trim()) {\n firstPrompt = item.text;\n break;\n }\n }\n }\n }\n };\n scan(head, true);\n scan(tail, false);\n if (firstPrompt !== null) out[\"first-prompt\"] = firstPrompt;\n return out;\n}\n","/**\n * IS THIS CHAT LIVE SOMEWHERE ELSE RIGHT NOW?\n *\n * Taking over a chat that another Claude Code or Codex is still driving puts\n * two agents on one conversation. We cannot know for certain, so we look for\n * evidence, strongest first, and the screen WARNS and asks — it never blocks\n * (the platform law: validation offers, never blocks).\n *\n * 1. a process whose arguments carry the session id — `claude --resume <id>`,\n * `--resume=<id>`, `codex exec … resume <id>` (one `ps` per check);\n * 2. the session file was written in the last two minutes;\n * 3. the file's last step is a tool call that never got its result, and the\n * file changed in the last fifteen minutes (an abandoned crash from last\n * week is not \"running\").\n */\n\nimport { execFile } from \"node:child_process\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexRolloutNormalizer } from \"../normalize/codex\";\nimport { PROVIDER_LABEL, type ActiveElsewhere, type CodingProvider, type TranscriptItem } from \"../types\";\n\nexport const RECENT_WRITE_MS = 2 * 60 * 1000;\nexport const OPEN_TOOL_WINDOW_MS = 15 * 60 * 1000;\n\nexport interface ProcessRow {\n pid: number;\n args: string;\n}\n\n/** Every process's pid and full argument line. Empty (never throws) when `ps` is unavailable. */\nexport function listProcesses(): Promise<ProcessRow[]> {\n return new Promise((resolve) => {\n execFile(\"ps\", [\"-axww\", \"-o\", \"pid=,args=\"], { maxBuffer: 64 * 1024 * 1024, timeout: 5000 }, (error, stdout) => {\n if (error) {\n resolve([]);\n return;\n }\n const rows: ProcessRow[] = [];\n for (const line of String(stdout).split(\"\\n\")) {\n const match = /^\\s*(\\d+)\\s+(.*)$/.exec(line);\n if (match?.[1] && match[2]) rows.push({ pid: Number(match[1]), args: match[2] });\n }\n resolve(rows);\n });\n });\n}\n\n/** A process driving this session: its args name the id, and it is not one of ours. */\nexport function findDrivingProcess(\n processes: readonly ProcessRow[],\n providerSessionId: string,\n excludePids: ReadonlySet<number> = new Set(),\n): ProcessRow | null {\n for (const row of processes) {\n if (excludePids.has(row.pid) || row.pid === process.pid) continue;\n if (!row.args.includes(providerSessionId)) continue;\n // Our own `ps`/`pgrep` and editors viewing the file are not drivers.\n if (/(^|\\/)(ps|pgrep|grep|rg|tail|less|cat)\\b/.test(row.args.split(\" \")[0] ?? \"\")) continue;\n return row;\n }\n return null;\n}\n\n/** True when the last meaningful item is a tool call with no result yet. */\nexport function endsWithOpenToolCall(provider: CodingProvider, entries: readonly unknown[]): boolean {\n const normalizer = provider === \"claude\" ? createClaudeNormalizer() : createCodexRolloutNormalizer();\n const items: TranscriptItem[] = [];\n for (const entry of entries) items.push(...normalizer.push(entry));\n const meaningful = items.filter((i) => i.kind !== \"usage\" && i.kind !== \"notice\" && i.kind !== \"text-delta\");\n const last = meaningful[meaningful.length - 1];\n if (!last || last.kind !== \"tool-call\") return false;\n return !items.some((i) => i.kind === \"tool-result\" && i.id === last.id);\n}\n\nexport function describeActivity(input: {\n provider: CodingProvider;\n providerSessionId: string;\n mtimeMs: number;\n now: number;\n processes: readonly ProcessRow[];\n excludePids?: ReadonlySet<number> | undefined;\n /** Writes at or before this time were OURS (our own run just ended), so\n * they are not evidence of another driver. */\n ownWritesUntilMs?: number | undefined;\n /** Parsed tail of the session file; only consulted when recent enough. */\n tail: () => Promise<readonly unknown[]>;\n}): Promise<ActiveElsewhere | null> {\n const label = PROVIDER_LABEL[input.provider];\n const driver = findDrivingProcess(input.processes, input.providerSessionId, input.excludePids);\n if (driver) {\n return Promise.resolve({\n reason: \"process\",\n message: `This chat is running right now in ${label} — an open ${label} process is using it.`,\n });\n }\n if (input.ownWritesUntilMs !== undefined && input.mtimeMs <= input.ownWritesUntilMs) return Promise.resolve(null);\n const age = input.now - input.mtimeMs;\n if (age <= RECENT_WRITE_MS) {\n return Promise.resolve({\n reason: \"recent-write\",\n message: `This chat was active in ${label} less than two minutes ago and may still be running there.`,\n });\n }\n if (age > OPEN_TOOL_WINDOW_MS) return Promise.resolve(null);\n return input.tail().then((entries) =>\n endsWithOpenToolCall(input.provider, entries)\n ? {\n reason: \"open-tool-call\" as const,\n message: `This chat may still be running in ${label}: its last step started and has not finished.`,\n }\n : null,\n );\n}\n","/**\n * The person's renames, pins and hides — one small JSON file in this package's\n * data dir, keyed by `chatKey()`. The providers' own files are never touched.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { TITLE_MAX } from \"../sessions/titles\";\nimport type { ChatPreference } from \"../types\";\n\nexport class PreferenceStore {\n private data: Record<string, ChatPreference> = {};\n private writing: Promise<void> = Promise.resolve();\n\n constructor(private readonly dir: string) {}\n\n get file(): string {\n return path.join(this.dir, \"preferences.json\");\n }\n\n async load(): Promise<void> {\n try {\n const parsed = JSON.parse(await fs.readFile(this.file, \"utf8\")) as unknown;\n this.data = typeof parsed === \"object\" && parsed !== null ? (parsed as Record<string, ChatPreference>) : {};\n } catch {\n this.data = {};\n }\n }\n\n all(): Record<string, ChatPreference> {\n return { ...this.data };\n }\n\n get(key: string): ChatPreference | null {\n return this.data[key] ?? null;\n }\n\n /** Merge `patch`; a null/false/empty field is removed, an empty preference deleted. */\n set(key: string, patch: ChatPreference): Record<string, ChatPreference> {\n if (!key || key.length > 200) throw new Error(\"That chat can't be found.\");\n const next: ChatPreference = { ...this.data[key] };\n if (\"title\" in patch) {\n const title = typeof patch.title === \"string\" ? patch.title.replace(/\\s+/g, \" \").trim().slice(0, TITLE_MAX) : \"\";\n if (title) next.title = title;\n else delete next.title;\n }\n if (\"pinned\" in patch) {\n if (patch.pinned === true) next.pinned = true;\n else delete next.pinned;\n }\n if (\"hidden\" in patch) {\n if (patch.hidden === true) next.hidden = true;\n else delete next.hidden;\n }\n delete next.updatedAt;\n if (Object.keys(next).length === 0) delete this.data[key];\n else this.data[key] = { ...next, updatedAt: new Date().toISOString() };\n this.persist();\n return this.all();\n }\n\n /**\n * Move a preference to the chat's lasting key (`session:<id>` → `<provider>:<id>` once the\n * provider's id is known), so a rename made early is the one rename everywhere. A preference\n * already under the lasting key wins field by field.\n */\n rekey(from: string, to: string): boolean {\n if (from === to || !this.data[from]) return false;\n this.data[to] = { ...this.data[from], ...this.data[to] };\n delete this.data[from];\n this.persist();\n return true;\n }\n\n private persist(): void {\n const snapshot = JSON.stringify(this.data, null, 1);\n this.writing = this.writing\n .then(async () => {\n await fs.mkdir(this.dir, { recursive: true });\n const tmp = `${this.file}.${randomUUID()}.tmp`;\n await fs.writeFile(tmp, snapshot, { mode: 0o600 });\n await fs.rename(tmp, this.file);\n })\n .catch(() => {\n /* the next write retries with everything */\n });\n }\n\n async flush(): Promise<void> {\n await this.writing;\n }\n}\n","/**\n * SEARCH — by title and by what was said, across every Claude Code and Codex\n * chat on this computer, newest first.\n *\n * A heavy user has tens of gigabytes of session files, so a search is a\n * PAGE: it reads chats newest-first until it has `limit` hits or its time\n * budget is spent, and says exactly how far it got (`scanned` of `total`,\n * `nextCursor` to keep going). It never claims \"no results\" for chats it did\n * not read.\n *\n * A match must be in the conversation — a message, a tool call or its output,\n * exactly as the transcript shows it — not in bookkeeping (ids, tool\n * catalogues, hook output), so \"type\" does not match every line of every file.\n */\n\nimport { createReadStream } from \"node:fs\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexRolloutNormalizer } from \"../normalize/codex\";\nimport type { ChatSearchHit, ChatSearchResult, CodingProvider, TranscriptItem } from \"../types\";\nimport {\n defaultProviderHomes,\n describeSessionFile,\n listSessionFiles,\n readCodexIndex,\n type FileCandidate,\n type ProviderHomes,\n} from \"./files\";\n\nexport interface SearchOptions {\n homes?: ProviderHomes | undefined;\n cursor?: number | undefined;\n limit?: number | undefined;\n /** Stop reading after this long and hand back a cursor. Default 3.5 s. */\n budgetMs?: number | undefined;\n}\n\n/**\n * The first conversation text in one saved line that contains `needle`: the\n * line goes through the SAME normalizer the transcript uses, so only what the\n * screen would show can match — a message, a tool's input or output — never\n * tool catalogues, hook output or ids.\n */\nfunction findInLine(provider: CodingProvider, value: unknown, needle: string): string | null {\n const items: TranscriptItem[] =\n provider === \"claude\" ? createClaudeNormalizer().push(value) : createCodexRolloutNormalizer().push(value);\n for (const item of items) {\n let text: string | null = null;\n switch (item.kind) {\n case \"user\":\n case \"text\":\n case \"reasoning\":\n case \"notice\":\n case \"error\":\n text = item.text;\n break;\n case \"tool-call\":\n text = typeof item.input === \"string\" ? item.input : JSON.stringify(item.input ?? \"\");\n break;\n case \"tool-result\":\n text = item.output;\n break;\n default:\n text = null;\n }\n if (text && text.toLowerCase().includes(needle)) return text;\n }\n return null;\n}\n\n/** ~140 characters around the first match, on one line. */\nexport function snippetAround(text: string, needle: string, width = 140): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n const at = flat.toLowerCase().indexOf(needle);\n if (at < 0) return flat.slice(0, width);\n const before = Math.floor((width - needle.length) / 3);\n const start = Math.max(0, at - before);\n const end = Math.min(flat.length, start + width);\n return `${start > 0 ? \"…\" : \"\"}${flat.slice(start, end)}${end < flat.length ? \"…\" : \"\"}`;\n}\n\n/**\n * Read one file until the first line whose CONVERSATION contains the query.\n * Returns that excerpt, or null.\n *\n * The hot path never decodes UTF-8: each chunk is read as latin1 (one char\n * per byte, so offsets stay byte offsets), lower-cased natively, and searched\n * for the query as it appears inside a JSON string (`raw`: quotes and\n * backslashes escaped). An ASCII query only ever matches ASCII bytes, so the\n * latin1 reading cannot invent or hide a match. Only\n * a line that matches there is decoded, parsed, and checked for the query in\n * its conversation (not its bookkeeping). A query with non-ASCII letters\n * takes the decoded path, which is exact but slower.\n */\nconst TIMED_OUT = Symbol(\"timed-out\");\n\nasync function scanFile(\n provider: CodingProvider,\n file: string,\n needle: string,\n raw: string,\n deadline: number,\n): Promise<string | null | typeof TIMED_OUT> {\n const ascii = /^[\\x00-\\x7f]*$/.test(raw);\n return new Promise((resolve) => {\n let carry: Buffer = Buffer.alloc(0);\n let done = false;\n const stream = createReadStream(file, { highWaterMark: 4 * 1024 * 1024 });\n const finish = (value: string | null | typeof TIMED_OUT) => {\n if (done) return;\n done = true;\n stream.destroy();\n resolve(value);\n };\n const verify = (line: Buffer): string | null => {\n try {\n const hit = findInLine(provider, JSON.parse(line.toString(\"utf8\")), needle);\n return hit === null ? null : snippetAround(hit, needle);\n } catch {\n return null;\n }\n };\n /** Search `block` (complete lines only); the first verified hit, else null. */\n const searchBlock = (block: Buffer): string | null => {\n if (!ascii) {\n for (const line of block.toString(\"utf8\").split(\"\\n\")) {\n if (line.toLowerCase().includes(raw)) {\n const hit = verify(Buffer.from(line, \"utf8\"));\n if (hit !== null) return hit;\n }\n }\n return null;\n }\n const lower = block.toString(\"latin1\").toLowerCase();\n let from = 0;\n for (;;) {\n const at = lower.indexOf(raw, from);\n if (at < 0) return null;\n const start = block.lastIndexOf(10, at) + 1;\n let end = block.indexOf(10, at);\n if (end < 0) end = block.length;\n const hit = verify(block.subarray(start, end));\n if (hit !== null) return hit;\n from = end + 1;\n }\n };\n stream.on(\"data\", (chunk) => {\n const data = carry.length ? Buffer.concat([carry, chunk as Buffer]) : (chunk as Buffer);\n const lastNewline = data.lastIndexOf(10);\n if (lastNewline < 0) {\n carry = data;\n return;\n }\n carry = Buffer.from(data.subarray(lastNewline + 1));\n const hit = searchBlock(data.subarray(0, lastNewline));\n if (hit !== null) return finish(hit);\n // A single file never overruns the whole search's budget.\n if (Date.now() > deadline) finish(TIMED_OUT);\n });\n stream.on(\"end\", () => finish(carry.length ? searchBlock(carry) : null));\n stream.on(\"error\", () => finish(null));\n });\n}\n\n/** The file list, reused briefly: a search typed letter by letter should not stat 9,000 files each time. */\nlet listed: { at: number; homes: ProviderHomes; files: FileCandidate[] } | null = null;\nasync function sessionFiles(homes: ProviderHomes): Promise<FileCandidate[]> {\n if (listed && listed.homes === homes && Date.now() - listed.at < 20_000) return listed.files;\n const files = await listSessionFiles(homes);\n listed = { at: Date.now(), homes, files };\n return files;\n}\n\nexport async function searchLocalChats(query: string, options: SearchOptions = {}): Promise<ChatSearchResult> {\n const needle = query.replace(/\\s+/g, \" \").trim().toLowerCase();\n const homes = options.homes ?? defaultProviderHomes();\n const files: FileCandidate[] = await sessionFiles(homes);\n const cursor = Math.max(0, Math.min(options.cursor ?? 0, files.length));\n if (needle.length < 2) return { query, hits: [], scanned: 0, total: files.length, nextCursor: null };\n\n const raw = JSON.stringify(needle).slice(1, -1);\n const limit = Math.max(1, Math.min(options.limit ?? 30, 100));\n const deadline = Date.now() + (options.budgetMs ?? 3500);\n const names = await readCodexIndex(homes.codex.map((h) => h.index));\n const hits: ChatSearchHit[] = [];\n\n let i = cursor;\n for (; i < files.length && hits.length < limit && Date.now() < deadline; i += 1) {\n const candidate = files[i] as FileCandidate;\n const named = candidate.provider === \"codex\" ? names.get(candidate.id) : undefined;\n const nameHit = named !== undefined && named.toLowerCase().includes(needle);\n const scanned = nameHit ? null : await scanFile(candidate.provider, candidate.file, needle, raw, deadline);\n // A file cut off by the budget is NOT counted as read: the cursor resumes at it.\n // (Unless it is the page's first file — a file too big for one budget is\n // skipped rather than stalling every page on it.)\n if (scanned === TIMED_OUT) {\n if (i === cursor) i += 1;\n break;\n }\n const snippet = scanned;\n if (!nameHit && snippet === null) continue;\n const described = await describeSessionFile(candidate, names);\n if (!described) continue; // sub-agent and hook-only files are not chats\n hits.push({\n provider: described.provider,\n providerSessionId: described.providerSessionId,\n title: described.title,\n cwd: described.cwd,\n updatedAt: described.updatedAt,\n where: nameHit || described.title.toLowerCase().includes(needle) ? \"title\" : \"content\",\n snippet,\n });\n }\n return {\n query,\n hits,\n scanned: i - cursor,\n total: files.length,\n nextCursor: i < files.length ? i : null,\n };\n}\n","/**\n * TITLE HINTS — the port through which the owner of the coding apps' index (Matrx 2's core, which\n * reads Claude's records, Codex's database and the rest through its own `fs`/`exec` owners) tells\n * this package what each chat is called and whether the app hides it. The package never walks the\n * apps' records itself: it reads transcripts (titles by the transcript rules, content search,\n * activity) and overlays these hints as they arrive. Pure: browser-safe types and helpers.\n */\n\nimport type { TitleSource } from \"./titles\";\n\nexport type HintProvider = \"claude\" | \"codex\";\n\nexport interface TitleHint {\n /** The app's title (pre-override: the person's rename is applied by whoever draws the row). */\n title: string;\n source: TitleSource;\n /** The app hides it: archived in the app (shown behind a toggle). */\n archived?: boolean | undefined;\n /** A scheduled or automated run (shown behind a toggle). */\n scheduled?: boolean | undefined;\n /** Listed by the app but its conversation file is gone: why (it is shown, never dropped). */\n unavailable?: string | null | undefined;\n /** Last activity the app records (ms), for chats only the app knows. */\n lastActiveMs?: number | null | undefined;\n}\n\nexport interface TitleHints {\n /** The hints now, keyed `titleHintKey()`; null while the owner's index is still loading. Never waits. */\n current(): ReadonlyMap<string, TitleHint> | null;\n /** Called after the hints change (a rename in the app, a new chat, the first load). */\n subscribe(listener: () => void): () => void;\n}\n\nexport function titleHintKey(provider: HintProvider, sessionId: string): string {\n return `${provider}:${sessionId}`;\n}\n\n/** A hints port the host fills by hand (tests, or an owner that pushes whole snapshots). */\nexport function createTitleHintsStore(): TitleHints & { set(hints: ReadonlyMap<string, TitleHint> | null): void } {\n let hints: ReadonlyMap<string, TitleHint> | null = null;\n const listeners = new Set<() => void>();\n return {\n current: () => hints,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n set(next) {\n hints = next;\n for (const l of listeners) l();\n },\n };\n}\n","/**\n * Overlaying the owner's title hints (`./sessions` TitleHints) on what this engine read from the\n * transcripts. The engine never waits for hints: with none loaded yet, every chat keeps its\n * transcript title and says so (`titlePending`), and a `titles` event follows when they arrive.\n *\n * What stays on node, in this package, and why: reading transcripts (titles by the transcript\n * rules for chats no app lists, content search across every chat, \"live elsewhere\" activity from\n * file tails and processes, history for takeover) — the drivers that resume a chat need the same\n * files on the same machine. What the apps' own records say (titles, archived, scheduled, chats\n * whose file is gone) comes only from the owner of the apps' index (Matrx 2's core).\n */\n\nimport type { DiscoveredSession } from \"../types\";\nimport { titleHintKey, type TitleHint, type TitleHints } from \"../sessions/hints\";\n\nexport function overlayHint<T extends Pick<DiscoveredSession, \"provider\" | \"providerSessionId\" | \"title\"> & Partial<DiscoveredSession>>(\n chat: T,\n hints: ReadonlyMap<string, TitleHint> | null,\n expected: boolean,\n): T {\n if (!expected) return chat;\n if (hints === null) return { ...chat, titlePending: true };\n const hint = hints.get(titleHintKey(chat.provider, chat.providerSessionId));\n if (!hint) return chat;\n return {\n ...chat,\n title: hint.title,\n titleSource: hint.source,\n ...(hint.archived || chat.archived ? { archived: true } : {}),\n ...(hint.scheduled ? { scheduled: true } : {}),\n };\n}\n\n/**\n * The chats the app lists whose conversation file is gone (never dropped: shown as unavailable),\n * newest first, that the transcript read did not already cover.\n */\nexport function unavailableFromHints(hints: ReadonlyMap<string, TitleHint> | null, covered: ReadonlySet<string>): DiscoveredSession[] {\n if (!hints) return [];\n const out: DiscoveredSession[] = [];\n for (const [key, hint] of hints) {\n if (!hint.unavailable || covered.has(key)) continue;\n const at = key.indexOf(\":\");\n const provider = key.slice(0, at);\n if (provider !== \"claude\" && provider !== \"codex\") continue;\n out.push({\n provider,\n providerSessionId: key.slice(at + 1),\n cwd: null,\n title: hint.title,\n titleSource: hint.source,\n updatedAt: new Date(hint.lastActiveMs ?? 0).toISOString(),\n source: null,\n activeElsewhere: null,\n unavailable: hint.unavailable,\n ...(hint.archived ? { archived: true } : {}),\n ...(hint.scheduled ? { scheduled: true } : {}),\n });\n }\n return out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n}\n\nexport type { TitleHints };\n","/**\n * The small local index: which sessions were driven from here and their runs,\n * so the list survives a restart. Transcripts are NEVER copied here — they stay\n * in the providers' own files. One JSON file, written atomically.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { CodingSession, RunRecord } from \"../types\";\n\ninterface IndexFile {\n version: 1;\n sessions: CodingSession[];\n runs: RunRecord[];\n}\n\nconst MAX_RUNS = 2000;\n\nexport interface Identity {\n companyId: string;\n agentId: string;\n}\n\nexport class RunIndex {\n private data: IndexFile = { version: 1, sessions: [], runs: [] };\n private writing: Promise<void> = Promise.resolve();\n\n constructor(private readonly dir: string) {}\n\n get file(): string {\n return path.join(this.dir, \"index.json\");\n }\n\n async load(): Promise<void> {\n await fs.mkdir(this.dir, { recursive: true });\n try {\n const parsed = JSON.parse(await fs.readFile(this.file, \"utf8\")) as Partial<IndexFile>;\n this.data = {\n version: 1,\n sessions: Array.isArray(parsed.sessions) ? parsed.sessions : [],\n runs: Array.isArray(parsed.runs) ? parsed.runs : [],\n };\n } catch {\n this.data = { version: 1, sessions: [], runs: [] };\n }\n }\n\n sessions(): CodingSession[] {\n return [...this.data.sessions].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n session(id: string): CodingSession | null {\n return (\n this.data.sessions.find((s) => s.id === id) ??\n this.data.sessions.find((s) => s.providerSessionId === id) ??\n null\n );\n }\n\n runs(sessionId: string): RunRecord[] {\n return this.data.runs.filter((r) => r.sessionId === sessionId);\n }\n\n run(runId: string): RunRecord | null {\n return this.data.runs.find((r) => r.runId === runId) ?? null;\n }\n\n allRuns(): RunRecord[] {\n return this.data.runs;\n }\n\n putSession(session: CodingSession): void {\n const at = this.data.sessions.findIndex((s) => s.id === session.id);\n if (at >= 0) this.data.sessions[at] = session;\n else this.data.sessions.push(session);\n this.persist();\n }\n\n putRun(run: RunRecord): void {\n const at = this.data.runs.findIndex((r) => r.runId === run.runId);\n if (at >= 0) this.data.runs[at] = run;\n else this.data.runs.push(run);\n if (this.data.runs.length > MAX_RUNS) this.data.runs.splice(0, this.data.runs.length - MAX_RUNS);\n this.persist();\n }\n\n /** Serialize writes; each writes the whole index to a temp file, then renames. */\n private persist(): void {\n const snapshot = JSON.stringify(this.data, null, 1);\n this.writing = this.writing.then(async () => {\n const tmp = `${this.file}.${randomUUID()}.tmp`;\n await fs.writeFile(tmp, snapshot, { mode: 0o600 });\n await fs.rename(tmp, this.file);\n }).catch(() => {\n /* the next write retries with the full index */\n });\n }\n\n async flush(): Promise<void> {\n await this.writing;\n }\n\n /** A stable Paperclip agent/company identity for this install, so the\n * driver's scratch state is reused rather than growing per run. */\n async identity(): Promise<Identity> {\n const file = path.join(this.dir, \"identity.json\");\n try {\n const parsed = JSON.parse(await fs.readFile(file, \"utf8\")) as Partial<Identity>;\n if (typeof parsed.companyId === \"string\" && typeof parsed.agentId === \"string\") {\n return { companyId: parsed.companyId, agentId: parsed.agentId };\n }\n } catch {\n /* first run */\n }\n const identity = { companyId: randomUUID(), agentId: randomUUID() };\n await fs.writeFile(file, JSON.stringify(identity), { mode: 0o600 });\n return identity;\n }\n}\n","/**\n * The person's OWN defaults — the model and effort their Claude Code and Codex\n * use when nothing is picked. The Claude driver otherwise forces its built-in\n * default (`claude-opus-5`) onto every run, silently overriding the model the\n * person chose in Claude Code itself; the engine passes theirs instead.\n * Read-only: these files are never written.\n */\n\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport type { CodingProvider } from \"../types\";\n\nexport interface UserDefaults {\n model: string | null;\n effort: string | null;\n}\n\nasync function readJson(file: string): Promise<Record<string, unknown> | null> {\n try {\n const parsed = JSON.parse(await fs.readFile(file, \"utf8\")) as unknown;\n return typeof parsed === \"object\" && parsed !== null ? (parsed as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\n/** Claude Code's precedence: the folder's local settings, its shared settings, then the person's. */\nexport async function claudeDefaults(cwd: string | null, home = os.homedir()): Promise<UserDefaults> {\n const files = [\n ...(cwd ? [path.join(cwd, \".claude\", \"settings.local.json\"), path.join(cwd, \".claude\", \"settings.json\")] : []),\n path.join(home, \".claude\", \"settings.json\"),\n ];\n let model: string | null = null;\n let effort: string | null = null;\n for (const file of files) {\n const settings = await readJson(file);\n if (!settings) continue;\n model ??= str(settings.model);\n effort ??= str(settings.effortLevel);\n if (model && effort) break;\n }\n return { model, effort };\n}\n\n/** Codex's top-level `model` and `model_reasoning_effort` from `~/.codex/config.toml`. */\nexport async function codexDefaults(home = os.homedir()): Promise<UserDefaults> {\n let text: string;\n try {\n text = await fs.readFile(path.join(home, \".codex\", \"config.toml\"), \"utf8\");\n } catch {\n return { model: null, effort: null };\n }\n const values: Record<string, string> = {};\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (line.startsWith(\"[\")) break; // top-level keys only\n const match = /^([A-Za-z0-9_]+)\\s*=\\s*\"([^\"]*)\"/.exec(line);\n if (match?.[1] && match[2] !== undefined) values[match[1]] = match[2];\n }\n return { model: str(values.model), effort: str(values.model_reasoning_effort) };\n}\n\nexport function userDefaults(provider: CodingProvider, cwd: string | null): Promise<UserDefaults> {\n return provider === \"claude\" ? claudeDefaults(cwd) : codexDefaults();\n}\n\n/** Effort levels each CLI accepts, lowest first (`claude --help`, the Codex driver's docs). */\nexport const EFFORT_LEVELS: Record<CodingProvider, string[]> = {\n claude: [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"],\n codex: [\"low\", \"medium\", \"high\", \"xhigh\"],\n};\n"],"mappings":"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","names":["import_node_child_process","import_node_crypto","import_node_fs","fs","import_promises","listed","path","fs","args","fs","import_node_crypto","import_promises","import_node_path","path","fs","import_promises","import_node_os","import_node_path","isObject","str","num","import_node_path","fsConstants","path","os","listed","import_node_os","import_node_path","path","os","import_node_fs","import_promises","import_node_os","import_node_path","import_node_child_process","path","os","fs","import_node_crypto","import_promises","import_node_path","path","fs","import_node_fs","import_node_crypto","import_promises","import_node_path","path","fs","import_promises","import_node_os","import_node_path","fs","str","os","path","path","fs","os","options","run"]}
|
|
1
|
+
{"version":3,"sources":["../../src/engine/index.ts","../../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.28_tsx@4.23.15_typescript@6.0.3_yaml@2.9.1/node_modules/tsup/assets/cjs_shims.js","../../src/engine/raw-backup.ts","../../src/engine/agent-attach.ts","../../src/normalize/agent-block.ts","../../src/engine/agents.ts","../../src/normalize/claude.ts","../../src/normalize/codex.ts","../../src/normalize/lines.ts","../../src/types.ts","../../src/provider-health.ts","../../src/engine/binaries.ts","../../src/engine/clean-env.ts","../../src/engine/files.ts","../../src/sessions/titles.ts","../../src/engine/activity.ts","../../src/engine/preferences.ts","../../src/engine/search.ts","../../src/sessions/hints.ts","../../src/engine/title-hints.ts","../../src/engine/store.ts","../../src/engine/user-defaults.ts"],"sourcesContent":["/**\n * `@ai-matrx/coding-sessions/engine` — drive the user's own Claude Code and\n * Codex on their own subscription logins, through Paperclip's MIT driver\n * packages, with every fix the 2026-09-27 spike found built in:\n *\n * - each run's driver lives in a forked worker with an ALLOWLISTED\n * environment (`clean-env.ts`), so a host running inside a Claude Code\n * session never leaks `CLAUDE_CODE_*` / `ANTHROPIC_BASE_URL` into the CLI;\n * - Claude runs on the CLI engine with the user's text as the whole prompt;\n * - no Paperclip skill is mounted and no skill-list prompt is appended\n * (`paperclipRuntimeSkills: []`), and a shim strips `PAPERCLIP_*` and\n * Paperclip's `--add-dir` before exec'ing the real CLI;\n * - Codex runs against the user's real `~/.codex`, so sessions appear in\n * their own history and no copy of their login is ever made;\n * - the driver's scratch state goes to this package's data dir, never\n * `~/.paperclip`, and its auth-cache vend is switched off;\n * - stop kills the CLI's process group (the driver ignores `signal`) and the\n * run is recorded as stopped even when Codex exits 0;\n * - a resume the driver would silently replace with a FRESH session is\n * refused and reported, and the driver may never delete the user's own\n * session files.\n */\n\nimport { execFile, fork, type ChildProcess } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport { createRawBackupScheduler, type RawBackupSink } from \"./raw-backup\";\nimport {\n AGENT_REMOVED_BLOCK,\n agentArgsFor,\n codexCompactionDroppedAgent,\n renderFallbackBlock,\n sessionAgentRecord,\n writeAgentAttachment,\n} from \"./agent-attach\";\nimport { createAgentConnection, type CodingSessionsAgentsOptions } from \"./agents\";\n\nexport type { CodingSessionsAgentsOptions } from \"./agents\";\nexport { DEFAULT_SERVER_URL, DEFAULT_SUPABASE_URL } from \"./agents\";\nimport type { McpHttpReply } from \"@ai-matrx/agents/portable/mcp\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexStreamNormalizer } from \"../normalize/codex\";\nimport { createLineSplitter } from \"../normalize/lines\";\nimport {\n PROVIDER_LABEL,\n isTerminalRunStatus,\n type Billing,\n type CodingEvent,\n type CodingProvider,\n type CodingSession,\n type CodingSessionsApi,\n type DiscoveredSession,\n type ProviderStatus,\n type RecentFolder,\n type RunRecord,\n type RunStatus,\n type RunUsage,\n type SendResult,\n type SessionHistory,\n type StartInput,\n type TakeoverInput,\n type TranscriptItem,\n} from \"../types\";\nimport {\n classifyProviderError,\n describeProblem,\n problemFromQuota,\n problemStillApplies,\n} from \"../provider-health\";\nimport type { ModelOption, OpenTarget, ProviderBinary, ProviderProblem, QuotaWindow } from \"../types\";\nimport { chatKey } from \"../types\";\nimport { resolveBinary } from \"./binaries\";\nimport { buildCleanEnv } from \"./clean-env\";\nimport {\n defaultProviderHomes,\n discoverLocalSessions,\n findSessionFile,\n readSessionFile,\n sessionActivity,\n type ProviderHomes,\n} from \"./files\";\nimport { PreferenceStore } from \"./preferences\";\nimport { searchLocalChats } from \"./search\";\nimport { overlayHint, unavailableFromHints, type TitleHints } from \"./title-hints\";\nimport { appTitlesOf, titleHintKey } from \"../sessions/hints\";\nimport { RunIndex, type Identity } from \"./store\";\nimport { EFFORT_LEVELS, userDefaults } from \"./user-defaults\";\n\nexport { buildCleanEnv, isAllowedEnvName } from \"./clean-env\";\n/** Largest transcript Full Download hands to a page in one message (the file stays on disk). */\nexport const RAW_TRANSCRIPT_MAX_BYTES = 200 * 1_048_576;\n\nexport { createRawBackupScheduler, createAiMatrxRawBackupSink } from \"./raw-backup\";\nexport type { RawBackupPolicy, RawBackupSink } from \"./raw-backup\";\nexport { codexHome, discoverLocalSessions, findSessionFile, readSessionFile, defaultProviderHomes, sessionActivity } from \"./files\";\nexport { describeActivity, findDrivingProcess, endsWithOpenToolCall, listProcesses } from \"./activity\";\nexport type { CodexHome, ProviderHomes } from \"./files\";\nexport { createTitleHintsStore, titleHintKey, type TitleHint, type TitleHints } from \"../sessions/hints\";\nexport { searchLocalChats, snippetAround } from \"./search\";\nexport { claudeDefaults, codexDefaults, EFFORT_LEVELS } from \"./user-defaults\";\nexport { PreferenceStore } from \"./preferences\";\n\nexport interface CodingSessionsEngineOptions {\n /** Where the run index and the driver's scratch state live. Default `~/.matrx/coding-sessions`. */\n dataDir?: string | undefined;\n /** The environment the clean one is built FROM. Default `process.env`. */\n hostEnv?: NodeJS.ProcessEnv | undefined;\n /** Explicit CLI paths; default: found on the clean PATH. */\n commands?: Partial<Record<CodingProvider, string>> | undefined;\n /** Where the providers keep their sessions. Default: the user's own homes. */\n homes?: ProviderHomes | undefined;\n /** Ask the drivers for usage windows during `providers()` (Codex). Default true. */\n quota?: boolean | undefined;\n /**\n * Where an opted-in owner's full transcripts are backed up (the host's AI\n * Matrx sign-in). Absent → nothing is ever uploaded. The sink's policy is\n * asked before every upload; with backup off not one byte leaves.\n */\n rawBackup?: RawBackupSink | undefined;\n /** Receives raw provider stdout per run — used to capture test fixtures. */\n onRawOutput?: ((runId: string, provider: CodingProvider, chunk: string) => void) | undefined;\n /**\n * The AI Matrx connection that loads the person's agents into sessions:\n * `credentials` (a `CredentialsPort`, read fresh per call) plus the\n * organization. Absent → the agent picker shows signed out; plain sessions\n * are unaffected.\n */\n agents?: CodingSessionsAgentsOptions | undefined;\n /**\n * What the coding apps' own records say each chat is called (and archived / scheduled / file\n * gone), from the owner of the apps' index — Matrx 2's core. Never waited for; absent → titles\n * come from the transcripts alone (the standalone host).\n */\n titleHints?: TitleHints | undefined;\n}\n\nexport interface CodingSessionsEngine extends CodingSessionsApi {\n subscribe(listener: (event: CodingEvent) => void): () => void;\n /** Where the providers keep their sessions, learned after start (Matrx 2: Codex homes from its core). */\n setHomes(homes: ProviderHomes): void;\n /** Stop every live run and wait for the index to be written. */\n dispose(): Promise<void>;\n readonly dataDir: string;\n /** The host serves agent tools at `<baseUrl>/mcp/<secret>`; null stops serving. */\n setMcpBaseUrl(baseUrl: string | null): void;\n /** One MCP POST for a session's agent tools; null = no session owns `secret`. */\n handleMcp(secret: string, body: unknown): Promise<McpHttpReply | null>;\n}\n\ninterface WorkerMessage {\n kind: string;\n [key: string]: unknown;\n}\n\ninterface LiveRun {\n run: RunRecord;\n child: ChildProcess;\n pgid: number | null;\n stopRequested: boolean;\n killTimer: NodeJS.Timeout | null;\n stderrTail: string;\n refusals: string[];\n /** The provider file's size when this run began (history reads stop there). */\n fileOffset: number | null;\n /** Items this run produced, for a history read that lands mid-run. */\n items: { seq: number; item: TranscriptItem }[];\n}\n\nfunction moduleDir(): string {\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\nfunction resolveWorkerPath(): string {\n const dir = moduleDir();\n // This module is bundled into BOTH dist/engine and dist/server, so the\n // worker is either beside it or in the sibling engine directory.\n for (const candidate of [\n path.join(dir, \"worker.js\"),\n path.join(dir, \"worker.ts\"),\n path.join(dir, \"..\", \"engine\", \"worker.js\"),\n path.join(dir, \"..\", \"engine\", \"worker.ts\"),\n ]) {\n if (existsSync(candidate)) return candidate;\n }\n throw new Error(`[coding-sessions] The driver worker is missing next to ${dir}.`);\n}\n\n/**\n * The shim must be EXECUTABLE, and npm does not preserve the executable bit of\n * a non-`bin` file in a tarball (the packed-tarball canary caught exactly\n * that). So the engine installs its own copy into its data dir, mode 0755,\n * rewriting it only when the packaged source changed.\n */\nasync function installShim(dataDir: string): Promise<string> {\n const source = path.resolve(moduleDir(), \"..\", \"..\", \"bin\", \"cli-shim.sh\");\n if (!existsSync(source)) throw new Error(`[coding-sessions] The CLI shim is missing at ${source}.`);\n const body = await fs.readFile(source, \"utf8\");\n const target = path.join(dataDir, \"bin\", \"cli-shim.sh\");\n const current = await fs.readFile(target, \"utf8\").catch(() => null);\n if (current !== body) {\n await fs.mkdir(path.dirname(target), { recursive: true });\n await fs.writeFile(target, body, { mode: 0o755 });\n }\n await fs.chmod(target, 0o755);\n return target;\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction titleFrom(prompt: string): string {\n const flat = prompt.replace(/\\s+/g, \" \").trim();\n return flat.length > 80 ? `${flat.slice(0, 79)}…` : flat || \"New session\";\n}\n\nfunction capitalize(value: string | null | undefined): string | null {\n if (!value) return null;\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n\nfunction asUsage(value: unknown): RunUsage | null {\n if (typeof value !== \"object\" || value === null) return null;\n const v = value as Record<string, unknown>;\n const n = (x: unknown) => (typeof x === \"number\" && Number.isFinite(x) ? x : 0);\n return {\n inputTokens: n(v.inputTokens),\n outputTokens: n(v.outputTokens),\n cachedInputTokens: n(v.cachedInputTokens),\n };\n}\n\nfunction asBilling(value: unknown): Billing | null {\n if (value === \"subscription\" || value === \"api\") return value;\n if (typeof value === \"string\") return \"unknown\";\n return null;\n}\n\n/**\n * The status the screen shows: what the provider's own auth check says, then\n * — for a provider that looks ready — any usage limit or expired sign-in a run\n * reported (until a run succeeds) or a full quota window.\n */\nexport function describeProviderStatus(\n provider: CodingProvider,\n probe: Record<string, unknown> | undefined,\n lastProblem: ProviderProblem | null = null,\n quota: QuotaWindow[] = [],\n): ProviderStatus {\n const base = describeAuthStatus(provider, probe);\n const withQuota = { ...base, quota };\n if (!base.installed || !base.loggedIn) return { ...withQuota, ready: false, lastProblem };\n const current =\n (lastProblem && problemStillApplies(lastProblem) ? lastProblem : null) ?? problemFromQuota(quota);\n if (!current) return { ...withQuota, ready: true, lastProblem: null };\n const words = describeProblem(provider, current);\n return { ...withQuota, ready: false, lastProblem: current, problem: words.problem, fix: words.fix };\n}\n\nfunction describeAuthStatus(\n provider: CodingProvider,\n probe: Record<string, unknown> | undefined,\n): ProviderStatus {\n const label = PROVIDER_LABEL[provider];\n const installed = probe?.installed === true;\n const binary = (probe?.binary ?? null) as ProviderBinary | null;\n const version = binary?.version ?? (typeof probe?.version === \"string\" ? probe.version : null);\n const base: ProviderStatus = {\n provider,\n label,\n installed,\n version,\n binary,\n loggedIn: false,\n billing: \"unknown\",\n plan: null,\n account: null,\n problem: null,\n fix: null,\n ready: false,\n lastProblem: null,\n quota: [],\n };\n if (!installed) {\n return {\n ...base,\n problem: `${label} isn't installed on this computer.`,\n fix:\n provider === \"claude\"\n ? \"Install Claude Code from claude.com/code and sign in once, then check again.\"\n : \"Install Codex from openai.com/codex and sign in once, then check again.\",\n };\n }\n const auth = (probe?.auth ?? null) as Record<string, unknown> | null;\n if (provider === \"claude\") {\n if (!auth || auth.loggedIn !== true) {\n return {\n ...base,\n problem: \"Claude Code is installed but not signed in.\",\n fix: \"Open Claude Code once and sign in with your Claude account, then check again.\",\n };\n }\n const subscription = auth.authMethod === \"claude.ai\";\n return {\n ...base,\n loggedIn: true,\n billing: subscription ? \"subscription\" : \"api\",\n plan: subscription ? capitalize(typeof auth.subscriptionType === \"string\" ? auth.subscriptionType : null) : null,\n };\n }\n if (!auth || auth.loggedIn !== true) {\n return {\n ...base,\n problem: \"Codex is installed but not signed in.\",\n fix: \"Open Codex once and sign in with your ChatGPT account, then check again.\",\n };\n }\n const apiKey = auth.apiKey === true;\n return {\n ...base,\n loggedIn: true,\n billing: apiKey ? \"api\" : \"subscription\",\n plan: capitalize(typeof auth.planType === \"string\" ? auth.planType : null),\n account: typeof auth.email === \"string\" ? auth.email : null,\n };\n}\n\nexport async function createCodingSessionsEngine(\n options: CodingSessionsEngineOptions = {},\n): Promise<CodingSessionsEngine> {\n const dataDir = options.dataDir ?? path.join(os.homedir(), \".matrx\", \"coding-sessions\");\n const stateDir = path.join(dataDir, \"paperclip-state\");\n // The host may learn the homes later (Matrx 2: Codex homes from its core) — `setHomes`.\n let homes = options.homes ?? defaultProviderHomes();\n const index = new RunIndex(dataDir);\n await index.load();\n const preferences = new PreferenceStore(dataDir);\n await preferences.load();\n await fs.mkdir(stateDir, { recursive: true });\n const identity: Identity = await index.identity();\n const agents = createAgentConnection(options.agents, dataDir);\n const backups = options.rawBackup\n ? createRawBackupScheduler({\n sink: options.rawBackup,\n findFile: (provider, providerSessionId) => findSessionFile(provider, providerSessionId, homes),\n onError: (error) => console.warn(\"[coding-sessions] raw transcript backup failed:\", error),\n })\n : null;\n /** Last `updatedAt` seen per discovered chat — a change is a turn that ended elsewhere. */\n const discoveredSeen = new Map<string, string>();\n\n // Last usage-limit / sign-in failure per provider, remembered across restarts.\n const healthFile = path.join(dataDir, \"provider-health.json\");\n let health: Partial<Record<CodingProvider, ProviderProblem>> = {};\n try {\n health = JSON.parse(await fs.readFile(healthFile, \"utf8\")) as typeof health;\n } catch {\n health = {};\n }\n const saveHealth = () =>\n fs.writeFile(healthFile, JSON.stringify(health), { mode: 0o600 }).catch(() => undefined);\n function noteRunOutcome(provider: CodingProvider, status: RunStatus, texts: string[]): void {\n if (status === \"completed\") {\n if (health[provider]) {\n delete health[provider];\n void saveHealth();\n }\n return;\n }\n if (status !== \"failed\") return;\n for (const text of texts) {\n const problem = classifyProviderError(text);\n if (problem) {\n health[provider] = problem;\n void saveHealth();\n return;\n }\n }\n }\n\n const workerEnv = buildCleanEnv(options.hostEnv ?? process.env, {\n // The driver's scratch state (prompt bundle, per-run MCP config) lives in\n // OUR data dir; nothing is ever written under ~/.paperclip.\n PAPERCLIP_HOME: stateDir,\n // The Codex driver otherwise \"vends\" cached copies of the user's login.\n PAPERCLIP_CODEX_AUTH_CACHE: \"0\",\n // Marks the forked process as a driver worker (see worker.ts).\n MATRX_CODING_SESSIONS_WORKER: \"1\",\n });\n // THE CLI EACH RUN USES: the newest copy on this computer (desktop app,\n // PATH, npm global), re-checked every few minutes so an app update is\n // picked up without a restart. A host-set command always wins.\n const binaryHome = options.hostEnv?.HOME ?? os.homedir();\n const binaryCache = new Map<CodingProvider, { at: number; value: Promise<ProviderBinary | null> }>();\n function binaryFor(provider: CodingProvider, fresh = false): Promise<ProviderBinary | null> {\n const cached = binaryCache.get(provider);\n if (cached && !fresh && Date.now() - cached.at < 5 * 60_000) return cached.value;\n const forced = options.commands?.[provider];\n const value = resolveBinary(provider, {\n env: workerEnv,\n home: binaryHome,\n forced,\n // A forced command needs no discovery to run; the status check still\n // looks, so it can say when a newer copy exists.\n discover: !forced || fresh,\n }).catch(() => (forced ? { path: forced, version: null, source: \"configured\" as const, sourceLabel: \"set by host\", newer: null } : null));\n if (!forced || !fresh) binaryCache.set(provider, { at: Date.now(), value });\n return value;\n }\n const commandFor = async (provider: CodingProvider): Promise<string | null> => (await binaryFor(provider))?.path ?? null;\n\n const workerPath = resolveWorkerPath();\n const shimPath = await installShim(dataDir);\n const listeners = new Set<(event: CodingEvent) => void>();\n const live = new Map<string, LiveRun>();\n const seqBySession = new Map<string, number>();\n\n function emit(event: CodingEvent): void {\n for (const listener of listeners) {\n try {\n listener(event);\n } catch {\n /* one bad listener never starves the rest */\n }\n }\n }\n const titleHints = options.titleHints;\n const hintsNow = () => titleHints?.current() ?? null;\n /** The apps' titles for the readers (`provider:id` → title); undefined = no owner, read the apps here. */\n const appTitles = (): ReadonlyMap<string, string> | undefined => {\n if (!titleHints) return undefined;\n const hints = hintsNow();\n return hints ? appTitlesOf(hints) : new Map();\n };\n const unsubscribeHints = titleHints?.subscribe(() => emit({ type: \"titles\" })) ?? null;\n /** A session the engine drives shows the app's title once the app has one. */\n const withHintTitle = (session: CodingSession): CodingSession => {\n const hint = session.providerSessionId ? hintsNow()?.get(titleHintKey(session.provider, session.providerSessionId)) : undefined;\n return hint ? { ...session, title: hint.title } : session;\n };\n\n\n function saveSession(session: CodingSession): CodingSession {\n index.putSession(session);\n emit({ type: \"session\", session });\n return session;\n }\n\n function saveRun(run: RunRecord): RunRecord {\n index.putRun(run);\n emit({ type: \"run\", run });\n if (backups && isTerminalRunStatus(run.status)) {\n const providerSessionId = index.session(run.sessionId)?.providerSessionId;\n if (providerSessionId) void backups.notify(run.provider, providerSessionId);\n }\n return run;\n }\n\n function emitItem(liveRun: LiveRun, item: TranscriptItem): void {\n const sessionId = liveRun.run.sessionId;\n const seq = (seqBySession.get(sessionId) ?? 0) + 1;\n seqBySession.set(sessionId, seq);\n liveRun.items.push({ seq, item });\n emit({ type: \"item\", sessionId, runId: liveRun.run.runId, seq, item });\n }\n\n // A run the index says is live, with no process behind it, died with the\n // previous host. Say so rather than showing it spinning forever.\n for (const run of index.allRuns()) {\n if (!isTerminalRunStatus(run.status)) {\n index.putRun({\n ...run,\n status: \"failed\",\n endedAt: run.endedAt ?? nowIso(),\n error: \"The app closed while this run was in progress, so it did not finish.\",\n });\n const session = index.session(run.sessionId);\n if (session && session.lastRunId === run.runId) {\n index.putSession({ ...session, lastRunStatus: \"failed\" });\n }\n }\n }\n\n function forkWorker(): ChildProcess {\n return fork(workerPath, [], {\n env: workerEnv,\n cwd: dataDir,\n stdio: [\"ignore\", \"pipe\", \"pipe\", \"ipc\"],\n serialization: \"json\",\n });\n }\n\n function ourPids(): Set<number> {\n const pids = new Set<number>();\n for (const liveRun of live.values()) {\n if (liveRun.pgid !== null) pids.add(liveRun.pgid);\n if (liveRun.child.pid !== undefined) pids.add(liveRun.child.pid);\n }\n return pids;\n }\n\n function activeRunFor(sessionId: string): LiveRun | null {\n for (const liveRun of live.values()) if (liveRun.run.sessionId === sessionId) return liveRun;\n return null;\n }\n\n async function startRun(session: CodingSession, prompt: string): Promise<RunRecord> {\n const provider = session.provider;\n const realCommand = await commandFor(provider);\n const runId = randomUUID();\n // No model picked: the person's OWN default. The Claude driver would\n // otherwise force its built-in model over the one they chose in Claude\n // Code; Codex already falls back to its own config when none is passed.\n const model =\n session.model ?? (provider === \"claude\" ? ((await userDefaults(provider, session.cwd)).model ?? null) : null);\n const run: RunRecord = {\n runId,\n sessionId: session.id,\n provider,\n cwd: session.cwd,\n prompt,\n model,\n status: \"starting\",\n startedAt: nowIso(),\n endedAt: null,\n error: null,\n usage: null,\n costUsd: null,\n billing: null,\n };\n saveRun(run);\n saveSession({\n ...session,\n lastRunId: runId,\n lastRunStatus: \"starting\",\n updatedAt: run.startedAt,\n });\n\n if (!realCommand) {\n const failed = saveRun({\n ...run,\n status: \"failed\",\n endedAt: nowIso(),\n error: `${PROVIDER_LABEL[provider]} isn't installed on this computer.`,\n });\n const current = index.session(session.id);\n if (current) saveSession({ ...current, lastRunStatus: \"failed\" });\n return failed;\n }\n\n let fileOffset: number | null = null;\n if (session.providerSessionId) {\n const file = await findSessionFile(provider, session.providerSessionId, homes);\n if (file) fileOffset = (await fs.stat(file).catch(() => null))?.size ?? null;\n }\n\n // THE AGENT, when the session has one: the SAME pinned bundle every turn,\n // loaded through the CLI's own slots (agent-attach.ts).\n let agentArgs: string[] = [];\n // What the CLI is sent: the person's words, behind a delimited agent block\n // when Codex must be TOLD (a takeover, a switch, a compaction that dropped\n // it) — Codex ignores developer_instructions on a resumed chat.\n let cliPrompt = prompt;\n let delivered: Partial<CodingSession> | null = null;\n if (!session.agent && session.agentRemovedDue) {\n cliPrompt = `${AGENT_REMOVED_BLOCK}${prompt}`;\n delivered = { agentRemovedDue: false };\n }\n if (session.agent) {\n const bundle = await agents.readSessionBundle(session.id);\n if (!bundle) {\n const failed = saveRun({\n ...run,\n status: \"failed\",\n endedAt: nowIso(),\n error: `The agent ${session.agent.name} could not be loaded on this computer anymore. Start a new session to load it again.`,\n });\n const current = index.session(session.id);\n if (current) saveSession({ ...current, lastRunStatus: \"failed\" });\n return failed;\n }\n const attachment = await writeAgentAttachment(agents.sessionDir(session.id), bundle, {\n mcpUrl: await agents.mcpUrlFor(session.id),\n });\n agentArgs = agentArgsFor(provider, attachment, { resuming: session.providerSessionId !== null });\n if (session.agent.blockDue) {\n cliPrompt = `${renderFallbackBlock(bundle, path.join(attachment.dir, \"skills\"), { replaces: session.agent.replaces })}${prompt}`;\n }\n delivered = { agent: { ...session.agent, blockDue: false, deliveredAt: run.startedAt } };\n }\n\n const child = forkWorker();\n const liveRun: LiveRun = {\n run,\n child,\n pgid: null,\n stopRequested: false,\n killTimer: null,\n stderrTail: \"\",\n refusals: [],\n fileOffset,\n items: [],\n };\n live.set(runId, liveRun);\n emitItem(liveRun, { kind: \"user\", id: `run-${runId}`, text: prompt, at: run.startedAt });\n if (delivered) {\n const current = index.session(session.id);\n if (current) saveSession({ ...current, ...delivered });\n }\n\n const splitter = createLineSplitter();\n const claude = provider === \"claude\" ? createClaudeNormalizer() : null;\n const codex = provider === \"codex\" ? createCodexStreamNormalizer(runId.slice(0, 8)) : null;\n let knownProviderSession = session.providerSessionId;\n\n const consume = (values: unknown[]) => {\n for (const value of values) {\n const items = claude ? claude.push(value) : codex ? codex.push(value) : [];\n const sid = claude?.sessionId ?? codex?.sessionId ?? null;\n if (sid && sid !== knownProviderSession) {\n knownProviderSession = sid;\n const current = index.session(session.id);\n if (current) {\n saveSession({ ...current, providerSessionId: sid });\n // A rename made before the provider id was known follows the chat to its lasting key.\n if (preferences.rekey(chatKey(current.provider, null, current.id), chatKey(current.provider, sid))) {\n emit({ type: \"preferences\", preferences: preferences.all() });\n }\n }\n }\n for (const item of items) emitItem(liveRun, item);\n }\n };\n\n const settle = (patch: Partial<RunRecord>) => {\n if (liveRun.killTimer) clearTimeout(liveRun.killTimer);\n live.delete(runId);\n const final = saveRun({ ...liveRun.run, ...patch, endedAt: nowIso() });\n liveRun.run = final;\n noteRunOutcome(provider, final.status, [\n final.error ?? \"\",\n ...liveRun.items.flatMap((entry) => (entry.item.kind === \"error\" ? [entry.item.text] : [])),\n ]);\n const current = index.session(session.id);\n if (current) {\n const [next, ...rest] = current.queued;\n saveSession({ ...current, lastRunStatus: final.status, updatedAt: final.endedAt ?? nowIso() });\n if (next !== undefined) {\n const updated = index.session(session.id);\n if (updated) {\n const trimmed = saveSession({ ...updated, queued: rest });\n void startRun(trimmed, next);\n }\n }\n }\n void pruneDriverScratch();\n if (provider === \"codex\" && final.status === \"completed\") void checkCompaction(session.id);\n };\n\n let settled = false;\n child.on(\"message\", (raw) => {\n const message = raw as WorkerMessage;\n switch (message.kind) {\n case \"log\": {\n const chunk = String(message.chunk ?? \"\");\n if (message.stream === \"stdout\") {\n options.onRawOutput?.(runId, provider, chunk);\n const { values } = splitter.push(chunk);\n consume(values);\n } else {\n liveRun.stderrTail = (liveRun.stderrTail + chunk).slice(-4000);\n }\n return;\n }\n case \"spawn\": {\n const pgid =\n typeof message.processGroupId === \"number\"\n ? message.processGroupId\n : typeof message.pid === \"number\"\n ? message.pid\n : null;\n liveRun.pgid = pgid;\n if (liveRun.stopRequested) {\n killGroup(liveRun);\n return;\n }\n liveRun.run = saveRun({ ...liveRun.run, status: \"running\" });\n const current = index.session(session.id);\n if (current) saveSession({ ...current, lastRunStatus: \"running\" });\n return;\n }\n case \"refused\": {\n liveRun.refusals.push(`${String(message.op)}: ${String(message.target)}`);\n if (message.op === \"config-guard\") {\n emitItem(liveRun, {\n kind: \"notice\",\n id: \"config-guard\",\n level: \"warning\",\n text: \"The Codex driver has changed, so this run could not stop it from rewriting your ~/.codex/config.toml. Its contents are kept; update AI Matrx to restore the protection.\",\n });\n return;\n }\n if (message.op === \"delete\" || message.op === \"remove\") {\n emitItem(liveRun, {\n kind: \"notice\",\n id: `refused-${liveRun.refusals.length}`,\n level: \"warning\",\n text: \"The driver tried to delete part of your saved chat history. That was blocked; your history is untouched.\",\n });\n }\n return;\n }\n case \"result\": {\n consume(splitter.flush().values);\n settled = true;\n const result = (message.result ?? {}) as Record<string, unknown>;\n const usage = asUsage(result.usage);\n const billing = asBilling(result.billingType);\n const costUsd = typeof result.costUsd === \"number\" ? result.costUsd : null;\n if (liveRun.stopRequested) {\n // Codex exits 0 when its process group is killed; the host knows\n // better — the person pressed Stop.\n settle({ status: \"stopped\", usage, billing, costUsd, error: null });\n return;\n }\n if (message.refusedFreshSession === true) {\n settle({\n status: \"failed\",\n usage,\n billing,\n costUsd,\n error:\n `${PROVIDER_LABEL[provider]} could not reopen this chat, and would have started a new, empty one instead. ` +\n \"Nothing was sent. The chat may have been deleted or moved on this computer.\",\n });\n return;\n }\n const exitCode = typeof result.exitCode === \"number\" ? result.exitCode : null;\n const errorMessage = typeof result.errorMessage === \"string\" ? result.errorMessage : null;\n if (exitCode === 0 && !errorMessage && result.timedOut !== true) {\n settle({ status: \"completed\", usage, billing, costUsd, error: null });\n } else {\n const tail = liveRun.stderrTail.trim().split(\"\\n\").slice(-6).join(\"\\n\");\n settle({\n status: \"failed\",\n usage,\n billing,\n costUsd,\n error:\n errorMessage ??\n (tail || `${PROVIDER_LABEL[provider]} exited with code ${exitCode ?? \"unknown\"}.`),\n });\n }\n return;\n }\n case \"fatal\": {\n settled = true;\n settle({\n status: liveRun.stopRequested ? \"stopped\" : \"failed\",\n error: liveRun.stopRequested ? null : String(message.message ?? \"The driver failed.\"),\n });\n return;\n }\n default:\n return;\n }\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n liveRun.stderrTail = (liveRun.stderrTail + chunk.toString(\"utf8\")).slice(-4000);\n });\n child.on(\"exit\", (code, signal) => {\n if (settled) return;\n settled = true;\n settle({\n status: liveRun.stopRequested ? \"stopped\" : \"failed\",\n error: liveRun.stopRequested\n ? null\n : `The driver process ended unexpectedly (${signal ?? `code ${code ?? \"unknown\"}`}). ${liveRun.stderrTail.trim().split(\"\\n\").slice(-3).join(\" \")}`.trim(),\n });\n });\n\n child.send({\n kind: \"run\",\n provider,\n runId,\n cwd: session.cwd,\n prompt: cliPrompt,\n model,\n effort: session.effort ?? null,\n resumeSessionId: session.providerSessionId,\n shimPath,\n realCommand,\n identity,\n agentArgs,\n });\n return run;\n }\n\n /** After a Codex turn: if a compaction dropped the agent, tell it again next turn. */\n async function checkCompaction(sessionId: string): Promise<void> {\n const session = index.session(sessionId);\n if (!session?.agent || session.agent.blockDue || !session.providerSessionId) return;\n const file = await findSessionFile(\"codex\", session.providerSessionId, homes);\n if (!file || !(await codexCompactionDroppedAgent(file, session.agent.deliveredAt ?? null))) return;\n const current = index.session(sessionId);\n if (current?.agent) {\n saveSession({ ...current, agent: { ...current.agent, blockDue: true } });\n }\n }\n\n /** Load an agent for a session and record it (refuses, in plain words, when signed out). */\n async function attachAgent(\n sessionId: string,\n selection: import(\"../types\").AgentSelection,\n options: { blockDue: boolean; replaces?: string | null },\n ): Promise<import(\"../types\").SessionAgent> {\n const bundle = await agents.loadBundle(selection);\n await agents.saveSessionBundle(sessionId, bundle);\n return {\n ...sessionAgentRecord(bundle, {\n toolsServed: (await agents.mcpUrlFor(sessionId)) !== null,\n variables: selection.variables ?? {},\n }),\n blockDue: options.blockDue,\n deliveredAt: null,\n replaces: options.replaces ?? null,\n };\n }\n\n function killGroup(liveRun: LiveRun): void {\n const target = liveRun.pgid;\n if (target === null) return;\n try {\n process.kill(-target, \"SIGTERM\");\n } catch {\n /* already gone */\n }\n liveRun.killTimer = setTimeout(() => {\n try {\n process.kill(-target, \"SIGKILL\");\n } catch {\n /* already gone */\n }\n }, 3000);\n }\n\n async function pruneDriverScratch(): Promise<void> {\n // The Claude driver writes a per-run MCP config under its state dir; it is\n // empty (no Paperclip MCP servers) and never read again.\n const runsDir = path.join(\n stateDir,\n \"instances\",\n \"default\",\n \"companies\",\n identity.companyId,\n \"agents\",\n identity.agentId,\n \"claude-runtime\",\n \"runs\",\n );\n const entries = await fs.readdir(runsDir).catch(() => [] as string[]);\n await Promise.all(\n entries\n .filter((name) => !live.has(name))\n .map((name) => fs.rm(path.join(runsDir, name), { recursive: true, force: true }).catch(() => undefined)),\n );\n }\n\n async function probe(): Promise<Record<string, Record<string, unknown>>> {\n const [claudeBinary, codexBinary] = await Promise.all([binaryFor(\"claude\", true), binaryFor(\"codex\", true)]);\n return new Promise((resolve) => {\n const child = forkWorker();\n let answered = false;\n const timer = setTimeout(() => {\n if (answered) return;\n answered = true;\n child.kill(\"SIGKILL\");\n resolve({});\n }, 20000);\n child.on(\"message\", (raw) => {\n const message = raw as WorkerMessage;\n if (message.kind === \"probe-result\" && !answered) {\n answered = true;\n clearTimeout(timer);\n resolve({\n claude: { ...((message.claude ?? {}) as Record<string, unknown>), binary: claudeBinary },\n codex: { ...((message.codex ?? {}) as Record<string, unknown>), binary: codexBinary },\n });\n }\n });\n child.on(\"exit\", () => {\n if (answered) return;\n answered = true;\n clearTimeout(timer);\n resolve({});\n });\n child.send({\n kind: \"probe\",\n commands: { claude: claudeBinary?.path ?? null, codex: codexBinary?.path ?? null },\n quota: options.quota !== false,\n });\n });\n }\n\n function newSession(input: {\n provider: CodingProvider;\n cwd: string;\n title: string;\n model: string | null;\n effort?: string | null;\n origin: CodingSession[\"origin\"];\n providerSessionId: string | null;\n }): CodingSession {\n const at = nowIso();\n return {\n id: randomUUID(),\n provider: input.provider,\n providerSessionId: input.providerSessionId,\n cwd: input.cwd,\n title: input.title,\n model: input.model,\n effort: input.effort ?? null,\n origin: input.origin,\n createdAt: at,\n updatedAt: at,\n lastRunId: null,\n lastRunStatus: null,\n queued: [],\n };\n }\n\n function resolveFolder(raw: string): string | null {\n const trimmed = raw.trim();\n if (!trimmed) return null;\n return path.resolve(trimmed.replace(/^~(?=$|\\/)/, os.homedir()));\n }\n\n async function checkFolder(raw: string): Promise<import(\"../types\").FolderCheck> {\n const target = resolveFolder(raw);\n if (!target) return { path: \"\", exists: false, isDirectory: false };\n const stat = await fs.stat(target).catch(() => null);\n return { path: target, exists: stat !== null, isDirectory: stat?.isDirectory() === true };\n }\n\n async function assertFolder(cwd: string): Promise<string> {\n const resolved = path.resolve(cwd.replace(/^~(?=$|\\/)/, os.homedir()));\n const stat = await fs.stat(resolved).catch(() => null);\n if (!stat?.isDirectory()) {\n throw new Error(`The folder ${resolved} doesn't exist on this computer.`);\n }\n return resolved;\n }\n\n const engine: CodingSessionsEngine = {\n dataDir,\n\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n\n async providers() {\n const result = await probe();\n return Promise.all(\n ([\"claude\", \"codex\"] as const).map(async (provider) => {\n const probeResult = result[provider];\n const quota = Array.isArray(probeResult?.quota) ? (probeResult.quota as QuotaWindow[]) : [];\n const status = describeProviderStatus(provider, probeResult, health[provider] ?? null, quota);\n const models = Array.isArray(probeResult?.models) ? (probeResult.models as ModelOption[]) : [];\n const mine = await userDefaults(provider, null);\n // With no model of their own, Claude runs on the driver's built-in\n // default; Codex omits the flag and uses the CLI's own.\n const driverDefault =\n provider === \"claude\" && typeof probeResult?.driverDefaultModel === \"string\"\n ? probeResult.driverDefaultModel\n : null;\n return {\n ...status,\n models,\n efforts: EFFORT_LEVELS[provider],\n defaultModel: mine.model\n ? { id: mine.model, source: \"settings\" as const }\n : driverDefault\n ? { id: driverDefault, source: \"driver\" as const }\n : null,\n defaultEffort: mine.effort,\n };\n }),\n );\n },\n\n async discoverSessions(opts) {\n const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids(), appTitles: appTitles() });\n const hints = hintsNow();\n const found = read.map((chat) => overlayHint(chat, hints, titleHints !== undefined));\n if (backups) {\n for (const chat of found) {\n const key = `${chat.provider}:${chat.providerSessionId}`;\n const previous = discoveredSeen.get(key);\n discoveredSeen.set(key, chat.updatedAt);\n // Only a CHANGE since this engine last looked — never a first-sight\n // sweep of someone's whole history.\n if (previous !== undefined && previous !== chat.updatedAt) {\n void backups.notify(chat.provider, chat.providerSessionId);\n }\n }\n }\n const limit = opts?.limit ?? 60;\n const oldest = found.length >= limit ? (found[found.length - 1]?.updatedAt ?? \"\") : \"\";\n const gone = unavailableFromHints(hints, new Set(found.map((c) => titleHintKey(c.provider, c.providerSessionId)))).filter(\n (c) => c.updatedAt >= oldest,\n );\n return gone.length ? [...found, ...gone].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, limit) : found;\n },\n\n async recentFolders(): Promise<RecentFolder[]> {\n const seen = new Map<string, string>();\n for (const session of index.sessions()) {\n if (!seen.has(session.cwd)) seen.set(session.cwd, session.updatedAt);\n }\n const discovered: DiscoveredSession[] = await discoverLocalSessions({ limit: 80, homes });\n for (const d of discovered) {\n if (d.cwd && !seen.has(d.cwd)) seen.set(d.cwd, d.updatedAt);\n }\n const folders = [...seen.entries()]\n .sort((a, b) => b[1].localeCompare(a[1]))\n .slice(0, 12);\n return Promise.all(\n folders.map(async ([folder, lastUsedAt]) => ({\n path: folder,\n lastUsedAt,\n exists: (await fs.stat(folder).catch(() => null))?.isDirectory() === true,\n })),\n );\n },\n\n async titleStatus() {\n if (!titleHints) return { owner: false, pending: false, problem: null };\n const problem = titleHints.problem?.() ?? null;\n return { owner: true, pending: hintsNow() === null && problem === null, problem };\n },\n\n async retryTitles() {\n titleHints?.retry?.();\n },\n\n setHomes(next: ProviderHomes) {\n homes = next;\n },\n\n async listSessions() {\n return index.sessions().map(withHintTitle);\n },\n\n async listRuns(sessionId) {\n const session = index.session(sessionId);\n return session ? index.runs(session.id) : [];\n },\n\n async history(sessionId, options): Promise<SessionHistory> {\n const session = index.session(sessionId);\n if (!session) {\n return { items: [], truncated: false, unavailable: \"This session is not in the list anymore.\", seq: 0 };\n }\n const active = activeRunFor(session.id);\n let base: SessionHistory = { items: [], truncated: false, unavailable: null, seq: 0 };\n if (session.providerSessionId) {\n const file = await findSessionFile(session.provider, session.providerSessionId, homes);\n if (file) {\n const endOffset = active ? (active.fileOffset ?? 0) : undefined;\n base = await readSessionFile(session.provider, file, endOffset, options?.maxBytes);\n } else if (!active) {\n base = {\n items: [],\n truncated: false,\n unavailable: `${PROVIDER_LABEL[session.provider]} has no saved transcript for this chat on this computer.`,\n seq: 0,\n };\n }\n }\n // Taken synchronously right before answering, so a live item is either\n // in this answer (seq ≤ answer.seq) or arrives after it.\n const liveItems = active ? active.items : [];\n return {\n ...base,\n items: [...base.items, ...liveItems.map((entry) => entry.item)],\n seq: seqBySession.get(session.id) ?? 0,\n };\n },\n\n async checkFolder(raw) {\n return checkFolder(raw);\n },\n\n async createFolder(raw) {\n const target = resolveFolder(raw);\n if (!target) throw new Error(\"Type a folder path first.\");\n await fs.mkdir(target, { recursive: true });\n return checkFolder(target);\n },\n\n async sessionActivity(provider, providerSessionId) {\n // A session WE are driving is not \"live elsewhere\".\n for (const liveRun of live.values()) {\n const session = index.session(liveRun.run.sessionId);\n if (session?.providerSessionId === providerSessionId) return null;\n }\n // Our own finished runs wrote the file too; those writes are not evidence.\n let ownWritesUntilMs: number | undefined;\n const ours = index.session(providerSessionId);\n if (ours) {\n for (const run of index.runs(ours.id)) {\n const ended = run.endedAt ? Date.parse(run.endedAt) + 5000 : undefined;\n if (ended !== undefined && (ownWritesUntilMs === undefined || ended > ownWritesUntilMs)) ownWritesUntilMs = ended;\n }\n }\n return sessionActivity(provider, providerSessionId, { homes, excludePids: ourPids(), ownWritesUntilMs });\n },\n\n async readTranscript(provider, providerSessionId, options) {\n const file = await findSessionFile(provider, providerSessionId, homes);\n if (!file) {\n return {\n items: [],\n truncated: false,\n unavailable: `${PROVIDER_LABEL[provider]} has no saved transcript for this chat on this computer.`,\n seq: 0,\n };\n }\n return readSessionFile(provider, file, undefined, options?.maxBytes);\n },\n\n async readRawTranscript(provider, providerSessionId) {\n const file = await findSessionFile(provider, providerSessionId, homes);\n if (!file) {\n return {\n available: false,\n reason: `${PROVIDER_LABEL[provider]} has no saved transcript for this chat on this computer.`,\n };\n }\n const stat = await fs.stat(file);\n if (stat.size > RAW_TRANSCRIPT_MAX_BYTES) {\n return {\n available: false,\n reason: `This transcript is ${formatFileSize(stat.size)}, larger than the ${formatFileSize(RAW_TRANSCRIPT_MAX_BYTES)} this page can hand over. It is at ${file}.`,\n };\n }\n const content = await fs.readFile(file, \"utf8\");\n return { available: true, fileName: path.basename(file), bytes: stat.size, content };\n },\n\n async start(input: StartInput): Promise<SendResult> {\n const prompt = input.prompt.trim();\n if (!prompt) throw new Error(\"Type what you want done before starting.\");\n const cwd = await assertFolder(input.cwd);\n const draft = newSession({\n provider: input.provider,\n cwd,\n title: titleFrom(prompt),\n model: input.model?.trim() || null,\n effort: input.effort?.trim() || null,\n origin: \"started\",\n providerSessionId: null,\n });\n // The agent is loaded BEFORE the session is saved, so a refusal (signed\n // out, not shared, gone) leaves nothing half-made in the list. A NEW\n // session loads it natively (Codex: developer_instructions), no block.\n if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: false });\n const session = saveSession(draft);\n const run = await startRun(session, prompt);\n return { session: index.session(session.id) ?? session, run, queued: false };\n },\n\n async takeover(input: TakeoverInput) {\n const existing = index.session(input.providerSessionId);\n if (existing) {\n if (!input.agent) return existing;\n return engine.setAgent(existing.id, input.agent);\n }\n const cwd = await assertFolder(input.cwd);\n const draft = newSession({\n provider: input.provider,\n cwd,\n title: input.title?.trim() || \"Taken-over chat\",\n model: null,\n origin: \"takeover\",\n providerSessionId: input.providerSessionId,\n });\n // \"Continue with agent\": Claude reads it every turn; Codex ignores\n // developer_instructions on a resumed chat, so it is TOLD in the next prompt.\n if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: input.provider === \"codex\" });\n return saveSession(draft);\n },\n\n async setAgent(sessionId, selection) {\n const session = index.session(String(sessionId ?? \"\"));\n if (!session) throw new Error(\"This session is not in the list anymore.\");\n if (!selection) {\n // A chat that ever followed an agent is TOLD it is gone, on both CLIs —\n // measured live: Claude, simply no longer given the instructions, kept\n // ending replies the way its earlier replies did.\n const told = session.agent?.deliveredAt != null;\n return saveSession({ ...session, agent: null, agentRemovedDue: told });\n }\n // A change mid-chat is TOLD in the next prompt, on both CLIs, naming the\n // agent it replaces (Claude also takes it natively every turn; Codex\n // only this way). Measured live: told only through the system prompt, a\n // model kept the rule its own earlier replies repeated.\n const previous = session.agent && session.agent.deliveredAt != null ? session.agent : null;\n const started = session.providerSessionId !== null;\n const agent = await attachAgent(session.id, selection, {\n blockDue: started,\n replaces: previous ? `${previous.name}${previous.versionNumber !== null ? ` v${previous.versionNumber}` : \"\"}` : null,\n });\n return saveSession({ ...session, agent, agentRemovedDue: false });\n },\n\n async send(sessionId, rawPrompt): Promise<SendResult> {\n const prompt = rawPrompt.trim();\n if (!prompt) throw new Error(\"Type a message before sending.\");\n const session = index.session(sessionId);\n if (!session) throw new Error(\"This session is not in the list anymore.\");\n if (activeRunFor(session.id)) {\n const queued = saveSession({ ...session, queued: [...session.queued, prompt] });\n return { session: queued, run: null, queued: true };\n }\n if (!session.providerSessionId && session.lastRunId) {\n // The first run never reported a session id (it failed before the\n // provider started a chat), so there is nothing to continue.\n const run = await startRun(session, prompt);\n return { session: index.session(session.id) ?? session, run, queued: false };\n }\n const run = await startRun(session, prompt);\n return { session: index.session(session.id) ?? session, run, queued: false };\n },\n\n async stop(runId) {\n const liveRun = live.get(runId);\n if (!liveRun) return index.run(runId);\n liveRun.stopRequested = true;\n if (liveRun.pgid !== null) {\n killGroup(liveRun);\n } else {\n // Not spawned yet: the worker is still preparing. End it; the CLI\n // never started.\n liveRun.child.kill(\"SIGTERM\");\n }\n return liveRun.run;\n },\n\n async chatPreferences() {\n return preferences.all();\n },\n\n async setChatPreference(key, patch) {\n const all = preferences.set(key, patch ?? {});\n emit({ type: \"preferences\", preferences: all });\n return all;\n },\n\n async searchChats(query, opts) {\n const result = await searchLocalChats(String(query ?? \"\"), { homes, cursor: opts?.cursor, limit: opts?.limit, appTitles: appTitles() });\n const hints = hintsNow();\n return { ...result, hits: result.hits.map((hit) => ({ ...hit, title: hints?.get(titleHintKey(hit.provider, hit.providerSessionId))?.title ?? hit.title })) };\n },\n\n async openFolder(raw, target) {\n const folder = await assertFolder(String(raw ?? \"\"));\n await openFolderIn(folder, target);\n },\n\n async setSessionOptions(sessionId, opts) {\n const session = index.session(sessionId);\n if (!session) throw new Error(\"This session is not in the list anymore.\");\n const next = { ...session };\n if (opts && \"model\" in opts) next.model = typeof opts.model === \"string\" && opts.model.trim() ? opts.model.trim() : null;\n if (opts && \"effort\" in opts) next.effort = typeof opts.effort === \"string\" && opts.effort.trim() ? opts.effort.trim() : null;\n return saveSession(next);\n },\n\n async agentAccess() {\n return agents.access();\n },\n\n async agentCatalogRpc(request) {\n return agents.catalogRpc(request);\n },\n\n async agentDetails(agentId) {\n return agents.details(String(agentId ?? \"\"));\n },\n\n setMcpBaseUrl(baseUrl) {\n agents.setMcpBaseUrl(baseUrl);\n },\n\n async handleMcp(secret, body) {\n return agents.handleMcp(secret, body);\n },\n\n async dispose() {\n unsubscribeHints?.();\n for (const liveRun of live.values()) {\n liveRun.stopRequested = true;\n if (liveRun.pgid !== null) killGroup(liveRun);\n else liveRun.child.kill(\"SIGTERM\");\n }\n const deadline = Date.now() + 5000;\n while (live.size > 0 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n await index.flush();\n await preferences.flush();\n },\n };\n\n return engine;\n}\n\nconst OPEN_APP: Record<Exclude<OpenTarget, \"finder\">, { app: string; label: string }> = {\n vscode: { app: \"Visual Studio Code\", label: \"VS Code\" },\n cursor: { app: \"Cursor\", label: \"Cursor\" },\n terminal: { app: \"Terminal\", label: \"Terminal\" },\n};\n\n/** Open a folder in Finder or an app (macOS `open`; Finder-only elsewhere). */\nfunction openFolderIn(folder: string, target: OpenTarget): Promise<void> {\n const mac = process.platform === \"darwin\";\n let command: string;\n let args: string[];\n if (target === \"finder\") {\n command = mac ? \"open\" : process.platform === \"win32\" ? \"explorer\" : \"xdg-open\";\n args = [folder];\n } else {\n const app = OPEN_APP[target];\n if (!app) return Promise.reject(new Error(\"That app can't open folders from here.\"));\n if (!mac) return Promise.reject(new Error(`Opening ${app.label} from here works on a Mac only.`));\n command = \"open\";\n args = [\"-a\", app.app, folder];\n }\n return new Promise((resolve, reject) => {\n execFile(command, args, { timeout: 10_000 }, (error) => {\n if (!error) return resolve();\n const label = target === \"finder\" ? \"the folder\" : (OPEN_APP[target]?.label ?? target);\n reject(\n new Error(\n target === \"finder\"\n ? `Couldn't open ${label}: ${error.message}`\n : `${label} isn't installed on this computer, or it couldn't open this folder.`,\n ),\n );\n });\n });\n}\n\nexport type { RunStatus };\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","/**\n * AUTOMATIC RAW BACKUP — the engine uploads a chat's full provider file after\n * its runs end, but ONLY when the owner opted in.\n *\n * The cloud keeps a coding chat's text and tool names; the full transcript is\n * the provider's own file on this computer. When the Feature Knob\n * `coding_session_bridge.raw_transcript_backup` resolves on for the owner, the\n * host's sink uploads that file through the server's one door.\n *\n * Guarantees (proven in `raw-backup.test.ts`):\n * - the sink's policy is asked FIRST; with `enabled: false` the file is not\n * even read for upload and nothing is sent;\n * - at most one upload per chat per `debounceSeconds`, plus one trailing upload\n * so the final state is always backed up;\n * - an unchanged file (by SHA-256, including the server's stored one) is never\n * sent twice.\n *\n * The engine holds no cloud credentials: a host that can reach AI Matrx passes\n * a sink (`createAiMatrxRawBackupSink`); without one nothing is ever uploaded.\n */\n\nimport { createHash } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\n\nimport type { CodingProvider } from \"../types\";\n\nexport interface RawBackupPolicy {\n enabled: boolean;\n debounceSeconds: number;\n backupSha256?: string | null;\n}\n\nexport interface RawBackupSink {\n policy(provider: CodingProvider, providerSessionId: string): Promise<RawBackupPolicy>;\n upload(provider: CodingProvider, providerSessionId: string, content: Buffer): Promise<void>;\n}\n\ninterface ChatState {\n lastUploadAt: number | null;\n lastSha: string | null;\n trailing: Promise<void> | null;\n}\n\nexport interface RawBackupScheduler {\n notify(provider: CodingProvider, providerSessionId: string): Promise<void>;\n idle(): Promise<void>;\n}\n\nexport function createRawBackupScheduler(options: {\n sink: RawBackupSink;\n findFile: (provider: CodingProvider, providerSessionId: string) => Promise<string | null>;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n onError?: (error: unknown) => void;\n}): RawBackupScheduler {\n const now = options.now ?? (() => Date.now());\n const sleep = options.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const chats = new Map<string, ChatState>();\n\n async function uploadNow(state: ChatState, provider: CodingProvider, id: string, policy: RawBackupPolicy) {\n const file = await options.findFile(provider, id);\n if (!file) return;\n const content = await fs.readFile(file);\n const sha = createHash(\"sha256\").update(content).digest(\"hex\");\n if (sha === state.lastSha || sha === policy.backupSha256) {\n state.lastSha = sha;\n return;\n }\n await options.sink.upload(provider, id, content);\n state.lastUploadAt = now();\n state.lastSha = sha;\n }\n\n async function notify(provider: CodingProvider, providerSessionId: string): Promise<void> {\n const key = `${provider}:${providerSessionId}`;\n const state = chats.get(key) ?? { lastUploadAt: null, lastSha: null, trailing: null };\n chats.set(key, state);\n if (state.trailing) return; // the trailing upload carries this change\n try {\n const policy = await options.sink.policy(provider, providerSessionId);\n if (!policy.enabled) return;\n const windowMs = Math.max(1, policy.debounceSeconds) * 1000;\n const elapsed = state.lastUploadAt === null ? Infinity : now() - state.lastUploadAt;\n if (elapsed >= windowMs) {\n await uploadNow(state, provider, providerSessionId, policy);\n return;\n }\n state.trailing = (async () => {\n try {\n await sleep(windowMs - elapsed);\n const again = await options.sink.policy(provider, providerSessionId);\n if (again.enabled) await uploadNow(state, provider, providerSessionId, again);\n } catch (error) {\n options.onError?.(error);\n } finally {\n state.trailing = null;\n }\n })();\n } catch (error) {\n options.onError?.(error);\n }\n }\n\n return {\n notify,\n async idle() {\n await Promise.all([...chats.values()].map((s) => s.trailing).filter(Boolean));\n },\n };\n}\n\nconst SERVER_PROVIDER: Record<CodingProvider, string> = { claude: \"claude_code\", codex: \"codex\" };\n\n/**\n * The sink a host with an AI Matrx sign-in passes to the engine: the server's\n * backup-policy answer, then its one upload door.\n */\nexport function createAiMatrxRawBackupSink(options: {\n baseUrl: string;\n accessToken: () => Promise<string | null>;\n organizationId?: () => Promise<string | null>;\n fetch?: typeof fetch;\n}): RawBackupSink {\n const doFetch = options.fetch ?? fetch;\n async function headers(extra: Record<string, string> = {}): Promise<Record<string, string> | null> {\n const token = await options.accessToken();\n if (!token) return null;\n const org = options.organizationId ? await options.organizationId() : null;\n return { Authorization: `Bearer ${token}`, ...(org ? { \"X-Organization-Id\": org } : {}), ...extra };\n }\n const base = options.baseUrl.replace(/\\/$/, \"\");\n return {\n async policy(provider, providerSessionId) {\n const auth = await headers();\n if (!auth) return { enabled: false, debounceSeconds: 0 };\n const query = new URLSearchParams({ provider: SERVER_PROVIDER[provider], provider_session_id: providerSessionId });\n const response = await doFetch(`${base}/coding-sessions/raw-transcripts/backup-policy?${query}`, { headers: auth });\n if (!response.ok) throw new Error(`backup policy answered HTTP ${response.status}`);\n const body = (await response.json()) as { enabled?: boolean; debounce_seconds?: number; backup_sha256?: string | null };\n return {\n enabled: body.enabled === true,\n debounceSeconds: Number(body.debounce_seconds ?? 0),\n backupSha256: body.backup_sha256 ?? null,\n };\n },\n async upload(provider, providerSessionId, content) {\n const auth = await headers({ \"Content-Type\": \"application/x-ndjson\" });\n if (!auth) return;\n const query = new URLSearchParams({ provider: SERVER_PROVIDER[provider], provider_session_id: providerSessionId });\n const response = await doFetch(`${base}/coding-sessions/raw-transcripts/backup?${query}`, {\n method: \"POST\",\n headers: auth,\n body: new Uint8Array(content),\n });\n if (!response.ok) throw new Error(`backup upload answered HTTP ${response.status}`);\n },\n };\n}\n","/**\n * AGENT ATTACH — loading an AI Matrx agent into the person's own Claude Code or\n * Codex, through each CLI's own slots and nothing else.\n *\n * Design of record: matrx-desktop/design/agents-in-sessions/DESIGN.md (slot\n * table proven live on Claude Code 2.1.283 and codex-cli 0.157.1).\n *\n * Per session we write ONE directory under this package's data dir:\n *\n * <dir>/instructions.md the agent's instructions (+ included skills)\n * <dir>/plugin/.claude-plugin/plugin.json a temporary Claude plugin …\n * <dir>/plugin/skills/<slug>/SKILL.md … carrying the listed skills\n * <dir>/skills/<slug>/SKILL.md the same files, read by Codex by absolute path\n * <dir>/mcp.json Claude's MCP config → our host's /mcp/<secret>\n *\n * and pass it through the drivers' `extraArgs` only:\n *\n * Claude --append-system-prompt-file <instructions> --system-prompt-snapshot off\n * --plugin-dir <plugin> --mcp-config <mcp.json> (every turn)\n * Codex -c developer_instructions=<instructions + skills list> (new session only —\n * it survives resume)\n * -c mcp_servers.matrx-agent.url=… default_tools_approval_mode=\"approve\"\n *\n * 🚨 NEVER: `--system-prompt`, `--agent`, `--strict-mcp-config`, `--bare`, `--add-dir`\n * (our shim strips it), `model_instructions_file`, CLAUDE.md / AGENTS.md,\n * `~/.codex/skills`, settings files or profiles — the person's own setup is\n * never touched, and the Paperclip drivers' own instruction/skill/MCP options\n * are never used. The access token NEVER enters these files, the args or the\n * CLI's environment: the CLI only ever sees a 127.0.0.1 URL.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { JsonValue, PortableAgentBundle } from \"@ai-matrx/agents/portable\";\n\nimport type { CodingProvider, SessionAgent, SessionAgentPart } from \"../types\";\n\n/** The MCP server name both CLIs see. Never `matrx` (the person's own plugin). */\nexport const AGENT_MCP_SERVER_NAME = \"matrx-agent\";\n/** The temporary Claude plugin's name: skills read `matrx-agent:<slug>`. */\nexport const AGENT_PLUGIN_NAME = \"matrx-agent\";\n\n/** Codex's developer instructions end with this: a later block may replace them. */\nexport const CODEX_REPLACEMENT_CLAUSE =\n \"If a later message in this chat begins with an <ai_matrx_agent> block, that block replaces these AI Matrx agent instructions from then on; an <ai_matrx_agent_removed> block withdraws them.\";\n\nexport interface AgentAttachment {\n dir: string;\n instructionsFile: string;\n pluginDir: string;\n /** Present only when the agent has server tools and the host serves MCP. */\n mcpConfigFile: string | null;\n mcpUrl: string | null;\n /** The instructions text (what Codex receives as developer_instructions). */\n codexInstructions: string;\n}\n\nfunction escapeAttr(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\");\n}\n\nfunction versionWords(bundle: PortableAgentBundle): string {\n return bundle.version_number !== null ? String(bundle.version_number) : \"latest\";\n}\n\n/**\n * The instructions both CLIs receive: the agent's text plus included skills in\n * full. `claudeSkills` names the listed skills as the agent's own — Claude lists\n * plugin skills by itself, but measured live (2026-10-02, Haiku): with readable\n * names alone it loaded the skill in 5 of 5 fresh chats yet answered \"I don't\n * have access\" in a chat several turns long; told which skills are its own, it\n * loads them there too. (Names are readable at the source — `assign_names` in\n * aidream — so no listing is needed to stop an id being read as content.)\n */\nexport function renderAgentInstructions(bundle: PortableAgentBundle, options: { claudeSkills?: boolean } = {}): string {\n const included = bundle.skills.filter((skill) => skill.tier === \"included\");\n const listed = bundle.skills.filter((skill) => skill.tier === \"listed\");\n // The agent's own words come LAST, so its standing rules (the line every\n // reply must end with, say) are the most recent thing the model read\n // (observed: with the skill list after them, Haiku dropped such a rule on\n // two turns of one live run).\n const parts = [`<ai_matrx_agent name=\"${escapeAttr(bundle.name)}\" version=\"${versionWords(bundle)}\">`];\n if (included.length > 0) {\n parts.push(\n \"## Skills (always in effect)\",\n ...included.map((skill) => `### ${skill.label}\\n\\n${skill.body.trim()}`),\n );\n }\n if (options.claudeSkills && listed.length > 0) {\n parts.push(\n [\n \"## Your skills\",\n \"When a request matches one of these, load it with your Skill tool and follow it before answering:\",\n ...listed.map((skill) => `- ${AGENT_PLUGIN_NAME}:${skill.slug} — ${skill.description || skill.label}`),\n ].join(\"\\n\"),\n );\n }\n if (included.length > 0 || (options.claudeSkills && listed.length > 0)) parts.push(\"## Your instructions\");\n parts.push(bundle.instructions.trim());\n parts.push(\"</ai_matrx_agent>\");\n return `${parts.filter(Boolean).join(\"\\n\\n\")}\\n`;\n}\n\n/** Codex's own `<skills_instructions>` list, pointing at our files by absolute path. */\nexport function renderCodexSkillsList(bundle: PortableAgentBundle, skillsRoot: string): string {\n const listed = bundle.skills.filter((skill) => skill.tier === \"listed\");\n if (listed.length === 0) return \"\";\n const lines = [\n \"<skills_instructions>\",\n \"## AI Matrx agent skills\",\n \"A skill is a set of instructions stored in a `SKILL.md` file. Each entry has a name, a description and the absolute path of its file. When a task matches a skill's description, read that file and follow it.\",\n \"### Available skills\",\n ...listed.map(\n (skill) =>\n `- ${skill.slug}: ${skill.description || skill.label} (file: ${path.join(skillsRoot, skill.slug, \"SKILL.md\")})`,\n ),\n \"</skills_instructions>\",\n ];\n return lines.join(\"\\n\");\n}\n\n/**\n * THE FALLBACK: the agent as a delimited block at the start of a first prompt,\n * for a CLI slot that cannot carry it (a Codex takeover ignores\n * developer_instructions). Listed skills are named, with their files' paths.\n */\nexport function renderFallbackBlock(\n bundle: PortableAgentBundle,\n skillsRoot: string,\n options: { replaces?: string | null | undefined } = {},\n): string {\n const skills = renderCodexSkillsList(bundle, skillsRoot);\n // The block arrives mid-chat (a takeover, a switch, an update, after a\n // compaction), so it says plainly that it is the agent from now on — and,\n // on a switch, WHICH earlier agent it replaces: measured live, a model kept\n // following the older rule its own earlier replies repeated when told only\n // through the system prompt.\n const lead = options.replaces\n ? `These instructions REPLACE the earlier AI Matrx agent \"${options.replaces}\" from this message on. Where they differ from anything said before — including how earlier replies ended — follow these.`\n : \"The instructions below are your AI Matrx agent for this chat from now on; they replace any AI Matrx agent instructions given earlier.\";\n const body = renderAgentInstructions(bundle)\n .trim()\n .replace(/^(<ai_matrx_agent [^>]*>)/, `$1\\n\\n${lead}`);\n return skills ? `${body}\\n\\n${skills}\\n\\n` : `${body}\\n\\n`;\n}\n\n/**\n * A TOML basic string. JSON escapes are TOML escapes, except two JSON leaves\n * raw or emits that TOML refuses: DEL (must be escaped) and lone surrogates\n * (not Unicode scalar values — replaced).\n */\nexport function tomlString(value: string): string {\n const scalar = value.replace(/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/g, \"�\");\n return JSON.stringify(scalar).replace(/\\u007f/g, \"\\\\u007f\");\n}\n\n/** Write (or rewrite — idempotent) one session's agent directory. */\nexport async function writeAgentAttachment(\n dir: string,\n bundle: PortableAgentBundle,\n options: { mcpUrl: string | null },\n): Promise<AgentAttachment> {\n const pluginDir = path.join(dir, \"plugin\");\n const skillsRoot = path.join(dir, \"skills\");\n await fs.mkdir(path.join(pluginDir, \".claude-plugin\"), { recursive: true, mode: 0o700 });\n await fs.mkdir(skillsRoot, { recursive: true, mode: 0o700 });\n\n const instructions = renderAgentInstructions(bundle);\n const instructionsFile = path.join(dir, \"instructions.md\");\n await fs.writeFile(instructionsFile, renderAgentInstructions(bundle, { claudeSkills: true }), { mode: 0o600 });\n\n await fs.writeFile(\n path.join(pluginDir, \".claude-plugin\", \"plugin.json\"),\n `${JSON.stringify(\n {\n name: AGENT_PLUGIN_NAME,\n description: `Skills of the AI Matrx agent \"${bundle.name}\"`,\n version: versionWords(bundle) === \"latest\" ? \"1.0.0\" : `${versionWords(bundle)}.0.0`,\n },\n null,\n 2,\n )}\\n`,\n { mode: 0o600 },\n );\n // Listed skills only: an included skill's body is already in the instructions.\n const listed = bundle.skills.filter((skill) => skill.tier === \"listed\");\n const wanted = new Set(listed.map((skill) => skill.slug));\n for (const root of [path.join(pluginDir, \"skills\"), skillsRoot]) {\n await fs.mkdir(root, { recursive: true, mode: 0o700 });\n for (const existing of await fs.readdir(root).catch(() => [] as string[])) {\n if (!wanted.has(existing)) await fs.rm(path.join(root, existing), { recursive: true, force: true });\n }\n for (const skill of listed) {\n const skillDir = path.join(root, skill.slug);\n await fs.mkdir(skillDir, { recursive: true, mode: 0o700 });\n await fs.writeFile(path.join(skillDir, \"SKILL.md\"), skill.content, { mode: 0o600 });\n }\n }\n\n let mcpConfigFile: string | null = null;\n const mcpUrl = options.mcpUrl && bundle.tools.length > 0 ? options.mcpUrl : null;\n const mcpPath = path.join(dir, \"mcp.json\");\n if (mcpUrl) {\n mcpConfigFile = mcpPath;\n await fs.writeFile(\n mcpPath,\n `${JSON.stringify({ mcpServers: { [AGENT_MCP_SERVER_NAME]: { type: \"http\", url: mcpUrl } } }, null, 2)}\\n`,\n { mode: 0o600 },\n );\n } else {\n await fs.rm(mcpPath, { force: true });\n }\n\n const skillsList = renderCodexSkillsList(bundle, skillsRoot);\n return {\n dir,\n instructionsFile,\n pluginDir,\n mcpConfigFile,\n mcpUrl,\n // Same order as Claude's: the skills list first, the agent's words last —\n // then the one sentence that lets a later block replace them. Codex ranks\n // developer instructions above a user message, so without this permission\n // a mid-chat switch or update is ignored (measured live: the v2 block was\n // delivered and Codex kept ending with v1's line).\n codexInstructions: `${skillsList ? `${skillsList}\\n\\n` : \"\"}${instructions}\\n${CODEX_REPLACEMENT_CLAUSE}\\n`,\n };\n}\n\n/** The `extraArgs` that load the agent into one run. */\nexport function agentArgsFor(\n provider: CodingProvider,\n attachment: AgentAttachment,\n options: { resuming: boolean },\n): string[] {\n if (provider === \"claude\") {\n const args = [\n // Every turn: without snapshot off, a resumed Claude drops appended instructions.\n \"--append-system-prompt-file\",\n attachment.instructionsFile,\n \"--system-prompt-snapshot\",\n \"off\",\n \"--plugin-dir\",\n attachment.pluginDir,\n ];\n // Never --strict-mcp-config: the person's own MCP servers stay loaded.\n if (attachment.mcpConfigFile) args.push(\"--mcp-config\", attachment.mcpConfigFile);\n return args;\n }\n const args: string[] = [];\n // Codex keeps developer_instructions in the session it starts; on resume the\n // flag is ignored, so it is sent only when the session is new.\n if (!options.resuming) args.push(\"-c\", `developer_instructions=${tomlString(attachment.codexInstructions)}`);\n if (attachment.mcpUrl) {\n const key = `mcp_servers.${AGENT_MCP_SERVER_NAME}`;\n args.push(\n \"-c\",\n `${key}.url=${tomlString(attachment.mcpUrl)}`,\n \"-c\",\n `${key}.default_tools_approval_mode=\"approve\"`,\n );\n }\n return args;\n}\n\n/** What the session records about its agent: identity, and what each part loaded. */\nexport function sessionAgentRecord(\n bundle: PortableAgentBundle,\n options: { toolsServed: boolean; variables?: Record<string, JsonValue> | undefined },\n): SessionAgent {\n const unavailable = bundle.unavailable.map((u) => ({ kind: u.kind, name: u.name, reason: u.reason }));\n const missingSkills = unavailable.filter((u) => u.kind === \"skill\").length;\n const missingTools = unavailable.filter((u) => u.kind === \"tool\").length;\n if (!options.toolsServed && bundle.tools.length > 0) {\n for (const tool of bundle.tools) {\n unavailable.push({ kind: \"tool\", name: tool.canonical_name, reason: \"Tools need the coding sessions host\" });\n }\n }\n const toolsLoaded = options.toolsServed ? bundle.tools.length : 0;\n const loaded: SessionAgentPart[] = [\n { part: \"instructions\", loaded: bundle.instructions.trim() ? 1 : 0, total: 1 },\n { part: \"skills\", loaded: bundle.skills.length, total: bundle.skills.length + missingSkills },\n { part: \"tools\", loaded: toolsLoaded, total: bundle.tools.length + missingTools },\n ];\n return {\n agentId: bundle.agent_id,\n versionId: bundle.version_id,\n versionNumber: bundle.version_number,\n name: bundle.name,\n definitionHash: bundle.definition_hash,\n loaded,\n unavailable,\n skills: bundle.skills.map((skill) => skill.label),\n tools: options.toolsServed ? bundle.tools.map((tool) => tool.canonical_name) : [],\n ...(options.variables ? { variables: options.variables } : {}),\n };\n}\n\nimport { AGENT_BLOCK_MARKER } from \"../normalize/agent-block\";\n\nexport { AGENT_BLOCK_MARKER };\n\n/** What Codex is told when the person removes the agent from a chat. */\nexport const AGENT_REMOVED_BLOCK =\n \"<ai_matrx_agent_removed>The AI Matrx agent instructions given earlier in this chat no longer apply — including any rule about how replies end. Answer normally from this message on.</ai_matrx_agent_removed>\\n\\n\";\n\nexport { stripAgentBlock } from \"../normalize/agent-block\";\n\n\n/**\n * Did a Codex compaction, after `sinceIso`, drop the agent? Codex records each\n * compaction in the rollout as `{\"type\":\"compacted\",\"payload\":{\"replacement_history\":[…]}}`\n * — the history the model keeps. When the LATEST such record is newer than the\n * last delivery and no longer carries our marker, the agent must be told again.\n */\nexport async function codexCompactionDroppedAgent(rolloutFile: string, sinceIso: string | null): Promise<boolean> {\n const text = await fs.readFile(rolloutFile, \"utf8\").catch(() => \"\");\n if (!text.includes('\"type\":\"compacted\"')) return false;\n let latest: { timestamp?: string; payload?: { replacement_history?: unknown } } | null = null;\n for (const line of text.split(\"\\n\")) {\n if (!line.includes('\"type\":\"compacted\"')) continue;\n try {\n const entry = JSON.parse(line) as { type?: string; timestamp?: string; payload?: { replacement_history?: unknown } };\n if (entry.type === \"compacted\") latest = entry;\n } catch {\n /* a torn last line: ignore */\n }\n }\n if (!latest) return false;\n if (sinceIso && latest.timestamp && latest.timestamp <= sinceIso) return false;\n return !JSON.stringify(latest.payload?.replacement_history ?? \"\").includes(AGENT_BLOCK_MARKER.trim());\n}\n","/**\n * The delimited AI Matrx agent block a coding session puts in front of a\n * person's message when a CLI must be TOLD about the agent (a Codex takeover,\n * an agent switch, after a compaction). Pure: the transcript strips it so the\n * screen shows what the person wrote, not how the CLI was told.\n */\n\n/** The marker every agent text we hand a CLI starts with. */\nexport const AGENT_BLOCK_MARKER = \"<ai_matrx_agent \";\n\n/**\n * Remove a leading agent block from a user message, so the transcript shows\n * what the PERSON wrote (the block is how the CLI was told, not their words).\n */\nexport function stripAgentBlock(text: string): string {\n const removed = text.match(/^<ai_matrx_agent_removed>[\\s\\S]*?<\\/ai_matrx_agent_removed>\\s*/);\n if (removed) return text.slice(removed[0].length);\n if (!text.startsWith(AGENT_BLOCK_MARKER)) return text;\n const end = text.indexOf(\"</ai_matrx_agent>\");\n if (end < 0) return text;\n let rest = text.slice(end + \"</ai_matrx_agent>\".length);\n // The Codex skills list rides after the block.\n const skills = rest.match(/^\\s*<skills_instructions>[\\s\\S]*?<\\/skills_instructions>/);\n if (skills) rest = rest.slice(skills[0].length);\n return rest.replace(/^\\s+/, \"\");\n}\n","/**\n * THE AI MATRX CONNECTION — what a host needs to load the person's agents into\n * their coding sessions: who they are (a `CredentialsPort`, read fresh on every\n * call), which organization the work runs in, the agent picker's catalogue\n * reads, the portable bundle, and one MCP endpoint per session for the agent's\n * server tools.\n *\n * The token lives only in this process. The browser page asks the host to make\n * each catalogue read (an allowlist of RPCs); the CLI only ever sees a\n * 127.0.0.1 URL carrying a per-session random secret.\n *\n * A host with no credentials (the standalone launchd page today) is a STATE,\n * not an error: `access()` says signed out, the page shows one line, and plain\n * sessions work exactly as before.\n */\n\nimport { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { MatrxTransport } from \"@ai-matrx/agents/matrx\";\nimport type { PortableAgentBundle } from \"@ai-matrx/agents/portable\";\nimport type { AgentToolsMcpHandler, McpHttpReply } from \"@ai-matrx/agents/portable/mcp\";\nimport type { CredentialsPort, MatrxCredential } from \"@ai-matrx/data\";\n\nimport type {\n AgentAccess,\n AgentCatalogRpcRequest,\n AgentCatalogRpcResult,\n AgentDetails,\n AgentSelection,\n} from \"../types\";\n\n/** The host option that connects coding sessions to AI Matrx. */\nexport interface CodingSessionsAgentsOptions {\n /** The person's AI Matrx sign-in. Absent or `get() → null` = signed out. */\n credentials?: CredentialsPort | null | undefined;\n /**\n * The organization agent work runs in: a value, or a getter read per call —\n * sync or async (Matrx 2's `codingSessionsCredentials()` hands an async one).\n */\n organizationId?:\n | string\n | null\n | (() => string | null | undefined | Promise<string | null | undefined>)\n | undefined;\n /** AI Matrx server. Default `https://server.app.matrxserver.com`. */\n serverUrl?: string | undefined;\n /** The platform database URL. Default `https://db.matrxserver.com`. */\n supabaseUrl?: string | undefined;\n /** The database's publishable key (the picker's reads). Default: the platform's. */\n supabaseKey?: string | undefined;\n}\n\nexport const DEFAULT_SERVER_URL = \"https://server.app.matrxserver.com\";\nexport const DEFAULT_SUPABASE_URL = \"https://db.matrxserver.com\";\n/**\n * The platform database's PUBLISHABLE key — meant to ship inside apps (the\n * same value Matrx 2's sign-in uses); row access is decided by the person's\n * token, never by this key. A host on another database passes its own.\n */\nexport const DEFAULT_SUPABASE_KEY = \"sb_publishable_scm0jzEJiFUB5ItiqOx5Fg_8BOjB6oA\";\n\n/** The only catalogue reads the page may ask the host to make. */\nexport const AGENT_CATALOG_RPCS: ReadonlySet<string> = new Set([\n \"agx_get_list_full\",\n \"agx_search\",\n \"agx_resolve_agent_address\",\n \"ues_get_bulk\",\n \"ues_list\",\n \"ues_set\",\n \"ues_touch\",\n]);\n\n/**\n * The agents client loads ONLY when a host connected AI Matrx: a host with no\n * `agents` option (the standalone page) never imports it, so it runs exactly\n * as before — including from workspace source, where these entries are\n * TypeScript the plain Node runtime cannot load.\n */\nconst agentsClient = async () => {\n const [matrx, portable, mcp] = await Promise.all([\n import(\"@ai-matrx/agents/matrx\"),\n import(\"@ai-matrx/agents/portable\"),\n import(\"@ai-matrx/agents/portable/mcp\"),\n ]);\n return { ...matrx, ...portable, ...mcp };\n};\n\nfunction sortedValues(values: Record<string, unknown>): [string, unknown][] {\n return Object.keys(values)\n .sort()\n .map((key) => [key, values[key]]);\n}\n\nconst BUNDLE_CACHE_MS = 24 * 60 * 60 * 1000;\n\nexport const SIGNED_OUT_AGENT_MESSAGE = \"Sign in to AI Matrx to use your agents.\";\n\ninterface SessionAgentMeta {\n mcpSecret: string;\n conversationId: string;\n}\n\nfunction userIdOf(credential: MatrxCredential | null): string | null {\n if (!credential || credential.kind !== \"user\") return null;\n const payload = credential.accessToken.split(\".\")[1];\n if (!payload) return null;\n try {\n const claims = JSON.parse(Buffer.from(payload, \"base64url\").toString(\"utf8\")) as { sub?: unknown };\n return typeof claims.sub === \"string\" ? claims.sub : null;\n } catch {\n return null;\n }\n}\n\nexport interface AgentConnection {\n access(): Promise<AgentAccess>;\n catalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;\n details(agentId: string): Promise<AgentDetails>;\n /** Load the bundle a new session pins (refuses, in plain words, when signed out). */\n loadBundle(selection: AgentSelection): Promise<PortableAgentBundle>;\n saveSessionBundle(sessionId: string, bundle: PortableAgentBundle): Promise<void>;\n readSessionBundle(sessionId: string): Promise<PortableAgentBundle | null>;\n sessionDir(sessionId: string): string;\n /** The MCP URL for a session's tools, or null when no host serves MCP. */\n mcpUrlFor(sessionId: string): Promise<string | null>;\n /** Set by the host once it listens: `http://127.0.0.1:<port>`. */\n setMcpBaseUrl(baseUrl: string | null): void;\n /** Answer one MCP POST for the session that owns `secret`; null = unknown secret. */\n handleMcp(secret: string, body: unknown): Promise<McpHttpReply | null>;\n}\n\nexport function createAgentConnection(\n options: CodingSessionsAgentsOptions | undefined,\n dataDir: string,\n): AgentConnection {\n const credentials = options?.credentials ?? null;\n const serverUrl = (options?.serverUrl ?? DEFAULT_SERVER_URL).replace(/\\/+$/, \"\");\n const supabaseUrl = (options?.supabaseUrl ?? DEFAULT_SUPABASE_URL).replace(/\\/+$/, \"\");\n const supabaseKey = options?.supabaseKey ?? (options?.supabaseUrl ? null : DEFAULT_SUPABASE_KEY);\n const root = path.join(dataDir, \"agents\");\n let mcpBaseUrl: string | null = null;\n const handlers = new Map<string, AgentToolsMcpHandler>();\n const secretToSession = new Map<string, string>();\n\n const organizationId = async (): Promise<string | null> => {\n const raw = typeof options?.organizationId === \"function\" ? await options.organizationId() : options?.organizationId;\n return raw && raw.trim() ? raw.trim() : null;\n };\n\n /** A transport for ONE call: the organization is read now, the token per request. */\n const transport = async (): Promise<MatrxTransport> => {\n const org = await organizationId();\n return (await agentsClient()).createMatrxTransport({\n baseUrl: serverUrl,\n ...(credentials ? { credentials } : {}),\n ...(org ? { organizationId: org } : {}),\n source: \"codingSessionsAgents\",\n });\n };\n\n const cacheDir = path.join(dataDir, \"agents\", \".bundles\");\n /**\n * A built bundle is reused when the SAME definition (by hash) is loaded with\n * the same values on the same surface — versions are immutable, so a hash is\n * an identity. The cache never holds a token, only what the CLI is given.\n */\n const cacheKey = (definitionHash: string, selection: AgentSelection, surface: string): string =>\n createHash(\"sha256\")\n .update(JSON.stringify([definitionHash, sortedValues(selection.variables ?? {}), surface]))\n .digest(\"hex\");\n\n const credential = async (): Promise<MatrxCredential | null> => (credentials ? credentials.get() : null);\n\n const requireSignedIn = async (): Promise<void> => {\n if (!(await credential())) throw new Error(SIGNED_OUT_AGENT_MESSAGE);\n };\n\n const sessionDir = (sessionId: string): string => path.join(root, sessionId.replace(/[^A-Za-z0-9_-]/g, \"_\"));\n\n async function meta(sessionId: string): Promise<SessionAgentMeta> {\n const file = path.join(sessionDir(sessionId), \"session.json\");\n const existing = await fs\n .readFile(file, \"utf8\")\n .then((text) => JSON.parse(text) as SessionAgentMeta)\n .catch(() => null);\n if (existing?.mcpSecret && existing.conversationId) return existing;\n const created: SessionAgentMeta = { mcpSecret: randomBytes(24).toString(\"base64url\"), conversationId: randomUUID() };\n await fs.mkdir(sessionDir(sessionId), { recursive: true, mode: 0o700 });\n await fs.writeFile(file, JSON.stringify(created), { mode: 0o600 });\n return created;\n }\n\n /** A secret this process has not handed out yet (the host restarted mid-session). */\n async function findSessionBySecret(secret: string): Promise<string | null> {\n for (const name of await fs.readdir(root).catch(() => [] as string[])) {\n const found = await fs\n .readFile(path.join(root, name, \"session.json\"), \"utf8\")\n .then((text) => (JSON.parse(text) as SessionAgentMeta).mcpSecret === secret)\n .catch(() => false);\n if (found) {\n secretToSession.set(secret, name);\n return name;\n }\n }\n return null;\n }\n\n async function readSessionBundle(sessionId: string): Promise<PortableAgentBundle | null> {\n return fs\n .readFile(path.join(sessionDir(sessionId), \"bundle.json\"), \"utf8\")\n .then((text) => JSON.parse(text) as PortableAgentBundle)\n .catch(() => null);\n }\n\n return {\n async access() {\n const current = await credential().catch(() => null);\n const userId = userIdOf(current);\n return {\n configured: credentials !== null && supabaseKey !== null,\n signedIn: userId !== null,\n userId,\n organizationId: await organizationId().catch(() => null),\n };\n },\n\n async catalogRpc(request) {\n if (!AGENT_CATALOG_RPCS.has(request.fn)) {\n return { data: null, error: { message: `Not an agent catalogue read: ${request.fn}` } };\n }\n const current = await credential();\n if (!current || current.kind !== \"user\") return { data: null, error: { message: SIGNED_OUT_AGENT_MESSAGE, code: \"signed_out\" } };\n if (!supabaseKey) return { data: null, error: { message: \"This host has no AI Matrx database key.\", code: \"not_configured\" } };\n const query = new URLSearchParams();\n if (request.order) query.set(\"order\", `${request.order.column}.${request.order.ascending === false ? \"desc\" : \"asc\"}`);\n if (request.range) {\n query.set(\"offset\", String(request.range[0]));\n query.set(\"limit\", String(request.range[1] - request.range[0] + 1));\n }\n const headers: Record<string, string> = {\n apikey: supabaseKey,\n Authorization: `Bearer ${current.accessToken}`,\n \"Content-Type\": \"application/json\",\n // Every catalogue RPC lives in `public`; the database's default\n // exposed schema is not `public`, so name it (supabase-js does).\n \"Content-Profile\": \"public\",\n \"Accept-Profile\": \"public\",\n };\n if (request.count) headers.Prefer = `count=${request.count}`;\n const qs = query.toString();\n const response = await fetch(`${supabaseUrl}/rest/v1/rpc/${encodeURIComponent(request.fn)}${qs ? `?${qs}` : \"\"}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(request.args ?? {}),\n });\n const text = await response.text();\n const body: unknown = text ? JSON.parse(text) : null;\n if (!response.ok) {\n const err = (body ?? {}) as { message?: string; code?: string; details?: string | null; hint?: string | null };\n return {\n data: null,\n error: { message: err.message ?? `HTTP ${response.status}`, code: err.code, details: err.details ?? null, hint: err.hint ?? null },\n };\n }\n const range = response.headers.get(\"content-range\");\n const total = range?.split(\"/\")[1];\n return { data: body, error: null, count: total && total !== \"*\" ? Number(total) : null };\n },\n\n async details(agentId) {\n await requireSignedIn();\n // THE LIGHT READ: no skills, no tools — choosing an agent is instant.\n const summary = await (await agentsClient()).fetchPortableAgentSummary(await transport(), agentId);\n return {\n agentId: summary.agent_id,\n name: summary.name,\n variables: summary.variables,\n versions: summary.versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at })),\n latestVersionNumber: summary.version_number,\n latestVersionId: summary.version_id,\n };\n },\n\n async loadBundle(selection) {\n await requireSignedIn();\n const client = await agentsClient();\n // Pin a version: \"Latest\" means the version that is latest NOW.\n const summary = await client.fetchPortableAgentSummary(await transport(), selection.agentId);\n const versionId = selection.versionId ?? summary.version_id;\n const definitionHash = versionId\n ? (summary.versions.find((v) => v.id === versionId)?.definition_hash ?? null)\n : summary.definition_hash;\n const surface = \"matrx-user/code-editor\";\n const file = definitionHash ? path.join(cacheDir, `${cacheKey(definitionHash, selection, surface)}.json`) : null;\n if (file) {\n const cached = await fs\n .readFile(file, \"utf8\")\n .then((text) => JSON.parse(text) as PortableAgentBundle)\n .catch(() => null);\n // A day at most: the platform's tool set can change under the same definition.\n const fresh = await fs\n .stat(file)\n .then((st) => Date.now() - st.mtimeMs < BUNDLE_CACHE_MS)\n .catch(() => false);\n if (cached && fresh && cached.definition_hash === definitionHash) return cached;\n }\n const bundle = await client.fetchPortableAgent(\n await transport(),\n versionId ? { versionId } : { agentId: selection.agentId },\n { variables: selection.variables ?? {}, surface },\n );\n if (file && bundle.definition_hash === definitionHash) {\n await fs.mkdir(cacheDir, { recursive: true, mode: 0o700 });\n await fs.writeFile(file, JSON.stringify(bundle), { mode: 0o600 });\n }\n return bundle;\n },\n\n async saveSessionBundle(sessionId, bundle) {\n await fs.mkdir(sessionDir(sessionId), { recursive: true, mode: 0o700 });\n await fs.writeFile(path.join(sessionDir(sessionId), \"bundle.json\"), JSON.stringify(bundle), { mode: 0o600 });\n await meta(sessionId);\n },\n\n readSessionBundle,\n sessionDir,\n\n async mcpUrlFor(sessionId) {\n if (!mcpBaseUrl) return null;\n const { mcpSecret } = await meta(sessionId);\n secretToSession.set(mcpSecret, sessionId);\n return `${mcpBaseUrl}/mcp/${mcpSecret}`;\n },\n\n setMcpBaseUrl(baseUrl) {\n mcpBaseUrl = baseUrl ? baseUrl.replace(/\\/+$/, \"\") : null;\n },\n\n async handleMcp(secret, body) {\n let handler = handlers.get(secret);\n if (!handler) {\n const sessionId = secretToSession.get(secret) ?? (await findSessionBySecret(secret));\n if (!sessionId) return null;\n const bundle = await readSessionBundle(sessionId);\n if (!bundle) return null;\n const { conversationId } = await meta(sessionId);\n const { createAgentToolsMcpHandler } = await agentsClient();\n handler = createAgentToolsMcpHandler({\n bundle,\n credentials,\n organizationId: () => organizationId(),\n baseUrl: serverUrl,\n conversationId,\n });\n handlers.set(secret, handler);\n }\n return handler.handle(body);\n },\n };\n}\n","/**\n * Claude Code → `TranscriptItem`.\n *\n * ONE normalizer reads both of Claude's shapes, because they are the same\n * shape: `claude --print --output-format stream-json` lines (live) and the\n * entries of the user's own session file `~/.claude/projects/<cwd>/<id>.jsonl`\n * (history) both carry `{ type: \"assistant\" | \"user\", message: { content } }`.\n * The live stream adds `system`/`stream_event`/`result`; the file adds its own\n * bookkeeping entries (titles, attachments, snapshots), which are skipped.\n *\n * Block identity: an assistant message arrives as several lines sharing one\n * `message.id`, one content block per line, in block order — the same order\n * the partial-message `content_block_start.index` counts. So a text block's id\n * is `<message id>:<index>` on both paths, and a streamed draft is replaced by\n * its final text rather than duplicated.\n */\n\nimport type { RunUsage, TranscriptItem } from \"../types\";\nimport { stripAgentBlock } from \"./agent-block\";\n\ntype Json = Record<string, unknown>;\n\nfunction isObject(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction num(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\n/** User-role text Claude Code writes that the person never typed. */\nconst SYNTHETIC_USER_PREFIXES = [\n \"<command-name>\",\n \"<command-message>\",\n \"<command-args>\",\n \"<local-command-stdout>\",\n \"<local-command-stderr>\",\n \"<local-command-caveat>\",\n \"<system-reminder>\",\n \"<bash-input>\",\n \"<bash-stdout>\",\n \"<bash-stderr>\",\n \"<user-memory-input>\",\n \"<task-notification>\",\n \"Caveat: The messages below were generated by the user while running local commands\",\n \"[Request interrupted by user\",\n];\n\nexport function isSyntheticClaudeUserText(text: string): boolean {\n const trimmed = text.trimStart();\n return SYNTHETIC_USER_PREFIXES.some((prefix) => trimmed.startsWith(prefix));\n}\n\nfunction toolResultText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((block) => {\n if (!isObject(block)) return \"\";\n if (block.type === \"text\") return str(block.text) ?? \"\";\n if (block.type === \"image\") return \"[image]\";\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n }\n return content === undefined || content === null ? \"\" : JSON.stringify(content);\n}\n\nexport interface ClaudeNormalizer {\n /** Feed one parsed JSON line; returns the items it produced (often none). */\n push(entry: unknown): TranscriptItem[];\n /** The Claude session id, once a line has carried it. */\n readonly sessionId: string | null;\n}\n\nexport function createClaudeNormalizer(): ClaudeNormalizer {\n let sessionId: string | null = null;\n let streamingMessageId: string | null = null;\n const blockCounters = new Map<string, number>();\n let userCounter = 0;\n let noticeCounter = 0;\n\n function nextBlockIndex(messageId: string): number {\n const index = blockCounters.get(messageId) ?? 0;\n blockCounters.set(messageId, index + 1);\n return index;\n }\n\n function pushAssistant(entry: Json): TranscriptItem[] {\n const message = isObject(entry.message) ? entry.message : null;\n if (!message) return [];\n const messageId = str(message.id) ?? str(entry.uuid) ?? `assistant-${blockCounters.size}`;\n const content = Array.isArray(message.content) ? message.content : [];\n const items: TranscriptItem[] = [];\n for (const block of content) {\n if (!isObject(block)) continue;\n const index = nextBlockIndex(messageId);\n const id = `${messageId}:${index}`;\n if (block.type === \"text\") {\n const text = str(block.text) ?? \"\";\n if (text.length > 0) items.push({ kind: \"text\", id, text });\n } else if (block.type === \"thinking\") {\n // Claude Code writes thinking blocks with an EMPTY text and only a\n // signature unless thinking display is on; an empty aside is noise.\n const text = str(block.thinking) ?? \"\";\n if (text.trim().length > 0) items.push({ kind: \"reasoning\", id, text });\n } else if (block.type === \"tool_use\" || block.type === \"server_tool_use\") {\n items.push({\n kind: \"tool-call\",\n id: str(block.id) ?? id,\n name: str(block.name) ?? \"tool\",\n input: block.input ?? null,\n });\n }\n }\n return items;\n }\n\n function pushUser(entry: Json): TranscriptItem[] {\n if (entry.isMeta === true || entry.isCompactSummary === true) return [];\n const message = isObject(entry.message) ? entry.message : null;\n if (!message) return [];\n const at = str(entry.timestamp);\n const content = message.content;\n if (typeof content === \"string\") {\n if (isSyntheticClaudeUserText(content) || content.trim().length === 0) return [];\n userCounter += 1;\n // The agent block is how the CLI was told, not the person's words.\n return [{ kind: \"user\", id: str(entry.uuid) ?? `user-${userCounter}`, text: stripAgentBlock(content), at }];\n }\n if (!Array.isArray(content)) return [];\n const items: TranscriptItem[] = [];\n const typed: string[] = [];\n for (const block of content) {\n if (!isObject(block)) continue;\n if (block.type === \"tool_result\") {\n items.push({\n kind: \"tool-result\",\n id: str(block.tool_use_id) ?? \"unknown\",\n output: toolResultText(block.content),\n isError: block.is_error === true,\n });\n } else if (block.type === \"text\") {\n const text = str(block.text) ?? \"\";\n if (text.trim().length > 0 && !isSyntheticClaudeUserText(text)) typed.push(text);\n }\n }\n if (typed.length > 0) {\n userCounter += 1;\n items.unshift({\n kind: \"user\",\n id: str(entry.uuid) ?? `user-${userCounter}`,\n text: stripAgentBlock(typed.join(\"\\n\\n\")),\n at,\n });\n }\n return items;\n }\n\n function pushStreamEvent(entry: Json): TranscriptItem[] {\n const event = isObject(entry.event) ? entry.event : null;\n if (!event) return [];\n if (event.type === \"message_start\" && isObject(event.message)) {\n streamingMessageId = str(event.message.id);\n return [];\n }\n if (event.type === \"content_block_delta\" && streamingMessageId !== null) {\n const delta = isObject(event.delta) ? event.delta : null;\n if (delta?.type === \"text_delta\") {\n const text = str(delta.text) ?? \"\";\n if (text.length === 0) return [];\n return [{ kind: \"text-delta\", id: `${streamingMessageId}:${num(event.index)}`, text }];\n }\n }\n return [];\n }\n\n function pushResult(entry: Json): TranscriptItem[] {\n const items: TranscriptItem[] = [];\n const usage = isObject(entry.usage) ? entry.usage : null;\n if (usage) {\n const runUsage: RunUsage = {\n inputTokens: num(usage.input_tokens) + num(usage.cache_creation_input_tokens),\n outputTokens: num(usage.output_tokens),\n cachedInputTokens: num(usage.cache_read_input_tokens),\n };\n const cost = typeof entry.total_cost_usd === \"number\" ? entry.total_cost_usd : null;\n items.push({ kind: \"usage\", usage: runUsage, costUsd: cost });\n }\n if (entry.is_error === true || (typeof entry.subtype === \"string\" && entry.subtype !== \"success\")) {\n const text =\n str(entry.result) ??\n (Array.isArray(entry.errors) ? entry.errors.map(String).join(\"\\n\") : null) ??\n `Claude Code stopped with \"${String(entry.subtype)}\".`;\n noticeCounter += 1;\n items.push({ kind: \"error\", id: `claude-result-${noticeCounter}`, text });\n }\n return items;\n }\n\n return {\n get sessionId() {\n return sessionId;\n },\n push(raw: unknown): TranscriptItem[] {\n if (!isObject(raw)) return [];\n const lineSession = str(raw.session_id) ?? str(raw.sessionId);\n if (lineSession && sessionId === null) sessionId = lineSession;\n if (raw.isSidechain === true) return [];\n switch (raw.type) {\n case \"assistant\":\n return pushAssistant(raw);\n case \"user\":\n return pushUser(raw);\n case \"stream_event\":\n return pushStreamEvent(raw);\n case \"result\":\n return pushResult(raw);\n case \"system\":\n if (raw.subtype === \"compact_boundary\") {\n noticeCounter += 1;\n return [\n {\n kind: \"notice\",\n id: `claude-compact-${noticeCounter}`,\n level: \"info\",\n text: \"Claude Code summarized the earlier part of this conversation to make room.\",\n },\n ];\n }\n return [];\n default:\n return [];\n }\n },\n };\n}\n","/**\n * Codex → `TranscriptItem`, from its two different shapes:\n *\n * - the LIVE stream (`codex exec --json`): `thread.started`, `item.started` /\n * `item.completed` for agent messages, commands, file changes, MCP calls,\n * web searches and plans, then `turn.completed` with usage;\n * - the user's own saved rollout file (`~/.codex/sessions/**\\/rollout-*.jsonl`):\n * `session_meta`, `event_msg` (the person's words, verbatim) and\n * `response_item` (assistant messages, tool calls and their outputs).\n *\n * Codex numbers stream items `item_0, item_1, …` again on every run, so live\n * ids carry a per-run prefix; rollout items carry globally unique call ids.\n */\n\nimport type { RunUsage, TranscriptItem } from \"../types\";\nimport { stripAgentBlock } from \"./agent-block\";\n\ntype Json = Record<string, unknown>;\n\nfunction isObject(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction num(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction codexUsage(usage: Json): RunUsage {\n return {\n inputTokens: num(usage.input_tokens),\n outputTokens: num(usage.output_tokens),\n cachedInputTokens: num(usage.cached_input_tokens),\n };\n}\n\n/** Human names for Codex's item kinds, so a tool card reads like a sentence. */\nfunction toolCall(id: string, item: Json): TranscriptItem | null {\n switch (item.type) {\n case \"command_execution\":\n return { kind: \"tool-call\", id, name: \"Shell\", input: { command: str(item.command) ?? \"\" } };\n case \"file_change\":\n return { kind: \"tool-call\", id, name: \"Edit files\", input: { changes: item.changes ?? [] } };\n case \"mcp_tool_call\": {\n const server = str(item.server) ?? \"mcp\";\n const tool = str(item.tool) ?? \"tool\";\n return { kind: \"tool-call\", id, name: `${server}.${tool}`, input: item.arguments ?? null };\n }\n case \"web_search\":\n return { kind: \"tool-call\", id, name: \"Web search\", input: { query: str(item.query) ?? \"\" } };\n case \"todo_list\":\n return { kind: \"tool-call\", id, name: \"Plan\", input: { items: item.items ?? [] } };\n default:\n return null;\n }\n}\n\nfunction toolResult(id: string, item: Json): TranscriptItem | null {\n switch (item.type) {\n case \"command_execution\": {\n const exit = typeof item.exit_code === \"number\" ? item.exit_code : null;\n const output = str(item.aggregated_output) ?? \"\";\n return {\n kind: \"tool-result\",\n id,\n output: exit !== null && exit !== 0 ? `${output}\\n(exit code ${exit})`.trim() : output,\n isError: (exit !== null && exit !== 0) || item.status === \"failed\",\n };\n }\n case \"file_change\":\n return {\n kind: \"tool-result\",\n id,\n output: item.status === \"failed\" ? \"The file change failed.\" : \"Applied.\",\n isError: item.status === \"failed\",\n };\n case \"mcp_tool_call\": {\n const error = isObject(item.error) ? str(item.error.message) : str(item.error);\n return {\n kind: \"tool-result\",\n id,\n output: error ?? (item.result === undefined ? \"\" : JSON.stringify(item.result)),\n isError: error !== null || item.status === \"failed\",\n };\n }\n case \"web_search\":\n case \"todo_list\":\n return { kind: \"tool-result\", id, output: \"\", isError: false };\n default:\n return null;\n }\n}\n\nexport interface CodexStreamNormalizer {\n push(entry: unknown): TranscriptItem[];\n readonly sessionId: string | null;\n}\n\n/** The live `codex exec --json` stream. `runPrefix` keeps ids unique per run. */\nexport function createCodexStreamNormalizer(runPrefix: string): CodexStreamNormalizer {\n let sessionId: string | null = null;\n const started = new Set<string>();\n let counter = 0;\n\n return {\n get sessionId() {\n return sessionId;\n },\n push(raw: unknown): TranscriptItem[] {\n if (!isObject(raw)) return [];\n switch (raw.type) {\n case \"thread.started\":\n sessionId = str(raw.thread_id) ?? sessionId;\n return [];\n case \"item.started\":\n case \"item.updated\":\n case \"item.completed\": {\n const item = isObject(raw.item) ? raw.item : null;\n if (!item) return [];\n const id = `${runPrefix}:${str(item.id) ?? `item-${counter++}`}`;\n const completed = raw.type === \"item.completed\";\n if (item.type === \"agent_message\") {\n if (!completed) return [];\n const text = str(item.text) ?? \"\";\n return text ? [{ kind: \"text\", id, text }] : [];\n }\n if (item.type === \"reasoning\") {\n if (!completed) return [];\n const text = str(item.text) ?? \"\";\n return text.trim() ? [{ kind: \"reasoning\", id, text }] : [];\n }\n if (item.type === \"error\") {\n if (!completed) return [];\n // An `error` ITEM is a non-fatal warning (the run continues); a\n // fatal failure arrives as `turn.failed` or a top-level `error`.\n return [{ kind: \"notice\", id, level: \"warning\", text: str(item.message) ?? \"Codex warning.\" }];\n }\n const items: TranscriptItem[] = [];\n if (!started.has(id)) {\n const call = toolCall(id, item);\n if (call) {\n started.add(id);\n items.push(call);\n }\n }\n if (completed) {\n const result = toolResult(id, item);\n if (result) items.push(result);\n }\n return items;\n }\n case \"turn.completed\":\n return isObject(raw.usage)\n ? [{ kind: \"usage\", usage: codexUsage(raw.usage), costUsd: null }]\n : [];\n case \"turn.failed\": {\n const error = isObject(raw.error) ? str(raw.error.message) : null;\n counter += 1;\n return [{ kind: \"error\", id: `${runPrefix}:failed-${counter}`, text: error ?? \"Codex reported that the turn failed.\" }];\n }\n case \"error\":\n counter += 1;\n return [{ kind: \"error\", id: `${runPrefix}:error-${counter}`, text: str(raw.message) ?? \"Codex reported an error.\" }];\n default:\n return [];\n }\n },\n };\n}\n\nfunction contentText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .map((block) => (isObject(block) ? (str(block.text) ?? \"\") : \"\"))\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction parseArguments(raw: unknown): unknown {\n if (typeof raw !== \"string\") return raw ?? null;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return raw;\n }\n}\n\nfunction shellName(name: string): string {\n return name === \"shell\" || name === \"exec_command\" || name === \"local_shell\" ? \"Shell\" : name;\n}\n\n/**\n * The Codex app prepends ambient context to what the person typed\n * (`<in-app-browser-context …>…</in-app-browser-context>\\n## My request:\\n…`).\n * It is not their words; a title or a transcript bubble shows only theirs.\n */\nexport function stripCodexInjectedContext(text: string): string {\n let out = text;\n const leading = /^\\s*<([a-z][\\w-]*)(?:\\s[^>]*)?>[\\s\\S]*?<\\/\\1>/i;\n for (let i = 0; i < 8 && leading.test(out); i += 1) out = out.replace(leading, \"\");\n return out.replace(/^\\s*#{1,6}\\s*My request:\\s*/i, \"\").trim() || text.trim();\n}\n\n/** Text of a rollout `item_completed` item's `content` blocks. */\nfunction itemText(content: unknown): string {\n if (!Array.isArray(content)) return \"\";\n return content\n .map((block) => (isObject(block) ? (str(block.text) ?? \"\") : \"\"))\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction commandLine(command: unknown): string {\n if (Array.isArray(command)) {\n // [\"/bin/zsh\", \"-lc\", \"ls -la\"] → \"ls -la\": the shell wrapper is noise.\n const last = command[command.length - 1];\n if (command.length >= 3 && typeof last === \"string\") return last;\n return command.map(String).join(\" \");\n }\n return typeof command === \"string\" ? command : \"\";\n}\n\n/**\n * Current Codex (0.15x) records each turn TWICE in a rollout: the model-level\n * `response_item`s (where a shell command is a JavaScript `exec` snippet) and\n * the app-level `event_msg: item_completed` items the Codex app itself renders\n * (UserMessage, AgentMessage, CommandExecution, FileChange, …). The app-level\n * items read the way a person thinks about the work, so once a file shows it\n * has them, they are the transcript and the response_items are skipped.\n * Older rollouts have only response_items plus `event_msg: user_message`.\n */\nfunction rolloutItem(item: Json, fallbackId: string, at: string | null): TranscriptItem[] {\n const id = str(item.id) ?? fallbackId;\n switch (item.type) {\n case \"UserMessage\": {\n const text = stripCodexInjectedContext(stripAgentBlock(itemText(item.content)));\n return text.trim() ? [{ kind: \"user\", id, text, at }] : [];\n }\n case \"AgentMessage\": {\n const text = itemText(item.content);\n return text ? [{ kind: \"text\", id, text }] : [];\n }\n case \"Reasoning\": {\n const text = Array.isArray(item.summary_text) ? item.summary_text.map(String).join(\"\\n\") : \"\";\n return text.trim() ? [{ kind: \"reasoning\", id, text }] : [];\n }\n case \"CommandExecution\": {\n const exit = typeof item.exit_code === \"number\" ? item.exit_code : null;\n const output = str(item.aggregated_output) ?? str(item.formatted_output) ?? str(item.stdout) ?? \"\";\n const failed = (exit !== null && exit !== 0) || item.status === \"failed\";\n return [\n { kind: \"tool-call\", id, name: \"Shell\", input: { command: commandLine(item.command) } },\n {\n kind: \"tool-result\",\n id,\n output: failed && exit !== null ? `${output}\\n(exit code ${exit})`.trim() : output,\n isError: failed,\n },\n ];\n }\n case \"FileChange\":\n return [\n { kind: \"tool-call\", id, name: \"Edit files\", input: { changes: item.changes ?? null } },\n { kind: \"tool-result\", id, output: item.status === \"failed\" ? \"The file change failed.\" : \"Applied.\", isError: item.status === \"failed\" },\n ];\n case \"McpToolCall\": {\n const name = `${str(item.server) ?? \"mcp\"}.${str(item.tool) ?? \"tool\"}`;\n const error = isObject(item.error) ? str(item.error.message) : str(item.error);\n return [\n { kind: \"tool-call\", id, name, input: item.arguments ?? null },\n {\n kind: \"tool-result\",\n id,\n output: error ?? (item.result === undefined ? \"\" : JSON.stringify(item.result)),\n isError: error !== null || item.status === \"failed\",\n },\n ];\n }\n case \"WebSearch\":\n return [\n { kind: \"tool-call\", id, name: \"Web search\", input: { query: str(item.query) ?? \"\" } },\n { kind: \"tool-result\", id, output: \"\", isError: false },\n ];\n default:\n return [];\n }\n}\n\nexport interface CodexRolloutNormalizer {\n push(entry: unknown): TranscriptItem[];\n readonly sessionId: string | null;\n readonly cwd: string | null;\n}\n\n/** The user's saved rollout file. */\nexport function createCodexRolloutNormalizer(): CodexRolloutNormalizer {\n let sessionId: string | null = null;\n let cwd: string | null = null;\n let counter = 0;\n let appItems = false;\n\n return {\n get sessionId() {\n return sessionId;\n },\n get cwd() {\n return cwd;\n },\n push(raw: unknown): TranscriptItem[] {\n if (!isObject(raw)) return [];\n const payload = isObject(raw.payload) ? raw.payload : null;\n if (!payload) return [];\n const at = str(raw.timestamp);\n counter += 1;\n const fallbackId = `rollout-${typeof raw.ordinal === \"number\" ? raw.ordinal : counter}`;\n if (raw.type === \"session_meta\") {\n sessionId = str(payload.id) ?? sessionId;\n cwd = str(payload.cwd) ?? cwd;\n return [];\n }\n if (raw.type === \"event_msg\") {\n if (payload.type === \"item_completed\" && isObject(payload.item)) {\n appItems = true;\n return rolloutItem(payload.item, fallbackId, at);\n }\n if (payload.type === \"user_message\" && !appItems) {\n const text = stripCodexInjectedContext(stripAgentBlock(str(payload.message) ?? \"\"));\n return text.trim() ? [{ kind: \"user\", id: fallbackId, text, at }] : [];\n }\n return [];\n }\n if (raw.type === \"compacted\") {\n return [\n {\n kind: \"notice\",\n id: fallbackId,\n level: \"info\",\n text: \"Codex summarized the earlier part of this conversation to make room.\",\n },\n ];\n }\n if (raw.type !== \"response_item\" || appItems) return [];\n switch (payload.type) {\n case \"message\": {\n if (payload.role !== \"assistant\") return [];\n const text = contentText(payload.content);\n return text ? [{ kind: \"text\", id: str(payload.id) ?? fallbackId, text }] : [];\n }\n case \"reasoning\": {\n const summary = Array.isArray(payload.summary)\n ? payload.summary.map((part) => (isObject(part) ? (str(part.text) ?? \"\") : \"\")).join(\"\\n\")\n : \"\";\n return summary.trim()\n ? [{ kind: \"reasoning\", id: str(payload.id) ?? fallbackId, text: summary }]\n : [];\n }\n case \"function_call\":\n return [\n {\n kind: \"tool-call\",\n id: str(payload.call_id) ?? fallbackId,\n name: shellName(str(payload.name) ?? \"tool\"),\n input: parseArguments(payload.arguments),\n },\n ];\n case \"custom_tool_call\":\n return [\n {\n kind: \"tool-call\",\n id: str(payload.call_id) ?? fallbackId,\n name: shellName(str(payload.name) ?? \"tool\"),\n input: payload.input ?? null,\n },\n ];\n case \"local_shell_call\": {\n const action = isObject(payload.action) ? payload.action : {};\n return [\n {\n kind: \"tool-call\",\n id: str(payload.call_id) ?? fallbackId,\n name: \"Shell\",\n input: { command: action.command ?? null },\n },\n ];\n }\n case \"web_search_call\":\n return [\n {\n kind: \"tool-call\",\n id: str(payload.id) ?? fallbackId,\n name: \"Web search\",\n input: payload.action ?? null,\n },\n { kind: \"tool-result\", id: str(payload.id) ?? fallbackId, output: \"\", isError: false },\n ];\n case \"function_call_output\":\n case \"custom_tool_call_output\":\n case \"local_shell_call_output\": {\n const output = payload.output;\n const text =\n typeof output === \"string\"\n ? output\n : isObject(output)\n ? (str(output.content) ?? JSON.stringify(output))\n : contentText(output);\n return [\n {\n kind: \"tool-result\",\n id: str(payload.call_id) ?? fallbackId,\n output: text,\n isError: isObject(output) && output.success === false,\n },\n ];\n }\n default:\n return [];\n }\n },\n };\n}\n","/**\n * Stdout arrives in arbitrary chunks; the providers write one JSON object per\n * line. This turns chunks into parsed lines, keeping a partial tail between\n * chunks, and reports (never throws on) a line that is not JSON — the CLIs do\n * print plain-text warnings on stdout now and then.\n */\n\nexport interface LineSplitter {\n push(chunk: string): { values: unknown[]; nonJson: string[] };\n /** Whatever is left when the stream ends. */\n flush(): { values: unknown[]; nonJson: string[] };\n}\n\nfunction parseLines(lines: string[]): { values: unknown[]; nonJson: string[] } {\n const values: unknown[] = [];\n const nonJson: string[] = [];\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n if (!trimmed.startsWith(\"{\")) {\n nonJson.push(trimmed);\n continue;\n }\n try {\n values.push(JSON.parse(trimmed) as unknown);\n } catch {\n nonJson.push(trimmed);\n }\n }\n return { values, nonJson };\n}\n\nexport function createLineSplitter(): LineSplitter {\n let buffer = \"\";\n return {\n push(chunk) {\n buffer += chunk;\n const parts = buffer.split(\"\\n\");\n buffer = parts.pop() ?? \"\";\n return parseLines(parts);\n },\n flush() {\n const rest = buffer;\n buffer = \"\";\n return parseLines([rest]);\n },\n };\n}\n\n/** Parse a whole JSONL text (a fixture, or a provider file read in one go). */\nexport function parseJsonl(text: string): unknown[] {\n return parseLines(text.split(\"\\n\")).values;\n}\n","/**\n * The public contract of `@ai-matrx/coding-sessions`, shared by the engine\n * (Node), the local host (Node) and the UI (browser). Pure types — nothing here\n * touches Node or the DOM, and every value is JSON-serializable because it\n * crosses a transport (WebSocket today, desktop IPC later).\n */\n\nimport type { JsonValue } from \"@ai-matrx/agents/portable\";\n\nimport type { TitleSource } from \"./sessions/titles\";\n\n/** The coding agents this package drives. \"coding session\" is the canonical\n * platform term (chat.coding_session, the Coding Session Bridge). */\nexport type CodingProvider = \"claude\" | \"codex\";\n\nexport const CODING_PROVIDERS: readonly CodingProvider[] = [\"claude\", \"codex\"];\n\nexport const PROVIDER_LABEL: Record<CodingProvider, string> = {\n claude: \"Claude Code\",\n codex: \"Codex\",\n};\n\nexport type Billing = \"subscription\" | \"api\" | \"unknown\";\n\n/** Where the CLI a provider runs came from. */\nexport type BinarySource = \"desktop-app\" | \"path\" | \"npm-global\" | \"configured\";\n\n/** The exact CLI runs use: the newest copy on this computer (or the host's pick). */\nexport interface ProviderBinary {\n path: string;\n version: string | null;\n source: BinarySource;\n /** \"from ChatGPT app\", \"from PATH\", … */\n sourceLabel: string;\n /** A newer copy than the one in use, when one exists. */\n newer: { path: string; version: string; sourceLabel: string } | null;\n}\n\n/** What `providers()` answers for one provider, in plain terms. */\nexport interface ProviderStatus {\n provider: CodingProvider;\n label: string;\n installed: boolean;\n version: string | null;\n loggedIn: boolean;\n billing: Billing;\n /** \"Max\", \"Pro\", \"Plus\", … when the provider reports a plan. */\n plan: string | null;\n /** The signed-in account label, when the provider reports one. */\n account: string | null;\n /** A plain-English sentence for the screen when it is not ready. */\n problem: string | null;\n /** A plain-English fix for `problem`. */\n fix: string | null;\n /** Installed, signed in, and no known usage limit or expired sign-in. */\n ready: boolean;\n /** The last usage-limit or sign-in failure a run reported, until a run succeeds. */\n lastProblem: ProviderProblem | null;\n /** Usage windows, when the provider exposes them (Codex does; see FEATURE.md). */\n quota: QuotaWindow[];\n /** Models the driver knows for this provider (the person may type any other). */\n models?: ModelOption[] | undefined;\n /** Reasoning-effort levels this provider accepts, lowest first. */\n efforts?: string[] | undefined;\n /**\n * The model a run uses when none is picked, and where that comes from: the\n * person's own settings (`~/.claude/settings.json`, `~/.codex/config.toml`)\n * or the driver's built-in default.\n */\n defaultModel?: { id: string; source: \"settings\" | \"driver\" } | null | undefined;\n /** The effort a run uses when none is picked (the person's own settings). */\n defaultEffort?: string | null | undefined;\n /** Which CLI runs use, and its version. */\n binary?: ProviderBinary | null | undefined;\n}\n\nexport interface ModelOption {\n id: string;\n label: string;\n}\n\n/**\n * The person's own organisation of their chats — a rename, a pin, a hide. Kept\n * in this package's data dir, keyed by `chatKey()`; the providers' own files\n * are NEVER touched (a rename here does not rename the chat in Claude Code).\n */\nexport interface ChatPreference {\n /** Shown instead of the chat's own title. */\n title?: string | null | undefined;\n pinned?: boolean | undefined;\n /** Hidden from the lists (still found by search, restorable). */\n hidden?: boolean | undefined;\n updatedAt?: string | undefined;\n}\n\n/** The one key a chat's preference lives under, for ours and discovered alike. */\nexport function chatKey(provider: CodingProvider, providerSessionId: string | null, sessionId?: string | null): string {\n return providerSessionId ? `${provider}:${providerSessionId}` : `session:${sessionId ?? \"\"}`;\n}\n\n/** One chat that matched a search. */\nexport interface ChatSearchHit {\n provider: CodingProvider;\n providerSessionId: string;\n title: string;\n cwd: string | null;\n updatedAt: string;\n /** Where the words were found. */\n where: \"title\" | \"content\";\n /** A short excerpt around the first match in the conversation. */\n snippet: string | null;\n}\n\nexport interface ChatSearchResult {\n query: string;\n hits: ChatSearchHit[];\n /** How many chats were read, newest first, starting from the cursor. */\n scanned: number;\n /** How many chats exist on this computer. */\n total: number;\n /** Pass back to keep searching older chats; null when every chat was read. */\n nextCursor: number | null;\n}\n\n/** Where \"Open folder\" can open a session's folder. */\nexport type OpenTarget = \"finder\" | \"vscode\" | \"cursor\" | \"terminal\";\n\nexport interface ProviderProblem {\n kind: \"usage-limit\" | \"signed-out\";\n /** The provider's own words, verbatim. */\n message: string;\n /** When a usage limit lifts: ISO when parseable, else the provider's phrase. */\n until: string | null;\n at: string;\n}\n\nexport interface QuotaWindow {\n label: string;\n usedPercent: number | null;\n resetsAt: string | null;\n valueLabel: string | null;\n}\n\n/** An existing local Claude Code or Codex chat, found on disk (metadata only). */\nexport interface DiscoveredSession {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string | null;\n /**\n * The chat's own title by the one rule (`./sessions`): the coding app's title when the owner of\n * the apps' index supplied it (title hints), else the transcript's. Never the person's rename —\n * that is applied once, by the screen, from the preferences.\n */\n title: string;\n /** Where `title` came from (`TITLE_PRECEDENCE`). */\n titleSource?: TitleSource | \"unknown\" | undefined;\n /** The app's title is still on its way (hints not loaded yet); `title` is the transcript's for now. */\n titlePending?: boolean | undefined;\n /** Archived in the app (hidden by default, like Code › Chats). */\n archived?: boolean | undefined;\n /** A scheduled or automated run (hidden by default). */\n scheduled?: boolean | undefined;\n /** The app lists it but its conversation file is gone: why. Shown, cannot be taken over. */\n unavailable?: string | null | undefined;\n updatedAt: string;\n /** Where it was started, when the provider records it (\"cli\", \"vscode\", \"exec\", …). */\n source: string | null;\n /** Set when the chat looks live somewhere else right now (see `ActiveElsewhere`). */\n activeElsewhere: ActiveElsewhere | null;\n}\n\n/**\n * Evidence that a chat is being driven somewhere else RIGHT NOW. Taking it\n * over then puts two agents on one conversation, so the screen warns and asks —\n * it never blocks (validation offers, never blocks).\n */\nexport interface ActiveElsewhere {\n /** How we know, strongest first. */\n reason: \"process\" | \"recent-write\" | \"open-tool-call\";\n /** One plain sentence for the screen. */\n message: string;\n}\n\nexport type RunStatus = \"starting\" | \"running\" | \"completed\" | \"stopped\" | \"failed\";\n\nexport const TERMINAL_RUN_STATUSES: readonly RunStatus[] = [\"completed\", \"stopped\", \"failed\"];\n\nexport function isTerminalRunStatus(status: RunStatus): boolean {\n return TERMINAL_RUN_STATUSES.includes(status);\n}\n\nexport interface RunUsage {\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n}\n\n/** One turn: one prompt sent to one provider process. */\nexport interface RunRecord {\n runId: string;\n /** Our session id (`CodingSession.id`). */\n sessionId: string;\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model: string | null;\n status: RunStatus;\n startedAt: string;\n endedAt: string | null;\n /** The real error, verbatim from the provider or the driver, when failed. */\n error: string | null;\n usage: RunUsage | null;\n costUsd: number | null;\n billing: Billing | null;\n}\n\n/** How a session came to be listed here. */\nexport type SessionOrigin = \"started\" | \"takeover\";\n\n/** A conversation driven from here. Its transcript lives in the provider's own\n * files; this is only the index row. */\nexport interface CodingSession {\n /** Our stable id. */\n id: string;\n provider: CodingProvider;\n /** The provider's own session/thread id — null until the first run reports it. */\n providerSessionId: string | null;\n cwd: string;\n title: string;\n model: string | null;\n /** Reasoning effort for the next run; null = the provider's own default. */\n effort?: string | null | undefined;\n origin: SessionOrigin;\n createdAt: string;\n updatedAt: string;\n /** The live or most recent run. */\n lastRunId: string | null;\n lastRunStatus: RunStatus | null;\n /** Prompts waiting for the active run to finish, oldest first. */\n queued: string[];\n /** The AI Matrx agent loaded into every run of this session, when one was picked. */\n agent?: SessionAgent | null | undefined;\n /** Codex must be told, in the next prompt, that an earlier agent no longer applies. */\n agentRemovedDue?: boolean | undefined;\n}\n\n/**\n * One normalized transcript item — the same shape from Claude and Codex, from\n * a live stream and from a provider's saved session file.\n */\nexport type TranscriptItem =\n | { kind: \"user\"; id: string; text: string; at: string | null }\n | { kind: \"text\"; id: string; text: string }\n | { kind: \"text-delta\"; id: string; text: string }\n | { kind: \"reasoning\"; id: string; text: string }\n | { kind: \"tool-call\"; id: string; name: string; input: unknown }\n | { kind: \"tool-result\"; id: string; output: string; isError: boolean }\n | { kind: \"usage\"; usage: RunUsage; costUsd: number | null }\n | { kind: \"notice\"; id: string; level: \"info\" | \"warning\"; text: string }\n | { kind: \"error\"; id: string; text: string };\n\nexport interface TitleStatus {\n owner: boolean;\n pending: boolean;\n problem: string | null;\n}\n\n/** Everything the engine pushes to a listener. */\nexport type CodingEvent =\n | { type: \"session\"; session: CodingSession }\n | { type: \"run\"; run: RunRecord }\n | { type: \"preferences\"; preferences: Record<string, ChatPreference> }\n /** The apps' titles changed (or finished loading): re-read the discovered chats. */\n | { type: \"titles\" }\n | {\n type: \"item\";\n sessionId: string;\n runId: string;\n /** Monotonic per session; a history read reports the last `seq` it includes. */\n seq: number;\n item: TranscriptItem;\n };\n\n/** A transcript read back from the provider's own file. */\nexport interface SessionHistory {\n items: TranscriptItem[];\n /** True when the file was larger than the read budget and only its end was read. */\n truncated: boolean;\n /** Plain-English reason when history could not be read (never thrown at the UI). */\n unavailable: string | null;\n /** The last live item `seq` this read already contains; apply only newer ones. */\n seq: number;\n}\n\nexport interface StartInput {\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model?: string | null | undefined;\n effort?: string | null | undefined;\n /** An AI Matrx agent to load into the CLI. Needs the host's `agents` credentials. */\n agent?: AgentSelection | null | undefined;\n}\n\n/** Which AI Matrx agent a new session loads, and the person's variable values. */\nexport interface AgentSelection {\n agentId: string;\n /** Pin one saved version; omitted = the latest, pinned at start. */\n versionId?: string | null | undefined;\n variables?: Record<string, JsonValue> | undefined;\n}\n\n/** One part of an agent and whether this session's CLI carries it. */\nexport interface SessionAgentPart {\n part: \"instructions\" | \"skills\" | \"tools\";\n loaded: number;\n total: number;\n}\n\n/**\n * The agent a session runs with. Recorded at start and never drifts: every\n * later turn reloads the SAME bundle (same version, same hash).\n */\nexport interface SessionAgent {\n agentId: string;\n versionId: string | null;\n versionNumber: number | null;\n name: string;\n definitionHash: string;\n loaded: SessionAgentPart[];\n /** What could not be carried, with the reason. */\n unavailable: { kind: string; name: string; reason: string }[];\n /** The skills it carries (labels) and the tools it serves (names) — the agent's own set. */\n skills?: string[] | undefined;\n tools?: string[] | undefined;\n /** The person's variable values, kept so \"Update to vN\" can reuse them. */\n variables?: Record<string, JsonValue> | undefined;\n /**\n * The CLI must be TOLD in the next prompt (a delimited block): a Codex\n * takeover or agent switch (Codex ignores developer_instructions on resume),\n * or a Codex compaction that dropped the block. Cleared once delivered.\n */\n blockDue?: boolean | undefined;\n /** When the block (or native instructions) last reached the CLI. */\n deliveredAt?: string | null | undefined;\n /** The agent this one replaced mid-chat (\"Code Reviewer v1\"), named in the block. */\n replaces?: string | null | undefined;\n}\n\n/** Whether this host can reach AI Matrx as a signed-in person. */\nexport interface AgentAccess {\n signedIn: boolean;\n userId: string | null;\n organizationId: string | null;\n /** True when the host was started with no AI Matrx connection at all. */\n configured: boolean;\n}\n\n/** A catalogue read the picker asks the host to make (PostgREST RPC shape). */\nexport interface AgentCatalogRpcRequest {\n fn: string;\n args?: Record<string, unknown> | undefined;\n count?: \"exact\" | \"planned\" | \"estimated\" | undefined;\n range?: [number, number] | undefined;\n order?: { column: string; ascending?: boolean | undefined } | undefined;\n}\n\nexport interface AgentCatalogRpcResult {\n data: unknown;\n error: {\n message: string;\n code?: string | undefined;\n details?: string | null | undefined;\n hint?: string | null | undefined;\n } | null;\n count?: number | null;\n}\n\n/** What a picker needs about one agent — the LIGHT read (no skills, no tools). */\nexport interface AgentDetails {\n agentId: string;\n name: string;\n /** Variable declarations as authored (camelCase). */\n variables: Record<string, JsonValue>[];\n /** Newest first. */\n versions: { id: string; versionNumber: number; changedAt: string | null }[];\n /** The version \"Latest\" resolves to right now. */\n latestVersionNumber: number | null;\n latestVersionId: string | null;\n}\n\nexport interface TakeoverInput {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string;\n title?: string | undefined;\n /** Continue the chat WITH an AI Matrx agent (\"Continue with agent\"). */\n agent?: AgentSelection | null | undefined;\n}\n\nexport interface SendResult {\n session: CodingSession;\n /** The run that started, or null when the prompt was queued behind a live run. */\n run: RunRecord | null;\n queued: boolean;\n}\n\nexport interface FolderCheck {\n /** The absolute path the check resolved. */\n path: string;\n exists: boolean;\n /** False when something that is NOT a folder sits at the path. */\n isDirectory: boolean;\n}\n\n/** A folder the New session flow offers (from discovered and driven sessions). */\nexport interface RecentFolder {\n path: string;\n lastUsedAt: string;\n exists: boolean;\n}\n\n/**\n * THE ENGINE CONTRACT — what the UI can ask for, independent of transport.\n * The WebSocket host implements it over the wire; a desktop app implements it\n * over IPC; the UI never knows which.\n */\nexport interface CodingSessionsApi {\n providers(): Promise<ProviderStatus[]>;\n discoverSessions(options?: { limit?: number }): Promise<DiscoveredSession[]>;\n /** Where the apps' own titles stand: an owner supplies them (`owner`), still loading, or failing (`problem`, shown with Retry). */\n titleStatus(): Promise<TitleStatus>;\n /** Ask the owner of the apps' titles again (the Retry). */\n retryTitles(): Promise<void>;\n recentFolders(): Promise<RecentFolder[]>;\n listSessions(): Promise<CodingSession[]>;\n listRuns(sessionId: string): Promise<RunRecord[]>;\n /** `maxBytes` reads more of a long chat's file (\"Show earlier\"). */\n history(sessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /** Read-only transcript of a chat found on disk, before taking it over. */\n readTranscript(provider: CodingProvider, providerSessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /**\n * FULL DOWNLOAD: the provider's own complete transcript file for this chat,\n * byte for byte (every tool input and output). AI Matrx's cloud keeps only\n * text and tool names, so this computer is the first place the full file\n * lives. `available: false` carries the sentence saying why.\n */\n readRawTranscript(provider: CodingProvider, providerSessionId: string): Promise<RawTranscript>;\n /** Does this folder exist here? `~` is the person's home. */\n checkFolder(path: string): Promise<FolderCheck>;\n /** Create a folder (and any missing parents), then report on it. */\n createFolder(path: string): Promise<FolderCheck>;\n /** Fresh check: is this chat live somewhere else right now? null when not. */\n sessionActivity(provider: CodingProvider, providerSessionId: string): Promise<ActiveElsewhere | null>;\n start(input: StartInput): Promise<SendResult>;\n takeover(input: TakeoverInput): Promise<CodingSession>;\n send(sessionId: string, prompt: string): Promise<SendResult>;\n stop(runId: string): Promise<RunRecord | null>;\n /** The person's renames, pins and hides, by `chatKey()`. */\n chatPreferences(): Promise<Record<string, ChatPreference>>;\n /** Merge a change into one chat's preference; `null` fields clear. Returns them all. */\n setChatPreference(key: string, patch: ChatPreference): Promise<Record<string, ChatPreference>>;\n /** Find chats by title and by what was said in them, newest first, within a time budget. */\n searchChats(query: string, options?: { cursor?: number; limit?: number }): Promise<ChatSearchResult>;\n /** Open a folder in Finder, VS Code, Cursor or Terminal. */\n openFolder(path: string, target: OpenTarget): Promise<void>;\n /** Change the model or effort the NEXT run of a session uses. */\n setSessionOptions(sessionId: string, options: { model?: string | null; effort?: string | null }): Promise<CodingSession>;\n /** Is this host signed in to AI Matrx (so agents can load)? */\n agentAccess(): Promise<AgentAccess>;\n /** One allowlisted agent-catalogue read, made by the host as the signed-in person. */\n agentCatalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;\n /** An agent's variables and saved versions, for the New session form. */\n agentDetails(agentId: string): Promise<AgentDetails>;\n /**\n * Load a different agent into a session from its next message on (or\n * remove it, with `null`). Claude reads it every turn; Codex is told in the\n * next prompt.\n */\n setAgent(sessionId: string, agent: AgentSelection | null): Promise<CodingSession>;\n}\n\nexport type RawTranscript =\n | { available: true; fileName: string; bytes: number; content: string }\n | { available: false; reason: string };\n\nexport interface HistoryOptions {\n /** Read up to this many bytes from the end of the file (default 24 MB). */\n maxBytes?: number | undefined;\n}\n\nexport type CodingSessionsMethod = keyof CodingSessionsApi;\n\n/** The transport the UI talks through (WebSocket, IPC, in-process). */\nexport interface CodingSessionsTransport {\n call<M extends CodingSessionsMethod>(\n method: M,\n ...args: Parameters<CodingSessionsApi[M]>\n ): ReturnType<CodingSessionsApi[M]>;\n subscribe(listener: (event: CodingEvent) => void): () => void;\n /** Connection state, for an honest banner. */\n status(): TransportStatus;\n onStatus(listener: (status: TransportStatus) => void): () => void;\n}\n\nexport type TransportStatus =\n | { state: \"connecting\" }\n | { state: \"open\" }\n | { state: \"closed\"; reason: string };\n","/**\n * USAGE LIMITS AND EXPIRED SIGN-INS, in plain English.\n *\n * A provider can be installed and signed in and still unable to run: the\n * ChatGPT or Claude plan hit its usage limit, or the saved login expired.\n * Runs report that in the provider's own words; this turns those words into\n * a remembered, honest status. Built from the real texts captured on\n * 2026-09-27 (Codex usage limit, Codex refresh failure).\n */\n\nimport { PROVIDER_LABEL, type CodingProvider, type ProviderProblem, type QuotaWindow } from \"./types\";\n\nconst USAGE_LIMIT = [\n /hit your usage limit/i,\n /usage limit (?:reached|exceeded)/i,\n /\\blimit reached\\b/i,\n /you'?ve hit your limit/i,\n /rate limit/i,\n /quota (?:exceeded|exhausted)/i,\n /purchase more credits/i,\n];\n\nconst SIGNED_OUT = [\n /access token could not be refreshed/i,\n /please sign in again/i,\n /(?:not|no longer) (?:logged|signed) in/i,\n /please run \\/login/i,\n /invalid api key/i,\n /oauth token (?:has )?expired/i,\n /authentication_error/i,\n /401 unauthorized/i,\n];\n\n/** \"Oct 4th, 2026 8:34 AM\" → ISO. null when the phrase is not a date. */\nexport function parseLimitDate(phrase: string): string | null {\n const cleaned = phrase.replace(/(\\d{1,2})(st|nd|rd|th)\\b/gi, \"$1\").replace(/[.,]\\s*$/, \"\").trim();\n const ms = Date.parse(cleaned);\n return Number.isNaN(ms) ? null : new Date(ms).toISOString();\n}\n\nfunction limitPhrase(text: string): string | null {\n const match =\n /try again (?:at|after|on) ([^\\n]+?)(?:\\.\\s|\\.$|$)/i.exec(text) ??\n /resets? (?:at |on )?([^\\n∙·|]+?)(?:\\.\\s|\\.$|$|\\s*[∙·|])/i.exec(text);\n return match?.[1]?.trim() ?? null;\n}\n\nexport function classifyProviderError(text: string, at = new Date().toISOString()): ProviderProblem | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n if (SIGNED_OUT.some((re) => re.test(trimmed))) {\n return { kind: \"signed-out\", message: trimmed, until: null, at };\n }\n if (USAGE_LIMIT.some((re) => re.test(trimmed))) {\n const phrase = limitPhrase(trimmed);\n return { kind: \"usage-limit\", message: trimmed, until: phrase ? (parseLimitDate(phrase) ?? phrase) : null, at };\n }\n return null;\n}\n\n/** A usage limit whose reset time has passed no longer applies. */\nexport function problemStillApplies(problem: ProviderProblem, now = Date.now()): boolean {\n if (problem.kind !== \"usage-limit\" || !problem.until) return true;\n const ms = Date.parse(problem.until);\n return Number.isNaN(ms) || ms > now;\n}\n\nexport function formatUntil(until: string | null): string | null {\n if (!until) return null;\n const ms = Date.parse(until);\n if (Number.isNaN(ms)) return until;\n return new Date(ms).toLocaleString(undefined, { month: \"short\", day: \"numeric\", hour: \"numeric\", minute: \"2-digit\" });\n}\n\n/** A full quota window (100% used) is a usage limit even before a run hits it. */\nexport function problemFromQuota(windows: readonly QuotaWindow[], at = new Date().toISOString()): ProviderProblem | null {\n const full = windows.find((w) => typeof w.usedPercent === \"number\" && w.usedPercent >= 100);\n if (!full) return null;\n return {\n kind: \"usage-limit\",\n message: `${full.label} is used up.`,\n until: full.resetsAt,\n at,\n };\n}\n\nexport function describeProblem(provider: CodingProvider, problem: ProviderProblem): { problem: string; fix: string } {\n const label = PROVIDER_LABEL[provider];\n if (problem.kind === \"signed-out\") {\n return {\n problem: `${label} — sign-in expired.`,\n fix: `Open ${label} and sign in again, then check again.`,\n };\n }\n const until = formatUntil(problem.until);\n return {\n problem: until ? `${label} — usage limit reached until ${until}.` : `${label} — usage limit reached.`,\n fix: until\n ? `It lifts on its own then, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`\n : `Wait for it to reset, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`,\n };\n}\n\n/**\n * A run refused because the CHOSEN MODEL is not available — to this account,\n * or to this version of the CLI. It is about the model, not the provider, so\n * the screen offers the model picker rather than a provider-wide warning.\n * Built from the real Codex text captured 2026-10-01\n * (fixtures/codex-model-unsupported.error.txt) and Claude Code's wording.\n */\nconst MODEL_UNAVAILABLE = [\n /model is not supported when using codex/i,\n /\\bmodel[\\s:'\"`][^.\\n]{0,80}\\b(?:not supported|does not exist|not available|not found)\\b/i,\n /\\bmodel_not_found\\b/i,\n /issue with the selected model/i,\n /may not exist or you may not have access to it/i,\n];\n\nexport const MODEL_UNAVAILABLE_LABEL = \"Model not available on this account\";\n\nexport function isModelUnavailable(text: string | null | undefined): boolean {\n const trimmed = (text ?? \"\").trim();\n return trimmed !== \"\" && MODEL_UNAVAILABLE.some((re) => re.test(trimmed));\n}\n\n/** What the screen says for a failed run: a short label for a known class, else the text itself. */\nexport function runErrorLabel(text: string): string {\n return isModelUnavailable(text) ? MODEL_UNAVAILABLE_LABEL : text;\n}\n","/**\n * WHICH `codex` / `claude` RUNS — the newest one on this computer.\n *\n * A person often has several copies: the CLI on PATH (Homebrew, npm, the\n * native installer) and the one bundled inside the desktop app (ChatGPT ships\n * Codex; Claude ships Claude Code). They drift. On 2026-10-01 the PATH Codex\n * was 0.157.1 while ChatGPT's bundled one was 0.159.2, and only the newer one\n * accepted the model the person had configured — the old one answered every\n * run with \"model is not supported\". So every candidate is collected, each\n * one's version read, and the highest wins.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { accessSync, constants as fsConstants, readdirSync, readFileSync, realpathSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport type { BinarySource, CodingProvider, ProviderBinary } from \"../types\";\n\nexport interface BinaryCandidate {\n path: string;\n source: BinarySource;\n version: string | null;\n}\n\nexport interface DiscoveryOptions {\n env: NodeJS.ProcessEnv;\n platform?: NodeJS.Platform;\n home?: string;\n /** Where desktop apps live. Default `/Applications` and `~/Applications`. */\n applications?: string[];\n}\n\nconst SOURCE_LABEL: Record<CodingProvider, Record<BinarySource, string>> = {\n codex: { \"desktop-app\": \"from ChatGPT app\", path: \"from PATH\", \"npm-global\": \"from npm\", configured: \"set by host\" },\n claude: { \"desktop-app\": \"from Claude app\", path: \"from PATH\", \"npm-global\": \"from npm\", configured: \"set by host\" },\n};\n\nexport function sourceLabel(provider: CodingProvider, source: BinarySource): string {\n return SOURCE_LABEL[provider][source];\n}\n\n/** \"codex-cli 0.159.2\" / \"2.1.284 (Claude Code)\" → \"0.159.2\". */\nexport function parseVersion(text: string | null | undefined): string | null {\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)(?:[-.][0-9A-Za-z.]+)?/.exec(text ?? \"\");\n return match ? match[0] : null;\n}\n\n/** Numeric compare of the dotted parts; a pre-release sorts below its release. */\nexport function compareVersions(a: string, b: string): number {\n const [aCore = \"\", aPre] = a.split(\"-\", 2);\n const [bCore = \"\", bPre] = b.split(\"-\", 2);\n const pa = aCore.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n const pb = bCore.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (d !== 0) return d < 0 ? -1 : 1;\n }\n if (aPre && !bPre) return -1;\n if (!aPre && bPre) return 1;\n return 0;\n}\n\n/**\n * The highest version wins. A candidate whose version could not be read ranks\n * below every readable one; ties keep the earlier candidate (desktop app,\n * then PATH order, then npm).\n */\nexport function pickBinary<T extends BinaryCandidate>(candidates: readonly T[]): T | null {\n let best: T | null = null;\n for (const c of candidates) {\n if (!best) {\n best = c;\n continue;\n }\n if (c.version && (!best.version || compareVersions(c.version, best.version) > 0)) best = c;\n }\n return best;\n}\n\nfunction executable(file: string): boolean {\n try {\n accessSync(file, fsConstants.X_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction exeName(name: string, platform: NodeJS.Platform): string[] {\n return platform === \"win32\" ? [`${name}.exe`, `${name}.cmd`, name] : [name];\n}\n\n/** Every executable `name` on PATH, in PATH order (`which -a`). */\nexport function allOnPath(name: string, pathValue: string, platform: NodeJS.Platform = process.platform): string[] {\n const found: string[] = [];\n for (const dir of pathValue.split(path.delimiter)) {\n if (!dir) continue;\n for (const file of exeName(name, platform)) {\n const candidate = path.join(dir, file);\n if (executable(candidate)) {\n found.push(candidate);\n break;\n }\n }\n }\n return found;\n}\n\nfunction desktopAppCandidates(\n provider: CodingProvider,\n platform: NodeJS.Platform,\n home: string,\n applications: string[],\n): string[] {\n if (platform !== \"darwin\") return [];\n if (provider === \"codex\") {\n return applications.map((apps) =>\n path.join(apps, \"ChatGPT.app\", \"Contents\", \"Resources\", \"codex-cli\", \"bin\", \"codex\"),\n );\n }\n // Claude's desktop app keeps each Claude Code it has downloaded in its own\n // version folder.\n const root = path.join(home, \"Library\", \"Application Support\", \"Claude\", \"claude-code\");\n let versions: string[] = [];\n try {\n versions = readdirSync(root);\n } catch {\n return [];\n }\n return versions.map((v) => path.join(root, v, \"claude.app\", \"Contents\", \"MacOS\", \"claude\"));\n}\n\nfunction npmGlobalPrefix(env: NodeJS.ProcessEnv): Promise<string | null> {\n const fromEnv = env.npm_config_prefix ?? env.NPM_CONFIG_PREFIX;\n if (fromEnv) return Promise.resolve(fromEnv);\n const npm = allOnPath(\"npm\", env.PATH ?? \"\")[0];\n if (!npm) return Promise.resolve(null);\n return new Promise((resolve) => {\n const child = execFile(npm, [\"prefix\", \"-g\"], { timeout: 5000, env }, (error, stdout) => {\n resolve(error ? null : String(stdout).trim() || null);\n });\n child.stdin?.end();\n });\n}\n\n/** The version a bundled copy declares on disk, without running it. */\nfunction declaredVersion(provider: CodingProvider, source: BinarySource, file: string): string | null {\n if (source !== \"desktop-app\") return null;\n if (provider === \"codex\") {\n try {\n const pkg = JSON.parse(readFileSync(path.join(path.dirname(path.dirname(file)), \"codex-package.json\"), \"utf8\")) as {\n version?: unknown;\n };\n return typeof pkg.version === \"string\" ? parseVersion(pkg.version) : null;\n } catch {\n return null;\n }\n }\n // …/claude-code/<version>/claude.app/Contents/MacOS/claude\n return parseVersion(path.basename(path.resolve(file, \"..\", \"..\", \"..\", \"..\")));\n}\n\n/** `<cli> --version`, stdin closed (Codex waits on an open one). */\nexport function runVersion(file: string, env: NodeJS.ProcessEnv): Promise<string | null> {\n return new Promise((resolve) => {\n const child = execFile(file, [\"--version\"], { timeout: 8000, env }, (error, stdout) => {\n resolve(error ? null : parseVersion(String(stdout)));\n });\n child.stdin?.end();\n });\n}\n\n/** Every copy of the CLI on this computer, deduplicated by real path. */\nexport async function discoverBinaries(provider: CodingProvider, options: DiscoveryOptions): Promise<BinaryCandidate[]> {\n const platform = options.platform ?? process.platform;\n const home = options.home ?? options.env.HOME ?? os.homedir();\n const listed: { path: string; source: BinarySource }[] = [\n ...desktopAppCandidates(provider, platform, home, options.applications ?? [\"/Applications\", path.join(home, \"Applications\")]).filter(executable).map((p) => ({ path: p, source: \"desktop-app\" as const })),\n ...allOnPath(provider, options.env.PATH ?? \"\", platform).map((p) => ({ path: p, source: \"path\" as const })),\n ];\n const prefix = await npmGlobalPrefix(options.env);\n if (prefix) {\n const dir = platform === \"win32\" ? prefix : path.join(prefix, \"bin\");\n for (const file of exeName(provider, platform)) {\n const candidate = path.join(dir, file);\n if (executable(candidate)) {\n listed.push({ path: candidate, source: \"npm-global\" });\n break;\n }\n }\n }\n const seen = new Set<string>();\n const unique = listed.filter((c) => {\n let real = c.path;\n try {\n real = realpathSync(c.path);\n } catch {\n /* keep the listed path */\n }\n if (seen.has(real)) return false;\n seen.add(real);\n return true;\n });\n return Promise.all(\n unique.map(async (c) => ({\n ...c,\n version: declaredVersion(provider, c.source, c.path) ?? (await runVersion(c.path, options.env)),\n })),\n );\n}\n\n/**\n * The binary runs use. `forced` (the host's `commands` option) always wins,\n * but a newer copy elsewhere is still reported as `newer`.\n */\nexport async function resolveBinary(\n provider: CodingProvider,\n options: DiscoveryOptions & { forced?: string | null | undefined; discover?: boolean },\n): Promise<ProviderBinary | null> {\n const candidates = options.discover === false ? [] : await discoverBinaries(provider, options);\n const best = pickBinary(candidates);\n const inUse: BinaryCandidate | null = options.forced\n ? {\n path: options.forced,\n source: \"configured\",\n version:\n candidates.find((c) => c.path === options.forced)?.version ??\n (options.discover === false ? null : await runVersion(options.forced, options.env)),\n }\n : best;\n if (!inUse) return null;\n const newer =\n best && best.path !== inUse.path && best.version && (!inUse.version || compareVersions(best.version, inUse.version) > 0)\n ? { path: best.path, version: best.version, sourceLabel: sourceLabel(provider, best.source) }\n : null;\n return {\n path: inUse.path,\n version: inUse.version,\n source: inUse.source,\n sourceLabel: sourceLabel(provider, inUse.source),\n newer,\n };\n}\n","/**\n * THE CLEAN ENVIRONMENT — built from an ALLOWLIST, never a denylist.\n *\n * The process that hosts this package is often itself running inside a Claude\n * Code or Codex session. Those sessions export variables (`CLAUDE_CODE_*`,\n * `CLAUDECODE`, `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `CODEX_*`,\n * `OTEL_*`, `GIT_EDITOR`, …) that make a child CLI talk to the wrong endpoint,\n * bill the wrong account, or believe it is a sub-agent. A denylist is always one\n * variable behind the next CLI release; an allowlist cannot be. The spike ran\n * under `env -i` for this reason, and this is that guarantee in code.\n *\n * API keys are deliberately NOT allowed through: the whole point is the user's\n * own subscription login. A host that truly wants API billing passes a key in\n * `extra` on purpose, and `providers()` then reports \"API\" honestly.\n */\n\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n/** Exact names that pass through. */\nconst ALLOWED_NAMES = new Set([\n \"HOME\",\n \"USER\",\n \"LOGNAME\",\n \"SHELL\",\n \"TMPDIR\",\n \"LANG\",\n \"TZ\",\n \"SSH_AUTH_SOCK\",\n \"HTTP_PROXY\",\n \"HTTPS_PROXY\",\n \"NO_PROXY\",\n \"http_proxy\",\n \"https_proxy\",\n \"no_proxy\",\n \"SSL_CERT_FILE\",\n \"NODE_EXTRA_CA_CERTS\",\n]);\n\n/** Prefixes that pass through (locale only). */\nconst ALLOWED_PREFIXES = [\"LC_\"];\n\n/**\n * Where the CLIs are commonly installed. A host launched from a GUI or a\n * launchd agent often has a bare PATH; without these the CLIs look\n * \"not installed\" when they are.\n */\nfunction wellKnownBinDirs(home: string): string[] {\n return [\n path.join(home, \".local\", \"bin\"),\n path.join(home, \".claude\", \"local\"),\n path.join(home, \".npm-global\", \"bin\"),\n path.join(home, \".bun\", \"bin\"),\n path.join(home, \".volta\", \"bin\"),\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\",\n \"/usr/bin\",\n \"/bin\",\n \"/usr/sbin\",\n \"/sbin\",\n ];\n}\n\nexport function isAllowedEnvName(name: string): boolean {\n return ALLOWED_NAMES.has(name) || ALLOWED_PREFIXES.some((prefix) => name.startsWith(prefix));\n}\n\n/**\n * Build the environment for a driver worker (and therefore for the CLI it\n * launches) from the host's environment.\n */\nexport function buildCleanEnv(\n hostEnv: NodeJS.ProcessEnv,\n extra: Record<string, string> = {},\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, value] of Object.entries(hostEnv)) {\n if (typeof value !== \"string\") continue;\n if (isAllowedEnvName(name)) out[name] = value;\n }\n const home = out.HOME ?? os.homedir();\n out.HOME = home;\n const hostPath = (hostEnv.PATH ?? \"\").split(path.delimiter).filter(Boolean);\n const merged: string[] = [];\n for (const dir of [...hostPath, ...wellKnownBinDirs(home)]) {\n if (!merged.includes(dir)) merged.push(dir);\n }\n out.PATH = merged.join(path.delimiter);\n for (const [name, value] of Object.entries(extra)) out[name] = value;\n return out;\n}\n","/**\n * Reading the providers' OWN files — cheaply, and never copying them.\n *\n * A heavy user has tens of gigabytes here (this Mac: 38 GB of Codex rollouts\n * across ~6,800 files, 18 GB of Claude sessions across ~1,900). Discovery\n * therefore stats every file (cheap) but READS only the head and tail of the\n * few newest, and a transcript read is capped with the cap announced.\n */\n\nimport { createReadStream } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexRolloutNormalizer } from \"../normalize/codex\";\nimport { claudeTranscriptTitleSources, resolveSessionTitle } from \"../sessions/titles\";\nimport { parseJsonl } from \"../normalize/lines\";\nimport { describeActivity, listProcesses, type ProcessRow } from \"./activity\";\nimport type {\n ActiveElsewhere,\n CodingProvider,\n DiscoveredSession,\n SessionHistory,\n TranscriptItem,\n} from \"../types\";\n\nexport interface CodexHome {\n /** `<CODEX_HOME>/sessions` (dated folders of rollouts). */\n sessions: string;\n /** `<CODEX_HOME>/archived_sessions` (rollouts Codex archived; flat). */\n archived: string;\n /** `<CODEX_HOME>/session_index.jsonl` (the app's thread names). */\n index: string;\n}\n\nexport interface ProviderHomes {\n claudeProjects: string;\n /** The claude-accounts holder's copies (`<vault>/<id>/transcript.jsonl`): a held chat's history when its own file is gone. */\n claudeVault?: string | undefined;\n /** Every Codex home to read (main first). The owner of the apps' index names them (Matrx 2: the Codex source's homes). */\n codex: CodexHome[];\n}\n\nexport function codexHome(dir: string): CodexHome {\n return {\n sessions: path.join(dir, \"sessions\"),\n archived: path.join(dir, \"archived_sessions\"),\n index: path.join(dir, \"session_index.jsonl\"),\n };\n}\n\nexport function defaultProviderHomes(home = os.homedir()): ProviderHomes {\n return {\n claudeProjects: path.join(home, \".claude\", \"projects\"),\n claudeVault: path.join(home, \".claude\", \"claude-app-vault\"),\n codex: [codexHome(path.join(home, \".codex\"))],\n };\n}\n\ninterface FileCandidate {\n provider: CodingProvider;\n file: string;\n id: string;\n mtimeMs: number;\n size: number;\n /** A Codex rollout in `archived_sessions/` (Codex archived the chat). */\n archived?: boolean;\n}\n\nconst UUIDISH = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\.jsonl$/i;\n\nasync function safeReaddir(dir: string): Promise<import(\"node:fs\").Dirent[]> {\n try {\n return await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nasync function statCandidate(\n provider: CodingProvider,\n file: string,\n): Promise<FileCandidate | null> {\n const match = UUIDISH.exec(file);\n if (!match?.[1]) return null;\n try {\n const stat = await fs.stat(file);\n return { provider, file, id: match[1], mtimeMs: stat.mtimeMs, size: stat.size };\n } catch {\n return null;\n }\n}\n\nasync function claudeCandidates(root: string): Promise<FileCandidate[]> {\n const out: FileCandidate[] = [];\n for (const project of await safeReaddir(root)) {\n if (!project.isDirectory()) continue;\n const dir = path.join(root, project.name);\n const entries = await safeReaddir(dir);\n const stats = await Promise.all(\n entries\n .filter((e) => e.isFile() && e.name.endsWith(\".jsonl\"))\n .map((e) => statCandidate(\"claude\", path.join(dir, e.name))),\n );\n for (const s of stats) if (s) out.push(s);\n }\n return out;\n}\n\nasync function codexTree(root: string): Promise<FileCandidate[]> {\n const out: FileCandidate[] = [];\n for (const year of await safeReaddir(root)) {\n if (!year.isDirectory()) continue;\n for (const month of await safeReaddir(path.join(root, year.name))) {\n if (!month.isDirectory()) continue;\n for (const day of await safeReaddir(path.join(root, year.name, month.name))) {\n if (!day.isDirectory()) continue;\n out.push(...(await codexFlat(path.join(root, year.name, month.name, day.name), false)));\n }\n }\n }\n return out;\n}\n\nasync function codexFlat(dir: string, archived: boolean): Promise<FileCandidate[]> {\n const entries = await safeReaddir(dir);\n const stats = await Promise.all(\n entries\n .filter((e) => e.isFile() && e.name.startsWith(\"rollout-\") && e.name.endsWith(\".jsonl\"))\n .map((e) => statCandidate(\"codex\", path.join(dir, e.name))),\n );\n return stats.filter((s): s is FileCandidate => s !== null).map((s) => (archived ? { ...s, archived: true } : s));\n}\n\n/** Every Codex rollout in every home, archived ones included (marked). */\nasync function codexCandidates(homes: readonly CodexHome[]): Promise<FileCandidate[]> {\n const lists = await Promise.all(homes.flatMap((h) => [codexTree(h.sessions), codexFlat(h.archived, true)]));\n return lists.flat();\n}\n\n/** Read `length` bytes at `start` as UTF-8. */\nasync function readSlice(file: string, start: number, length: number): Promise<string> {\n const handle = await fs.open(file, \"r\");\n try {\n const buffer = Buffer.alloc(length);\n const { bytesRead } = await handle.read(buffer, 0, length, start);\n return buffer.subarray(0, bytesRead).toString(\"utf8\");\n } finally {\n await handle.close();\n }\n}\n\n/** Complete lines only: drop a partial first line (tail reads) and a partial last line. */\nfunction completeLines(text: string, droppedFirst: boolean): string {\n let body = text;\n if (droppedFirst) {\n const nl = body.indexOf(\"\\n\");\n body = nl >= 0 ? body.slice(nl + 1) : \"\";\n }\n const last = body.lastIndexOf(\"\\n\");\n return last >= 0 ? body.slice(0, last) : body;\n}\n\nconst HEAD_BYTES = 256 * 1024;\nconst TAIL_BYTES = 128 * 1024;\n\n\nasync function describeClaude(candidate: FileCandidate): Promise<DiscoveredSession | null> {\n const head = parseJsonl(completeLines(await readSlice(candidate.file, 0, HEAD_BYTES), false));\n const tailStart = Math.max(0, candidate.size - TAIL_BYTES);\n const tail =\n tailStart > 0\n ? parseJsonl(completeLines(await readSlice(candidate.file, tailStart, TAIL_BYTES), true))\n : head;\n\n let cwd: string | null = null;\n let entrypoint: string | null = null;\n for (const entry of head) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (!cwd && typeof e.cwd === \"string\") cwd = e.cwd;\n if (!entrypoint && typeof e.entrypoint === \"string\") entrypoint = e.entrypoint;\n if (cwd && entrypoint) break;\n }\n // The transcript's own title (the one rule, ./sessions); the app's record title, when the\n // owner of the apps' index knows it, is overlaid by the engine (title hints).\n const resolved = resolveSessionTitle(claudeTranscriptTitleSources(head, tailStart > 0 ? tail : []));\n // A file with no conversation in it (a session that only ran start-up hooks)\n // is not a chat anyone can take over.\n if (!resolved) return null;\n return {\n provider: \"claude\",\n providerSessionId: candidate.id,\n cwd,\n title: resolved.title,\n titleSource: resolved.source,\n updatedAt: new Date(candidate.mtimeMs).toISOString(),\n source: entrypoint,\n activeElsewhere: null,\n };\n}\n\n/** Codex's thread names across homes (`session_index.jsonl`, the app's own names; later homes never override). */\nasync function readCodexIndex(files: readonly string[]): Promise<Map<string, string>> {\n const names = new Map<string, string>();\n for (const file of files) for (const [id, name] of await readCodexIndexFile(file)) if (!names.has(id)) names.set(id, name);\n return names;\n}\n\nasync function readCodexIndexFile(file: string): Promise<Map<string, string>> {\n const names = new Map<string, string>();\n let text: string;\n try {\n const stat = await fs.stat(file);\n const budget = 4 * 1024 * 1024;\n text =\n stat.size <= budget\n ? await fs.readFile(file, \"utf8\")\n : completeLines(await readSlice(file, stat.size - budget, budget), true);\n } catch {\n return names;\n }\n for (const entry of parseJsonl(text)) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (typeof e.id === \"string\" && typeof e.thread_name === \"string\" && e.thread_name.trim()) {\n names.set(e.id, e.thread_name);\n }\n }\n return names;\n}\n\nasync function describeCodex(\n candidate: FileCandidate,\n names: Map<string, string>,\n): Promise<DiscoveredSession | null> {\n const head = parseJsonl(completeLines(await readSlice(candidate.file, 0, HEAD_BYTES), false));\n let cwd: string | null = null;\n let source: string | null = null;\n let isSubAgent = false;\n let firstPrompt: string | null = null;\n const normalizer = createCodexRolloutNormalizer();\n for (const entry of head) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (e.type === \"session_meta\" && typeof e.payload === \"object\" && e.payload !== null) {\n const p = e.payload as Record<string, unknown>;\n cwd = typeof p.cwd === \"string\" ? p.cwd : cwd;\n source = typeof p.source === \"string\" ? p.source : typeof p.originator === \"string\" ? p.originator : null;\n if (typeof p.parent_thread_id === \"string\" && p.parent_thread_id) isSubAgent = true;\n if (p.thread_source === \"subagent\" || p.thread_source === \"sub_agent\") isSubAgent = true;\n }\n if (firstPrompt === null) {\n for (const item of normalizer.push(entry)) {\n if (item.kind === \"user\") {\n firstPrompt = item.text;\n break;\n }\n }\n }\n }\n // A sub-agent thread belongs to its parent conversation; taking it over on\n // its own would answer a question nobody in this chat asked.\n if (isSubAgent) return null;\n const resolved = resolveSessionTitle({ app: names.get(candidate.id), \"first-prompt\": firstPrompt });\n if (!resolved) return null;\n return {\n provider: \"codex\",\n providerSessionId: candidate.id,\n cwd,\n title: resolved.title,\n titleSource: resolved.source,\n ...(candidate.archived ? { archived: true } : {}),\n updatedAt: new Date(candidate.mtimeMs).toISOString(),\n source,\n activeElsewhere: null,\n };\n}\n\nexport interface DiscoverOptions {\n limit?: number | undefined;\n homes?: ProviderHomes | undefined;\n /** Processes that are OUR runs (never \"live elsewhere\"). */\n excludePids?: ReadonlySet<number> | undefined;\n /**\n * The apps' own titles from the owner of their index (`provider:id` → title). Given → the apps'\n * files are not read here at all (Codex thread names come from it); absent → the standalone host\n * reads Codex's `session_index.jsonl` itself.\n */\n appTitles?: ReadonlyMap<string, string> | undefined;\n}\n\n/** Codex thread names: from the owner's titles when it supplied them, else Codex's own index. */\nexport async function codexNames(homes: ProviderHomes, appTitles: ReadonlyMap<string, string> | undefined): Promise<Map<string, string>> {\n if (!appTitles) return readCodexIndex(homes.codex.map((h) => h.index));\n const out = new Map<string, string>();\n for (const [key, title] of appTitles) if (key.startsWith(\"codex:\")) out.set(key.slice(6), title);\n return out;\n}\n\nasync function readTail(file: string, size: number): Promise<unknown[]> {\n const start = Math.max(0, size - TAIL_BYTES);\n return parseJsonl(completeLines(await readSlice(file, start, Math.min(size, TAIL_BYTES)), start > 0));\n}\n\nasync function activityFor(\n candidate: FileCandidate,\n processes: readonly ProcessRow[],\n excludePids: ReadonlySet<number> | undefined,\n ownWritesUntilMs?: number | undefined,\n): Promise<ActiveElsewhere | null> {\n return describeActivity({\n ownWritesUntilMs,\n provider: candidate.provider,\n providerSessionId: candidate.id,\n mtimeMs: candidate.mtimeMs,\n now: Date.now(),\n processes,\n excludePids,\n tail: () => readTail(candidate.file, candidate.size).catch(() => []),\n });\n}\n\n/** Fresh \"is it live elsewhere?\" for one session (the preview and the takeover confirm). */\nexport async function sessionActivity(\n provider: CodingProvider,\n providerSessionId: string,\n options: {\n homes?: ProviderHomes | undefined;\n excludePids?: ReadonlySet<number> | undefined;\n ownWritesUntilMs?: number | undefined;\n } = {},\n): Promise<ActiveElsewhere | null> {\n const file = await findSessionFile(provider, providerSessionId, options.homes);\n const processes = await listProcesses();\n if (!file) {\n return describeActivity({\n provider,\n providerSessionId,\n mtimeMs: 0,\n now: Date.now(),\n processes,\n excludePids: options.excludePids,\n tail: async () => [],\n });\n }\n const candidate = await statCandidate(provider, file);\n if (!candidate) return null;\n return activityFor(candidate, processes, options.excludePids, options.ownWritesUntilMs);\n}\n\n/** Recent existing local Claude Code and Codex chats, newest first (metadata only). */\nexport async function discoverLocalSessions(options: DiscoverOptions = {}): Promise<DiscoveredSession[]> {\n const limit = options.limit ?? 60;\n const homes = options.homes ?? defaultProviderHomes();\n const [claude, codex, names] = await Promise.all([\n claudeCandidates(homes.claudeProjects),\n codexCandidates(homes.codex),\n codexNames(homes, options.appTitles),\n ]);\n const candidates = [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);\n const processes = await listProcesses();\n const out: DiscoveredSession[] = [];\n // Describe in small batches, newest first, until the page is full.\n for (let i = 0; i < candidates.length && out.length < limit; i += 12) {\n const batch = candidates.slice(i, i + 12);\n const described = await Promise.all(\n batch.map(async (c) => {\n const d = await (c.provider === \"claude\" ? describeClaude(c) : describeCodex(c, names)).catch(() => null);\n if (!d) return null;\n return { ...d, activeElsewhere: await activityFor(c, processes, options.excludePids).catch(() => null) };\n }),\n );\n for (const d of described) if (d && out.length < limit) out.push(d);\n }\n return out;\n}\n\n/** Where a provider keeps one session's transcript, or null when it has none on disk. */\nexport async function findSessionFile(\n provider: CodingProvider,\n providerSessionId: string,\n homes: ProviderHomes = defaultProviderHomes(),\n): Promise<string | null> {\n if (!/^[0-9a-f-]{36}$/i.test(providerSessionId)) return null;\n const candidates =\n provider === \"claude\"\n ? await claudeCandidates(homes.claudeProjects)\n : await codexCandidates(homes.codex);\n const hits = candidates.filter((c) => c.id === providerSessionId).sort((a, b) => b.mtimeMs - a.mtimeMs);\n if (hits[0]) return hits[0].file;\n // A held chat whose own file is gone: the holder's copy is its history.\n if (provider === \"claude\" && homes.claudeVault) {\n const copy = path.join(homes.claudeVault, providerSessionId, \"transcript.jsonl\");\n if ((await fs.stat(copy).catch(() => null))?.isFile()) return copy;\n }\n return null;\n}\n\nexport const HISTORY_BUDGET = 24 * 1024 * 1024;\n/** \"Show earlier\" never reads more than this at once. */\nexport const MAX_HISTORY_BUDGET = 256 * 1024 * 1024;\n\n/**\n * Read a transcript from the provider's own file, up to `endOffset` bytes (the\n * file's size when a run started, so a live run's lines are not read twice).\n */\nexport async function readSessionFile(\n provider: CodingProvider,\n file: string,\n endOffset?: number | undefined,\n maxBytes: number = HISTORY_BUDGET,\n): Promise<SessionHistory> {\n let size: number;\n try {\n size = (await fs.stat(file)).size;\n } catch {\n return {\n items: [],\n truncated: false,\n unavailable: \"The saved transcript for this chat could not be found on this computer.\",\n seq: 0,\n };\n }\n const end = Math.min(size, endOffset ?? size);\n const start = Math.max(0, end - Math.max(1024 * 1024, Math.min(maxBytes, MAX_HISTORY_BUDGET)));\n const items: TranscriptItem[] = [];\n const normalizer = provider === \"claude\" ? createClaudeNormalizer() : createCodexRolloutNormalizer();\n let droppedFirst = start > 0;\n let carry = \"\";\n await new Promise<void>((resolve, reject) => {\n const stream = createReadStream(file, { start, end: Math.max(start, end - 1), encoding: \"utf8\" });\n stream.on(\"data\", (chunk) => {\n const text = carry + String(chunk);\n const lines = text.split(\"\\n\");\n carry = lines.pop() ?? \"\";\n if (droppedFirst) {\n lines.shift();\n droppedFirst = false;\n }\n for (const value of parseJsonl(lines.join(\"\\n\"))) items.push(...normalizer.push(value));\n });\n stream.on(\"end\", () => {\n for (const value of parseJsonl(carry)) items.push(...normalizer.push(value));\n resolve();\n });\n stream.on(\"error\", reject);\n });\n // Live-only kinds never come from a saved file; usage is per run, not history.\n return {\n items: items.filter((item) => item.kind !== \"usage\" && item.kind !== \"text-delta\"),\n truncated: start > 0,\n unavailable: null,\n seq: 0,\n };\n}\n\n/** Every session file on this computer, newest first (a stat each; nothing read). */\nexport async function listSessionFiles(homes: ProviderHomes = defaultProviderHomes()): Promise<FileCandidate[]> {\n const [claude, codex] = await Promise.all([\n claudeCandidates(homes.claudeProjects),\n codexCandidates(homes.codex),\n ]);\n return [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);\n}\n\n/** Title, folder and time for one file (null for sub-agent and hook-only files). */\nexport async function describeSessionFile(\n candidate: FileCandidate,\n codexNames: Map<string, string>,\n): Promise<DiscoveredSession | null> {\n return (candidate.provider === \"claude\" ? describeClaude(candidate) : describeCodex(candidate, codexNames)).catch(\n () => null,\n );\n}\n\nexport { readCodexIndex };\nexport type { FileCandidate };\n","/**\n * THE ONE TITLE RULE for a coding chat, shared by every reader (Matrx 2's Coding Sessions and\n * Code › Chats, the standalone host, search). Pure: no file access, browser-safe.\n *\n * What a chat is called is what the person sees in the coding app, so the app's own record leads;\n * the CLI's transcript entries fill in for chats the app never listed. The person's rename inside\n * Matrx sits on top and is applied ONCE, by whoever draws the row (never baked into the engine's\n * own `title`). Plan: common-docs/projects/matrx-2/apps-chats.md §12.\n */\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\n\n/** Every title is cut to this (the app tables' rule); the screen truncates further visually. */\nexport const TITLE_MAX = 300;\n/** What a row shows when no source has a title. */\nexport const UNTITLED = \"(untitled)\";\n\n/**\n * The name the AI Matrx coding-session bridge used to stamp on every mirrored Claude Code prompt\n * (`sessionTitle` from its UserPromptSubmit hook; stopped at the source 2026-10-06, still inside\n * old transcripts as `custom-title` / `agent-name` entries). Never a chat's title.\n */\nexport const BRIDGE_PLACEHOLDER = /^AI Matrx · [a-z-]+$/;\n\n/** Where a title came from, strongest first. */\nexport const TITLE_PRECEDENCE = [\n /** The person's rename inside Matrx (Coding Sessions' preference). */\n \"override\",\n /** What the coding app's own sidebar shows: Claude's record `title` (renames included); Codex's thread name; Cursor's name. */\n \"app\",\n /** The title the app last showed, remembered by the claude-accounts engine after the record went away. */\n \"app-remembered\",\n /** Claude Code transcript entries (the last one of each kind that is not the bridge placeholder). */\n \"custom-title\",\n \"ai-title\",\n \"agent-name\",\n \"summary\",\n /** The person's first typed message (Codex: the thread's title / first user message). */\n \"first-prompt\",\n \"last-prompt\",\n] as const;\n\nexport type TitleSource = (typeof TITLE_PRECEDENCE)[number];\n\n/** Whatever each source says; absent, null and blank all mean \"no title here\". */\nexport type TitleSources = Partial<Record<TitleSource, string | null | undefined>>;\n\nexport interface ResolvedTitle {\n title: string;\n source: TitleSource;\n}\n\n/** Transcript-only sources the bridge placeholder can poison. */\nconst STAMPABLE: ReadonlySet<TitleSource> = new Set([\"custom-title\", \"ai-title\", \"agent-name\"]);\n\nexport function isBridgePlaceholder(value: unknown): boolean {\n return typeof value === \"string\" && BRIDGE_PLACEHOLDER.test(value.trim());\n}\n\n/** The first non-empty line, trimmed, cut to `TITLE_MAX` with \"…\"; null when there is none. */\nexport function cleanTitle(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n const line = value\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .find((l) => l.length > 0);\n if (!line) return null;\n return line.length > TITLE_MAX ? `${line.slice(0, TITLE_MAX - 1)}…` : line;\n}\n\n/** The longest title a list shows in full (the stored title stays exact; the full text goes on hover). */\nexport const DISPLAY_MAX = 100;\n\n/** A list marker, heading mark or opening quote a pasted first line starts with (\"1) \", \"- \", \"# \", \"> \", \"“\"). */\nconst LEADING_NOISE = /^(?:\\s*(?:\\d{1,3}[.)]|[-*•]|#{1,6}|>)\\s+|\\s*[\"“'‘`]+)+/;\n\n/**\n * How a list draws a title: leading list markers and quotes dropped, cut to `max` with \"…\". Only for\n * display — the stored title (and search, and the hover text) stays exactly `title`.\n */\nexport function displayTitle(title: string, max: number = DISPLAY_MAX): string {\n const stripped = title.replace(LEADING_NOISE, \"\").replace(/[\"”'’`]+$/, \"\").trim() || title.trim();\n return stripped.length > max ? `${stripped.slice(0, max - 1).trimEnd()}…` : stripped;\n}\n\n/** The title to show and where it came from: the first source in `TITLE_PRECEDENCE` that has one. */\nexport function resolveSessionTitle(sources: TitleSources): ResolvedTitle | null {\n for (const source of TITLE_PRECEDENCE) {\n const raw = sources[source];\n if (STAMPABLE.has(source) && isBridgePlaceholder(raw)) continue;\n const title = cleanTitle(raw);\n if (title) return { title, source };\n }\n return null;\n}\n\n/**\n * Claude Code's own title entries from transcript lines (already parsed JSON), plus the person's\n * first typed message from `head` (the same normalizer the transcript screen uses). Later entries\n * win within a kind; a bridge placeholder never replaces a real one.\n */\nexport function claudeTranscriptTitleSources(head: Iterable<unknown>, tail: Iterable<unknown> = []): TitleSources {\n const out: TitleSources = {};\n const take = (source: TitleSource, value: unknown) => {\n if (typeof value !== \"string\" || !value.trim()) return;\n if (STAMPABLE.has(source) && isBridgePlaceholder(value)) return;\n out[source] = value;\n };\n const normalizer = createClaudeNormalizer();\n let firstPrompt: string | null = null;\n const scan = (entries: Iterable<unknown>, findPrompt: boolean) => {\n for (const entry of entries) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const e = entry as Record<string, unknown>;\n if (e.type === \"custom-title\") take(\"custom-title\", e.customTitle);\n else if (e.type === \"ai-title\") take(\"ai-title\", e.aiTitle);\n else if (e.type === \"agent-name\") take(\"agent-name\", e.agentName);\n else if (e.type === \"summary\") take(\"summary\", e.summary);\n else if (e.type === \"last-prompt\") take(\"last-prompt\", e.lastPrompt);\n else if (findPrompt && firstPrompt === null) {\n for (const item of normalizer.push(entry)) {\n if (item.kind === \"user\" && item.text.trim()) {\n firstPrompt = item.text;\n break;\n }\n }\n }\n }\n };\n scan(head, true);\n scan(tail, false);\n if (firstPrompt !== null) out[\"first-prompt\"] = firstPrompt;\n return out;\n}\n","/**\n * IS THIS CHAT LIVE SOMEWHERE ELSE RIGHT NOW?\n *\n * Taking over a chat that another Claude Code or Codex is still driving puts\n * two agents on one conversation. We cannot know for certain, so we look for\n * evidence, strongest first, and the screen WARNS and asks — it never blocks\n * (the platform law: validation offers, never blocks).\n *\n * 1. a process whose arguments carry the session id — `claude --resume <id>`,\n * `--resume=<id>`, `codex exec … resume <id>` (one `ps` per check);\n * 2. the session file was written in the last two minutes;\n * 3. the file's last step is a tool call that never got its result, and the\n * file changed in the last fifteen minutes (an abandoned crash from last\n * week is not \"running\").\n */\n\nimport { execFile } from \"node:child_process\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexRolloutNormalizer } from \"../normalize/codex\";\nimport { PROVIDER_LABEL, type ActiveElsewhere, type CodingProvider, type TranscriptItem } from \"../types\";\n\nexport const RECENT_WRITE_MS = 2 * 60 * 1000;\nexport const OPEN_TOOL_WINDOW_MS = 15 * 60 * 1000;\n\nexport interface ProcessRow {\n pid: number;\n args: string;\n}\n\n/** Every process's pid and full argument line. Empty (never throws) when `ps` is unavailable. */\nexport function listProcesses(): Promise<ProcessRow[]> {\n return new Promise((resolve) => {\n execFile(\"ps\", [\"-axww\", \"-o\", \"pid=,args=\"], { maxBuffer: 64 * 1024 * 1024, timeout: 5000 }, (error, stdout) => {\n if (error) {\n resolve([]);\n return;\n }\n const rows: ProcessRow[] = [];\n for (const line of String(stdout).split(\"\\n\")) {\n const match = /^\\s*(\\d+)\\s+(.*)$/.exec(line);\n if (match?.[1] && match[2]) rows.push({ pid: Number(match[1]), args: match[2] });\n }\n resolve(rows);\n });\n });\n}\n\n/** A process driving this session: its args name the id, and it is not one of ours. */\nexport function findDrivingProcess(\n processes: readonly ProcessRow[],\n providerSessionId: string,\n excludePids: ReadonlySet<number> = new Set(),\n): ProcessRow | null {\n for (const row of processes) {\n if (excludePids.has(row.pid) || row.pid === process.pid) continue;\n if (!row.args.includes(providerSessionId)) continue;\n // Our own `ps`/`pgrep` and editors viewing the file are not drivers.\n if (/(^|\\/)(ps|pgrep|grep|rg|tail|less|cat)\\b/.test(row.args.split(\" \")[0] ?? \"\")) continue;\n return row;\n }\n return null;\n}\n\n/** True when the last meaningful item is a tool call with no result yet. */\nexport function endsWithOpenToolCall(provider: CodingProvider, entries: readonly unknown[]): boolean {\n const normalizer = provider === \"claude\" ? createClaudeNormalizer() : createCodexRolloutNormalizer();\n const items: TranscriptItem[] = [];\n for (const entry of entries) items.push(...normalizer.push(entry));\n const meaningful = items.filter((i) => i.kind !== \"usage\" && i.kind !== \"notice\" && i.kind !== \"text-delta\");\n const last = meaningful[meaningful.length - 1];\n if (!last || last.kind !== \"tool-call\") return false;\n return !items.some((i) => i.kind === \"tool-result\" && i.id === last.id);\n}\n\nexport function describeActivity(input: {\n provider: CodingProvider;\n providerSessionId: string;\n mtimeMs: number;\n now: number;\n processes: readonly ProcessRow[];\n excludePids?: ReadonlySet<number> | undefined;\n /** Writes at or before this time were OURS (our own run just ended), so\n * they are not evidence of another driver. */\n ownWritesUntilMs?: number | undefined;\n /** Parsed tail of the session file; only consulted when recent enough. */\n tail: () => Promise<readonly unknown[]>;\n}): Promise<ActiveElsewhere | null> {\n const label = PROVIDER_LABEL[input.provider];\n const driver = findDrivingProcess(input.processes, input.providerSessionId, input.excludePids);\n if (driver) {\n return Promise.resolve({\n reason: \"process\",\n message: `This chat is running right now in ${label} — an open ${label} process is using it.`,\n });\n }\n if (input.ownWritesUntilMs !== undefined && input.mtimeMs <= input.ownWritesUntilMs) return Promise.resolve(null);\n const age = input.now - input.mtimeMs;\n if (age <= RECENT_WRITE_MS) {\n return Promise.resolve({\n reason: \"recent-write\",\n message: `This chat was active in ${label} less than two minutes ago and may still be running there.`,\n });\n }\n if (age > OPEN_TOOL_WINDOW_MS) return Promise.resolve(null);\n return input.tail().then((entries) =>\n endsWithOpenToolCall(input.provider, entries)\n ? {\n reason: \"open-tool-call\" as const,\n message: `This chat may still be running in ${label}: its last step started and has not finished.`,\n }\n : null,\n );\n}\n","/**\n * The person's renames, pins and hides — one small JSON file in this package's\n * data dir, keyed by `chatKey()`. The providers' own files are never touched.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { TITLE_MAX } from \"../sessions/titles\";\nimport type { ChatPreference } from \"../types\";\n\nexport class PreferenceStore {\n private data: Record<string, ChatPreference> = {};\n private writing: Promise<void> = Promise.resolve();\n\n constructor(private readonly dir: string) {}\n\n get file(): string {\n return path.join(this.dir, \"preferences.json\");\n }\n\n async load(): Promise<void> {\n try {\n const parsed = JSON.parse(await fs.readFile(this.file, \"utf8\")) as unknown;\n this.data = typeof parsed === \"object\" && parsed !== null ? (parsed as Record<string, ChatPreference>) : {};\n } catch {\n this.data = {};\n }\n }\n\n all(): Record<string, ChatPreference> {\n return { ...this.data };\n }\n\n get(key: string): ChatPreference | null {\n return this.data[key] ?? null;\n }\n\n /** Merge `patch`; a null/false/empty field is removed, an empty preference deleted. */\n set(key: string, patch: ChatPreference): Record<string, ChatPreference> {\n if (!key || key.length > 200) throw new Error(\"That chat can't be found.\");\n const next: ChatPreference = { ...this.data[key] };\n if (\"title\" in patch) {\n const title = typeof patch.title === \"string\" ? patch.title.replace(/\\s+/g, \" \").trim().slice(0, TITLE_MAX) : \"\";\n if (title) next.title = title;\n else delete next.title;\n }\n if (\"pinned\" in patch) {\n if (patch.pinned === true) next.pinned = true;\n else delete next.pinned;\n }\n if (\"hidden\" in patch) {\n if (patch.hidden === true) next.hidden = true;\n else delete next.hidden;\n }\n delete next.updatedAt;\n if (Object.keys(next).length === 0) delete this.data[key];\n else this.data[key] = { ...next, updatedAt: new Date().toISOString() };\n this.persist();\n return this.all();\n }\n\n /**\n * Move a preference to the chat's lasting key (`session:<id>` → `<provider>:<id>` once the\n * provider's id is known), so a rename made early is the one rename everywhere. A preference\n * already under the lasting key wins field by field.\n */\n rekey(from: string, to: string): boolean {\n if (from === to || !this.data[from]) return false;\n this.data[to] = { ...this.data[from], ...this.data[to] };\n delete this.data[from];\n this.persist();\n return true;\n }\n\n private persist(): void {\n const snapshot = JSON.stringify(this.data, null, 1);\n this.writing = this.writing\n .then(async () => {\n await fs.mkdir(this.dir, { recursive: true });\n const tmp = `${this.file}.${randomUUID()}.tmp`;\n await fs.writeFile(tmp, snapshot, { mode: 0o600 });\n await fs.rename(tmp, this.file);\n })\n .catch(() => {\n /* the next write retries with everything */\n });\n }\n\n async flush(): Promise<void> {\n await this.writing;\n }\n}\n","/**\n * SEARCH — by title and by what was said, across every Claude Code and Codex\n * chat on this computer, newest first.\n *\n * A heavy user has tens of gigabytes of session files, so a search is a\n * PAGE: it reads chats newest-first until it has `limit` hits or its time\n * budget is spent, and says exactly how far it got (`scanned` of `total`,\n * `nextCursor` to keep going). It never claims \"no results\" for chats it did\n * not read.\n *\n * A match must be in the conversation — a message, a tool call or its output,\n * exactly as the transcript shows it — not in bookkeeping (ids, tool\n * catalogues, hook output), so \"type\" does not match every line of every file.\n */\n\nimport { createReadStream } from \"node:fs\";\n\nimport { createClaudeNormalizer } from \"../normalize/claude\";\nimport { createCodexRolloutNormalizer } from \"../normalize/codex\";\nimport type { ChatSearchHit, ChatSearchResult, CodingProvider, TranscriptItem } from \"../types\";\nimport {\n defaultProviderHomes,\n describeSessionFile,\n codexNames,\n listSessionFiles,\n type FileCandidate,\n type ProviderHomes,\n} from \"./files\";\n\nexport interface SearchOptions {\n homes?: ProviderHomes | undefined;\n cursor?: number | undefined;\n limit?: number | undefined;\n /** The apps' own titles (`provider:id` → title) from the owner of their index; absent → Codex's index is read here. */\n appTitles?: ReadonlyMap<string, string> | undefined;\n /** Stop reading after this long and hand back a cursor. Default 3.5 s. */\n budgetMs?: number | undefined;\n}\n\n/**\n * The first conversation text in one saved line that contains `needle`: the\n * line goes through the SAME normalizer the transcript uses, so only what the\n * screen would show can match — a message, a tool's input or output — never\n * tool catalogues, hook output or ids.\n */\nfunction findInLine(provider: CodingProvider, value: unknown, needle: string): string | null {\n const items: TranscriptItem[] =\n provider === \"claude\" ? createClaudeNormalizer().push(value) : createCodexRolloutNormalizer().push(value);\n for (const item of items) {\n let text: string | null = null;\n switch (item.kind) {\n case \"user\":\n case \"text\":\n case \"reasoning\":\n case \"notice\":\n case \"error\":\n text = item.text;\n break;\n case \"tool-call\":\n text = typeof item.input === \"string\" ? item.input : JSON.stringify(item.input ?? \"\");\n break;\n case \"tool-result\":\n text = item.output;\n break;\n default:\n text = null;\n }\n if (text && text.toLowerCase().includes(needle)) return text;\n }\n return null;\n}\n\n/** ~140 characters around the first match, on one line. */\nexport function snippetAround(text: string, needle: string, width = 140): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n const at = flat.toLowerCase().indexOf(needle);\n if (at < 0) return flat.slice(0, width);\n const before = Math.floor((width - needle.length) / 3);\n const start = Math.max(0, at - before);\n const end = Math.min(flat.length, start + width);\n return `${start > 0 ? \"…\" : \"\"}${flat.slice(start, end)}${end < flat.length ? \"…\" : \"\"}`;\n}\n\n/**\n * Read one file until the first line whose CONVERSATION contains the query.\n * Returns that excerpt, or null.\n *\n * The hot path never decodes UTF-8: each chunk is read as latin1 (one char\n * per byte, so offsets stay byte offsets), lower-cased natively, and searched\n * for the query as it appears inside a JSON string (`raw`: quotes and\n * backslashes escaped). An ASCII query only ever matches ASCII bytes, so the\n * latin1 reading cannot invent or hide a match. Only\n * a line that matches there is decoded, parsed, and checked for the query in\n * its conversation (not its bookkeeping). A query with non-ASCII letters\n * takes the decoded path, which is exact but slower.\n */\nconst TIMED_OUT = Symbol(\"timed-out\");\n\nasync function scanFile(\n provider: CodingProvider,\n file: string,\n needle: string,\n raw: string,\n deadline: number,\n): Promise<string | null | typeof TIMED_OUT> {\n const ascii = /^[\\x00-\\x7f]*$/.test(raw);\n return new Promise((resolve) => {\n let carry: Buffer = Buffer.alloc(0);\n let done = false;\n const stream = createReadStream(file, { highWaterMark: 4 * 1024 * 1024 });\n const finish = (value: string | null | typeof TIMED_OUT) => {\n if (done) return;\n done = true;\n stream.destroy();\n resolve(value);\n };\n const verify = (line: Buffer): string | null => {\n try {\n const hit = findInLine(provider, JSON.parse(line.toString(\"utf8\")), needle);\n return hit === null ? null : snippetAround(hit, needle);\n } catch {\n return null;\n }\n };\n /** Search `block` (complete lines only); the first verified hit, else null. */\n const searchBlock = (block: Buffer): string | null => {\n if (!ascii) {\n for (const line of block.toString(\"utf8\").split(\"\\n\")) {\n if (line.toLowerCase().includes(raw)) {\n const hit = verify(Buffer.from(line, \"utf8\"));\n if (hit !== null) return hit;\n }\n }\n return null;\n }\n const lower = block.toString(\"latin1\").toLowerCase();\n let from = 0;\n for (;;) {\n const at = lower.indexOf(raw, from);\n if (at < 0) return null;\n const start = block.lastIndexOf(10, at) + 1;\n let end = block.indexOf(10, at);\n if (end < 0) end = block.length;\n const hit = verify(block.subarray(start, end));\n if (hit !== null) return hit;\n from = end + 1;\n }\n };\n stream.on(\"data\", (chunk) => {\n const data = carry.length ? Buffer.concat([carry, chunk as Buffer]) : (chunk as Buffer);\n const lastNewline = data.lastIndexOf(10);\n if (lastNewline < 0) {\n carry = data;\n return;\n }\n carry = Buffer.from(data.subarray(lastNewline + 1));\n const hit = searchBlock(data.subarray(0, lastNewline));\n if (hit !== null) return finish(hit);\n // A single file never overruns the whole search's budget.\n if (Date.now() > deadline) finish(TIMED_OUT);\n });\n stream.on(\"end\", () => finish(carry.length ? searchBlock(carry) : null));\n stream.on(\"error\", () => finish(null));\n });\n}\n\n/** The file list, reused briefly: a search typed letter by letter should not stat 9,000 files each time. */\nlet listed: { at: number; homes: ProviderHomes; files: FileCandidate[] } | null = null;\nasync function sessionFiles(homes: ProviderHomes): Promise<FileCandidate[]> {\n if (listed && listed.homes === homes && Date.now() - listed.at < 20_000) return listed.files;\n const files = await listSessionFiles(homes);\n listed = { at: Date.now(), homes, files };\n return files;\n}\n\nexport async function searchLocalChats(query: string, options: SearchOptions = {}): Promise<ChatSearchResult> {\n const needle = query.replace(/\\s+/g, \" \").trim().toLowerCase();\n const homes = options.homes ?? defaultProviderHomes();\n const files: FileCandidate[] = await sessionFiles(homes);\n const cursor = Math.max(0, Math.min(options.cursor ?? 0, files.length));\n if (needle.length < 2) return { query, hits: [], scanned: 0, total: files.length, nextCursor: null };\n\n const raw = JSON.stringify(needle).slice(1, -1);\n const limit = Math.max(1, Math.min(options.limit ?? 30, 100));\n const deadline = Date.now() + (options.budgetMs ?? 3500);\n const names = await codexNames(homes, options.appTitles);\n const hits: ChatSearchHit[] = [];\n\n let i = cursor;\n for (; i < files.length && hits.length < limit && Date.now() < deadline; i += 1) {\n const candidate = files[i] as FileCandidate;\n const named = options.appTitles?.get(`${candidate.provider}:${candidate.id}`) ?? (candidate.provider === \"codex\" ? names.get(candidate.id) : undefined);\n const nameHit = named !== undefined && named.toLowerCase().includes(needle);\n const scanned = nameHit ? null : await scanFile(candidate.provider, candidate.file, needle, raw, deadline);\n // A file cut off by the budget is NOT counted as read: the cursor resumes at it.\n // (Unless it is the page's first file — a file too big for one budget is\n // skipped rather than stalling every page on it.)\n if (scanned === TIMED_OUT) {\n if (i === cursor) i += 1;\n break;\n }\n const snippet = scanned;\n if (!nameHit && snippet === null) continue;\n const described = await describeSessionFile(candidate, names);\n if (!described) continue; // sub-agent and hook-only files are not chats\n hits.push({\n provider: described.provider,\n providerSessionId: described.providerSessionId,\n title: described.title,\n cwd: described.cwd,\n updatedAt: described.updatedAt,\n where: nameHit || described.title.toLowerCase().includes(needle) ? \"title\" : \"content\",\n snippet,\n });\n }\n return {\n query,\n hits,\n scanned: i - cursor,\n total: files.length,\n nextCursor: i < files.length ? i : null,\n };\n}\n","/**\n * TITLE HINTS — the port through which the owner of the coding apps' index (Matrx 2's core, which\n * reads Claude's records, Codex's database and the rest through its own `fs`/`exec` owners) tells\n * this package what each chat is called and whether the app hides it. The package never walks the\n * apps' records itself: it reads transcripts (titles by the transcript rules, content search,\n * activity) and overlays these hints as they arrive. Pure: browser-safe types and helpers.\n */\n\nimport type { TitleSource } from \"./titles\";\n\nexport type HintProvider = \"claude\" | \"codex\";\n\nexport interface TitleHint {\n /** The app's title (pre-override: the person's rename is applied by whoever draws the row). */\n title: string;\n /** Where the owner's title came from; \"unknown\" when the owner did not say (shown as such, never guessed). */\n source: TitleSource | \"unknown\";\n /** The app hides it: archived in the app (shown behind a toggle). */\n archived?: boolean | undefined;\n /** A scheduled or automated run (shown behind a toggle). */\n scheduled?: boolean | undefined;\n /** Listed by the app but its conversation file is gone: why (it is shown, never dropped). */\n unavailable?: string | null | undefined;\n /** Last activity the app records (ms), for chats only the app knows. */\n lastActiveMs?: number | null | undefined;\n}\n\nexport interface TitleHints {\n /** The hints now, keyed `titleHintKey()`; null while the owner's index is still loading. Never waits. */\n current(): ReadonlyMap<string, TitleHint> | null;\n /** Called after the hints change (a rename in the app, a new chat, the first load, a failure). */\n subscribe(listener: () => void): () => void;\n /** Why the apps' titles could not be had right now (shown with a Retry), or null. */\n problem?(): string | null;\n /** Ask the owner again now (the Retry). */\n retry?(): void;\n}\n\nexport function titleHintKey(provider: HintProvider, sessionId: string): string {\n return `${provider}:${sessionId}`;\n}\n\n/** A hints port the host fills by hand (tests, or an owner that pushes whole snapshots). */\nexport function createTitleHintsStore(): TitleHints & {\n set(hints: ReadonlyMap<string, TitleHint> | null): void;\n setProblem(problem: string | null): void;\n} {\n let hints: ReadonlyMap<string, TitleHint> | null = null;\n let problem: string | null = null;\n const listeners = new Set<() => void>();\n const tell = () => {\n for (const l of listeners) l();\n };\n return {\n current: () => hints,\n problem: () => problem,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n set(next) {\n hints = next;\n problem = null;\n tell();\n },\n setProblem(next) {\n if (next === problem) return;\n problem = next;\n tell();\n },\n };\n}\n\n/** The app titles a hints map carries, keyed `provider:id` (for title search and Codex names). */\nexport function appTitlesOf(hints: ReadonlyMap<string, TitleHint>): Map<string, string> {\n const out = new Map<string, string>();\n for (const [key, hint] of hints) out.set(key, hint.title);\n return out;\n}\n","/**\n * Overlaying the owner's title hints (`./sessions` TitleHints) on what this engine read from the\n * transcripts. The engine never waits for hints: with none loaded yet, every chat keeps its\n * transcript title and says so (`titlePending`), and a `titles` event follows when they arrive.\n *\n * What stays on node, in this package, and why: reading transcripts (titles by the transcript\n * rules for chats no app lists, content search across every chat, \"live elsewhere\" activity from\n * file tails and processes, history for takeover) — the drivers that resume a chat need the same\n * files on the same machine. What the apps' own records say (titles, archived, scheduled, chats\n * whose file is gone) comes only from the owner of the apps' index (Matrx 2's core).\n */\n\nimport type { DiscoveredSession } from \"../types\";\nimport { titleHintKey, type TitleHint, type TitleHints } from \"../sessions/hints\";\n\nexport function overlayHint<T extends Pick<DiscoveredSession, \"provider\" | \"providerSessionId\" | \"title\"> & Partial<DiscoveredSession>>(\n chat: T,\n hints: ReadonlyMap<string, TitleHint> | null,\n expected: boolean,\n): T {\n if (!expected) return chat;\n if (hints === null) return { ...chat, titlePending: true };\n const hint = hints.get(titleHintKey(chat.provider, chat.providerSessionId));\n if (!hint) return chat;\n return {\n ...chat,\n title: hint.title,\n titleSource: hint.source,\n ...(hint.archived || chat.archived ? { archived: true } : {}),\n ...(hint.scheduled ? { scheduled: true } : {}),\n };\n}\n\n/**\n * The chats the app lists whose conversation file is gone (never dropped: shown as unavailable),\n * newest first, that the transcript read did not already cover.\n */\nexport function unavailableFromHints(hints: ReadonlyMap<string, TitleHint> | null, covered: ReadonlySet<string>): DiscoveredSession[] {\n if (!hints) return [];\n const out: DiscoveredSession[] = [];\n for (const [key, hint] of hints) {\n if (!hint.unavailable || covered.has(key)) continue;\n const at = key.indexOf(\":\");\n const provider = key.slice(0, at);\n if (provider !== \"claude\" && provider !== \"codex\") continue;\n out.push({\n provider,\n providerSessionId: key.slice(at + 1),\n cwd: null,\n title: hint.title,\n titleSource: hint.source,\n updatedAt: new Date(hint.lastActiveMs ?? 0).toISOString(),\n source: null,\n activeElsewhere: null,\n unavailable: hint.unavailable,\n ...(hint.archived ? { archived: true } : {}),\n ...(hint.scheduled ? { scheduled: true } : {}),\n });\n }\n return out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n}\n\nexport type { TitleHints };\n","/**\n * The small local index: which sessions were driven from here and their runs,\n * so the list survives a restart. Transcripts are NEVER copied here — they stay\n * in the providers' own files. One JSON file, written atomically.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { CodingSession, RunRecord } from \"../types\";\n\ninterface IndexFile {\n version: 1;\n sessions: CodingSession[];\n runs: RunRecord[];\n}\n\nconst MAX_RUNS = 2000;\n\nexport interface Identity {\n companyId: string;\n agentId: string;\n}\n\nexport class RunIndex {\n private data: IndexFile = { version: 1, sessions: [], runs: [] };\n private writing: Promise<void> = Promise.resolve();\n\n constructor(private readonly dir: string) {}\n\n get file(): string {\n return path.join(this.dir, \"index.json\");\n }\n\n async load(): Promise<void> {\n await fs.mkdir(this.dir, { recursive: true });\n try {\n const parsed = JSON.parse(await fs.readFile(this.file, \"utf8\")) as Partial<IndexFile>;\n this.data = {\n version: 1,\n sessions: Array.isArray(parsed.sessions) ? parsed.sessions : [],\n runs: Array.isArray(parsed.runs) ? parsed.runs : [],\n };\n } catch {\n this.data = { version: 1, sessions: [], runs: [] };\n }\n }\n\n sessions(): CodingSession[] {\n return [...this.data.sessions].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n session(id: string): CodingSession | null {\n return (\n this.data.sessions.find((s) => s.id === id) ??\n this.data.sessions.find((s) => s.providerSessionId === id) ??\n null\n );\n }\n\n runs(sessionId: string): RunRecord[] {\n return this.data.runs.filter((r) => r.sessionId === sessionId);\n }\n\n run(runId: string): RunRecord | null {\n return this.data.runs.find((r) => r.runId === runId) ?? null;\n }\n\n allRuns(): RunRecord[] {\n return this.data.runs;\n }\n\n putSession(session: CodingSession): void {\n const at = this.data.sessions.findIndex((s) => s.id === session.id);\n if (at >= 0) this.data.sessions[at] = session;\n else this.data.sessions.push(session);\n this.persist();\n }\n\n putRun(run: RunRecord): void {\n const at = this.data.runs.findIndex((r) => r.runId === run.runId);\n if (at >= 0) this.data.runs[at] = run;\n else this.data.runs.push(run);\n if (this.data.runs.length > MAX_RUNS) this.data.runs.splice(0, this.data.runs.length - MAX_RUNS);\n this.persist();\n }\n\n /** Serialize writes; each writes the whole index to a temp file, then renames. */\n private persist(): void {\n const snapshot = JSON.stringify(this.data, null, 1);\n this.writing = this.writing.then(async () => {\n const tmp = `${this.file}.${randomUUID()}.tmp`;\n await fs.writeFile(tmp, snapshot, { mode: 0o600 });\n await fs.rename(tmp, this.file);\n }).catch(() => {\n /* the next write retries with the full index */\n });\n }\n\n async flush(): Promise<void> {\n await this.writing;\n }\n\n /** A stable Paperclip agent/company identity for this install, so the\n * driver's scratch state is reused rather than growing per run. */\n async identity(): Promise<Identity> {\n const file = path.join(this.dir, \"identity.json\");\n try {\n const parsed = JSON.parse(await fs.readFile(file, \"utf8\")) as Partial<Identity>;\n if (typeof parsed.companyId === \"string\" && typeof parsed.agentId === \"string\") {\n return { companyId: parsed.companyId, agentId: parsed.agentId };\n }\n } catch {\n /* first run */\n }\n const identity = { companyId: randomUUID(), agentId: randomUUID() };\n await fs.writeFile(file, JSON.stringify(identity), { mode: 0o600 });\n return identity;\n }\n}\n","/**\n * The person's OWN defaults — the model and effort their Claude Code and Codex\n * use when nothing is picked. The Claude driver otherwise forces its built-in\n * default (`claude-opus-5`) onto every run, silently overriding the model the\n * person chose in Claude Code itself; the engine passes theirs instead.\n * Read-only: these files are never written.\n */\n\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport type { CodingProvider } from \"../types\";\n\nexport interface UserDefaults {\n model: string | null;\n effort: string | null;\n}\n\nasync function readJson(file: string): Promise<Record<string, unknown> | null> {\n try {\n const parsed = JSON.parse(await fs.readFile(file, \"utf8\")) as unknown;\n return typeof parsed === \"object\" && parsed !== null ? (parsed as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\n/** Claude Code's precedence: the folder's local settings, its shared settings, then the person's. */\nexport async function claudeDefaults(cwd: string | null, home = os.homedir()): Promise<UserDefaults> {\n const files = [\n ...(cwd ? [path.join(cwd, \".claude\", \"settings.local.json\"), path.join(cwd, \".claude\", \"settings.json\")] : []),\n path.join(home, \".claude\", \"settings.json\"),\n ];\n let model: string | null = null;\n let effort: string | null = null;\n for (const file of files) {\n const settings = await readJson(file);\n if (!settings) continue;\n model ??= str(settings.model);\n effort ??= str(settings.effortLevel);\n if (model && effort) break;\n }\n return { model, effort };\n}\n\n/** Codex's top-level `model` and `model_reasoning_effort` from `~/.codex/config.toml`. */\nexport async function codexDefaults(home = os.homedir()): Promise<UserDefaults> {\n let text: string;\n try {\n text = await fs.readFile(path.join(home, \".codex\", \"config.toml\"), \"utf8\");\n } catch {\n return { model: null, effort: null };\n }\n const values: Record<string, string> = {};\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (line.startsWith(\"[\")) break; // top-level keys only\n const match = /^([A-Za-z0-9_]+)\\s*=\\s*\"([^\"]*)\"/.exec(line);\n if (match?.[1] && match[2] !== undefined) values[match[1]] = match[2];\n }\n return { model: str(values.model), effort: str(values.model_reasoning_effort) };\n}\n\nexport function userDefaults(provider: CodingProvider, cwd: string | null): Promise<UserDefaults> {\n return provider === \"claude\" ? claudeDefaults(cwd) : codexDefaults();\n}\n\n/** Effort levels each CLI accepts, lowest first (`claude --help`, the Codex driver's docs). */\nexport const EFFORT_LEVELS: Record<CodingProvider, string[]> = {\n claude: [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"],\n codex: [\"low\", \"medium\", \"high\", \"xhigh\"],\n};\n"],"mappings":"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","names":["import_node_child_process","import_node_crypto","import_node_fs","fs","import_promises","listed","path","fs","args","fs","import_node_crypto","import_promises","import_node_path","path","fs","import_promises","import_node_os","import_node_path","isObject","str","num","import_node_path","fsConstants","path","os","listed","import_node_os","import_node_path","path","os","import_node_fs","import_promises","import_node_os","import_node_path","import_node_child_process","path","os","fs","codexNames","import_node_crypto","import_promises","import_node_path","path","fs","import_node_fs","import_node_crypto","import_promises","import_node_path","path","fs","import_promises","import_node_os","import_node_path","fs","str","os","path","path","fs","os","options","run"]}
|