sessionpipe 0.9.0 → 0.10.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/README.md +25 -2
- package/dist/cli.js +4358 -3288
- package/dist/cli.js.map +4 -4
- package/dist/control/aliases.d.ts +5 -0
- package/dist/control/aliases.d.ts.map +1 -1
- package/dist/control/autoupdate.d.ts +1 -18
- package/dist/control/autoupdate.d.ts.map +1 -1
- package/dist/control/cli.d.ts +1 -1
- package/dist/control/cli.d.ts.map +1 -1
- package/dist/control/daemon.d.ts +83 -12
- package/dist/control/daemon.d.ts.map +1 -1
- package/dist/control/files.d.ts +6 -4
- package/dist/control/files.d.ts.map +1 -1
- package/dist/control/pair.d.ts +15 -23
- package/dist/control/pair.d.ts.map +1 -1
- package/dist/control/route.d.ts +1 -1
- package/dist/control/route.d.ts.map +1 -1
- package/dist/control/sdk.d.ts.map +1 -1
- package/dist/control/store.d.ts +21 -2
- package/dist/control/store.d.ts.map +1 -1
- package/dist/hook.d.ts.map +1 -1
- package/dist/hook.js +7 -1
- package/dist/hook.js.map +2 -2
- package/dist/index.js +150 -44
- package/dist/index.js.map +4 -4
- package/dist/run.d.ts.map +1 -1
- package/dist/update.d.ts +1 -7
- package/dist/update.d.ts.map +1 -1
- package/dist/worker.js +152 -46
- package/dist/worker.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/cli.ts", "../../core/src/adapters/antigravity.ts", "../../core/src/paths.ts", "../../core/src/readers/files.ts", "../../core/src/adapters/codex-rollout.ts", "../../core/src/readers/transcripts.ts", "../../core/src/adapters/claude-shaped.ts", "../../core/src/adapters/antigravity-control.ts", "../../core/src/adapters/
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n// SPDX-License-Identifier: Apache-2.0\n// sessionpipe: install once, hook everything, choose per sink what leaves.\n// connect \u00B7 install \u00B7 uninstall \u00B7 sink add|list|remove|test \u00B7 secrets \u00B7 status \u00B7\n// doctor \u00B7 tail \u00B7 backfill \u00B7 forget \u00B7 replay \u00B7 update \u00B7 hook \u00B7 worker\nimport { execFileSync, spawnSync } from \"node:child_process\";\nimport {\n existsSync,\n mkdtempSync,\n readdirSync,\n readFileSync,\n realpathSync,\n rmSync,\n statSync,\n unlinkSync,\n} from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n ADAPTERS,\n adapterByName,\n type BackfillRow,\n type Config,\n Cursors,\n claudeControl,\n claudeDirs,\n configFile,\n type Event,\n filterEvent,\n type HookCommand,\n machineName,\n makeEvent,\n Outbox,\n readConfig,\n type SinkConfig,\n stateDir,\n type Tier,\n tilde,\n writeConfig,\n} from \"@sessionpipe/core\";\nimport { connectFolders, connectTier } from \"./connect.js\";\nimport { autoUpdateOff, readUpdate, updateFile, updateLine, updateSummary } from \"./control/autoupdate.js\";\nimport { CONTROL_HELP, controlMain, enabledHarnesses, waitMain } from \"./control/cli.js\";\nimport type { Status } from \"./control/daemon.js\";\nimport { ask, socketPath } from \"./control/local.js\";\nimport { moveControlSecrets, pairedCount, readControl, writeControl } from \"./control/store.js\";\nimport { commandHelp } from \"./help.js\";\nimport { installLauncher, launcherPath, launcherState, removeLauncher, usesLauncher } from \"./launcher.js\";\nimport { buildSinks, drain, factsState, flush, jobsDir, runJob, VERSION } from \"./run.js\";\nimport { assertSetupVersion, rerunGlobally, stableNode, viaNpx } from \"./runtime.js\";\nimport { bestStore, dropSinkSecrets, moveSinkSecrets, type StoreName, sinkWithSecrets, storeLabel } from \"./secrets.js\";\nimport { globalPrefix, installVersion, isNewer, latestVersion } from \"./update.js\";\n\nconst print = (s = \"\"): void => {\n process.stdout.write(`${s}\\n`);\n};\n// One command per process: `main` sets these for the run, every command reads them.\nlet args: string[] = [];\nlet out: (s?: string) => void = print;\nlet state = \"\";\nconst flag = (name: string): string | undefined => {\n const i = args.indexOf(name);\n return i >= 0 ? args[i + 1] : undefined;\n};\nconst has = (name: string): boolean => args.includes(name);\nconst distDir = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface Io {\n /** One line of output. */\n out: (s?: string) => void;\n /** What a failed command says, then `exit(1)`. */\n err: (s: string) => void;\n exit: (code: number) => void;\n}\n\n/** Run one command: `argv` is what follows `sessionpipe`; `io` is this process by default. */\nexport async function main(\n argv: string[],\n io: Io = { out: print, err: (s) => void process.stderr.write(s), exit: (c) => process.exit(c) },\n): Promise<void> {\n args = argv;\n out = io.out;\n state = stateDir();\n try {\n await command(args[0] ?? \"help\");\n } catch (e) {\n io.err(`sessionpipe: ${(e as Error).message}\\n`);\n io.exit(1);\n }\n}\n\n/** Is this file the process entrypoint? By real path: npm's bin link to it counts. */\nexport function isEntrypoint(argv1: string | undefined, url: string): boolean {\n try {\n return !!argv1 && realpathSync(argv1) === fileURLToPath(url);\n } catch {\n return false;\n }\n}\n\n/** The command a hook entry runs: the launcher, which outlives node upgrades\n * (launcher.ts); on Windows, this node by a stable absolute path and hook.js by its\n * real path. */\nfunction hookCommand(): HookCommand {\n if (usesLauncher()) {\n const l = launcherPath();\n return (a) => ({ argv: [l, ...a], command: `${JSON.stringify(l)} ${a.join(\" \")}` });\n }\n const node = stableNode(process.execPath);\n let script = path.join(distDir, \"hook.js\");\n try {\n script = realpathSync(script);\n } catch {}\n return (a) => ({\n argv: [node, script, ...a],\n command: `${JSON.stringify(node)} ${JSON.stringify(script)} ${a.join(\" \")}`,\n });\n}\n\nfunction selectedAdapters(): typeof ADAPTERS {\n const named = ADAPTERS.filter((a) => has(`--${a.name}`));\n if (named.length) return named;\n return ADAPTERS.filter((a) => a.detect());\n}\n\nasync function command(cmd: string): Promise<void> {\n // Help wins over every command and argument, before any command can do work.\n if (has(\"--help\") || has(\"-h\")) {\n const usage = commandHelp(\n args,\n ADAPTERS.map((a) => a.name),\n );\n return usage ? out(usage) : help();\n }\n switch (cmd) {\n case \"connect\":\n return connect();\n case \"install\":\n return install();\n case \"secrets\":\n return secrets();\n case \"uninstall\":\n return uninstall();\n case \"sink\":\n return sink();\n case \"status\":\n return status();\n case \"doctor\":\n return await doctor();\n case \"tail\":\n return tail();\n case \"backfill\":\n return backfill();\n case \"forget\":\n return forget();\n case \"replay\":\n return replay();\n case \"update\":\n return update();\n case \"worker\":\n return workerFromArgv();\n case \"control\":\n return controlMain(args, out, distDir);\n case \"wait\":\n return waitMain(args, out);\n case \"hook\":\n out(\"sessionpipe hook is dist/hook.js; harnesses run it directly\");\n return;\n case \"--version\":\n case \"-v\":\n case \"version\":\n out(VERSION);\n return;\n default:\n return help();\n }\n}\n\nfunction help(): void {\n out(`sessionpipe ${VERSION} \u2014 an open protocol for what your coding agents are doing\n\nUsage:\n sessionpipe connect <receiver> [--machine NAME] [--rename-machine] [--allow-downgrade] [--tier 0-3] [--mode safe|auto] [--folder DIR]\u2026\n (everything, in one go: hooks, a sink, signed messages, keys)\n sessionpipe install [--claude-code --codex --gemini-cli --antigravity --devin] [--machine NAME] [--rename-machine] [--allow-downgrade] [--backfill DAYS] [--sink URL --tier N]\n sessionpipe uninstall [--claude-code --codex --gemini-cli --antigravity --devin | --all] [--keep-state]\n sessionpipe sink add <url|file:PATH|stdout> [--tier 0-3] [--token T] [--pii] [--name N]\n sessionpipe sink list | remove <name> | test <name>\n sessionpipe secrets [move keychain|secret-service|file] (where the machine's keys live)\n sessionpipe status [--json] | doctor [--json]\n sessionpipe tail [--session ID] [--tier N] [--harness NAME]\n sessionpipe backfill [--days 30] | forget <harness> <session> | replay --sink NAME\n sessionpipe update [off|on] (install the latest now; off/on: the daemon's daily update)\n${CONTROL_HELP}\n\nDocs: https://sessionpipe.org \u00B7 nothing leaves this machine until you add a sink.`);\n}\n\n/** --machine names a first install. A repeat setup must not split sessions from control. */\nfunction setupConfig(): Config {\n const cfg = readConfig();\n const requested = flag(\"--machine\");\n if ((has(\"--machine\") || has(\"--rename-machine\")) && (!requested || requested.startsWith(\"-\")))\n throw new Error(\"--machine NAME is required when naming or renaming a machine\");\n const machine = requested?.slice(0, 80);\n const control = readControl();\n const hooksName = existsSync(configFile()) ? machineName(cfg, os.hostname()) : undefined;\n // A daemon paired as `<host>.local` (what `control pair` did before 0.9.0 on a Mac) is\n // this machine under the hooks' name, `<host>`: that name keeps a receiver's sessions\n // in one place, and the daemon is renamed to it below, which costs nothing since\n // receivers key a pairing by id. A daemon named on purpose keeps its name.\n const pairedName =\n control && hooksName && machineName({} as Config, control.name) === hooksName ? hooksName : control?.name;\n const current = cfg.machine || pairedName || hooksName;\n if (current && machine && machine !== current && !has(\"--rename-machine\")) {\n out(\n ` Keeping configured machine name ${current}; ignoring --machine ${machine}. Use --rename-machine with --machine NAME for an explicit rename.`,\n );\n cfg.machine = current;\n } else {\n const name = machine || current || machineName(cfg, os.hostname());\n // The daemon goes by the same name as the hooks, or a receiver shows one machine\n // twice. An explicit rename renames the paired daemon too: control.json carries the\n // name, the daemon re-reads it and says it in its next hello (receivers key machines\n // by id, so the pairing holds). receivers[].machine is that id, not the name.\n if (control && control.name !== name && (machine || name === pairedName)) {\n writeControl({ ...control, name });\n out(` Renamed the control daemon ${control.name} \u2192 ${name}; its next hello tells each receiver.`);\n }\n cfg.machine = name;\n }\n return cfg;\n}\n\nasync function install(): Promise<void> {\n const cfg = setupConfig();\n if (viaNpx(distDir)) return rerunGlobally(args, out, { allowDowngrade: has(\"--allow-downgrade\") });\n assertSetupVersion(has(\"--allow-downgrade\"));\n // A sink URL given here is added first, so the install knows whether it needs\n // every tool event or only the heartbeat's one.\n const sinkUrl = flag(\"--sink\");\n if (sinkUrl) await sinkAdd(sinkUrl, cfg);\n const adapters = selectedAdapters();\n if (!adapters.length) {\n out(\n \" No supported harness found on this machine (Claude Code, Codex, Gemini CLI, Antigravity, Devin). Pass --<harness> to force one.\",\n );\n return;\n }\n out(` Machine: ${machineName(cfg, os.hostname())}`);\n const lean = isLean(cfg);\n if (lean)\n out(\n \" No sink above tier 0: hooking one tool event per harness (the heartbeat's). `sink add \u2026 --tier 1` or higher hooks the rest.\",\n );\n installHarnesses(adapters, cfg, lean);\n writeConfig(cfg);\n const days = Number(flag(\"--backfill\") ?? 30);\n if (days > 0) backfillRows(adapters, days, cfg);\n out(\"\");\n const live = cfg.sinks.filter((s) => !s.paused);\n if (live.length) out(` Reporting to ${live.map((s) => `${s.name} (tier ${s.tier})`).join(\", \")}.`);\n else\n out(\n \" Nothing leaves this machine yet: events go to the local outbox. `sessionpipe tail` shows them; `sessionpipe sink add <url> --tier N` sends them.\",\n );\n out(\" Sessions already running pick up hooks on their next start (Claude Code \u2265 2.1.280 picks them up live).\");\n}\n\n/** No sink takes tier \u2265 1: the harness only needs one tool event (issue #12). */\nfunction isLean(cfg: Config): boolean {\n return !cfg.sinks.some((s) => !s.paused && Math.min(s.tier, s.max_tier ?? 3) >= 1);\n}\n\n/** Write the hooks for these harnesses; remember which files sessionpipe created. */\nfunction installHarnesses(adapters: readonly (typeof ADAPTERS)[number][], cfg: Config, lean: boolean): void {\n if (usesLauncher()) {\n const node = stableNode(process.execPath);\n const l = installLauncher({ distDir, node, version: VERSION });\n if (l.changed)\n out(` \u2713 hook launcher: ${tilde(l.launcher)} (node ${tilde(node)}, or any node on PATH once that one is gone)`);\n }\n const hc = hookCommand();\n for (const a of adapters) {\n const prev = cfg.harnesses[a.name] ?? {};\n const created = new Set(prev.created ?? []);\n const reports = a.install(hc, process.env, { lean, created: [...created] });\n for (const r of reports) {\n if (r.created) created.add(r.file);\n const mark = r.skipped ? \"!\" : r.changed ? \"\u2713\" : \"=\";\n out(\n ` ${mark} ${a.name}: ${tilde(r.file)}${r.note ? ` \u2014 ${r.note}` : r.changed ? \" written\" : \" already current\"}`,\n );\n }\n cfg.harnesses[a.name] = { enabled: true, ...(created.size ? { created: [...created] } : {}) };\n if (a.name === \"gemini-cli\")\n out(\" note: Gemini CLI's own telemetry defaults logPrompts on; that is Google's setting, not sessionpipe's.\");\n if (a.name === \"devin\" && !reports.some((r) => r.skipped))\n out(\n \" note: Devin ignores a hooks file whole if it holds one event name it doesn't know; run `/hooks` in `devin` to see what loaded.\",\n );\n if (a.name === \"codex\" && !reports.some((r) => r.skipped))\n out(\n \" note: Codex runs non-managed hooks only after you approve them: start `codex` and accept the hook review. The notify fallback reports turn ends meanwhile.\",\n );\n }\n}\n\n/** `sessionpipe connect <receiver>`: everything a machine needs, in one command and one\n * approval \u2014 the hooks for every agent and every Claude Code account here, a sink at\n * tier 2, signed messages (the daemon, paired with open pairing), the keys moved into\n * the keychain when there is one, the daemon kept running past logout, the last 30\n * days backfilled. Run it again and it only fixes what's missing. Asks nothing: the\n * mode is --mode or safe, the folders are --folder, this one, or where your recent\n * sessions ran \u2014 never the home folder. */\nasync function connect(): Promise<void> {\n const raw = args[1];\n if (!raw || raw.startsWith(\"-\"))\n return out(\n \"usage: sessionpipe connect <receiver> [--machine NAME] [--rename-machine] [--allow-downgrade] [--tier 0-3] [--mode safe|auto] [--folder DIR]\u2026 [--no-service]\",\n );\n const cfg = setupConfig();\n if (viaNpx(distDir)) return rerunGlobally(args, out, { allowDowngrade: has(\"--allow-downgrade\") });\n assertSetupVersion(has(\"--allow-downgrade\"));\n const url = (/^https?:\\/\\//.test(raw) ? raw : `https://${raw}`).replace(/\\/$/, \"\");\n const host = new URL(url).host;\n const name = machineName(cfg, os.hostname());\n const before = cfg.sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n const tier = connectTier(flag(\"--tier\"), before?.tier);\n out(` Connecting ${name} to ${host}.`);\n\n // 1. The hooks, for every agent on this machine (and every Claude Code account).\n const adapters = ADAPTERS.filter((a) => a.detect());\n if (!adapters.length)\n out(\n \" ! No coding agent here yet (Claude Code, Codex, Gemini CLI, Antigravity, Devin): run `sessionpipe install` once you have one.\",\n );\n else installHarnesses(adapters, cfg, tier < 1);\n writeConfig(cfg);\n await reportClaudeAccounts();\n const rows = collectRows(adapters, 30);\n\n // 2. One approval on any signed-in device: the machine's control token and its\n // sessions key together.\n const control = readControl();\n const paired = control?.receivers.find((r) => r.url === url);\n const sinkNow = readConfig().sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n if (paired && sinkNow && (sinkNow.token || sinkNow.token_in)) {\n out(` \u2713 Already paired with ${host} as ${paired.machine}: nothing to approve.`);\n } else {\n const recent = rows\n .slice()\n .sort((a, b) => b.row.last_at - a.row.last_at)\n .map((r) => r.row.session.cwd ?? \"\");\n const choice = connectFolders({\n cwd: process.cwd(),\n home: os.homedir(),\n flags: argsAll(\"--folder\"),\n existing: control?.folders ?? [],\n recent,\n exists: (d) => {\n try {\n return statSync(d).isDirectory();\n } catch {\n return false;\n }\n },\n });\n if (choice.from === \"recent\")\n out(` Folders from your recent sessions: ${choice.folders.map((d) => tilde(d)).join(\", \")}`);\n if (choice.from === \"none\")\n out(\n \" ! No folder for sessions you message yet (this ran from your home folder, and no recent session ran anywhere else). Run `sessionpipe control pair` again from a project folder, or with --folder.\",\n );\n const mode =\n flag(\"--mode\") === \"auto\" || flag(\"--mode\") === \"safe\" ? (flag(\"--mode\") as string) : (control?.mode ?? \"safe\");\n await controlMain(\n [\n \"control\",\n \"pair\",\n url,\n \"--mode\",\n mode,\n \"--tier\",\n String(tier),\n \"--name\",\n control?.name ?? name,\n ...choice.folders.flatMap((d) => [\"--folder\", d]),\n ...(has(\"--no-service\") ? [\"--no-service\"] : []),\n ],\n out,\n distDir,\n );\n if (mode === \"safe\")\n out(\n \" Safe mode: `sessionpipe control mode auto` lets sessions you message work unattended (Claude Code's auto mode).\",\n );\n }\n\n // 3. The sink at the tier asked for, with the receiver's cap and endpoints.\n const after = readConfig();\n const sink = after.sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n if (sink) {\n const old = sink.tier;\n sink.tier = tier;\n await learnReceiver(sink, tier);\n writeConfig(after);\n const eff = Math.min(sink.tier, sink.max_tier ?? 3) as Tier;\n out(` \u2713 Sink ${sink.name}: tier ${eff}${old !== tier ? ` (was ${old})` : \"\"} \u2014 sends ${TIER_TEXT[eff]}`);\n } else out(` ! No sink for ${host}: \\`sessionpipe sink add ${url} --token <key> --tier ${tier}\\``);\n\n // 4. Keys into the keychain, when this session has one unlocked.\n const store = bestStore();\n if (store !== \"file\") {\n const a = moveSinkSecrets(store);\n const b = moveControlSecrets(store);\n const kept = [...a.kept, ...b.kept];\n out(` \u2713 Keys: in ${storeLabel(store)}${kept.length ? ` (left in the file: ${kept.join(\", \")})` : \"\"}`);\n } else\n out(\n ` Keys: in ${tilde(path.dirname(configFile()))} at 0600 \u2014 no unlocked keychain in this session${process.env.SSH_CONNECTION ? \" (an ssh shell)\" : \"\"}`,\n );\n\n // 5. The last 30 days, now that there is somewhere to send them.\n if (rows.length) queueBackfill(rows, 30, readConfig());\n out(\"\");\n out(` Done: ${name} reports to ${host} and takes messages you sign on a device it trusts.`);\n out(\" Run this again any time; it only fixes what's missing. `sessionpipe doctor` checks everything.\");\n}\n\nfunction argsAll(name: string): string[] {\n return args.flatMap((a, i) => (a === name && args[i + 1] ? [args[i + 1] as string] : []));\n}\n\n/** Each Claude Code account on this machine, and whether Claude Code says it's signed\n * in from here (a message's headless run uses this login). */\nasync function reportClaudeAccounts(): Promise<void> {\n const bin = claudeControl.findClaude();\n if (!bin) return;\n const dirs = claudeDirs();\n const answers = await Promise.all(dirs.map((d) => claudeControl.claudeLogin(bin, d)));\n dirs.forEach((d, i) => {\n const l = answers[i] as claudeControl.Login;\n if (l.loggedIn === true)\n out(\n ` \u2713 Claude Code ${tilde(d)}: signed in${l.method ? ` (${[l.method, l.subscription].filter(Boolean).join(\", \")})` : \"\"}`,\n );\n else if (l.loggedIn === false)\n out(\n ` ! Claude Code ${tilde(d)}: not signed in as this shell sees it \u2014 ${claudeControl.loginCommand(d)}${process.platform === \"darwin\" && process.env.SSH_CONNECTION ? \" (over ssh a Mac's keychain login can't be read; log in at the screen)\" : \"\"}`,\n );\n });\n}\n\n/** `sessionpipe secrets [move <store>]`: where this machine's keys live. */\nfunction secrets(): void {\n const sub = args[1];\n if (sub === \"move\") {\n const to = args[2] as StoreName | undefined;\n if (to !== \"keychain\" && to !== \"secret-service\" && to !== \"file\") {\n out(\"usage: sessionpipe secrets move keychain|secret-service|file\");\n return;\n }\n const a = moveSinkSecrets(to);\n const b = moveControlSecrets(to);\n const moved = [...a.moved, ...b.moved];\n const kept = [...a.kept, ...b.kept];\n out(\n moved.length ? ` \u2713 moved to ${storeLabel(to)}: ${moved.join(\", \")}` : ` nothing to move to ${storeLabel(to)}`,\n );\n if (kept.length)\n out(` ! left where they are (unreadable here, or ${storeLabel(to)} refused them): ${kept.join(\", \")}`);\n return;\n }\n const cfg = readConfig();\n const where = (s: SinkConfig): string =>\n s.token_in\n ? `${storeLabel(s.token_in)}${sinkWithSecrets(s) ? \"\" : \" \u2014 can't be read from this session (locked?)\"}`\n : s.token || s.secret\n ? `${tilde(configFile())} (0600)`\n : \"no key\";\n for (const s of cfg.sinks) out(` sink ${s.name.padEnd(20)} ${where(s)}`);\n for (const r of readControl()?.receivers ?? [])\n out(\n ` control ${new URL(r.url).host.padEnd(17)} ${r.token_in ? `${storeLabel(r.token_in)}${r.token ? \"\" : \" \u2014 can't be read from this session (locked?)\"}` : \"control.json (0600)\"}`,\n );\n if (!cfg.sinks.length && !readControl()?.receivers.length) out(\" no keys on this machine\");\n out(` best store from this session: ${storeLabel(bestStore())}`);\n}\n\n/** The one env var that moves a harness's config off the real home (`antigravity`\n * lives under Gemini CLI's). A harness with none (null) can never be isolated. */\nconst AWAY_FROM_HOME: Record<string, string | null> = {\n \"claude-code\": \"CLAUDE_CONFIG_DIR\",\n codex: \"CODEX_HOME\",\n \"gemini-cli\": \"GEMINI_CLI_HOME\",\n antigravity: \"GEMINI_CLI_HOME\",\n devin: \"XDG_CONFIG_HOME\",\n};\n/** Harnesses this process would read out of the real home although SESSIONPIPE_CONFIG\n * or SESSIONPIPE_STATE say \"not this machine\". Setting those is how a test or an agent\n * sandboxes sessionpipe \u2014 but they only cover sessionpipe's own files, so an\n * all-harnesses uninstall under them still empties the live hooks files (measured\n * twice on a reporting machine, 8 Oct 2026: six config files rewritten, every `status`\n * row `missing`). */\nfunction unisolated(): string[] {\n if (!process.env.SESSIONPIPE_CONFIG && !process.env.SESSIONPIPE_STATE) return [];\n return ADAPTERS.filter((a) => {\n const v = AWAY_FROM_HOME[a.name];\n return v === null || (typeof v === \"string\" && !process.env[v]);\n }).map((a) => a.name);\n}\n\nfunction uninstall(): void {\n // `install` has had a per-harness selector all along; uninstall taking every harness\n // with no way to say otherwise is how one harness's test strips the other four.\n const named = ADAPTERS.filter((a) => has(`--${a.name}`));\n const all = !named.length;\n if (all && !has(\"--all\")) {\n const exposed = unisolated();\n if (exposed.length) {\n out(\n ` ! Refusing an uninstall of every harness: SESSIONPIPE_CONFIG/SESSIONPIPE_STATE point away from this machine, but ${exposed.join(\", \")} still resolve from ${tilde(os.homedir())}.`,\n );\n out(` Nothing was changed. Name what to remove (${exposed.map((n) => `--${n}`).join(\" \")}),`);\n out(\" pass --all if you do mean every harness on this machine, or unset SESSIONPIPE_CONFIG/SESSIONPIPE_STATE.\");\n process.exitCode = 2;\n return;\n }\n }\n const cfg = readConfig();\n for (const a of all ? ADAPTERS : named) {\n const created = cfg.harnesses[a.name]?.created ?? [];\n for (const r of a.uninstall(process.env, { created }))\n if (r.changed) out(` \u2713 ${a.name}: ${r.note ?? `hooks removed from ${tilde(r.file)}`}`);\n else if (r.skipped) out(` ! ${a.name}: ${tilde(r.file)} \u2014 ${r.note}`);\n delete cfg.harnesses[a.name];\n }\n writeConfig(cfg);\n // The launcher is shared: removing it while another harness still has hook entries\n // would leave that harness running a path that is gone.\n if (all && usesLauncher()) removeLauncher();\n if (!all) {\n out(` Still installed: ${Object.keys(cfg.harnesses).join(\", \") || \"nothing\"}.`);\n return;\n }\n if (!has(\"--keep-state\"))\n out(\n ` Outbox and state kept under ${tilde(state)} (delete it yourself, or pass nothing: it prunes after ${readConfig().keep_days ?? 30} days).`,\n );\n out(\" Done. Every config file is byte-identical except for the entries sessionpipe wrote.\");\n}\n\nasync function sink(): Promise<void> {\n const sub = args[1];\n const cfg = readConfig();\n if (sub === \"add\" && args[2]) return sinkAdd(args[2], cfg);\n if (sub === \"list\") {\n if (!cfg.sinks.length) out(\" no sinks\");\n for (const s of cfg.sinks)\n out(\n ` ${s.name.padEnd(16)} ${s.url.padEnd(44)} tier ${s.tier}${s.max_tier !== undefined && s.max_tier < s.tier ? ` (capped ${s.max_tier})` : \"\"}${s.pii ? \" pii\" : \"\"}${s.control ? \" control\" : \"\"}${s.paused ? ` PAUSED ${s.paused}` : \"\"}`,\n );\n return;\n }\n if (sub === \"remove\" && args[2]) {\n const n = cfg.sinks.length;\n for (const s of cfg.sinks) if (s.name === args[2]) dropSinkSecrets(s);\n cfg.sinks = cfg.sinks.filter((s) => s.name !== args[2]);\n writeConfig(cfg);\n out(cfg.sinks.length < n ? ` \u2713 removed ${args[2]}` : ` no sink named ${args[2]}`);\n return;\n }\n if (sub === \"test\" && args[2]) {\n const s = cfg.sinks.find((x) => x.name === args[2]);\n if (!s) return out(` no sink named ${args[2]}`);\n const [sk] = buildSinks([s]);\n if (!sk) return out(\" sink type not supported yet\");\n // One heartbeat, then its forget: the receiver sees the round trip and keeps no row.\n const session = { id: `test-${Date.now()}`, machine: machineName(cfg, os.hostname()) };\n const mk = (type: string, seq: number) =>\n makeEvent(\n { type, harnessEvent: \"test\", data: {} },\n { harness: { name: \"sessionpipe\" }, session: { ...session, seq } },\n );\n const r = await sk.send([\n filterEvent(mk(\"session.heartbeat\", 0), sk.tier, sk.pii) as Event,\n filterEvent(mk(\"session.forgotten\", 1), sk.tier, sk.pii) as Event,\n ]);\n out(\n r.ok\n ? ` \u2713 ${s.name}: ${r.status ?? \"ok\"} accepted ${r.accepted ?? 2} (a heartbeat and its forget)`\n : ` \u2717 ${s.name}: ${r.status ?? \"\"} ${r.error ?? \"\"} (${r.action})`,\n );\n return;\n }\n out(\n \"usage: sessionpipe sink add <url|file:PATH|stdout> [--tier N] [--token T] [--pii] [--name N] | list | remove <name> | test <name>\",\n );\n}\n\nasync function sinkAdd(url: string, cfg: Config): Promise<void> {\n const tier = Math.max(0, Math.min(3, Number(flag(\"--tier\") ?? 0))) as Tier;\n const name = flag(\"--name\") ?? (url === \"stdout\" ? \"stdout\" : url.startsWith(\"file:\") ? \"file\" : new URL(url).host);\n // Control is not a property of a sink: it is set up per machine, with keys enrolled\n // at this terminal (spec/CONTROL.md \u00A72, `sessionpipe control pair`). A sink never\n // carries `control: true`.\n if (has(\"--control\"))\n out(\" --control is ignored: control is set up per machine (`sessionpipe control pair <url>`, spec/CONTROL.md)\");\n const s: SinkConfig = { name, url, tier, pii: has(\"--pii\") };\n // Changing a sink's tier keeps the key it has (pairing may have handed it over, and\n // it may live in a keychain): only --token / --secret replace one.\n const prev = cfg.sinks.find((x) => x.name === name && x.url === url);\n const token = flag(\"--token\");\n const secret = flag(\"--secret\");\n if (prev?.token_in && !token && !secret) s.token_in = prev.token_in;\n else {\n const kept = prev ? sinkWithSecrets(prev) : null;\n const t = token ?? kept?.token;\n const sec = secret ?? kept?.secret;\n if (t) s.token = t;\n if (sec) s.secret = sec;\n if (prev?.token_in) dropSinkSecrets(prev);\n }\n await learnReceiver(s, tier);\n cfg.sinks = cfg.sinks.filter((x) => x.name !== name).concat([s]);\n writeConfig(cfg);\n out(` \u2713 sink ${name}: ${url} at tier ${Math.min(tier, s.max_tier ?? 3)}${s.pii ? \", pii\" : \"\"}`);\n out(` tier ${tier} sends: ${TIER_TEXT[Math.min(tier, s.max_tier ?? 3) as Tier]}`);\n}\n/** Read the receiver's well-known file onto the sink: its tier cap and endpoints. */\nasync function learnReceiver(s: SinkConfig, tier: Tier): Promise<void> {\n if (!/^https?:\\/\\//.test(s.url)) return;\n try {\n const r = await fetch(`${s.url.replace(/\\/$/, \"\")}/.well-known/sessionpipe`, { signal: AbortSignal.timeout(8000) });\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n const wk = (await r.json()) as { max_tier?: number; endpoints?: { events?: string }; capabilities?: string[] };\n if (typeof wk.max_tier === \"number\") {\n s.max_tier = wk.max_tier as Tier;\n if (wk.max_tier < tier) out(` receiver's max_tier is ${wk.max_tier}: sending tier ${wk.max_tier}, not ${tier}`);\n }\n if (wk.endpoints) (s as SinkConfig & { endpoints?: unknown }).endpoints = wk.endpoints;\n s.well_known_at = new Date().toISOString();\n } catch (e) {\n out(\n ` ! ${s.url} has no readable /.well-known/sessionpipe (${(e as Error).message}); added anyway, at tier ${tier}`,\n );\n }\n}\n\nconst TIER_TEXT: Record<Tier, string> = {\n 0: \"session state and timing, machine, folder, repo, branch, model, title, link, the KIND of attention needed \u2014 no tool names, no words\",\n 1: \"tier 0 + tool names, durations, ok/error, file paths, the attention message, subagents, compactions \u2014 no prompts\",\n 2: \"tier 1 + your prompts and the assistant's text, secrets removed\",\n 3: \"everything, including tool input and output\",\n};\n\n/** Each harness's sessions of the last `days` days, as the backfill reads them. */\nfunction collectRows(\n adapters: readonly (typeof ADAPTERS)[number][],\n days: number,\n): { harness: string; row: BackfillRow }[] {\n const since = Date.now() - days * 86_400_000;\n const rows: { harness: string; row: BackfillRow }[] = [];\n for (const a of adapters) {\n try {\n for (const row of a.backfill(since)) rows.push({ harness: a.name, row });\n } catch {}\n }\n return rows;\n}\n\nfunction backfillRows(adapters: readonly (typeof ADAPTERS)[number][], days: number, cfg: Config): void {\n queueBackfill(collectRows(adapters, days), days, cfg);\n}\n\nfunction queueBackfill(rows: { harness: string; row: BackfillRow }[], days: number, cfg: Config): void {\n const outbox = new Outbox(state);\n let n = 0;\n const machine = machineName(cfg, os.hostname());\n for (const { harness, row } of rows) {\n const ref = { harness, session: row.session.id };\n const facts = factsState(state).get(harness, row.session.id);\n if (facts.backfilled) continue;\n const { id, ...rest } = row.session;\n const e = makeEvent(\n {\n type: \"session.backfill\",\n harnessEvent: \"backfill\",\n data: {\n started_at: new Date(row.started_at).toISOString(),\n last_at: new Date(row.last_at).toISOString(),\n ...(row.turns !== undefined ? { turns: row.turns } : {}),\n },\n },\n {\n harness: { name: harness },\n session: { ...rest, id, seq: outbox.nextSeq(ref), machine, ...(rest.cwd ? { cwd: tilde(rest.cwd) } : {}) },\n now: row.last_at,\n },\n );\n outbox.append(ref, [e]);\n factsState(state).save(harness, row.session.id, { backfilled: true });\n n++;\n }\n out(` \u2713 Backfill: ${n} session${n === 1 ? \"\" : \"s\"} from the last ${days} days queued as session.backfill`);\n void drain(state, cfg.sinks, outbox);\n}\n\nfunction backfill(): void {\n backfillRows(selectedAdapters(), Number(flag(\"--days\") ?? 30), readConfig());\n}\n\nasync function forget(): Promise<void> {\n const [, harness, session] = args;\n if (!harness || !session) return out(\"usage: sessionpipe forget <harness> <session>\");\n const cfg = readConfig();\n const outbox = new Outbox(state);\n const ref = { harness, session };\n const e = makeEvent(\n { type: \"session.forgotten\", harnessEvent: \"forget\", data: {} },\n {\n harness: { name: harness },\n session: { id: session, seq: outbox.nextSeq(ref), machine: machineName(cfg, os.hostname()) },\n },\n );\n const sinks = buildSinks(cfg.sinks);\n for (const s of sinks) {\n const r = await s.send([filterEvent(e, s.tier, s.pii) as Event]);\n out(r.ok ? ` \u2713 ${s.name}: asked to delete ${harness}:${session}` : ` \u2717 ${s.name}: ${r.error ?? r.status}`);\n }\n outbox.delete(ref);\n out(\" local outbox for the session removed\");\n}\n\nasync function replay(): Promise<void> {\n const name = flag(\"--sink\");\n const cfg = readConfig();\n const sinks = name ? cfg.sinks.filter((s) => s.name === name) : cfg.sinks;\n if (!sinks.length) return out(\" no such sink\");\n for (const s of sinks) {\n if (has(\"--from-start\")) new Cursors(state, s.name).write({});\n }\n const d = await flush(state, sinks, new Outbox(state), undefined, { force: true });\n for (const [k, v] of Object.entries(d)) out(` ${k}: ${v} event${v === 1 ? \"\" : \"s\"} delivered`);\n}\n\ntype ControlHealth = {\n running: boolean;\n receivers: (Pick<Status[\"receivers\"][number], \"url\" | \"polling\" | \"last_poll\" | \"last_error\"> & {\n last_poll_age_ms: number | null;\n })[];\n};\n\nasync function controlHealth(): Promise<ControlHealth | null> {\n if (!pairedCount()) return null;\n const reply = await ask(socketPath(state), { op: \"status\" }, 1500);\n if (reply?.op !== \"status\") return { running: false, receivers: [] };\n const status = reply.status as Status;\n return {\n running: true,\n receivers: status.receivers.map((r) => ({\n url: r.url,\n polling: r.polling,\n last_poll: r.last_poll,\n last_error: r.last_error,\n // An older daemon has no age field. Its last_poll still exposes a loop\n // that stopped long ago, and polling=false catches the terminal 401.\n last_poll_age_ms: r.last_poll_age_ms ?? (r.last_poll === null ? null : Math.max(0, Date.now() - r.last_poll)),\n })),\n };\n}\n\nfunction controlLines(control: ControlHealth | null): void {\n if (!control) {\n out(\" control: not paired\");\n return;\n }\n if (!control.running) {\n out(\" control: daemon not running or not responding; polling: no\");\n return;\n }\n for (const r of control.receivers) {\n const age = r.last_poll_age_ms === null ? \"unknown\" : `${Math.floor(r.last_poll_age_ms / 60_000)} minutes`;\n out(\n ` control: ${r.url} \u00B7 polling: ${r.polling ? \"yes\" : \"no\"} \u00B7 last successful poll: ${r.last_poll === null ? `never (${age} since start)` : `${age} ago`} \u00B7 last error: ${r.last_error ?? \"none\"}`,\n );\n }\n}\n\nasync function status(): Promise<void> {\n const cfg = readConfig();\n const hc = hookCommand();\n const json = has(\"--json\");\n const harnesses: Record<string, { file: string; state: string; note?: string }[]> = {};\n const sinks = [];\n if (!json) out(` machine: ${machineName(cfg, os.hostname())} sessionpipe ${VERSION} state ${tilde(state)}`);\n for (const a of ADAPTERS) {\n if (!a.detect() && !cfg.harnesses[a.name]) continue;\n const installed = a.installed(hc, process.env, { lean: isLean(cfg) });\n harnesses[a.name] = installed.map((r) => ({\n file: tilde(r.file),\n state: r.state,\n ...(r.note ? { note: r.note } : {}),\n }));\n if (!json)\n for (const r of installed)\n out(\n ` ${a.name.padEnd(12)} ${tilde(r.file).padEnd(44)} ${r.state}${r.state !== \"current\" && r.note ? ` \u2014 ${r.note}` : \"\"}`,\n );\n }\n if (!json && !cfg.sinks.length) out(\" sinks: none (events stay in the local outbox)\");\n for (const s of cfg.sinks) {\n const c = new Cursors(state, s.name).read();\n const outbox = new Outbox(state);\n let pending = 0;\n for (const ref of outbox.sessions()) {\n const f = outbox.file(ref);\n try {\n pending += Math.max(0, statSync(f).size - (c[`${ref.harness}/${ref.session}`] ?? 0)) > 0 ? 1 : 0;\n } catch {}\n }\n sinks.push({\n name: s.name,\n url: s.url,\n tier: s.tier,\n max_tier: s.max_tier ?? null,\n pii: !!s.pii,\n control: !!s.control,\n paused: s.paused ?? null,\n pending_sessions: pending,\n });\n if (!json)\n out(\n ` sink ${s.name.padEnd(16)} tier ${Math.min(s.tier, s.max_tier ?? 3)} ${s.paused ? `PAUSED ${s.paused}` : pending ? `${pending} session file(s) with undelivered events` : \"up to date\"}`,\n );\n }\n const control = await controlHealth();\n if (!json) controlLines(control);\n const update = updateState(cfg);\n if (!json) out(` update: ${updateLine(update, Date.now())}`);\n const t = timing();\n if (!json && t)\n out(\n ` hook: in-process p50 ${t.p50} ms over ${t.n} runs (\\`sessionpipe doctor\\` measures the wall clock the harness waits)`,\n );\n let jobs = 0;\n try {\n jobs = readdirSync(jobsDir(state)).filter((n) => n.endsWith(\".json\")).length;\n } catch {}\n if (json)\n out(\n JSON.stringify(\n {\n version: VERSION,\n machine: machineName(cfg, os.hostname()),\n state,\n config: configFile(),\n harnesses,\n sinks,\n timing: t,\n control,\n update,\n jobs,\n },\n null,\n 2,\n ),\n );\n else if (jobs) out(` jobs: ${jobs} waiting`);\n}\n\n/** Spawn the hook the way a harness does and time the whole process (issue #12:\n * the in-process clock misses Node's startup, ~200 ms on an older Intel Mac). */\nfunction hookWall(runs = 8): { n: number; p50: number; p95: number } | null {\n const hook = path.join(distDir, \"hook.js\");\n const tmp = mkdtempSync(path.join(os.tmpdir(), \"sessionpipe-doctor-\"));\n const env = {\n ...process.env,\n SESSIONPIPE_STATE: tmp,\n SESSIONPIPE_CONFIG: path.join(tmp, \"config.json\"),\n SESSIONPIPE_NO_WORKER: \"1\",\n };\n const input = JSON.stringify({\n session_id: \"doctor\",\n hook_event_name: \"PostToolUse\",\n tool_name: \"Bash\",\n cwd: process.cwd(),\n });\n const times: number[] = [];\n try {\n for (let i = 0; i < runs; i++) {\n const t0 = process.hrtime.bigint();\n const r = spawnSync(process.execPath, [hook, \"claude-code\", \"PostToolUse\"], { input, env, encoding: \"utf8\" });\n if (r.status !== 0) return null;\n times.push(Number(process.hrtime.bigint() - t0) / 1e6);\n }\n } catch {\n return null;\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n times.sort((a, b) => a - b);\n // `?? 0` satisfies noUncheckedIndexedAccess: the index is clamped to the last of `runs` entries.\n const q = (p: number) =>\n Math.round(/* v8 ignore next */ times[Math.min(times.length - 1, Math.floor(p * times.length))] ?? 0);\n return { n: times.length, p50: q(0.5), p95: q(0.95) };\n}\n\nfunction timing(): { n: number; p50: number; p95: number } | null {\n try {\n const lines = readFileSync(path.join(state, \"timing.jsonl\"), \"utf8\").trim().split(\"\\n\").slice(-100);\n const ms = lines\n .map((l) => (JSON.parse(l) as { ms: number }).ms)\n .filter((x) => x >= 0)\n .sort((a, b) => a - b);\n if (!ms.length) return null;\n // `?? 0` satisfies noUncheckedIndexedAccess: the index is clamped to the last of a non-empty list.\n const q = (p: number) =>\n Math.round(/* v8 ignore next */ ms[Math.min(ms.length - 1, Math.floor(p * ms.length))] ?? 0);\n return { n: ms.length, p50: q(0.5), p95: q(0.95) };\n } catch {\n return null;\n }\n}\n\nasync function doctor(): Promise<void> {\n const cfg = readConfig();\n const hc = hookCommand();\n const report: Record<string, unknown> = {\n version: VERSION,\n node: process.version,\n node_path: stableNode(process.execPath),\n machine: machineName(cfg, os.hostname()),\n state: state,\n config: configFile(),\n harnesses: {},\n sinks: [],\n timing: timing(),\n hook_wall_ms: hookWall(),\n update: updateState(cfg),\n warnings: [] as string[],\n };\n const warnings = report.warnings as string[];\n const health = await controlHealth();\n report.control = health;\n if (health && !health.running)\n warnings.push(\"the control daemon is not running or not responding; polling is stopped\");\n for (const r of health?.receivers ?? []) {\n // A normal long-poll takes 25 s (35 s deadline). Allow one minute at startup\n // and between responses, but report a stopped/backing-off loop immediately.\n if (!r.polling || (r.last_poll_age_ms !== null && r.last_poll_age_ms >= 60_000)) {\n const age =\n r.last_poll_age_ms === null\n ? \"never polled\"\n : `not polled for ${Math.floor(r.last_poll_age_ms / 60_000)} minutes`;\n warnings.push(\n `${r.url}: the daemon has ${age}: ${r.last_error ?? (r.polling ? \"no successful poll response\" : \"polling stopped\")}`,\n );\n }\n }\n const upd = report.update as ReturnType<typeof updateState>;\n if (upd.failed)\n warnings.push(\n `the control daemon couldn't install sessionpipe ${upd.failed.version}: ${upd.failed.error}. It tries again tomorrow; \\`sessionpipe update\\` tries now.`,\n );\n if (usesLauncher()) {\n const l = launcherState(VERSION);\n report.launcher = { file: tilde(l.file), node: l.node, node_ok: l.nodeOk, version: l.version };\n if (Object.keys(cfg.harnesses).length) warnings.push(...l.problems);\n }\n // Where each key lives, and whether this session can read it.\n const keys: { what: string; where: string; readable: boolean }[] = [];\n for (const s of cfg.sinks)\n if (s.token_in || s.token || s.secret)\n keys.push({ what: `sink ${s.name}`, where: s.token_in ?? \"file\", readable: !!sinkWithSecrets(s) });\n const control = readControl();\n for (const r of control?.receivers ?? [])\n keys.push({ what: `control ${new URL(r.url).host}`, where: r.token_in ?? \"file\", readable: !!r.token });\n report.keys = keys;\n for (const k of keys)\n if (!k.readable)\n warnings.push(\n `${k.what}: its key is in ${storeLabel(k.where as StoreName)}, which this session can't read (locked, or an ssh shell). Events wait; the control daemon sends them from your own session.`,\n );\n // Each Claude Code account: a message's headless run needs its login.\n const claudeBin = claudeControl.findClaude();\n if (claudeBin) {\n const dirs = claudeDirs();\n const logins = await Promise.all(dirs.map((d) => claudeControl.claudeLogin(claudeBin, d)));\n report.claude_accounts = dirs.map((d, i) => ({ dir: tilde(d), signed_in: logins[i]?.loggedIn ?? null }));\n dirs.forEach((d, i) => {\n if (logins[i]?.loggedIn === false && control?.receivers.length)\n warnings.push(`Claude Code ${tilde(d)} isn't signed in from here: ${claudeControl.loginCommand(d)}`);\n });\n }\n // A systemd user service stops at logout unless the user lingers.\n if (process.platform === \"linux\" && control?.receivers.length) {\n let linger: boolean | null = null;\n try {\n linger = /^Linger=yes/m.test(\n execFileSync(\"loginctl\", [\"show-user\", os.userInfo().username, \"--property=Linger\"], {\n encoding: \"utf8\",\n timeout: 5000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }),\n );\n } catch {}\n report.linger = linger;\n if (linger === false)\n warnings.push(\n `the control daemon stops when you log out: \\`loginctl enable-linger ${os.userInfo().username}\\` (with sudo if refused) keeps it running`,\n );\n }\n if (/\\/Cellar\\/node(?:@\\d+)?\\/[^/]+\\//.test(distDir))\n warnings.push(\n \"sessionpipe is installed inside Homebrew's versioned node folder; `brew upgrade node` will delete it. Install with `npm install -g --prefix ~/.local sessionpipe`.\",\n );\n for (const a of ADAPTERS) {\n if (!a.detect()) continue;\n const st = a.installed(hc, process.env, { lean: isLean(cfg) });\n (report.harnesses as Record<string, unknown>)[a.name] = st.map((r) => ({\n file: tilde(r.file),\n state: r.state,\n ...(r.note ? { note: r.note } : {}),\n }));\n for (const r of st)\n if (r.state === \"inactive\")\n warnings.push(`${a.name}: hooks are written but the harness will not run them \u2014 ${r.note ?? \"\"}`);\n for (const r of st)\n if (r.state === \"stale\")\n warnings.push(\n `${a.name}: the hook in ${tilde(r.file)} points at an old node or script path; run \\`sessionpipe install\\` again.`,\n );\n for (const r of st)\n if (r.state === \"misplaced\")\n warnings.push(\n `${a.name}: the notify line in ${tilde(r.file)} sits inside a [table], where Codex never reads it; run \\`sessionpipe install\\` again.`,\n );\n }\n for (const s of cfg.sinks)\n (report.sinks as unknown[]).push({\n name: s.name,\n url: s.url,\n tier: s.tier,\n max_tier: s.max_tier ?? null,\n pii: !!s.pii,\n control: !!s.control,\n paused: s.paused ?? null,\n token: s.token_in ? `in ${s.token_in}` : s.token ? `${s.token.slice(0, 4)}\u2026` : null,\n });\n const w = report.hook_wall_ms as { p50: number; p95: number; n: number } | null;\n if (w && w.p50 > 150)\n warnings.push(\n `the harness waits ${w.p50} ms per hook (p50, target < 150): that is Node's own startup on this machine. A lean install (no sink above tier 0) hooks fewer events.`,\n );\n if (has(\"--json\")) {\n out(JSON.stringify(report, null, 2));\n return;\n }\n out(` sessionpipe ${VERSION} \u00B7 node ${process.version} at ${report.node_path}`);\n out(` config ${tilde(configFile())} \u00B7 state ${tilde(state)}`);\n for (const [h, st] of Object.entries(report.harnesses as Record<string, { file: string; state: string }[]>))\n for (const r of st) out(` ${h.padEnd(12)} ${r.file.padEnd(44)} ${r.state}`);\n for (const s of report.sinks as { name: string; tier: number; max_tier: number | null; paused: string | null }[])\n out(\n ` sink ${s.name.padEnd(16)} tier ${s.tier}${s.max_tier !== null ? ` (receiver max ${s.max_tier})` : \"\"}${s.paused ? ` PAUSED ${s.paused}` : \"\"}`,\n );\n controlLines(health);\n const lr = report.launcher as { file: string; node: string | null; node_ok: boolean } | undefined;\n if (lr)\n out(` hooks run ${lr.file} \u2192 node ${lr.node ? tilde(lr.node) : \"?\"}${lr.node_ok ? \"\" : \" (gone: PATH's node)\"}`);\n for (const k of keys)\n out(` key ${k.what.padEnd(28)} ${storeLabel(k.where as StoreName)}${k.readable ? \"\" : \" (unreadable here)\"}`);\n for (const a of (report.claude_accounts as { dir: string; signed_in: boolean | null }[] | undefined) ?? [])\n out(\n ` claude ${a.dir.padEnd(26)} ${a.signed_in === true ? \"signed in\" : a.signed_in === false ? \"NOT signed in from here\" : \"can't tell\"}`,\n );\n out(` update ${updateLine(upd, Date.now())}`);\n const t = report.timing as { p50: number; p95: number; n: number } | null;\n out(\n w\n ? ` hook wall clock (what the harness waits): p50 ${w.p50} ms \u00B7 p95 ${w.p95} ms over ${w.n} spawns`\n : \" hook wall clock: could not spawn dist/hook.js\",\n );\n out(\n t\n ? ` hook in-process: p50 ${t.p50} ms \u00B7 p95 ${t.p95} ms over the last ${t.n} runs`\n : \" hook in-process: no runs yet\",\n );\n for (const w of warnings) out(` ! ${w}`);\n if (!warnings.length) out(\" no warnings\");\n}\n\n/** Follow the local outbox: one event per line, filtered to a tier. The zero-server demo. */\nasync function tail(): Promise<void> {\n const tier = Math.max(0, Math.min(3, Number(flag(\"--tier\") ?? 1))) as Tier;\n const onlySession = flag(\"--session\");\n const onlyHarness = flag(\"--harness\");\n const outbox = new Outbox(state);\n const offsets = new Map<string, number>();\n const fmt = (e: Event): string => {\n const t = e.time.slice(11, 19);\n const d = e.data as Record<string, unknown>;\n let detail = \"\";\n switch (e.type) {\n case \"session.started\":\n detail = `source=${d.source} ${e.session.cwd ?? \"\"} ${e.session.branch ?? \"\"}`;\n break;\n case \"turn.started\":\n detail = d.prompt_chars !== undefined ? `prompt_chars=${d.prompt_chars}` : \"\";\n break;\n case \"tool.started\":\n detail = String(d.tool ?? \"\");\n break;\n case \"tool.ended\":\n detail = `${d.tool} ${d.ok ? \"ok\" : \"error\"}${d.ms !== undefined ? ` ${d.ms}ms` : \"\"}`;\n break;\n case \"attention.needed\":\n detail = `${d.kind}${d.tool ? ` ${d.tool}` : \"\"}${d.message ? ` \"${String(d.message).slice(0, 60)}\"` : \"\"}`;\n break;\n case \"turn.ended\":\n detail = String(d.reason ?? \"\");\n break;\n case \"session.ended\":\n detail = `reason=${d.reason}`;\n break;\n case \"turn.transcript\":\n detail = `#${d.turn} \"${String(d.user).slice(0, 50).replace(/\\s+/g, \" \")}\"`;\n break;\n case \"turn.progress\":\n detail = `#${d.turn} ${String(d.assistant ?? \"\").length} chars so far`;\n break;\n case \"session.backfill\":\n detail = `${e.session.title ?? \"\"}`;\n break;\n default:\n detail = JSON.stringify(d).slice(0, 80);\n }\n return `${t} ${e.harness.name.padEnd(11)} ${e.session.id.slice(0, 4)}\u2026 ${e.type.padEnd(17)} ${detail}`;\n };\n out(`sessionpipe tail \u00B7 tier ${tier} \u00B7 ${tilde(state)}/outbox (Ctrl-C to stop)`);\n // Start at the end of each file unless --all.\n for (const ref of outbox.sessions()) {\n try {\n offsets.set(`${ref.harness}/${ref.session}`, has(\"--all\") ? 0 : statSync(outbox.file(ref)).size);\n } catch {}\n }\n for (;;) {\n for (const ref of outbox.sessions()) {\n if (onlyHarness && ref.harness !== onlyHarness) continue;\n if (onlySession && !ref.session.startsWith(onlySession)) continue;\n const k = `${ref.harness}/${ref.session}`;\n const from = offsets.get(k) ?? 0;\n const { events, offset } = outbox.read(ref, from, 200);\n offsets.set(k, offset);\n for (const e of events) {\n const f = filterEvent(e, tier, false);\n if (f) out(has(\"--json\") ? JSON.stringify(f) : fmt(f));\n }\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n}\n\nasync function workerFromArgv(): Promise<void> {\n const f = args[1];\n if (!f) return;\n const job = JSON.parse(readFileSync(f, \"utf8\"));\n try {\n unlinkSync(f);\n } catch {}\n await runJob(job);\n}\n\n/** Whether the daemon updates this copy by itself, and what it last found. */\nfunction updateState(cfg: Config) {\n return updateSummary({\n // The shell's own SESSIONPIPE_NO_UPDATE_CHECK says nothing about the daemon's\n // environment; the daemon records that one itself.\n off: autoUpdateOff({ env: {}, config: cfg, distDir }),\n paired: pairedCount() > 0,\n rec: readUpdate(updateFile()),\n });\n}\n\n/** `sessionpipe update [off|on]`: install the latest release into this copy's prefix\n * now, then have the daemon restart onto it once idle; or switch the daemon's daily\n * update off or on (config.json `update_check`; the daemon reads it every ten minutes). */\nasync function update(): Promise<void> {\n const sub = args[1];\n if (sub === \"off\" || sub === \"on\") {\n const cfg = readConfig();\n cfg.update_check = sub === \"on\";\n writeConfig(cfg);\n return out(\n sub === \"off\"\n ? \" \u2713 The control daemon no longer checks npm or updates itself. `sessionpipe update` still updates by hand; `sessionpipe update on` undoes this.\"\n : \" \u2713 The control daemon checks npm once a day and installs a new release when it's idle.\",\n );\n }\n if (process.env.SESSIONPIPE_NO_UPDATE_CHECK) return out(\" update check is off (SESSIONPIPE_NO_UPDATE_CHECK)\");\n let latest: string;\n try {\n latest = await latestVersion();\n } catch (e) {\n return out(` couldn't check npm: ${(e as Error).message}`);\n }\n if (!isNewer(latest, VERSION)) return out(` sessionpipe ${VERSION} is current (npm latest: ${latest})`);\n const prefix = globalPrefix(distDir);\n if (!prefix)\n return out(\n ` ${latest} is available (you run ${VERSION}), but this copy isn't a global npm install (npx, a checkout or a dev build): \\`npm install -g sessionpipe@${latest}\\` installs one.`,\n );\n out(` ${latest} is available (you run ${VERSION}); installing into ${tilde(prefix)}\u2026`);\n const r = await installVersion(latest, {\n node: process.execPath,\n distDir,\n harnesses: enabledHarnesses(readConfig().harnesses),\n });\n if (!r.ok) {\n process.exitCode = 1;\n return out(` \u2717 ${r.error}`);\n }\n out(` \u2713 sessionpipe ${latest} installed in ${(r.ms / 1000).toFixed(1)} s; ${r.hooks}`);\n // The daemon still runs the old code: it restarts onto this copy when nothing is in hand.\n const sock = socketPath(state);\n const st = await ask(sock, { op: \"status\" }, 2000);\n if (st?.op !== \"status\") return;\n const running = (st.status as { version?: string }).version ?? \"?\";\n if (running === latest) return;\n const r2 = await ask(sock, { op: \"restart\" }, 2000);\n if (r2?.op === \"ok\") out(` The control daemon (${running}) restarts onto ${latest} as soon as nothing is in hand.`);\n else\n out(\n ` The control daemon still runs ${running} and can't restart itself: ${\n process.platform === \"darwin\"\n ? `\\`launchctl kickstart -k gui/${process.getuid?.() ?? \"$(id -u)\"}/org.sessionpipe.control\\``\n : process.platform === \"linux\"\n ? \"`systemctl --user restart sessionpipe-control.service`\"\n : \"stop `sessionpipe control run` and start it again\"\n } moves it (a run in progress stops).`,\n );\n}\n\n// The process entrypoint (`node dist/cli.js`, or npm's bin link to it) runs the command;\n// an import of this module runs nothing.\nif (isEntrypoint(process.argv[1], import.meta.url)) {\n process.stdout.on(\"error\", (e: NodeJS.ErrnoException) => {\n if (e.code === \"EPIPE\") process.exit(0);\n });\n void main(process.argv.slice(2));\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Antigravity (Google) \u2014 docs: https://antigravity.google/docs/hooks\n// Config: ~/.gemini/config/hooks.json \u2014 top-level keys are hook NAMES, ours is\n// \"sessionpipe\". stdin is camelCase with NO event name (it rides in argv). A hook's\n// stdout is its answer; non-JSON is a deny. Timeouts in seconds. No session end\n// exists. Ported from spacesheep-cli lib/sessions.js (facts, remote url, projects).\n//\n// No PreToolUse. Its answer must carry a `decision` (allow / deny / ask / force_ask),\n// none of which means \"carry on\": `{}` is read as a deny with no reason, which blocked\n// every tool call on every machine 0.1\u20130.6.0 was installed on (2026-10-04, Antigravity\n// 2.19.1), and `allow` would wave calls past the person's own review settings. So the\n// tool events come from PostToolUse alone, which carries no tool name (only `stepIdx`\n// and `error`): it is a \"still working\" beat.\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n realpathSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines } from \"../readers/files.js\";\nimport { readAntigravity } from \"../readers/transcripts.js\";\nimport { formatJson, readJsonFile } from \"./claude-shaped.js\";\nimport type {\n Adapter,\n BackfillRow,\n HookCommand,\n HookInput,\n HookResult,\n InstallOptions,\n InstallReport,\n SessionFacts,\n} from \"./types.js\";\n\nconst NAME = \"antigravity\";\nconst HOOK_NAME = \"sessionpipe\";\nexport const AG_EVENTS = [\"PreInvocation\", \"PostInvocation\", \"PostToolUse\", \"Stop\"] as const;\n/** What a PreToolUse entry an older install left behind gets, until a restarted\n * conversation reads the rewritten hooks.json: the person's own prompt, with why. The\n * hook (cli/src/hook.ts) and the launcher (cli/src/launcher.ts) print the same line. */\nexport const AG_STALE_PRETOOL =\n '{\"decision\":\"ask\",\"reason\":\"sessionpipe: an outdated PreToolUse hook is still loaded. Restart this conversation (or run sessionpipe install) to drop it.\"}\\n';\n/** Antigravity's answer for one event: `{}` is \"carry on\" for every event we register. */\nexport const antigravityAnswer = (event: string): string => (event === \"PreToolUse\" ? AG_STALE_PRETOOL : \"{}\\n\");\nconst gemini = (env: NodeJS.ProcessEnv) => env.GEMINI_CLI_HOME || path.join(homeDir(), \".gemini\");\nconst hooksFile = (env: NodeJS.ProcessEnv) => path.join(gemini(env), \"config\", \"hooks.json\");\nconst projectsDir = (env: NodeJS.ProcessEnv) => path.join(gemini(env), \"config\", \"projects\");\nconst dataDirs = (env: NodeJS.ProcessEnv) =>\n [\"antigravity\", \"antigravity-cli\", \"antigravity-ide\"].map((d) => path.join(gemini(env), d));\nconst ID_RE = /^[A-Za-z0-9_-]{1,128}$/;\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\n\n// One tool event already, so a lean install is the same entry.\nfunction entry(cmd: HookCommand) {\n const handler = (e: string) => ({ type: \"command\", command: cmd([NAME, e]).command, timeout: 5 });\n const out: Record<string, unknown> = { enabled: true };\n for (const e of AG_EVENTS) out[e] = /Tool/.test(e) ? [{ matcher: \"*\", hooks: [handler(e)] }] : [handler(e)];\n return out;\n}\n\nexport const antigravity: Adapter = {\n name: NAME,\n events: AG_EVENTS,\n detect: (env = process.env) =>\n existsSync(path.join(gemini(env), \"config\")) || dataDirs(env).some((d) => existsSync(d)),\n configFiles: (env = process.env) => [hooksFile(env)],\n install(cmd, env = process.env): InstallReport[] {\n const file = hooksFile(env);\n const f = readJsonFile(file);\n if (!f.ok) return [{ file, changed: false, skipped: true, note: `${f.reason}; not touched` }];\n const hooks = f.value;\n const e = entry(cmd);\n if (JSON.stringify(hooks[HOOK_NAME]) === JSON.stringify(e)) return [{ file, changed: false }];\n hooks[HOOK_NAME] = e;\n mkdirSync(path.dirname(file), { recursive: true });\n writeFileSync(file, formatJson(hooks, f));\n return [\n {\n file,\n changed: true,\n created: !f.existed,\n note: \"hooks.json is read when a conversation starts; open ones report after a restart\",\n },\n ];\n },\n uninstall(env = process.env, opts: InstallOptions = {}): InstallReport[] {\n const file = hooksFile(env);\n if (!existsSync(file)) return [{ file, changed: false }];\n const f = readJsonFile(file);\n if (!f.ok) return [{ file, changed: false, skipped: true, note: `${f.reason}; not touched` }];\n const hooks = f.value;\n if (!(HOOK_NAME in hooks)) return [{ file, changed: false }];\n delete hooks[HOOK_NAME];\n if (opts.created?.includes(file) && !Object.keys(hooks).length) {\n unlinkSync(file);\n return [{ file, changed: true, note: \"removed (sessionpipe created it)\" }];\n }\n writeFileSync(file, formatJson(hooks, f));\n return [{ file, changed: true }];\n },\n installed(cmd, env = process.env) {\n const file = hooksFile(env);\n const f = readJsonFile(file);\n const have = f.ok ? f.value[HOOK_NAME] : undefined;\n return [\n {\n file,\n state: !have ? \"missing\" : JSON.stringify(have) === JSON.stringify(entry(cmd)) ? \"current\" : \"stale\",\n },\n ];\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = (s.conversationId ?? s.session_id ?? s.sessionId) as string | undefined;\n const stdout = antigravityAnswer(event);\n if (!id) return { session: { id: \"\" }, events: [], stdout };\n const workspaces = agWorkspaces(s.workspacePaths);\n const session: HookResult[\"session\"] = { id: String(id), cwd: workspaces[0] ?? input.cwd };\n if (typeof s.modelName === \"string\" && s.modelName !== \"auto\") session.model = s.modelName;\n const toolCall = s.toolCall as { name?: unknown; args?: unknown } | undefined;\n const tool = validTool(toolCall?.name) ? toolCall?.name : validTool(s.toolName) ? s.toolName : undefined;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"PreInvocation\":\n // Fires before every model call of an execution; only the first is the person's ask.\n if (Number(s.invocationNum) === 0 || s.invocationNum === undefined) {\n events.push(ev(\"session.started\", { source: \"unknown\" }));\n events.push(ev(\"turn.started\", {}));\n } else events.push(ev(\"session.heartbeat\", {}));\n break;\n case \"PostInvocation\":\n break;\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, input: toolCall?.args }));\n break;\n case \"PostToolUse\":\n // Antigravity names no tool here; a beat keeps a long run of tools \"working\".\n if (!tool) events.push(ev(\"session.heartbeat\", {}));\n else\n events.push(\n ev(\"tool.ended\", {\n tool,\n ok: !s.error,\n error: typeof s.error === \"string\" ? s.error.slice(0, 2000) : undefined,\n input: toolCall?.args,\n }),\n );\n break;\n case \"Stop\":\n events.push(ev(\"turn.ended\", { reason: s.error ? \"error\" : \"stop\" }));\n break;\n default:\n return { session, events: [], stdout };\n }\n const r: HookResult = { session, events, stdout, hints: { workspaces } };\n if (typeof s.transcriptPath === \"string\") r.transcript = s.transcriptPath;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readAntigravity(text.split(\"\\n\"), fromLine);\n },\n\n facts(session, transcript, hints): SessionFacts {\n if (!transcript) return {};\n return antigravityFacts(transcript, {\n conversation: session.id,\n workspaces: (hints.workspaces as string[] | undefined) ?? (session.cwd ? [session.cwd] : []),\n env: process.env,\n });\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows: BackfillRow[] = [];\n for (const data of dataDirs(env)) {\n let ids: string[] = [];\n try {\n ids = readdirSync(path.join(data, \"brain\")).filter((n) => /^[0-9a-f-]{36}$/i.test(n));\n } catch {}\n for (const id of ids) {\n const f = path.join(data, \"brain\", id, \".system_generated\", \"logs\", \"transcript.jsonl\");\n try {\n if (statSync(f).mtimeMs < sinceMs) continue;\n } catch {\n continue;\n }\n const facts = antigravityFacts(f, { conversation: id, workspaces: [], env });\n if (!facts.started_at || !facts.last_at) continue;\n const { started_at, last_at, first_ask: _fa, harness_version: _hv, ...rest } = facts;\n rows.push({ session: { id, ...rest }, started_at, last_at });\n }\n }\n return rows;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n\n/** A folder as Antigravity writes it (a file:// URI or a path) \u2192 an absolute path, or null. */\nexport function agPath(p: unknown): string | null {\n if (typeof p !== \"string\" || !p) return null;\n let s = p;\n if (/^file:/i.test(s)) {\n try {\n s = decodeURIComponent(new URL(s).pathname);\n } catch {\n return null;\n }\n if (process.platform === \"win32\" && /^\\/[A-Za-z]:/.test(s)) s = s.slice(1);\n } else if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(s)) return null;\n if (!path.isAbsolute(s)) return null;\n return path.resolve(s);\n}\nexport const agWorkspaces = (paths: unknown): string[] =>\n (Array.isArray(paths) ? paths : [])\n .map(agPath)\n .filter((p): p is string => !!p)\n .filter((p, i, a) => a.indexOf(p) === i);\n\nfunction agVariants(p: string): string[] {\n const out = [p];\n try {\n const r = realpathSync.native(p);\n if (r !== p) out.push(r);\n } catch {}\n return out;\n}\nfunction agProjects(dir: string): { id: string; folders: string[] }[] {\n const out: { id: string; folders: string[] }[] = [];\n let names: string[] = [];\n try {\n names = readdirSync(dir).filter((n) => n.endsWith(\".json\"));\n } catch {\n return out;\n }\n for (const n of names) {\n const id = n.slice(0, -5);\n if (!ID_RE.test(id)) continue;\n let j: { projectResources?: { resources?: { folderUri?: unknown; gitFolder?: { folderUri?: unknown } }[] } };\n try {\n j = JSON.parse(readFileSync(path.join(dir, n), \"utf8\"));\n } catch {\n continue;\n }\n const folders: string[] = [];\n // A resource is one of the kinds in Antigravity's project.proto: a plain folder is\n // `{ folderUri }`, a git checkout `{ gitFolder: { folderUri, defaultBranch, allowWrite } }`\n // (what 2.23.1 writes for a folder under git); google3 and remote resources name no folder.\n for (const r of j?.projectResources?.resources ?? []) {\n const f = agPath(r?.folderUri ?? r?.gitFolder?.folderUri);\n if (f) folders.push(...agVariants(f));\n }\n if (folders.length) out.push({ id, folders });\n }\n return out;\n}\n/** The project whose folder is the workspace or contains it; the deepest wins. */\nexport function agMatchProject(projects: { id: string; folders: string[] }[], workspaces: string[]): string | null {\n const ws: string[] = [];\n for (const w of workspaces) {\n const p = agPath(w);\n if (p) ws.push(...agVariants(p));\n }\n let best: string | null = null;\n let bestLen = -1;\n for (const pr of projects)\n for (const f of pr.folders) {\n const within = ws.some((w) => w === f || w.startsWith(f.endsWith(path.sep) ? f : f + path.sep));\n if (within && f.length > bestLen) {\n best = pr.id;\n bestLen = f.length;\n }\n }\n return best;\n}\n\n/** Antigravity's web remote: https://antigravity.google.com/r/<installation uuid>-v2, with\n * ?p=c/<conversation>?section=<project> when the project is known. */\nexport function antigravityRemoteUrl(\n transcript: string,\n opts: { conversation?: string; workspaces?: string[]; env: NodeJS.ProcessEnv; projectsDir?: string },\n): string | null {\n const i = transcript.indexOf(`${path.sep}brain${path.sep}`);\n const dirs = (i > 0 ? [transcript.slice(0, i)] : []).concat(dataDirs(opts.env));\n for (const d of dirs) {\n try {\n const m = /installation_uuid:\\s*\"([0-9a-f-]{36})\"/i.exec(\n readFileSync(path.join(d, \"antigravity_state.pbtxt\"), \"utf8\"),\n );\n if (!m) continue;\n const base = `https://antigravity.google.com/r/${m[1]}-v2`;\n const conv = opts.conversation ?? \"\";\n if (!ID_RE.test(conv) || !opts.workspaces?.length) return base;\n const project = agMatchProject(agProjects(opts.projectsDir ?? projectsDir(opts.env)), opts.workspaces);\n return project ? `${base}?p=${encodeURIComponent(`c/${conv}?section=${project}`)}` : base;\n } catch {}\n }\n return null;\n}\n\nexport function antigravityFacts(\n file: string,\n opts: { conversation: string; workspaces: string[]; env: NodeJS.ProcessEnv },\n): SessionFacts {\n const { head, tail } = ends(file, 128 * 1024, 64 * 1024);\n const H = parseLines(head);\n const T = parseLines(tail);\n const out: SessionFacts = {};\n const url = antigravityRemoteUrl(file, opts);\n if (url) out.url = url;\n for (const j of H) {\n if (j.type !== \"USER_INPUT\" || typeof j.content !== \"string\") continue;\n const m = /<USER_REQUEST>([\\s\\S]*?)(?:<\\/USER_REQUEST>|$)/.exec(j.content);\n const text = (m ? (m[1] as string) : j.content).trim();\n const line = (text.split(\"\\n\").find((l) => l.trim()) ?? \"\").trim();\n if (!line || /^<[a-z_-]+>/i.test(line)) continue;\n out.title = line.length > 80 ? `${line.slice(0, 80).replace(/\\s+\\S*$/, \"\")}\u2026` : line;\n out.title_source = \"first-ask\";\n break;\n }\n const times = H.concat(T)\n .map((j) => Date.parse(String(j.created_at ?? j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Where sessionpipe keeps its files (spec: the client's Files section).\n// config ~/.config/sessionpipe/config.json SESSIONPIPE_CONFIG\n// state ~/.local/state/sessionpipe/ SESSIONPIPE_STATE\n// Windows %APPDATA%\\sessionpipe\\ and %LOCALAPPDATA%\\sessionpipe\\\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n/** The home directory, read when asked: a test that sets HOME after importing core\n * (or a process whose HOME changes) gets the new one, never one cached at load. */\nexport const homeDir = (): string => os.homedir();\n\nexport function configFile(env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_CONFIG) return path.resolve(env.SESSIONPIPE_CONFIG);\n if (process.platform === \"win32\")\n return path.join(env.APPDATA || path.join(homeDir(), \"AppData\", \"Roaming\"), \"sessionpipe\", \"config.json\");\n return path.join(env.XDG_CONFIG_HOME || path.join(homeDir(), \".config\"), \"sessionpipe\", \"config.json\");\n}\n\nexport function stateDir(env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_STATE) return path.resolve(env.SESSIONPIPE_STATE);\n if (process.platform === \"win32\")\n return path.join(env.LOCALAPPDATA || path.join(homeDir(), \"AppData\", \"Local\"), \"sessionpipe\");\n return path.join(env.XDG_STATE_HOME || path.join(homeDir(), \".local\", \"state\"), \"sessionpipe\");\n}\n\n/** `~` for the home directory, as the session block writes paths. */\nexport function tilde(p: string, home: string = homeDir()): string {\n if (!p) return p;\n if (p === home) return \"~\";\n return p.startsWith(home + path.sep) || p.startsWith(`${home}/`) ? `~${p.slice(home.length)}` : p;\n}\n\n/** A file-name-safe id. */\nexport const safeId = (s: string): string =>\n String(s)\n .replace(/[^A-Za-z0-9_.-]/g, \"_\")\n .slice(0, 160);\n", "// SPDX-License-Identifier: Apache-2.0\n// Reading the ends of large files, JSON lines, and recent files under a root.\nimport { closeSync, fstatSync, openSync, readdirSync, readSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** The first and last bytes of a file, as lines \u2014 a transcript can be tens of MB. */\nexport function ends(file: string, headBytes: number, tailBytes: number): { head: string[]; tail: string[] } {\n let fd: number | undefined;\n try {\n fd = openSync(file, \"r\");\n const size = fstatSync(fd).size;\n const read = (pos: number, len: number) => {\n const b = Buffer.alloc(len);\n const n = readSync(fd as number, b, 0, len, pos);\n return b.subarray(0, n).toString(\"utf8\");\n };\n const head = read(0, Math.min(size, headBytes));\n const tail = size > headBytes ? read(Math.max(0, size - tailBytes), Math.min(size, tailBytes)) : head;\n return { head: head.split(\"\\n\").slice(0, -1), tail: tail.split(\"\\n\").slice(size > headBytes ? 1 : 0) };\n } catch {\n return { head: [], tail: [] };\n } finally {\n if (fd !== undefined)\n try {\n closeSync(fd);\n } catch {}\n }\n}\n\nexport const parseLines = (lines: string[]): Record<string, unknown>[] =>\n lines\n .map((l) => {\n try {\n return JSON.parse(l) as Record<string, unknown>;\n } catch {\n return null;\n }\n })\n .filter((x): x is Record<string, unknown> => !!x);\n\n/** Read line by line up to `cap` bytes, stopping when `visit` returns a value. */\nexport function scanLines<T>(file: string, visit: (line: string) => T | null, cap = 16 * 1024 * 1024): T | null {\n let fd: number | undefined;\n try {\n fd = openSync(file, \"r\");\n const buf = Buffer.alloc(1024 * 1024);\n let pos = 0;\n let rest: Buffer = Buffer.alloc(0);\n while (pos < cap) {\n const n = readSync(fd, buf, 0, buf.length, pos);\n if (!n) break;\n pos += n;\n let chunk = Buffer.concat([rest, buf.subarray(0, n)]);\n let nl = chunk.indexOf(10);\n while (nl >= 0) {\n const r = visit(chunk.subarray(0, nl).toString(\"utf8\"));\n if (r !== null) return r;\n chunk = chunk.subarray(nl + 1);\n nl = chunk.indexOf(10);\n }\n rest = chunk;\n }\n } catch {\n } finally {\n if (fd !== undefined)\n try {\n closeSync(fd);\n } catch {}\n }\n return null;\n}\n\nexport function recentFiles(root: string, depth: number, sinceMs: number, match: (name: string) => boolean): string[] {\n const out: string[] = [];\n const walk = (dir: string, d: number) => {\n let names: import(\"node:fs\").Dirent[] = [];\n try {\n names = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const e of names) {\n const p = path.join(dir, e.name);\n if (e.isDirectory()) {\n if (d < depth) walk(p, d + 1);\n continue;\n }\n if (!match(e.name)) continue;\n try {\n if (statSync(p).mtimeMs >= sinceMs) out.push(p);\n } catch {}\n }\n };\n walk(root, 0);\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n\n/** A thread another thread started \u2014 a subagent, a review \u2014 names a `source.subagent`\n * in its own metadata (the rollout's first record). A fork the person made carries\n * only `forked_from_id`, and is a session of its own. */\nexport function codexSubagent(meta: Record<string, unknown> | null | undefined): boolean {\n if (meta?.type !== \"session_meta\") return false;\n const p = meta.payload as { source?: { subagent?: unknown } } | undefined;\n return !!p?.source?.subagent;\n}\n\n/** A fork starts with its own metadata, then replays the parent's history. Only\n * an event naming the new thread establishes where its own records begin. */\nexport function codexReplayBoundary(meta: Record<string, unknown> | null | undefined) {\n if (meta?.type !== \"session_meta\") return undefined;\n const p = meta.payload as { id?: unknown; forked_from_id?: unknown; source?: { subagent?: unknown } } | undefined;\n if (!p || (!p.forked_from_id && !p.source?.subagent)) return undefined;\n return (record: Record<string, unknown> | null) =>\n typeof p.id === \"string\" &&\n !!p.id &&\n record?.type === \"event_msg\" &&\n (record.payload as { thread_id?: unknown } | undefined)?.thread_id === p.id;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Transcript readers: complete turns (a person's message + everything the assistant\n// said before the next one), each with the line it ends on, and the line the\n// cursor may advance to once every turn is delivered. Ported from spacesheep-cli\n// lib/memory.js. One reader per harness file format; nothing else is vendor code.\nimport { codexReplayBoundary } from \"../adapters/codex-rollout.js\";\nimport type { TranscriptRead } from \"../adapters/types.js\";\n\ninterface Msg {\n role: \"user\" | \"assistant\";\n text: string;\n at: number;\n line: number;\n}\n\nexport function pairTurns(msgs: Msg[], endLine: number): TranscriptRead {\n const turns: { user: string; assistant: string; at: number; startLine: number; endLine: number }[] = [];\n let cur: (typeof turns)[number] | null = null;\n for (const m of msgs) {\n if (m.role === \"user\") {\n // Never overwrite a prompt that has no reply yet: in an agentic turn the reply\n // comes after tool calls, and a second user record is not a new question.\n if (cur && !cur.assistant) {\n cur.user += `\\n\\n${m.text}`;\n continue;\n }\n if (cur) turns.push(cur);\n cur = { user: m.text, assistant: \"\", at: m.at, startLine: m.line, endLine: m.line };\n } else {\n if (!cur) cur = { user: \"\", assistant: \"\", at: m.at, startLine: m.line, endLine: m.line };\n cur.assistant += (cur.assistant ? \"\\n\\n\" : \"\") + m.text;\n cur.endLine = m.line;\n }\n }\n if (cur?.assistant) turns.push(cur);\n // A user message with no reply yet stays unsent: the cursor stops before it.\n const line = cur && !cur.assistant ? cur.startLine : endLine;\n const out: TranscriptRead = {\n turns: turns.map((t) => ({ user: t.user, assistant: t.assistant, at: t.at, endLine: t.endLine })),\n line,\n };\n if (cur && !cur.assistant && cur.user) out.open = { user: cur.user, at: cur.at };\n return out;\n}\n\n/** Injected context the person never typed: <tag>\u2026</tag> wrappers (the tag may carry\n * attributes, as Claude Code's `<cross-session-message from=\"\u2026\">` does), HTML comments,\n * slash-command expansions. */\nexport const isInjected = (text: string): boolean =>\n (/^<[a-z_-]+(?:\\s[^>]*)?>/i.test(text) && /<\\/[a-z_-]+>\\s*$/i.test(text)) ||\n /^<!--\\s/.test(text) ||\n /^<command-/.test(text);\n\nconst parse = (raw: string): Record<string, unknown> | null => {\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n};\n/** The line after the last whole one. A trailing line that does not parse has no\n * newline yet (a write in progress): the cursor stops before it, or the prompt in\n * it would never be read. */\nconst endOf = (lines: string[]) => {\n const last = lines[lines.length - 1];\n if (last === undefined) return 0;\n return last === \"\" || parse(last) === null ? lines.length - 1 : lines.length;\n};\nconst textParts = (c: unknown, kinds: string[]): string => {\n if (typeof c === \"string\") return c;\n if (!Array.isArray(c)) return \"\";\n return c\n .filter(\n (b) =>\n b &&\n typeof b === \"object\" &&\n kinds.includes((b as { type?: string }).type ?? \"\") &&\n typeof (b as { text?: unknown }).text === \"string\",\n )\n .map((b) => (b as { text: string }).text)\n .join(\"\\n\");\n};\n\n/** A message the person sent while a turn was running, absorbed by that turn. Claude Code\n * writes it as an attachment, never as a `user` record: {type:\"attachment\",\n * attachment:{type:\"queued_command\", prompt, commandMode:\"prompt\", origin:{kind:\"human\"}}}.\n * Task notifications and other sessions' messages share the record with another\n * `commandMode` or `origin.kind`; older versions wrote no origin. */\nconst queuedPrompt = (a: unknown): string => {\n if (!a || typeof a !== \"object\") return \"\";\n const q = a as { type?: unknown; commandMode?: unknown; origin?: { kind?: string }; prompt?: unknown };\n if (q.type !== \"queued_command\" || (q.commandMode ?? \"prompt\") !== \"prompt\") return \"\";\n if (q.origin?.kind && q.origin.kind !== \"human\") return \"\";\n return textParts(q.prompt, [\"text\"]).trim();\n};\n\n/** Claude Code / Droid: {type:\"user\"|\"assistant\", message:{content}, timestamp, isMeta, isSidechain, origin},\n * plus the person's mid-turn messages (queuedPrompt). */\nexport function readClaude(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n for (let i = from; i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j || j.isSidechain) continue;\n const origin = j.origin as { kind?: string } | undefined;\n if (\n j.type === \"user\" &&\n (j.isMeta || j.isCompactSummary || j.repeatsCompactSummary || (origin?.kind && origin.kind !== \"human\"))\n )\n continue;\n const at = Date.parse(String(j.timestamp ?? \"\")) || Date.now();\n const c = (j.message as { content?: unknown } | undefined)?.content;\n if (j.type === \"user\") {\n const text = textParts(c, [\"text\"]).trim();\n if (!text || isInjected(text)) continue;\n msgs.push({ role: \"user\", text, at, line: i });\n } else if (j.type === \"assistant\" && Array.isArray(c)) {\n const text = textParts(c, [\"text\"]).trim();\n if (text) msgs.push({ role: \"assistant\", text, at, line: i });\n } else if (j.type === \"attachment\") {\n const text = queuedPrompt(j.attachment);\n if (text && !isInjected(text)) msgs.push({ role: \"user\", text, at, line: i });\n }\n }\n return pairTurns(msgs, endOf(lines));\n}\n\n/** What Codex writes into a session as a \"user\" message that the person never typed:\n * `<environment_context>` and the like, and the AGENTS.md it read (`# AGENTS.md\n * instructions for <folder>` followed by `<INSTRUCTIONS>`). */\nexport function codexInjected(text: string): boolean {\n return /^<[a-z_-]+>/i.test(text) || /^# AGENTS\\.md instructions\\b/i.test(text);\n}\n\n/** Codex rollout: {type:\"response_item\", payload:{type:\"message\", role, content:[{type:\"input_text\"|\"output_text\", text}]}}. */\nexport function readCodex(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n const boundary = codexReplayBoundary(parse(lines.find((line) => line.trim()) ?? \"\"));\n // Find the boundary from the header even when resuming inside the replay.\n // Keep absolute line numbers: the delivery cursor refers to the original file.\n const start = boundary ? lines.findIndex((line) => boundary(parse(line))) : 0;\n if (start < 0) return pairTurns(msgs, endOf(lines));\n for (let i = Math.max(from, start); i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j || j.type !== \"response_item\") continue;\n const p = j.payload as { type?: string; role?: string; content?: unknown } | undefined;\n if (!p || p.type !== \"message\") continue;\n const at = Date.parse(String(j.timestamp ?? \"\")) || Date.now();\n const text = textParts(p.content, [\"input_text\", \"output_text\"]).trim();\n if (!text) continue;\n if (p.role === \"user\") {\n if (codexInjected(text)) continue; // Codex's own injections, not the person's words\n msgs.push({ role: \"user\", text, at, line: i });\n } else if (p.role === \"assistant\") msgs.push({ role: \"assistant\", text, at, line: i });\n }\n return pairTurns(msgs, endOf(lines));\n}\n\n/** Gemini CLI chat log: {type:\"user\"|\"gemini\", content|message|text, timestamp}. */\nexport function readGemini(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n for (let i = from; i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j) continue;\n const role = j.type === \"user\" ? \"user\" : j.type === \"gemini\" || j.type === \"model\" ? \"assistant\" : null;\n if (!role) continue;\n const raw = j.content ?? j.message ?? j.text;\n const text = (typeof raw === \"string\" ? raw : textParts(raw, [\"text\"])).trim();\n if (!text) continue;\n const at = Date.parse(String(j.timestamp ?? \"\")) || Date.now();\n msgs.push({ role, text, at, line: i });\n }\n return pairTurns(msgs, endOf(lines));\n}\n\n/** Antigravity: one step per line, type USER_INPUT | PLANNER_RESPONSE, content with <USER_REQUEST> wrapping. */\nexport function readAntigravity(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n for (let i = from; i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j || typeof j.content !== \"string\") continue;\n const at = Date.parse(String(j.created_at ?? j.timestamp ?? \"\")) || Date.now();\n if (j.type === \"USER_INPUT\") {\n const m = /<USER_REQUEST>([\\s\\S]*?)(?:<\\/USER_REQUEST>|$)/.exec(j.content);\n const text = (m ? (m[1] as string) : j.content).trim();\n if (text) msgs.push({ role: \"user\", text, at, line: i });\n } else if (j.type === \"PLANNER_RESPONSE\") {\n const text = j.content.trim();\n if (text) msgs.push({ role: \"assistant\", text, at, line: i });\n }\n }\n return pairTurns(msgs, endOf(lines));\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The hooks file shape Claude Code introduced and Codex, Droid and (with\n// `version: 1`) Cursor and Copilot reuse: {\"hooks\":{\"<Event>\":[{\"matcher\"?,\n// \"hooks\":[{\"type\":\"command\",\"command\",\"timeout\"}]}]}}. Ours is one entry per\n// event; a re-install replaces a stale entry of ours (an old node path) and never\n// touches anyone else's.\n//\n// Two rules from issue #8: a file that is not plain JSON (a comment, a trailing\n// comma, a write in progress) is never written back \u2014 the harness is skipped and\n// the report says why; and a file is written back in its own shape (indent, final\n// newline) so uninstall leaves it byte-identical. A file that did not exist before\n// install is reported `created`, and uninstall deletes it once it is empty again.\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { HookCommand, InstallReport } from \"./types.js\";\n\nexport interface ClaudeShapedOptions {\n /** Which events take a `matcher` (tool and permission events). */\n matcherFor: (event: string) => string | undefined;\n /** Seconds (milliseconds for Gemini CLI). */\n timeout: number;\n /** A longer timeout for one event (Claude Code's PermissionRequest, which may wait\n * for a verified control answer: spec/CONTROL.md \u00A76). */\n timeoutFor?: (event: string) => number | undefined;\n /** Extra top-level keys the file must carry (Cursor/Copilot: version: 1). */\n top?: Record<string, unknown>;\n}\n\n/** A command of ours: a path that contains \"sessionpipe\" and ends in hook.js (or in\n * sessionpipe-hook, the launcher that outlives a node upgrade), then a harness and an event. */\nexport const OURS = /(?:sessionpipe[^\"\\n]*[\\\\/]hook\\.js|[\\\\/]sessionpipe-hook)\"?\\s+[a-z][a-z-]*\\s+[A-Za-z]+\\s*$/;\nexport const isOurs = (h: { hooks?: { command?: string }[] }): boolean =>\n Array.isArray(h?.hooks) && h.hooks.some((x) => typeof x.command === \"string\" && OURS.test(x.command));\n\nexport type JsonFile =\n | {\n ok: true;\n existed: true;\n value: Record<string, unknown>;\n raw: string;\n indent: string;\n eol: string;\n finalNewline: boolean;\n }\n | { ok: true; existed: false; value: Record<string, unknown>; raw: \"\"; indent: \" \"; eol: \"\\n\"; finalNewline: true }\n | { ok: false; existed: true; reason: string };\n\n/** Read a JSON config file with its shape. Never guesses: a parse failure is a\n * refusal to touch the file, not an empty object. */\nexport function readJsonFile(file: string): JsonFile {\n let raw: string;\n try {\n raw = readFileSync(file, \"utf8\");\n } catch {\n return { ok: true, existed: false, value: {}, raw: \"\", indent: \" \", eol: \"\\n\", finalNewline: true };\n }\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n const hint = /^\\s*\\/\\/|\\/\\*/m.test(raw) ? \"not plain JSON (it has comments)\" : \"not plain JSON\";\n return { ok: false, existed: true, reason: hint };\n }\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n return { ok: false, existed: true, reason: \"not a JSON object\" };\n const eol = raw.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const m = /^( +|\\t+)\\S/m.exec(raw);\n const indent = m?.[1] ?? \" \";\n return {\n ok: true,\n existed: true,\n value: value as Record<string, unknown>,\n raw,\n indent,\n eol,\n finalNewline: /\\r?\\n$/.test(raw),\n };\n}\n\n/** Serialise in the file's own shape. */\nexport function formatJson(value: unknown, f: { indent: string; eol: string; finalNewline: boolean }): string {\n const text = JSON.stringify(value, null, f.indent).replace(/\\n/g, f.eol);\n return f.finalNewline ? text + f.eol : text;\n}\n\n/** Back-compat helper for callers that only read. */\nexport function readJson(file: string): Record<string, unknown> {\n const f = readJsonFile(file);\n return f.ok ? f.value : {};\n}\n\nfunction entryFor(event: string, harness: string, cmd: HookCommand, o: ClaudeShapedOptions) {\n const matcher = o.matcherFor(event);\n return {\n ...(matcher !== undefined ? { matcher } : {}),\n hooks: [{ type: \"command\", command: cmd([harness, event]).command, timeout: o.timeoutFor?.(event) ?? o.timeout }],\n };\n}\n\nexport function installClaudeShaped(\n file: string,\n harness: string,\n events: readonly string[],\n cmd: HookCommand,\n o: ClaudeShapedOptions,\n): InstallReport {\n const f = readJsonFile(file);\n if (!f.ok) return { file, changed: false, skipped: true, note: `${f.reason}; not touched` };\n const settings = f.value;\n const hooks = (settings.hooks && typeof settings.hooks === \"object\" ? settings.hooks : {}) as Record<\n string,\n unknown[]\n >;\n let changed = false;\n const want = new Set(events);\n // Events we no longer hook (a lean install) lose their entry of ours.\n for (const ev of Object.keys(hooks)) {\n if (want.has(ev)) continue;\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const kept = list.filter((h) => !isOurs(h as never));\n if (kept.length !== list.length) {\n changed = true;\n if (kept.length) hooks[ev] = kept;\n else delete hooks[ev];\n }\n }\n for (const ev of events) {\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const entry = entryFor(ev, harness, cmd, o);\n const mine = list.filter((h) => isOurs(h as never));\n if (mine.length === 1 && JSON.stringify(mine[0]) === JSON.stringify(entry)) continue;\n hooks[ev] = list.filter((h) => !isOurs(h as never)).concat([entry]);\n changed = true;\n }\n if (o.top)\n for (const [k, v] of Object.entries(o.top))\n if (settings[k] !== v) {\n settings[k] = v;\n changed = true;\n }\n if (changed) {\n settings.hooks = hooks;\n mkdirSync(path.dirname(file), { recursive: true });\n writeFileSync(file, formatJson(settings, f));\n }\n return { file, changed, created: !f.existed && changed };\n}\n\nexport function uninstallClaudeShaped(\n file: string,\n events: readonly string[],\n opts: { created?: boolean | undefined } = {},\n): InstallReport {\n if (!existsSync(file)) return { file, changed: false };\n const f = readJsonFile(file);\n if (!f.ok) return { file, changed: false, skipped: true, note: `${f.reason}; not touched` };\n const settings = f.value;\n const hooks = settings.hooks as Record<string, unknown[]> | undefined;\n if (!hooks || typeof hooks !== \"object\") return { file, changed: false };\n let changed = false;\n for (const ev of [...events, ...Object.keys(hooks)]) {\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const kept = list.filter((h) => !isOurs(h as never));\n if (kept.length !== list.length) {\n changed = true;\n if (kept.length) hooks[ev] = kept;\n else delete hooks[ev];\n }\n }\n if (!changed) return { file, changed: false };\n if (!Object.keys(hooks).length) delete settings.hooks;\n if (opts.created && !Object.keys(settings).length) {\n unlinkSync(file);\n return { file, changed: true, note: \"removed (sessionpipe created it)\" };\n }\n writeFileSync(file, formatJson(settings, f));\n return { file, changed: true };\n}\n\nexport function installedClaudeShaped(\n file: string,\n harness: string,\n events: readonly string[],\n cmd: HookCommand,\n o: ClaudeShapedOptions,\n): \"current\" | \"stale\" | \"missing\" {\n const f = readJsonFile(file);\n const hooks = (f.ok ? (f.value.hooks ?? {}) : {}) as Record<string, unknown[]>;\n let present = 0;\n let current = 0;\n for (const ev of events) {\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const mine = list.filter((h) => isOurs(h as never));\n if (mine.length) present++;\n if (mine.length === 1 && JSON.stringify(mine[0]) === JSON.stringify(entryFor(ev, harness, cmd, o))) current++;\n }\n // An entry of ours on an event outside the wanted set (a lean install after a full one) is stale.\n for (const ev of Object.keys(hooks))\n if (!events.includes(ev) && (Array.isArray(hooks[ev]) ? hooks[ev] : []).some((h) => isOurs(h as never)))\n return \"stale\";\n if (!present) return \"missing\";\n return current === events.length ? \"current\" : \"stale\";\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Antigravity (Google) \u2014 control delivery (spec/CONTROL.md \u00A76). Its CLI, `agy`, as the\n// control daemon needs it: which `agy` to run, one headless turn (`agy -p \u2026 --output-\n// format stream-json`, and `--conversation <id>` for the next message), and its stream\n// read as it arrives. agy picks a new conversation's id itself (the `init` line) and\n// starts a fresh one for an id it doesn't know, so the daemon names it after the\n// command that started it (CONTROL.md \u00A76 `start`). No transcript records the folder, so\n// the daemon keeps that too. Shapes measured on agy 1.2.16, 2026-10-04.\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { deniedNote, findBinary, jobEnv, type Mode, type Reading, type RunResult, runFailure } from \"./headless.js\";\n\nconst LABEL = \"Antigravity\";\n\n/** The `agy` to run: SESSIONPIPE_AGY, else on PATH, else where its installer puts it. */\nexport function findAgy(env: NodeJS.ProcessEnv = process.env, home = os.homedir()): string | null {\n return findBinary({\n override: env.SESSIONPIPE_AGY,\n names: process.platform === \"win32\" ? [\"agy.exe\", \"agy.cmd\"] : [\"agy\"],\n env,\n dirs: [path.join(home, \".local\", \"bin\"), \"/opt/homebrew/bin\", \"/usr/local/bin\"],\n });\n}\n\n/** Permission flags for the machine's mode. Safe: none \u2014 agy denies every tool call\n * nobody is there to approve, and says which. Auto: `--mode accept-edits`. Never\n * `--dangerously-skip-permissions`: no path here writes it. */\nexport function agyModeFlags(mode: Mode): string[] {\n return mode === \"auto\" ? [\"--mode\", \"accept-edits\"] : [];\n}\n\n/** One headless turn in the folder it is spawned in. A message that starts with a dash\n * would read as a flag after `-p`; a leading space keeps it the prompt. */\nexport function agyArgs(o: { mode: Mode; prompt: string; resume?: string }): string[] {\n const prompt = o.prompt.startsWith(\"-\") ? ` ${o.prompt}` : o.prompt;\n return [\n ...(o.resume ? [\"--conversation\", o.resume] : []),\n \"-p\",\n prompt,\n \"--output-format\",\n \"stream-json\",\n ...agyModeFlags(o.mode),\n ];\n}\n\n/** The env a headless turn runs with. */\nexport const agyEnv = (env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv => jobEnv(env);\n\nexport interface AgyResult {\n status: string;\n response: string;\n error: string;\n denied: unknown[];\n}\n\n/** One stream-json line, as much of it as the daemon uses. */\nexport interface AgyPiece {\n /** The conversation's id, which agy chose (`init`, then every step and the result). */\n session?: string;\n /** Text an `agent_response` step wrote, and which step it belongs to. */\n delta?: { step: number; text: string };\n /** The final `result`. */\n result?: AgyResult;\n /** An `error_message` step's words: the reason only if the run then fails. */\n note?: string;\n}\n\nexport function agyLine(line: string): AgyPiece | null {\n let j: Record<string, unknown>;\n try {\n j = JSON.parse(line);\n } catch {\n return null;\n }\n if (!j || typeof j !== \"object\") return null;\n const str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n const out: AgyPiece = {};\n if (j.event === \"init\") {\n if (str(j.conversation_id)) out.session = str(j.conversation_id);\n } else if (j.event === \"step_update\") {\n const s = (j.step_update ?? {}) as Record<string, unknown>;\n if (str(s.conversation_id)) out.session = str(s.conversation_id);\n if (s.step_type === \"agent_response\" && str(s.text_delta))\n out.delta = { step: Number(s.step_index ?? 0), text: str(s.text_delta) };\n if (s.step_type === \"error_message\") {\n const why = str(s.text_delta) || str(s.error) || str(s.message);\n if (why) out.note = why;\n }\n } else if (j.event === \"result\") {\n const r = (j.result ?? {}) as Record<string, unknown>;\n if (str(r.conversation_id)) out.session = str(r.conversation_id);\n out.result = {\n status: str(r.status),\n response: str(r.response),\n error: str(r.error),\n denied: Array.isArray(r.denied_actions) ? r.denied_actions : [],\n };\n } else return null;\n return Object.keys(out).length ? out : null;\n}\n\n/** What agy names a denied action by, whatever shape the entry has. */\nfunction deniedName(d: unknown): string | null {\n if (typeof d === \"string\") return d.slice(0, 80);\n if (!d || typeof d !== \"object\") return null;\n const o = d as Record<string, unknown>;\n for (const k of [\"tool_name\", \"toolName\", \"name\", \"tool\", \"action\", \"type\"])\n if (typeof o[k] === \"string\" && o[k]) return (o[k] as string).slice(0, 80);\n return null;\n}\n\n/** An `AGY_ERROR: {\u2026}` agy may end stderr with, in words. */\nexport function agyError(stderr: string | undefined): string {\n const s = String(stderr || \"\");\n const i = s.lastIndexOf(\"AGY_ERROR:\");\n if (i < 0) return \"\";\n const raw = s.slice(i + \"AGY_ERROR:\".length).trim();\n try {\n const j = JSON.parse(raw) as Record<string, unknown>;\n for (const k of [\"message\", \"error\", \"detail\"]) if (typeof j[k] === \"string\" && j[k]) return j[k] as string;\n } catch {}\n return (raw.split(\"\\n\")[0] as string).slice(0, 300);\n}\n\n/** An agy run read as it streams: the answer is the agent_response steps' text, and the\n * result's `response` once it comes. */\nexport class AgyReading implements Reading {\n session: string | null = null;\n lines = 0;\n private buf = \"\";\n private step: number | null = null;\n private result: AgyResult | null = null;\n private note: string | null = null;\n\n get text(): string {\n return this.buf;\n }\n\n feed(line: string): boolean {\n this.lines++;\n const p = agyLine(line);\n if (!p) return false;\n if (p.session && !this.session) this.session = p.session;\n if (p.note) this.note = p.note;\n if (p.result) this.result = p.result;\n if (!p.delta) return false;\n // A new response step after a tool step starts a new paragraph.\n if (this.step !== null && p.delta.step !== this.step && this.buf && !this.buf.endsWith(\"\\n\\n\")) this.buf += \"\\n\\n\";\n this.step = p.delta.step;\n this.buf += p.delta.text;\n return true;\n }\n\n outcome(res: RunResult): { failed: string } | { reply: string } {\n const broke = runFailure(LABEL, res);\n if (broke) return { failed: broke };\n const r = this.result;\n if (!r) {\n const why = agyError(res.stderr) || this.note || \"\";\n return {\n failed: `Antigravity exited (${res.signal || `code ${res.code}`}) without an answer${why ? `: ${why}` : \"\"}`,\n };\n }\n if (r.status !== \"SUCCESS\")\n return { failed: r.error || agyError(res.stderr) || this.note || \"Antigravity reported an error\" };\n const names = [...new Set(r.denied.map(deniedName).filter((n): n is string => !!n))];\n const text = r.response.trim()\n ? r.response.trim()\n : this.buf.trim() || \"(Antigravity finished without a written reply.)\";\n return { reply: text + deniedNote(names, r.denied.length) };\n }\n}\n\nexport const reading = (): AgyReading => new AgyReading();\n", "// SPDX-License-Identifier: Apache-2.0\n// One headless agent turn as a child process (spec/CONTROL.md \u00A76): the spawner the\n// control daemon runs every harness through, and the shape each harness's reading of\n// its own output takes. Which binary, which flags and how the answer is read are the\n// harness's own (`<harness>-control.ts`); what is the same for all of them is here.\nimport { spawn } from \"node:child_process\";\nimport { accessSync, constants, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** A headless turn still running after this is stopped. */\nexport const JOB_TIMEOUT_MS = 30 * 60_000;\nconst OUT_CAP = 1024 * 1024;\n\nexport type Mode = \"safe\" | \"auto\";\n\nexport function isExe(p: string): boolean {\n try {\n if (!statSync(p).isFile()) return false;\n accessSync(p, constants.X_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/** A harness's CLI: the override the person set (`SESSIONPIPE_<NAME>`), else the first\n * of `names` on PATH, else the first of `dirs` that holds one. A launchd or systemd\n * service starts with a short PATH, so the installers' own folders are looked in too. */\nexport function findBinary(o: {\n override?: string | undefined;\n names: string[];\n dirs: string[];\n env?: NodeJS.ProcessEnv;\n}): string | null {\n if (o.override && isExe(o.override)) return o.override;\n for (const d of String(o.env?.PATH || \"\").split(path.delimiter)) {\n if (!d || !path.isAbsolute(d)) continue;\n for (const n of o.names) if (isExe(path.join(d, n))) return path.join(d, n);\n }\n for (const d of o.dirs) for (const n of o.names) if (isExe(path.join(d, n))) return path.join(d, n);\n return null;\n}\n\n/** The env every headless turn runs with: SESSIONPIPE_CONTROL_JOB tells the turn's own\n * hooks that the daemon runs it, so its Stop hook never takes a message meant for a\n * person's session (cli/src/hook.ts). */\nexport function jobEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n return { ...env, SESSIONPIPE_CONTROL_JOB: \"1\" };\n}\n\n/** Whether a harness is signed in, in its own words. `loggedIn: null` means it can't\n * say (too old, or it didn't answer): never a reason to refuse. */\nexport interface Login {\n loggedIn: boolean | null;\n /** claude.ai, an API key, a long-lived token\u2026 as the harness names it. */\n method?: string;\n subscription?: string;\n}\n\nexport interface RunResult {\n error?: string;\n code?: number | null;\n signal?: NodeJS.Signals | null;\n stdout?: string | null;\n tooBig?: boolean;\n stderr?: string;\n timedOut?: boolean;\n}\n\nexport interface RunOptions {\n cwd: string;\n env: NodeJS.ProcessEnv;\n timeoutMs?: number;\n /** Streaming: each stdout line as it arrives. Only the lines `keep` names are kept\n * for the RunResult (none by default), so a long stream never hits the cap. */\n onLine?: (line: string) => void;\n keep?: (line: string) => boolean;\n}\n\n/** Run one headless turn in its own process group, stdin closed (Codex waits on an open\n * one), holding at most 1 MB of stdout. */\nexport function runHeadless(bin: string, args: string[], o: RunOptions): Promise<RunResult> {\n return new Promise((resolve) => {\n let out: Buffer[] = [];\n let outLen = 0;\n let tooBig = false;\n let errTail = \"\";\n let timedOut = false;\n let settled = false;\n let child: import(\"node:child_process\").ChildProcess;\n try {\n child = spawn(bin, args, {\n cwd: o.cwd,\n env: o.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: process.platform !== \"win32\",\n windowsHide: true,\n });\n } catch (e) {\n resolve({ error: (e as Error).message });\n return;\n }\n const kill = (sig: NodeJS.Signals) => {\n try {\n if (process.platform !== \"win32\" && child.pid) process.kill(-child.pid, sig);\n else child.kill(sig);\n } catch {\n try {\n child.kill(sig);\n } catch {}\n }\n };\n const keep = (line: string) => {\n if (!o.keep?.(line)) return;\n out = [Buffer.from(line)];\n outLen = line.length;\n };\n let partial = \"\";\n child.stdout?.on(\"data\", (b: Buffer) => {\n if (o.onLine) {\n const chunk = partial + b.toString(\"utf8\");\n const lines = chunk.split(\"\\n\");\n partial = lines.pop() as string;\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n o.onLine(line);\n } catch {}\n keep(line);\n }\n if (partial.length > OUT_CAP) partial = \"\";\n return;\n }\n if (tooBig) return;\n if (outLen + b.length > OUT_CAP) {\n tooBig = true;\n out = [];\n return;\n }\n out.push(b);\n outLen += b.length;\n });\n child.stderr?.on(\"data\", (b: Buffer) => {\n errTail = (errTail + b.toString(\"utf8\")).slice(-4000);\n });\n const timer = setTimeout(() => {\n timedOut = true;\n kill(\"SIGTERM\");\n setTimeout(() => kill(\"SIGKILL\"), 10_000).unref();\n }, o.timeoutMs ?? JOB_TIMEOUT_MS);\n const result = (code: number | null, signal: NodeJS.Signals | null): RunResult => ({\n code,\n signal,\n stdout: tooBig ? null : Buffer.concat(out).toString(\"utf8\"),\n tooBig,\n stderr: errTail,\n timedOut,\n });\n const finish = (r: RunResult) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(r);\n };\n child.on(\"error\", (e) => finish({ error: e.message }));\n // A tool the agent left running can hold stdout open after the harness exits.\n child.on(\"exit\", (code, signal) => setTimeout(() => finish(result(code, signal)), 2000).unref());\n child.on(\"close\", (code, signal) => {\n // The last line may end without a newline: it is often the result itself.\n if (o.onLine && partial.trim()) {\n try {\n o.onLine(partial);\n } catch {}\n keep(partial);\n partial = \"\";\n }\n finish(result(code, signal));\n });\n });\n}\n\n/** A harness's output read as it streams: the session it names, the answer so far, and\n * the outcome once the process is gone. One per run. */\nexport interface Reading {\n /** One stdout line. True when the answer so far changed. */\n feed(line: string): boolean;\n /** The session id the harness revealed (it picks its own), or null so far. */\n readonly session: string | null;\n /** The answer so far, whole. */\n readonly text: string;\n /** How many lines were fed. */\n readonly lines: number;\n outcome(res: RunResult): { failed: string } | { reply: string };\n}\n\n/** The last few lines a harness wrote to stderr, on one line. */\nexport function stderrTail(stderr: string | undefined, n = 3): string {\n return String(stderr || \"\")\n .trim()\n .split(\"\\n\")\n .slice(-n)\n .join(\" \")\n .trim();\n}\n\n/** What a run that wasn't there to ask says about the actions it was refused. */\nexport function deniedNote(names: string[], count: number): string {\n if (!count) return \"\";\n return `\\n\\n(Not allowed on this machine, since nobody was there to approve: ${names.join(\", \") || `${count} action(s)`}.)`;\n}\n\n/** A process that failed before or without its answer, in words. */\nexport function runFailure(label: string, res: RunResult): string | null {\n if (res.error) return `couldn't start ${label}: ${res.error}`;\n if (res.timedOut) return `${label} was still working after 30 minutes, so it was stopped`;\n return null;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Claude Code (Anthropic) \u2014 docs: https://code.claude.com/docs/en/hooks\n// Config: settings.json in EVERY config dir (~/.claude, $CLAUDE_CONFIG_DIR, ~/.claude-*):\n// one per account; hooks written to one never fire for the others. Reads only the\n// hook's stdin, the transcript it names, the per-pid session registry and the config\n// dir's .claude.json account (its id; its email only for control's pair and hello).\n// Ported from spacesheep-cli lib/sessions.js.\n\nimport { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines, recentFiles, scanLines } from \"../readers/files.js\";\nimport { gitFacts } from \"../readers/git.js\";\nimport { isInjected, readClaude } from \"../readers/transcripts.js\";\nimport type { HarnessAccount } from \"../types.js\";\nimport { installClaudeShaped, installedClaudeShaped, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport type {\n Adapter,\n BackfillRow,\n FactsState,\n HookCommand,\n HookInput,\n HookResult,\n InstallOptions,\n SessionFacts,\n} from \"./types.js\";\n\nconst NAME = \"claude-code\";\nexport const CLAUDE_EVENTS = [\n \"SessionStart\",\n \"UserPromptSubmit\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PostToolUseFailure\",\n \"PermissionRequest\",\n \"Notification\",\n \"Stop\",\n \"SubagentStart\",\n \"SubagentStop\",\n \"PreCompact\",\n \"PostCompact\",\n \"SessionEnd\",\n \"StopFailure\",\n] as const;\n/** With no sink above tier 0 only the heartbeat needs a tool event: one, not three (issue #12). */\nconst LEAN_SKIP = new Set([\"PreToolUse\", \"PostToolUseFailure\"]);\nconst eventsFor = (lean?: boolean) => (lean ? CLAUDE_EVENTS.filter((e) => !LEAN_SKIP.has(e)) : [...CLAUDE_EVENTS]);\nconst OPTS = {\n matcherFor: (e: string) => (/Tool|Permission/.test(e) ? \"\" : undefined),\n timeout: 5,\n // The hook waits up to 125 s for a verified control answer, and only when control\n // is paired on this machine; everywhere else it exits in milliseconds as before.\n timeoutFor: (e: string) => (e === \"PermissionRequest\" ? 130 : undefined),\n};\nconst DESKTOP_ID = /^local_[A-Za-z0-9-]{1,64}$/;\n\n/** Every Claude Code config dir on this machine. `home` follows the env's HOME, so a\n * caller with its own env (a test) never reaches the real ~/.claude: the install test\n * once rewrote a real settings.json with its fake hook paths on every run. */\nexport function claudeDirs(env: NodeJS.ProcessEnv = process.env, home = env.HOME || homeDir()): string[] {\n const out: string[] = [];\n const add = (d?: string) => {\n if (!d) return;\n const r = path.resolve(d);\n if (!out.includes(r)) out.push(r);\n };\n add(path.join(home, \".claude\"));\n add(env.CLAUDE_CONFIG_DIR);\n try {\n for (const e of readdirSync(home, { withFileTypes: true })) {\n if (!e.isDirectory() || !/^\\.claude[-_.]/.test(e.name)) continue;\n const d = path.join(home, e.name);\n if (existsSync(path.join(d, \"projects\")) || existsSync(path.join(d, \"settings.json\"))) add(d);\n }\n } catch {}\n return out.filter((d, i) => i === 0 || existsSync(d));\n}\nconst settingsIn = (dir: string) => path.join(dir, \"settings.json\");\nconst configDirOf = (transcript: string) => path.dirname(path.dirname(path.dirname(transcript)));\n\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst endReason = (r: unknown): \"clear\" | \"logout\" | \"exit\" | \"other\" =>\n r === \"clear\" || r === \"logout\" || r === \"exit\" ? r : r === \"prompt_input_exit\" ? \"exit\" : \"other\";\nconst notifKind = (t: unknown): \"permission\" | \"question\" | \"elicitation\" | \"idle\" | \"error\" =>\n t === \"permission_prompt\"\n ? \"permission\"\n : t === \"idle_prompt\"\n ? \"idle\"\n : t === \"elicitation_dialog\"\n ? \"elicitation\"\n : \"question\";\n\nexport const claudeCode: Adapter = {\n name: NAME,\n events: CLAUDE_EVENTS,\n detect: (env = process.env) => claudeDirs(env).some((d) => existsSync(d)),\n configFiles: (env = process.env) => claudeDirs(env).map(settingsIn),\n install: (cmd, env = process.env, opts: InstallOptions = {}) =>\n claudeDirs(env).map((d) => installClaudeShaped(settingsIn(d), NAME, eventsFor(opts.lean), cmd, OPTS)),\n uninstall: (env = process.env, opts: InstallOptions = {}) =>\n claudeDirs(env).map((d) =>\n uninstallClaudeShaped(settingsIn(d), CLAUDE_EVENTS, { created: opts.created?.includes(settingsIn(d)) }),\n ),\n installed: (cmd, env = process.env, opts: InstallOptions = {}) =>\n claudeDirs(env).map((d) => ({\n file: settingsIn(d),\n state: installedClaudeShaped(settingsIn(d), NAME, eventsFor(opts.lean), cmd, OPTS),\n })),\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = (s.session_id ?? s.sessionId) as string | undefined;\n if (!id) return null;\n if (notClaudeCode(String(id), s)) return null;\n const session: HookResult[\"session\"] = { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd };\n if (typeof s.model === \"string\") session.model = s.model;\n if (typeof s.agent_id === \"string\" && event.startsWith(\"Subagent\") === false && s.agent_id)\n session.parent_id = null;\n const turn_id = typeof s.prompt_id === \"string\" ? s.prompt_id : undefined;\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const call_id = typeof s.tool_use_id === \"string\" ? s.tool_use_id : undefined;\n const ms = typeof s.duration_ms === \"number\" ? Math.round(s.duration_ms) : undefined;\n const agent_id = typeof s.agent_id === \"string\" ? s.agent_id : undefined;\n // PermissionRequest carries no tool_use_id (recorded 2026-09-28): the id is a hash\n // of the prompt, the tool and its input, so the same prompt yields the same id and\n // a later control answer can name it.\n const permissionId = () =>\n `perm-${createHash(\"sha256\")\n .update(`${turn_id ?? \"\"}|${tool ?? \"\"}|${JSON.stringify(s.tool_input ?? null)}`)\n .digest(\"hex\")\n .slice(0, 16)}`;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(ev(\"session.started\", { source: pickSource(s.source ?? s.trigger) }));\n break;\n case \"UserPromptSubmit\":\n events.push(\n ev(\"turn.started\", {\n turn_id,\n prompt_chars: typeof s.prompt === \"string\" ? [...s.prompt].length : undefined,\n }),\n );\n break;\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, call_id, turn_id, agent_id, input: s.tool_input }));\n break;\n case \"PostToolUse\":\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n call_id,\n turn_id,\n agent_id,\n ms,\n ok: true,\n input: s.tool_input,\n output: s.tool_response,\n }),\n );\n break;\n case \"PostToolUseFailure\":\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n call_id,\n turn_id,\n agent_id,\n ms,\n ok: false,\n error: errText(s.error ?? s.tool_response),\n input: s.tool_input,\n output: s.tool_response,\n }),\n );\n break;\n case \"PermissionRequest\":\n events.push(\n ev(\"attention.needed\", {\n attention_id: call_id ?? permissionId(),\n kind: \"permission\",\n tool,\n message: tool ? `${tool}${describe(s.tool_input)}` : undefined,\n }),\n );\n break;\n case \"Notification\":\n events.push(\n ev(\"attention.needed\", {\n attention_id: `notif-${Date.now()}`,\n kind: notifKind(s.notification_type),\n message: typeof s.message === \"string\" ? s.message.slice(0, 200) : undefined,\n }),\n );\n break;\n case \"Stop\":\n events.push(ev(\"turn.ended\", { turn_id, reason: \"stop\" }));\n break;\n case \"StopFailure\":\n // The turn ended on an API error (rate_limit, overloaded, authentication_failed,\n // server_error \u2026); the payload key is `error` (issue #10, recorded 2026-09-28).\n events.push(\n ev(\"turn.ended\", {\n turn_id,\n reason: \"error\",\n error: typeof s.error === \"string\" ? s.error.slice(0, 200) : undefined,\n }),\n );\n break;\n case \"SubagentStart\":\n events.push(\n ev(\"subagent.started\", {\n agent_id: String(s.agent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"SubagentStop\":\n events.push(\n ev(\"subagent.ended\", {\n agent_id: String(s.agent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"PreCompact\":\n events.push(ev(\"context.compacted\", { trigger: s.trigger === \"manual\" ? \"manual\" : \"auto\" }));\n break;\n case \"PostCompact\":\n break; // PreCompact already said it; a second event would double-count\n case \"SessionEnd\":\n events.push(ev(\"session.ended\", { reason: endReason(s.reason) }));\n break;\n default:\n return null;\n }\n const hints: Record<string, unknown> = {};\n // The prompt, for the turn's first turn.progress: the transcript may not hold it\n // yet when the worker runs. Never an event field of its own (tier 2 carries it).\n if (event === \"UserPromptSubmit\" && typeof s.prompt === \"string\") hints.prompt = s.prompt;\n const host = input.env.CLAUDE_CODE_HOST_SESSION_ID;\n if (host && DESKTOP_ID.test(host)) hints.desktop_id = host;\n // The registry file is found while the process tree stands (the detached\n // worker's parent is gone by the time it runs). Heartbeat-class events skip it.\n if (event !== \"PreToolUse\" && event !== \"PostToolUse\") hints.claude_pid = claudePid(input.env);\n const r: HookResult = { session, events, hints };\n if (typeof s.transcript_path === \"string\") r.transcript = s.transcript_path;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readClaude(text.split(\"\\n\"), fromLine);\n },\n\n facts(session, transcript, hints, state): SessionFacts {\n const out: SessionFacts = {};\n if (transcript) Object.assign(out, claudeFacts(transcript, session.id, hints, state));\n const cwd = out.cwd ?? session.cwd;\n Object.assign(out, gitFacts(cwd), out.branch ? { branch: out.branch } : {});\n if (!out.url && typeof hints.desktop_id === \"string\") out.url = `claude://code/continue/${hints.desktop_id}`;\n return out;\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows: BackfillRow[] = [];\n const files: string[] = [];\n for (const d of claudeDirs(env))\n files.push(...recentFiles(path.join(d, \"projects\"), 1, sinceMs, (n) => /^[0-9a-f-]{36}\\.jsonl$/.test(n)));\n const noState: FactsState = { get: () => ({}), save: () => {} };\n for (const f of files) {\n const id = path.basename(f, \".jsonl\");\n const facts = claudeFacts(f, id, {}, noState);\n if (!facts.started_at || !facts.last_at) continue;\n const { started_at, last_at, first_ask: _fa, harness_version: _hv, ...rest } = facts;\n const cwd = rest.cwd;\n rows.push({\n session: { id, ...rest, ...gitFacts(cwd), ...(rest.branch ? { branch: rest.branch } : {}) },\n started_at,\n last_at,\n });\n }\n return rows;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/** Another harness reading this settings file, not Claude Code. Several harnesses\n * import `~/.claude/settings.json` hooks, so our entries there can be run by a tool\n * that has its own adapter: it would arrive under the wrong name, with ids that mean\n * nothing to a Claude Code reader. Every Claude Code payload names a transcript and a\n * UUID session (all 21 recorded fixtures do); a payload with neither is somebody else's. */\nexport function notClaudeCode(id: string, s: Record<string, unknown>): boolean {\n return typeof s.transcript_path !== \"string\" && !UUID.test(id);\n}\nfunction pickSource(v: unknown): string {\n return typeof v === \"string\" && [\"startup\", \"resume\", \"clear\", \"compact\", \"fork\"].includes(v) ? v : \"unknown\";\n}\nfunction errText(v: unknown): string | undefined {\n if (typeof v === \"string\") return v.slice(0, 2000);\n if (v && typeof v === \"object\") {\n const e = v as { error?: unknown; message?: unknown };\n if (typeof e.error === \"string\") return e.error.slice(0, 2000);\n if (typeof e.message === \"string\") return e.message.slice(0, 2000);\n }\n return undefined;\n}\nfunction describe(input: unknown): string {\n if (!input || typeof input !== \"object\") return \"\";\n const i = input as Record<string, unknown>;\n const v = i.command ?? i.file_path ?? i.path ?? i.url ?? i.pattern;\n return typeof v === \"string\" ? ` ${v.slice(0, 120)}` : \"\";\n}\n\n// --- facts: title, url, model, account, from Claude Code's own files ------------------\n\nconst NAME_RANK: Record<string, \"custom\" | \"harness\"> = {\n user: \"custom\",\n auto: \"harness\",\n hook: \"harness\",\n peer: \"harness\",\n};\ninterface Registry {\n sessionId: string | null;\n name: string | null;\n name_source: \"custom\" | \"harness\" | null;\n bridge: string | null;\n}\nfunction registryEntry(j: unknown): Registry | null {\n if (!j || typeof j !== \"object\") return null;\n const r = j as { sessionId?: unknown; name?: unknown; nameSource?: string; bridgeSessionId?: unknown };\n const source = r.nameSource ? NAME_RANK[r.nameSource] : undefined;\n return {\n sessionId: r.sessionId ? String(r.sessionId) : null,\n name: source && typeof r.name === \"string\" && r.name.trim() ? r.name.trim() : null,\n name_source: source ?? null,\n bridge: typeof r.bridgeSessionId === \"string\" ? r.bridgeSessionId : null,\n };\n}\nconst liveCache = new Map<string, Map<string, Registry>>();\nfunction claudeLive(dir: string): Map<string, Registry> {\n const hit = liveCache.get(dir);\n if (hit) return hit;\n const map = new Map<string, Registry>();\n let names: string[] = [];\n try {\n names = readdirSync(path.join(dir, \"sessions\")).filter((n) => n.endsWith(\".json\"));\n } catch {}\n for (const n of names) {\n try {\n const e = registryEntry(JSON.parse(readFileSync(path.join(dir, \"sessions\", n), \"utf8\")));\n if (e?.sessionId) map.set(e.sessionId, e);\n } catch {}\n }\n liveCache.set(dir, map);\n return map;\n}\nfunction claudeLiveByPid(dir: string, pid: unknown): Registry | null {\n if (!pid) return null;\n try {\n return registryEntry(JSON.parse(readFileSync(path.join(dir, \"sessions\", `${pid}.json`), \"utf8\")));\n } catch {\n return null;\n }\n}\n/** The Claude Code process that ran this hook: the nearest ancestor with a registry\n * file (hooks run under a shell, so usually the parent's parent). */\nexport function claudePid(env: NodeJS.ProcessEnv = process.env): number | null {\n try {\n const dirs = claudeDirs(env);\n const has = (pid: number) => dirs.some((d) => existsSync(path.join(d, \"sessions\", `${pid}.json`)));\n let pid = process.ppid;\n if (has(pid)) return pid;\n const parent = parentOf();\n for (let hop = 0; hop < 6 && pid > 1; hop++) {\n pid = parent(pid);\n if (pid > 1 && has(pid)) return pid;\n }\n } catch {}\n return null;\n}\nfunction parentOf(): (pid: number) => number {\n if (process.platform === \"linux\") {\n return (pid) => {\n try {\n const st = readFileSync(`/proc/${pid}/stat`, \"utf8\");\n return Number(st.slice(st.lastIndexOf(\")\") + 2).split(\" \")[1]) || 0;\n } catch {\n return 0;\n }\n };\n }\n const table = new Map<number, number>();\n try {\n const out = execFileSync(\"ps\", [\"-axo\", \"pid=,ppid=\"], {\n encoding: \"utf8\",\n timeout: 2000,\n maxBuffer: 8 * 1024 * 1024,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n for (const l of out.split(\"\\n\")) {\n const m = /^\\s*(\\d+)\\s+(\\d+)/.exec(l);\n if (m) table.set(Number(m[1]), Number(m[2]));\n }\n } catch {}\n return (pid) => table.get(pid) || 0;\n}\nconst EMAIL_RE = /^[^@\\s]{1,64}@[^@\\s]{1,189}$/;\n/** Who a config dir is signed in as, from its .claude.json (the default dir keeps it\n * at ~/.claude.json): the account id, and the email it signs in with. */\nfunction claudeLogin(dir: string, home = homeDir()): { id: string; email?: string } | null {\n const files = [path.join(dir, \".claude.json\")];\n if (path.resolve(dir) === path.join(home, \".claude\")) files.unshift(path.join(home, \".claude.json\"));\n for (const f of files) {\n try {\n const a = (\n JSON.parse(readFileSync(f, \"utf8\")) as { oauthAccount?: { accountUuid?: unknown; emailAddress?: unknown } }\n ).oauthAccount;\n if (typeof a?.accountUuid === \"string\" && a.accountUuid) {\n const email = typeof a.emailAddress === \"string\" && EMAIL_RE.test(a.emailAddress) ? a.emailAddress : undefined;\n return { id: a.accountUuid.slice(0, 128), ...(email ? { email } : {}) };\n }\n } catch {}\n }\n return null;\n}\nconst accountCache = new Map<string, string | null>();\n/** The account id for `session.account_id`: never the email. Events go to every sink,\n * a team board included; the email reaches only a receiver the person paired with,\n * in control's pair and hello (claudeAccounts). */\nfunction claudeAccount(dir: string): string | null {\n const hit = accountCache.get(dir);\n if (hit !== undefined) return hit;\n const acct = claudeLogin(dir)?.id ?? null;\n accountCache.set(dir, acct);\n return acct;\n}\n/** Every account signed in across these config dirs, read fresh (a person signs in to\n * another account without restarting anything), for control's pair and hello. */\nexport function claudeAccounts(dirs: string[], home = homeDir()): HarnessAccount[] {\n const out: HarnessAccount[] = [];\n for (const d of dirs) {\n const l = claudeLogin(d, home);\n if (!l) continue;\n const seen = out.find((a) => a.id === l.id);\n if (!seen) out.push({ harness: NAME, ...l });\n else if (!seen.email && l.email) seen.email = l.email;\n }\n return out;\n}\nconst LINK_RE = /^https:\\/\\/claude\\.ai\\/code\\/session_[A-Za-z0-9]+$/;\nfunction transcriptLink(records: Record<string, unknown>[]): string | null {\n for (let i = records.length - 1; i >= 0; i--) {\n const j = records[i] as { type?: string; subtype?: string; url?: unknown; bridgeSessionId?: unknown };\n if (j.type === \"system\" && j.subtype === \"bridge_status\" && typeof j.url === \"string\" && LINK_RE.test(j.url))\n return j.url;\n if (j.type === \"bridge-session\" && typeof j.bridgeSessionId === \"string\") {\n const m = /^(?:cse|session)_([A-Za-z0-9]+)$/.exec(j.bridgeSessionId);\n if (m) return `https://claude.ai/code/session_${m[1]}`;\n }\n }\n return null;\n}\n/** A first ask as the Claude Code app titles an untitled session: whitespace\n * collapsed, whole up to 50 characters, else its first 50 and \"...\". */\nexport function appTitle(text: string): string {\n const t = String(text).replace(/\\s+/g, \" \").trim();\n return t.length > 50 ? `${t.slice(0, 50)}...` : t;\n}\nfunction askText(j: Record<string, unknown> | null): string | null {\n if (!j || j.type !== \"user\" || j.isMeta || j.isSidechain) return null;\n const origin = j.origin as { kind?: string } | undefined;\n if (origin?.kind && origin.kind !== \"human\") return null;\n const c = (j.message as { content?: unknown } | undefined)?.content;\n const text = (\n typeof c === \"string\"\n ? c\n : Array.isArray(c)\n ? c\n .filter((b) => b && b.type === \"text\" && typeof b.text === \"string\")\n .map((b) => b.text as string)\n .join(\"\\n\")\n : \"\"\n ).trim();\n if (!text || isInjected(text)) return null;\n return text;\n}\nfunction firstAsk(records: Record<string, unknown>[]): string | null {\n for (const j of records) {\n const t = askText(j);\n if (t) return appTitle(t);\n }\n return null;\n}\nfunction scanTitles(file: string, from: number, found: { custom?: string | null; ai?: string | null }) {\n const out = { custom: found.custom ?? null, ai: found.ai ?? null, upto: from };\n let size = 0;\n try {\n size = statSync(file).size;\n } catch {\n return out;\n }\n if (size < from) {\n out.upto = 0;\n out.custom = out.ai = null;\n from = 0;\n }\n // Only lines carrying a title record are parsed; the rest of the new bytes are skipped.\n let pos = 0;\n scanLines<null>(\n file,\n (l) => {\n pos += Buffer.byteLength(l, \"utf8\") + 1;\n if (pos <= from || l.indexOf('-title\"') < 0) return null;\n try {\n const j = JSON.parse(l) as { type?: string; customTitle?: string; aiTitle?: string };\n if (j.type === \"custom-title\" && j.customTitle) out.custom = j.customTitle;\n if (j.type === \"ai-title\" && j.aiTitle) out.ai = j.aiTitle;\n } catch {}\n return null;\n },\n 512 * 1024 * 1024,\n );\n out.upto = size;\n return out;\n}\n\n/** A session's title and where it came from, best first: /rename (registry \"user\"\n * name or custom-title) \u2192 Claude Code's own title (registry \"auto\" name or\n * ai-title) \u2192 the first ask, marked first-ask so a real title later replaces it. */\nexport function claudeFacts(\n file: string,\n sessionId: string,\n hints: Record<string, unknown>,\n state: FactsState,\n): SessionFacts {\n const { head, tail } = ends(file, 64 * 1024, 256 * 1024);\n const H = parseLines(head);\n const T = parseLines(tail);\n const out: SessionFacts = {};\n const id = sessionId || path.basename(file, \".jsonl\");\n const mem = state.get(NAME, id);\n let custom: string | null = null;\n let ai: string | null = null;\n for (const j of H.concat(T)) {\n if (j.type === \"custom-title\" && typeof j.customTitle === \"string\") custom = j.customTitle;\n if (j.type === \"ai-title\" && typeof j.aiTitle === \"string\") ai = j.aiTitle;\n }\n let size = 0;\n try {\n size = statSync(file).size;\n } catch {}\n if (!custom && !ai && size > 64 * 1024 + 256 * 1024) {\n const s = scanTitles(file, Number(mem.scan_upto) || 0, {\n custom: mem.scan_custom as string | null,\n ai: mem.scan_ai as string | null,\n });\n custom = s.custom;\n ai = s.ai;\n state.save(NAME, id, { scan_upto: s.upto, scan_custom: s.custom, scan_ai: s.ai });\n }\n const dir = configDirOf(file);\n const live = claudeLive(dir).get(id) ?? claudeLiveByPid(dir, hints.claude_pid);\n if (live?.name) state.save(NAME, id, { name: live.name, name_source: live.name_source });\n const bridge =\n live?.bridge && /^session_[A-Za-z0-9]+$/.test(live.bridge) ? `https://claude.ai/code/${live.bridge}` : null;\n const url = bridge ?? transcriptLink(T) ?? transcriptLink(H) ?? (typeof mem.url === \"string\" ? mem.url : null);\n if (url) {\n out.url = url;\n state.save(NAME, id, { url });\n }\n const name = live?.name\n ? { title: live.name, source: live.name_source as \"custom\" | \"harness\" }\n : typeof mem.name === \"string\"\n ? { title: mem.name, source: mem.name_source as \"custom\" | \"harness\" }\n : null;\n const pick =\n (name && name.source === \"custom\" && name) ||\n (custom && { title: custom, source: \"custom\" as const }) ||\n name ||\n (ai && { title: ai, source: \"harness\" as const });\n let ask = typeof mem.first_ask === \"string\" ? mem.first_ask : firstAsk(H);\n if (!ask && size > 64 * 1024 && !mem.first_ask_none) {\n ask = scanLines<string>(file, (l) => {\n try {\n const t = askText(JSON.parse(l) as Record<string, unknown>);\n return t ? appTitle(t) : null;\n } catch {\n return null;\n }\n });\n if (!ask && size > 16 * 1024 * 1024) state.save(NAME, id, { first_ask_none: true });\n }\n if (ask) {\n out.first_ask = ask;\n if (!mem.first_ask) state.save(NAME, id, { first_ask: ask });\n }\n if (pick) {\n out.title = String(pick.title).slice(0, 120);\n out.title_source = pick.source;\n } else if (ask) {\n out.title = ask;\n out.title_source = \"first-ask\";\n }\n const acct = claudeAccount(dir);\n if (acct) out.account_id = acct;\n for (let i = T.length - 1; i >= 0; i--) {\n const m = (T[i] as { message?: { model?: string } }).message?.model;\n if (T[i]?.type === \"assistant\" && m && m !== \"<synthetic>\") {\n out.model = m;\n break;\n }\n }\n const meta = [...T].reverse().find((j) => j.version) ?? H.find((j) => j.version);\n if (meta?.version) out.harness_version = String(meta.version);\n const times = H.concat(T)\n .map((j) => Date.parse(String(j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n const withCwd = H.find((j) => typeof j.cwd === \"string\");\n if (withCwd) {\n out.cwd = withCwd.cwd as string;\n if (typeof withCwd.gitBranch === \"string\" && withCwd.gitBranch !== \"HEAD\") out.branch = withCwd.gitBranch;\n }\n return out;\n}\n\n/** For tests: each hook runs in a fresh process; a test that edits the registry mid-run clears the cache. */\nexport const _resetClaudeCaches = (): void => {\n liveCache.clear();\n accountCache.clear();\n};\n", "// SPDX-License-Identifier: Apache-2.0\n// The repo and branch of a folder, from git itself; credentials stripped from the\n// remote. Cached per folder for the life of the process (a worker run).\nimport { execFileSync } from \"node:child_process\";\n\nconst cache = new Map<string, { repo?: string; branch?: string }>();\n\nexport function gitFacts(cwd: string | undefined): { repo?: string; branch?: string } {\n if (!cwd) return {};\n const hit = cache.get(cwd);\n if (hit) return hit;\n const run = (args: string[]) => {\n try {\n return execFileSync(\"git\", [\"-C\", cwd, ...args], {\n encoding: \"utf8\",\n timeout: 1500,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return \"\";\n }\n };\n const out: { repo?: string; branch?: string } = {};\n const repo = run([\"remote\", \"get-url\", \"origin\"]);\n if (repo) out.repo = stripCredentials(repo);\n const branch = run([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n if (branch && branch !== \"HEAD\") out.branch = branch;\n cache.set(cwd, out);\n return out;\n}\n\n/** `https://user:token@host/x` \u2192 `https://host/x`; `git@github.com:a/b.git` \u2192 `github.com/a/b`. */\nexport function stripCredentials(url: string): string {\n // The ssh forms first: the `git@` they are known by is what the credential strip removes.\n const ssh = /^(?:ssh:\\/\\/)?git@([^:/]+)[:/](.+?)(?:\\.git)?$/.exec(url);\n if (ssh) return `${ssh[1]}/${ssh[2]}`;\n return url\n .replace(/\\/\\/[^/@]*@/, \"//\")\n .replace(/^https?:\\/\\//, \"\")\n .replace(/\\.git$/, \"\");\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Claude Code (Anthropic) \u2014 control delivery (spec/CONTROL.md \u00A76). Claude Code on\n// this machine, as the control daemon needs it: which `claude` to\n// run and with which permission flags, where a session's transcript is and which\n// folder it runs in, whether a live process holds it, and running one headless\n// turn (`claude -p --resume`, `--fork-session`, `--session-id`). Ported from the\n// spacesheep CLI's machine listener (lib/machine.js, 1.22), which ran it in\n// production first.\nimport { execFile, execFileSync } from \"node:child_process\";\nimport { closeSync, openSync, readdirSync, readFileSync, readSync, statSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n isExe,\n JOB_TIMEOUT_MS,\n type Login,\n type Mode,\n type RunOptions,\n type RunResult,\n runHeadless,\n} from \"./headless.js\";\n\nexport { JOB_TIMEOUT_MS, type Login, type Mode, type RunResult };\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/** A transcript someone else wrote this recently is in use. */\nconst LIVE_WRITE_MS = 90_000;\n\n/** Dotted versions by number, a missing part as 0: 1.9.0 < 1.10 = 1.10.0. */\nexport const cmpVersion = (a: string, b: string) => {\n const pa = a.split(\".\").map(Number);\n const pb = b.split(\".\").map(Number);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++)\n if ((pa[i] ?? 0) !== (pb[i] ?? 0)) return (pa[i] ?? 0) - (pb[i] ?? 0);\n return 0;\n};\n\n/** The `claude` to run: on PATH, else where the installers put it, else the newest\n * copy the desktop app ships. Null when this machine has none. */\nexport function findClaude(env: NodeJS.ProcessEnv = process.env, home = os.homedir()): string | null {\n if (env.SESSIONPIPE_CLAUDE && isExe(env.SESSIONPIPE_CLAUDE)) return env.SESSIONPIPE_CLAUDE;\n const names = process.platform === \"win32\" ? [\"claude.exe\", \"claude.cmd\"] : [\"claude\"];\n for (const d of String(env.PATH || \"\").split(path.delimiter)) {\n if (!d || !path.isAbsolute(d)) continue;\n for (const n of names) if (isExe(path.join(d, n))) return path.join(d, n);\n }\n for (const p of [\n path.join(home, \".claude\", \"local\", \"claude\"),\n path.join(home, \".local\", \"bin\", \"claude\"),\n \"/opt/homebrew/bin/claude\",\n \"/usr/local/bin/claude\",\n ])\n if (isExe(p)) return p;\n const app = path.join(home, \"Library\", \"Application Support\", \"Claude\", \"claude-code\");\n let versions: string[] = [];\n try {\n versions = readdirSync(app)\n .filter((n) => /^\\d+(\\.\\d+)*$/.test(n))\n .sort(cmpVersion)\n .reverse();\n } catch {}\n for (const v of versions) {\n const p = path.join(app, v, \"claude.app\", \"Contents\", \"MacOS\", \"claude\");\n if (isExe(p)) return p;\n }\n return null;\n}\n\n/** One option's text in `claude --help`: its line and the deeper-indented lines under it. */\nfunction optionBlock(help: string, flag: string): string | null {\n const lines = help.split(\"\\n\");\n const re = new RegExp(`^\\\\s{0,4}(?:-\\\\w, )?${flag.replace(/-/g, \"\\\\-\")}(?![\\\\w-])`);\n const start = lines.findIndex((l) => re.test(l));\n if (start < 0) return null;\n const out = [lines[start] as string];\n for (let i = start + 1; i < lines.length && lines[i]?.trim() && !/^\\s{0,4}-/.test(lines[i] as string); i++)\n out.push(lines[i] as string);\n return out.join(\" \");\n}\n\nexport interface Caps {\n hasMode: boolean;\n modes: string[];\n promptsNone: boolean;\n fork: boolean;\n /** `--output-format stream-json` with `--include-partial-messages`: the answer can be\n * forwarded as it is written. Optional so older callers' literals still type. */\n stream?: boolean;\n}\n\nexport function parseCaps(help: string): Caps {\n const pm = optionBlock(help, \"--permission-mode\");\n const pp = optionBlock(help, \"--permission-prompts\");\n return {\n hasMode: !!pm,\n modes: pm ? [...pm.matchAll(/\"([A-Za-z]+)\"/g)].map((m) => m[1] as string) : [],\n promptsNone: !!pp && /\"none\"/.test(pp),\n fork: !!optionBlock(help, \"--fork-session\"),\n stream: !!optionBlock(help, \"--include-partial-messages\"),\n };\n}\n\n/** Permission flags for the machine's mode. Safe: `dontAsk` (nothing that needs\n * approval runs). Auto: Claude Code's own auto mode, or a refusal. Never\n * bypassPermissions \u2014 no path here writes it. */\nexport function modeFlags(mode: Mode, caps: Caps): { args: string[] } | { error: string } {\n if (mode === \"auto\") {\n if (!caps.modes.includes(\"auto\"))\n return { error: \"this machine is in auto mode, but its Claude Code has no auto permission mode\" };\n return { args: [\"--permission-mode\", \"auto\"] };\n }\n if (caps.modes.includes(\"dontAsk\")) return { args: [\"--permission-mode\", \"dontAsk\"] };\n const args: string[] = [];\n if (caps.hasMode)\n args.push(\n \"--permission-mode\",\n caps.modes.includes(\"manual\") && !caps.modes.includes(\"default\") ? \"manual\" : \"default\",\n );\n if (caps.promptsNone) args.push(\"--permission-prompts\", \"none\");\n return { args };\n}\n\n/** The env a headless turn runs with: ours, minus the markers that make Claude Code\n * think it runs inside another session, with CLAUDE_CONFIG_DIR naming the account. */\nexport function claudeEnv(configDir?: string, env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n const e = { ...env };\n for (const k of [\n \"CLAUDECODE\",\n \"CLAUDE_CODE_SESSION_ID\",\n \"CLAUDE_CODE_HOST_SESSION_ID\",\n \"CLAUDE_CODE_ENTRYPOINT\",\n \"CLAUDE_CODE_SESSION_ATTENDED\",\n \"CLAUDE_CODE_SSE_PORT\",\n ])\n delete e[k];\n e.SESSIONPIPE_CONTROL_JOB = \"1\";\n if (configDir !== undefined) {\n if (path.resolve(configDir) === path.resolve(os.homedir(), \".claude\")) delete e.CLAUDE_CONFIG_DIR;\n else e.CLAUDE_CONFIG_DIR = configDir;\n }\n return e;\n}\n\n/** Whether Claude Code is signed in for one account, in Claude Code's own words\n * (`claude auth status --json`). `loggedIn: null` means this Claude Code can't say\n * (too old for `auth status`, or it didn't answer): never a reason to refuse. */\nexport function parseAuthStatus(stdout: string | null | undefined): Login {\n const text = String(stdout || \"\").trim();\n const start = text.indexOf(\"{\");\n if (start < 0) return { loggedIn: null };\n try {\n const j = JSON.parse(text.slice(start)) as Record<string, unknown>;\n if (typeof j.loggedIn !== \"boolean\") return { loggedIn: null };\n return {\n loggedIn: j.loggedIn,\n ...(typeof j.authMethod === \"string\" ? { method: j.authMethod } : {}),\n ...(typeof j.subscriptionType === \"string\" ? { subscription: j.subscriptionType } : {}),\n };\n } catch {\n return { loggedIn: null };\n }\n}\n\n/** Ask Claude Code whether the account in `configDir` (the default one when omitted)\n * is signed in, from this process \u2014 which is the point: a login kept in the macOS\n * keychain is readable from the screen's own session and not from a background\n * service on a Mac nobody is logged in to, or from an ssh shell, so a headless turn\n * started there dies with \"please run /login\". */\nexport function claudeLogin(bin: string, configDir?: string, env: NodeJS.ProcessEnv = process.env): Promise<Login> {\n return new Promise((resolve) => {\n execFile(\n bin,\n [\"auth\", \"status\", \"--json\"],\n { encoding: \"utf8\", timeout: 20_000, env: claudeEnv(configDir, env), maxBuffer: 256 * 1024 },\n // `auth status` may exit non-zero when signed out; its JSON still says so.\n (_err, stdout) => resolve(parseAuthStatus(stdout)),\n );\n });\n}\n\n/** The command that signs one account in, quoted for a sentence. */\nexport function loginCommand(configDir: string | undefined): string {\n const home = os.homedir();\n const isDefault = !configDir || path.resolve(configDir) === path.resolve(home, \".claude\");\n return isDefault ? \"`claude auth login`\" : `\\`CLAUDE_CONFIG_DIR=${configDir.replace(home, \"~\")} claude auth login\\``;\n}\n\n/** What to tell the person when an account isn't signed in for the daemon. */\nexport function loginHint(configDir: string | undefined, platform: NodeJS.Platform = process.platform): string {\n const shown = configDir ? configDir.replace(os.homedir(), \"~\") : \"~/.claude\";\n const login = loginCommand(configDir);\n if (platform === \"darwin\")\n return `Claude Code (${shown}) isn't signed in as this machine's background service sees it. On a Mac its login lives in the login keychain, which a background service can read only while someone is logged in at the screen: log in at the Mac, or run ${login} there.`;\n return `Claude Code (${shown}) isn't signed in on this machine: run ${login} there.`;\n}\n\nexport function detectCaps(bin: string): Caps {\n let help = \"\";\n try {\n help = execFileSync(bin, [\"--help\"], {\n encoding: \"utf8\",\n timeout: 30_000,\n env: claudeEnv(),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n maxBuffer: 4 * 1024 * 1024,\n });\n } catch (e) {\n help = String((e as { stdout?: string })?.stdout || \"\");\n }\n return parseCaps(help);\n}\n\nexport interface Transcript {\n file: string;\n configDir: string;\n project: string;\n}\n\n/** <config dir>/projects/<folder>/<session>.jsonl in any Claude Code config dir. */\nexport function findTranscript(session: string, dirs: string[]): Transcript | null {\n if (!UUID_RE.test(session)) return null;\n for (const dir of dirs) {\n let projects: import(\"node:fs\").Dirent[] = [];\n try {\n projects = readdirSync(path.join(dir, \"projects\"), { withFileTypes: true });\n } catch {\n continue;\n }\n for (const p of projects) {\n if (!p.isDirectory()) continue;\n const file = path.join(dir, \"projects\", p.name, `${session}.jsonl`);\n try {\n if (statSync(file).isFile()) return { file, configDir: dir, project: p.name };\n } catch {}\n }\n }\n return null;\n}\n\nconst projectName = (cwd: string) => cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n\n/** The folder a session runs in, from its transcript's own records (never from a\n * command): the `cwd` whose project name is the folder the transcript is filed\n * under, else the first `cwd`. Streams; a line over 2 MB is skipped. */\nexport function sessionFolder(t: Transcript, cap = 8 * 1024 * 1024): string | null {\n let first: string | null = null;\n let count = 0;\n let fd: number | undefined;\n const look = (line: Buffer): string | null => {\n if (line.indexOf('\"cwd\"') < 0) return null;\n let j: { cwd?: unknown };\n try {\n j = JSON.parse(line.toString(\"utf8\"));\n } catch {\n return null;\n }\n if (!j || typeof j.cwd !== \"string\" || !path.isAbsolute(j.cwd)) return null;\n if (projectName(j.cwd) === t.project) return j.cwd;\n first ??= j.cwd;\n count++;\n return null;\n };\n try {\n fd = openSync(t.file, \"r\");\n const buf = Buffer.alloc(256 * 1024);\n let pos = 0;\n let rest = Buffer.alloc(0);\n let skipping = false;\n while (pos < cap && count < 50) {\n const n = readSync(fd, buf, 0, buf.length, pos);\n if (!n) {\n if (!skipping && rest.length) {\n const hit = look(rest);\n if (hit) return hit;\n }\n break;\n }\n pos += n;\n let chunk = rest.length ? Buffer.concat([rest, buf.subarray(0, n)]) : buf.subarray(0, n);\n let nl = chunk.indexOf(10);\n while (nl >= 0) {\n const line = chunk.subarray(0, nl);\n chunk = chunk.subarray(nl + 1);\n if (skipping) skipping = false;\n else {\n const hit = look(line);\n if (hit) return hit;\n }\n nl = chunk.indexOf(10);\n }\n if (chunk.length > 2 * 1024 * 1024) {\n skipping = true;\n rest = Buffer.alloc(0);\n } else rest = skipping ? Buffer.alloc(0) : Buffer.from(chunk);\n }\n } catch {\n } finally {\n if (fd !== undefined)\n try {\n closeSync(fd);\n } catch {}\n }\n return first;\n}\n\nfunction pidAlive(pid: number): boolean {\n if (!Number.isSafeInteger(pid) || pid <= 1) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n return (e as { code?: string }).code === \"EPERM\";\n }\n}\n\n/** A Claude Code process holds this session right now: its registry file,\n * <config>/sessions/<pid>.json, names it and the pid is alive (interactive and\n * Agent SDK sessions both file one). */\nexport function liveProcess(session: string, configDir: string): boolean {\n let names: string[] = [];\n try {\n names = readdirSync(path.join(configDir, \"sessions\")).filter((n) => /^\\d+\\.json$/.test(n));\n } catch {\n return false;\n }\n for (const n of names) {\n try {\n const j = JSON.parse(readFileSync(path.join(configDir, \"sessions\", n), \"utf8\")) as {\n sessionId?: unknown;\n pid?: unknown;\n };\n if (String(j.sessionId) !== session) continue;\n if (pidAlive(Number(j.pid ?? n.slice(0, -5)))) return true;\n } catch {}\n }\n return false;\n}\n\n/** Written in the last 90 s, and not by a job of ours. */\nexport function recentlyWritten(file: string, ourLastEnd?: number, now = Date.now()): boolean {\n let m: number;\n try {\n m = statSync(file).mtimeMs;\n } catch {\n return false;\n }\n if (now - m > LIVE_WRITE_MS) return false;\n return !(ourLastEnd && m <= ourLastEnd + 2000);\n}\n\n/** Run one headless turn (headless.ts). Streaming (`--output-format stream-json`), only\n * the `result` line is kept for the RunResult unless the caller says otherwise. */\nexport function runClaude(bin: string, args: string[], o: RunOptions): Promise<RunResult> {\n return runHeadless(bin, args, { ...o, keep: o.keep ?? ((line) => line.includes('\"type\":\"result\"')) });\n}\n\nexport interface ClaudeResult {\n type?: string;\n result?: unknown;\n is_error?: boolean;\n subtype?: string;\n session_id?: unknown;\n permission_denials?: { tool_name?: unknown }[];\n}\n\n/** `--output-format json`: one result object, or an array whose last `result` entry it is. */\nexport function parseResult(stdout: string | null | undefined): ClaudeResult | null {\n const s = String(stdout || \"\").trim();\n if (!s) return null;\n const pick = (j: unknown): ClaudeResult | null => {\n if (Array.isArray(j)) {\n for (let i = j.length - 1; i >= 0; i--) if (j[i]?.type === \"result\") return j[i];\n return null;\n }\n return j && typeof j === \"object\" ? (j as ClaudeResult) : null;\n };\n try {\n return pick(JSON.parse(s));\n } catch {}\n const lines = s.split(\"\\n\");\n for (let i = lines.length - 1; i >= 0; i--) {\n try {\n const j = pick(JSON.parse(lines[i] as string));\n if (j && (j.type === \"result\" || \"result\" in j)) return j;\n } catch {}\n }\n return null;\n}\n\nexport const isUuid = (s: unknown): s is string => typeof s === \"string\" && UUID_RE.test(s);\n", "// SPDX-License-Identifier: Apache-2.0\n// Codex CLI (OpenAI) \u2014 docs: https://learn.chatgpt.com/docs/hooks\n// Config: ~/.codex/hooks.json (Claude-shaped, 12 events, timeouts in seconds) AND\n// `notify` at the top level of config.toml as the fallback when hooks are off or\n// not yet trusted (non-managed hooks need a /hooks review in the CLI). An existing\n// notify (Codex Computer Use) is chained through --previous-notify, never replaced.\nimport { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines, recentFiles, scanLines } from \"../readers/files.js\";\nimport { codexInjected, readCodex } from \"../readers/transcripts.js\";\nimport { installClaudeShaped, installedClaudeShaped, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport * as toml from \"./codex-config.js\";\nimport { codexReplayBoundary, codexSubagent } from \"./codex-rollout.js\";\nimport type {\n Adapter,\n BackfillRow,\n HookCommand,\n HookInput,\n HookResult,\n InstalledReport,\n InstallOptions,\n SessionFacts,\n} from \"./types.js\";\n\nconst NAME = \"codex\";\nexport const CODEX_EVENTS = [\n \"SessionStart\",\n \"UserPromptSubmit\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PermissionRequest\",\n \"Stop\",\n \"Interrupt\",\n \"SubagentStart\",\n \"SubagentStop\",\n \"PreCompact\",\n \"PostCompact\",\n \"SessionEnd\",\n] as const;\nconst OPTS = { matcherFor: (e: string) => (/Tool|Permission/.test(e) ? \"\" : undefined), timeout: 5 };\nconst eventsFor = (lean?: boolean) => (lean ? CODEX_EVENTS.filter((e) => e !== \"PreToolUse\") : [...CODEX_EVENTS]);\n\nconst codexHome = (env: NodeJS.ProcessEnv) => env.CODEX_HOME || path.join(homeDir(), \".codex\");\nconst hooksFile = (env: NodeJS.ProcessEnv) => path.join(codexHome(env), \"hooks.json\");\nconst configFile = (env: NodeJS.ProcessEnv) => path.join(codexHome(env), \"config.toml\");\nconst sessionsDir = (env: NodeJS.ProcessEnv) => path.join(codexHome(env), \"sessions\");\n\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst endReason = (r: unknown): \"clear\" | \"logout\" | \"exit\" | \"other\" =>\n r === \"clear\" || r === \"logout\" || r === \"exit\" ? r : \"other\";\n\nfunction installNotify(cmd: HookCommand, env: NodeJS.ProcessEnv) {\n const file = configFile(env);\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {}\n const argv = cmd([NAME, \"notify\"]).argv;\n const line = `notify = ${JSON.stringify(argv)}`;\n const n = toml.readNotify(text);\n const write = (next: string) => {\n mkdirSync(path.dirname(file), { recursive: true });\n writeFileSync(file, next);\n };\n if (n && !n.other) {\n if (!n.misplaced && JSON.stringify(n.argv) === JSON.stringify(argv))\n return { file, changed: false, note: \"notify current\" };\n write(toml.withNotify(text, line));\n return {\n file,\n changed: true,\n note: n.misplaced\n ? \"notify moved to the top level (it sat inside a [table], where Codex never reads it)\"\n : \"notify updated\",\n };\n }\n if (n?.other) {\n const prev = toml.previousNotify(n.argv);\n if (toml.isComputerUse(n.argv)) {\n if (prev && toml.OURS.test(JSON.stringify(prev))) {\n if (JSON.stringify(prev) === JSON.stringify(argv))\n return { file, changed: false, note: \"notify current (after Codex Computer Use)\" };\n }\n if (!prev || toml.OURS.test(JSON.stringify(prev))) {\n write(toml.replaceNotify(text, n, `notify = ${toml.withPreviousRaw(n.raw, argv)}`));\n return { file, changed: true, note: \"chained after Codex Computer Use (--previous-notify)\" };\n }\n }\n return {\n file,\n changed: false,\n skipped: true,\n note: `notify belongs to ${(n.argv?.[0] ?? n.raw).replace(/^.*\\//, \"\").slice(0, 40)}; left alone. Codex will report nothing until you approve the hooks: start \\`codex\\` and accept the hook review`,\n };\n }\n write(toml.withNotify(text, line));\n return { file, changed: true, note: \"notify set at the top level\" };\n}\n\nfunction uninstallNotify(env: NodeJS.ProcessEnv) {\n const file = configFile(env);\n let text: string;\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { file, changed: false };\n }\n const n = toml.readNotify(text);\n if (!n) return { file, changed: false };\n if (!n.other) {\n writeFileSync(file, toml.withoutNotify(text));\n return { file, changed: true };\n }\n const prev = toml.previousNotify(n.argv);\n if (toml.isComputerUse(n.argv) && prev && toml.OURS.test(JSON.stringify(prev))) {\n writeFileSync(file, toml.replaceNotify(text, n, `notify = ${toml.stripPreviousRaw(n.raw)}`));\n return { file, changed: true };\n }\n return { file, changed: false };\n}\n\n/** The rollout file of one thread: `<CODEX_HOME>/sessions/YYYY/MM/DD/rollout-<time>-<thread\n * id>.jsonl`, newest day first. Null for an id that isn't a thread id's shape, so a\n * short or odd one never matches some other session's file. */\nexport function findRollout(threadId: string, env: NodeJS.ProcessEnv = process.env): string | null {\n if (!/^[A-Za-z0-9-]{8,128}$/.test(threadId)) return null;\n let best: string | null = null;\n const walk = (dir: string, depth: number) => {\n let names: string[] = [];\n try {\n names = readdirSync(dir);\n } catch {\n return;\n }\n for (const n of names.sort().reverse()) {\n const p = path.join(dir, n);\n if (n.endsWith(`-${threadId}.jsonl`)) {\n best = p;\n return;\n }\n if (depth < 3) {\n walk(p, depth + 1);\n if (best) return;\n }\n }\n };\n walk(sessionsDir(env), 0);\n return best;\n}\n\n/** A rollout's first record, its own session_meta. About 50 KB (it carries the base\n * instructions), so it is read on its own rather than from a sampled head. */\nfunction rolloutMeta(file: string): Record<string, unknown> | null {\n return scanLines(file, (line) => parseLines([line])[0] ?? {});\n}\n\n/** A rollout named for a thread other than `id` (`rollout-<time>-<thread id>.jsonl`).\n * A name of any other shape says nothing, so it is not taken for another thread's. */\nfunction ofAnotherThread(file: string, id: string): boolean {\n const m = /-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\.jsonl(?:\\.zst)?$/i.exec(file);\n return !!m?.[1] && m[1].toLowerCase() !== id.toLowerCase();\n}\n\nexport const codex: Adapter = {\n name: NAME,\n events: CODEX_EVENTS,\n detect: (env = process.env) => existsSync(codexHome(env)),\n configFiles: (env = process.env) => [hooksFile(env), configFile(env)],\n install: (cmd, env = process.env, opts: InstallOptions = {}) => [\n installClaudeShaped(hooksFile(env), NAME, eventsFor(opts.lean), cmd, OPTS),\n installNotify(cmd, env),\n ],\n uninstall: (env = process.env, opts: InstallOptions = {}) => [\n uninstallClaudeShaped(hooksFile(env), CODEX_EVENTS, { created: opts.created?.includes(hooksFile(env)) }),\n uninstallNotify(env),\n ],\n installed: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const out: InstalledReport[] = [\n {\n file: hooksFile(env),\n state: installedClaudeShaped(hooksFile(env), NAME, eventsFor(opts.lean), cmd, OPTS),\n note: \"Codex runs non-managed hooks only after the review in `codex` (/hooks); until then nothing is reported unless the notify fallback is ours\",\n },\n ];\n let text = \"\";\n try {\n text = readFileSync(configFile(env), \"utf8\");\n } catch {}\n const n = toml.readNotify(text);\n const argv = cmd([NAME, \"notify\"]).argv;\n const prev = n ? toml.previousNotify(n.argv) : null;\n const ours = n && (!n.other || (prev && JSON.stringify(prev) === JSON.stringify(argv)));\n out.push({\n file: configFile(env),\n state:\n !n || (n.other && !ours)\n ? \"missing\"\n : n.misplaced\n ? \"misplaced\"\n : JSON.stringify(n.argv) === JSON.stringify(argv) || (prev && JSON.stringify(prev) === JSON.stringify(argv))\n ? \"current\"\n : \"stale\",\n });\n return out;\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n if (event === \"notify\") {\n // Codex's notify passes one JSON argument: {\"type\":\"agent-turn-complete\",\"thread-id\":\u2026,\"turn-id\":\u2026,\"cwd\":\u2026}\n const raw = input.argv.find((a) => a.startsWith(\"{\")) ?? input.stdin;\n try {\n const j: unknown = raw ? JSON.parse(raw) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = (s[\"thread-id\"] ?? s.thread_id ?? s[\"session-id\"] ?? s.session_id) as string | undefined;\n if (!id) return null;\n // Notify names the thread whose turn ended. Without a rollout it is an ephemeral\n // thread, kept nowhere (the hooks' `transcript_path: null` below). A subagent's\n // thread belongs to its parent, whose hooks already report it: SubagentStart and\n // SubagentStop name it as `agent_id`. Neither is a session of its own.\n const file = findRollout(String(id), input.env as NodeJS.ProcessEnv);\n if (!file || codexSubagent(rolloutMeta(file))) return null;\n const r: HookResult = {\n session: { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd },\n events: [\n {\n type: \"turn.ended\",\n data: { reason: \"stop\", ...(typeof s[\"turn-id\"] === \"string\" ? { turn_id: s[\"turn-id\"] } : {}) },\n harnessEvent: \"notify\",\n },\n ],\n hints: {},\n transcript: file,\n };\n return r;\n }\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = s.session_id as string | undefined;\n if (!id) return null;\n // `transcript_path: null` is an ephemeral thread (recorded on codex-cli 0.160.0):\n // Codex Desktop's own background threads (ambient suggestions and their safety\n // review) and `codex exec --ephemeral`. Codex keeps nothing of one, so there is no\n // session to name, read or resume.\n if (s.transcript_path === null) return null;\n const session: HookResult[\"session\"] = { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd };\n if (typeof s.model === \"string\") session.model = s.model;\n const turn_id = typeof s.turn_id === \"string\" ? s.turn_id : undefined;\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const call_id = typeof s.tool_use_id === \"string\" ? s.tool_use_id : undefined;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(\n ev(\"session.started\", {\n source:\n typeof s.source === \"string\" && [\"startup\", \"resume\", \"clear\", \"compact\", \"fork\"].includes(s.source)\n ? s.source\n : \"unknown\",\n }),\n );\n break;\n case \"UserPromptSubmit\":\n events.push(\n ev(\"turn.started\", {\n turn_id,\n prompt_chars: typeof s.prompt === \"string\" ? [...s.prompt].length : undefined,\n }),\n );\n break;\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, call_id, turn_id, input: s.tool_input }));\n break;\n case \"PostToolUse\":\n if (tool)\n events.push(\n ev(\"tool.ended\", { tool, call_id, turn_id, ok: true, input: s.tool_input, output: s.tool_response }),\n );\n break;\n case \"PermissionRequest\":\n events.push(\n ev(\"attention.needed\", { attention_id: call_id ?? `perm-${Date.now()}`, kind: \"permission\", tool }),\n );\n break;\n case \"Stop\":\n events.push(ev(\"turn.ended\", { turn_id, reason: \"stop\" }));\n break;\n case \"Interrupt\":\n events.push(ev(\"turn.ended\", { turn_id, reason: \"interrupt\" }));\n break;\n case \"SubagentStart\":\n events.push(\n ev(\"subagent.started\", {\n agent_id: String(s.agent_id ?? s.subagent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"SubagentStop\":\n events.push(\n ev(\"subagent.ended\", {\n agent_id: String(s.agent_id ?? s.subagent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"PreCompact\":\n events.push(ev(\"context.compacted\", { trigger: s.trigger === \"manual\" ? \"manual\" : \"auto\" }));\n break;\n case \"PostCompact\":\n break;\n case \"SessionEnd\":\n events.push(ev(\"session.ended\", { reason: endReason(s.reason) }));\n break;\n default:\n return null;\n }\n const r: HookResult = { session, events, hints: {} };\n // Inside a subagent Codex sends the parent's session_id with the subagent's own\n // rollout (its SubagentStart, its tool calls): that file is not this session's.\n if (typeof s.transcript_path === \"string\" && !ofAnotherThread(s.transcript_path, String(id)))\n r.transcript = s.transcript_path;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readCodex(text.split(\"\\n\"), fromLine);\n },\n\n facts(session, transcript): SessionFacts {\n const out: SessionFacts = {};\n if (transcript) Object.assign(out, codexFacts(transcript));\n return out;\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows: BackfillRow[] = [];\n for (const f of recentFiles(sessionsDir(env), 3, sinceMs, (n) => /^rollout-.*\\.jsonl$/.test(n))) {\n const m = /([0-9a-f]{8}-[0-9a-f-]{27,})\\.jsonl$/i.exec(path.basename(f));\n if (!m?.[1]) continue;\n // A subagent's rollout is part of its parent's session, as in fromHook's notify.\n if (codexSubagent(rolloutMeta(f))) continue;\n const facts = codexFacts(f);\n if (!facts.started_at || !facts.last_at) continue;\n const { started_at, last_at, first_ask: _fa, harness_version: _hv, ...rest } = facts;\n rows.push({ session: { id: m[1], ...rest }, started_at, last_at });\n }\n return rows;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n\n/** Codex keeps no title; its first real ask stands in. A fork's replay is not its ask. */\nexport function codexFacts(file: string): SessionFacts {\n const { head, tail } = ends(file, 128 * 1024, 64 * 1024);\n let H = parseLines(head);\n let T = parseLines(tail);\n const out: SessionFacts = {};\n const meta = H.find((j) => j.type === \"session_meta\" && j.payload);\n const boundary = codexReplayBoundary(meta);\n if (meta?.payload) {\n const p = meta.payload as {\n cwd?: string;\n cli_version?: string;\n git?: { branch?: string; repository_url?: string };\n };\n if (p.cwd) out.cwd = p.cwd;\n if (p.cli_version) out.harness_version = String(p.cli_version);\n if (p.git?.branch) out.branch = p.git.branch;\n if (p.git?.repository_url) out.repo = String(p.git.repository_url).replace(/\\/\\/[^/@]*@/, \"//\");\n }\n if (boundary) {\n const h = H.findIndex(boundary);\n const t = T.findIndex(boundary);\n H = h < 0 ? [] : H.slice(h);\n // The samples can overlap, so trim each one at the boundary independently.\n // If both miss it, scan the gap before trusting the tail: it could still be\n // parent replay. Stop as soon as the boundary is found, without loading the file.\n const found =\n h >= 0 ||\n t >= 0 ||\n scanLines(file, (line) => (boundary(parseLines([line])[0] ?? null) ? true : null), Number.POSITIVE_INFINITY);\n T = t >= 0 ? T.slice(t) : found ? T : [];\n }\n const ctx = H.concat(T)\n .reverse()\n .find((j) => j.type === \"turn_context\" && (j.payload as { model?: string } | undefined)?.model) as\n | { payload?: { model?: string } }\n | undefined;\n if (ctx?.payload?.model) out.model = ctx.payload.model;\n for (const j of H) {\n const p = j.payload as { type?: string; role?: string; content?: { type?: string; text?: string }[] } | undefined;\n if (j.type !== \"response_item\" || !p || p.type !== \"message\" || p.role !== \"user\") continue;\n const text = (p.content ?? [])\n .filter((b) => b && b.type === \"input_text\" && typeof b.text === \"string\")\n .map((b) => b.text as string)\n .join(\"\\n\")\n .trim();\n if (!text || codexInjected(text)) continue;\n const line = text.split(\"\\n\")[0] as string; // trimmed, so its first line is its first non-blank one\n out.title = line.length > 80 ? `${line.slice(0, 80).replace(/\\s+\\S*$/, \"\")}\u2026` : line;\n out.title_source = \"first-ask\";\n break;\n }\n const times = (boundary && meta ? [meta, ...H, ...T] : H.concat(T))\n .map((j) => Date.parse(String(j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Codex's ~/.codex/config.toml, as far as the notify fallback needs it: its one\n// top-level `notify` command. Codex reads `notify` only at the top level \u2014 before\n// the first [table] \u2014 and Codex itself appends a [projects.\"<path>\"] table for every\n// folder it trusts, so a line appended at the end lands inside one and never runs.\n// Ported from spacesheep-cli lib/codex-config.js. Pure text in, text out.\n\nconst NOTIFY_LINE = /^[ \\t]*notify[ \\t]*=[ \\t]*(\\[.*\\])[ \\t]*(?:#.*)?$/m;\nconst NOTIFY_KEY = /^[ \\t]*notify[ \\t]*=/m;\n/** A notify that runs sessionpipe's hook directly (or through its launcher). */\nexport const OURS = /(?:hook\\.js|sessionpipe-hook)\",\\s*\"codex\",\\s*\"notify\"/;\n\nfunction scan(line: string, st: { depth: number; str: string | null }): void {\n let i = 0;\n while (i < line.length) {\n if (st.str) {\n const j = line.indexOf(st.str, i);\n if (j < 0) return;\n i = j + 3;\n st.str = null;\n continue;\n }\n const ch = line[i];\n if (ch === \"#\") return;\n if (line.startsWith('\"\"\"', i) || line.startsWith(\"'''\", i)) {\n st.str = line.slice(i, i + 3);\n i += 3;\n continue;\n }\n if (ch === '\"') {\n i++;\n while (i < line.length && line[i] !== '\"') i += line[i] === \"\\\\\" ? 2 : 1;\n i++;\n continue;\n }\n if (ch === \"'\") {\n const j = line.indexOf(\"'\", i + 1);\n i = j < 0 ? line.length : j + 1;\n continue;\n }\n if (ch === \"[\") st.depth++;\n else if (ch === \"]\") st.depth = Math.max(0, st.depth - 1);\n i++;\n }\n}\n\n/** Offset of the first table header, or -1. */\nexport function firstTableAt(text: string): number {\n const st = { depth: 0, str: null as string | null };\n let pos = 0;\n for (const line of text.split(\"\\n\")) {\n if (!st.str && st.depth === 0 && /^[ \\t]*\\[/.test(line)) return pos;\n scan(line, st);\n pos += line.length + 1;\n }\n return -1;\n}\n\nfunction split(text: string) {\n const at = firstTableAt(text);\n return at < 0 ? { head: text, tail: \"\", at: text.length } : { head: text.slice(0, at), tail: text.slice(at), at };\n}\n\nexport function parseArgv(raw: string): string[] | null {\n try {\n const a = JSON.parse(raw) as unknown;\n return Array.isArray(a) && a.every((x) => typeof x === \"string\") ? (a as string[]) : null;\n } catch {\n return null;\n }\n}\n\nexport interface Notify {\n raw: string;\n argv: string[] | null;\n index: number;\n length: number;\n misplaced: boolean;\n other: boolean;\n}\n\n/** notify as Codex sees it; `misplaced` for a line of ours inside a table. */\nexport function readNotify(text: string): Notify | null {\n const { head, tail, at } = split(text);\n const m = NOTIFY_LINE.exec(head);\n if (m) {\n const raw = m[1] as string;\n return { raw, argv: parseArgv(raw), index: m.index, length: m[0].length, misplaced: false, other: !OURS.test(raw) };\n }\n const k = NOTIFY_KEY.exec(head);\n if (k) {\n const rest = head.slice(k.index).split(\"\\n\")[0] as string;\n return {\n raw: rest.replace(NOTIFY_KEY, \"\").trim(),\n argv: null,\n index: k.index,\n length: 0,\n misplaced: false,\n other: true,\n };\n }\n const t = NOTIFY_LINE.exec(tail);\n if (t) {\n const raw = t[1] as string;\n if (OURS.test(raw))\n return { raw, argv: parseArgv(raw), index: at + t.index, length: t[0].length, misplaced: true, other: false };\n }\n return null;\n}\n\nfunction dropLine(text: string, index: number, length: number): string {\n return text.slice(0, index) + text.slice(index + length).replace(/^\\r?\\n/, \"\");\n}\n\n/** Put `line` at the top level: before the first table, or at the end of a file that has none. */\nexport function insertTopLevel(text: string, line: string): string {\n const { head, tail } = split(text);\n if (!tail) return (head.trim() ? head.replace(/\\s*$/, \"\\n\") : \"\") + line + \"\\n\";\n return `${(head.trim() ? head.replace(/\\s*$/, \"\\n\") : \"\") + line}\\n\\n${tail}`;\n}\n\n/** The config with `line` as its notify, for a config whose notify is ours or absent. */\nexport function withNotify(text: string, line: string): string {\n const n = readNotify(text);\n if (n && !n.misplaced && !n.other) return text.slice(0, n.index) + line + text.slice(n.index + n.length);\n if (n?.misplaced) return insertTopLevel(dropLine(text, n.index, n.length), line);\n return insertTopLevel(text, line);\n}\n\n/** The config with its notify line `n` (as readNotify found it in `text`) replaced by `line`. */\nexport function replaceNotify(text: string, n: Notify, line: string): string {\n return text.slice(0, n.index) + line + text.slice(n.index + n.length);\n}\n\n/** The config with our top-level or misplaced notify removed. */\nexport function withoutNotify(text: string): string {\n const n = readNotify(text);\n if (!n || n.other || !n.length) return text;\n return dropLine(text, n.index, n.length);\n}\n\n// Codex Computer Use takes the notify slot itself and keeps the command it found in\n// its own argv: [client, \"turn-ended\", \"--previous-notify\", \"<that command as JSON>\"].\nconst PREVIOUS = \"--previous-notify\";\nexport function previousNotify(argv: string[] | null): string[] | null {\n if (!Array.isArray(argv)) return null;\n const i = argv.indexOf(PREVIOUS);\n return i >= 0 && typeof argv[i + 1] === \"string\" ? parseArgv(argv[i + 1] as string) : null;\n}\nexport function withPrevious(argv: string[], prev: string[] | null): string[] {\n const out = argv.slice();\n const i = out.indexOf(PREVIOUS);\n if (i >= 0) out.splice(i, 2);\n if (prev) out.push(PREVIOUS, JSON.stringify(prev));\n return out;\n}\n/** The raw notify value with its --previous-notify pair removed, formatting kept. */\nexport function stripPreviousRaw(raw: string): string {\n return raw.replace(/,\\s*\"--previous-notify\",\\s*\"(?:[^\"\\\\]|\\\\.)*\"\\s*(?=\\])/, \"\");\n}\n/** The raw notify value with `prev` as its --previous-notify, formatting of the rest kept. */\nexport function withPreviousRaw(raw: string, prev: string[]): string {\n const base = stripPreviousRaw(raw).replace(/\\s*\\]\\s*$/, \"\");\n return `${base}, \"--previous-notify\", ${JSON.stringify(JSON.stringify(prev))}]`;\n}\nexport const isComputerUse = (argv: string[] | null): boolean =>\n Array.isArray(argv) && typeof argv[0] === \"string\" && /(^|\\/)SkyComputerUseClient$/.test(argv[0]);\n", "// SPDX-License-Identifier: Apache-2.0\n// Codex CLI (OpenAI) \u2014 control delivery (spec/CONTROL.md \u00A76). Codex on this machine,\n// as the control daemon needs it: which `codex` to run, with which sandbox flags, one\n// headless turn (`codex exec --json` for a new session, `codex exec resume --json <id>`\n// for the next message), and its JSONL output read as it streams. Codex picks a new\n// session's id itself (the first line, `thread.started`), so the daemon names it after\n// the command that started it (CONTROL.md \u00A76 `start`). Shapes measured on codex-cli\n// 0.160.0, 2026-10-04.\nimport { execFile } from \"node:child_process\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n findBinary,\n jobEnv,\n type Login,\n type Mode,\n type Reading,\n type RunResult,\n runFailure,\n stderrTail,\n} from \"./headless.js\";\n\nexport { codexFacts, findRollout } from \"./codex.js\";\n\nconst LABEL = \"Codex\";\n\n/** The `codex` to run: SESSIONPIPE_CODEX, else on PATH, else beside the node running\n * this (an `npm install -g` there) or where the installers put it. */\nexport function findCodex(\n env: NodeJS.ProcessEnv = process.env,\n home = os.homedir(),\n nodeDir = path.dirname(process.execPath),\n): string | null {\n return findBinary({\n override: env.SESSIONPIPE_CODEX,\n names: process.platform === \"win32\" ? [\"codex.exe\", \"codex.cmd\"] : [\"codex\"],\n env,\n dirs: [nodeDir, path.join(home, \".local\", \"bin\"), \"/opt/homebrew/bin\", \"/usr/local/bin\"],\n });\n}\n\n/** Sandbox flags for the machine's mode. Safe: workspace-write, and nothing escalates\n * unattended (exec never asks). Auto: approval requests go through Codex's own\n * automatic review. Never `--dangerously-bypass-approvals-and-sandbox` or\n * `--dangerously-bypass-hook-trust`: no path here writes them. */\nexport function codexModeFlags(mode: Mode, resume = false): string[] {\n // `codex exec resume` takes neither `-s` nor `--approve-for-me` (0.160: \"unexpected\n // argument\"), so a resume says the same thing as config overrides, which it does take.\n if (resume)\n return mode === \"auto\"\n ? [\n \"-c\",\n 'sandbox_mode=\"workspace-write\"',\n \"-c\",\n 'approval_policy=\"on-request\"',\n \"-c\",\n 'approvals_reviewer=\"auto_review\"',\n ]\n : [\"-c\", 'sandbox_mode=\"workspace-write\"'];\n return mode === \"auto\" ? [\"--approve-for-me\"] : [\"-s\", \"workspace-write\"];\n}\n\n/** One headless turn. A new session runs in `cwd` (`-C`); a resume names the thread.\n * The prompt goes after `--`, so a message that starts with a dash is never a flag. */\nexport function codexArgs(o: { mode: Mode; prompt: string; cwd?: string; resume?: string }): string[] {\n const common = [\"--json\", \"--skip-git-repo-check\"];\n if (o.resume) return [\"exec\", \"resume\", ...common, ...codexModeFlags(o.mode, true), \"--\", o.resume, o.prompt];\n return [\"exec\", ...common, ...(o.cwd ? [\"-C\", o.cwd] : []), ...codexModeFlags(o.mode), \"--\", o.prompt];\n}\n\n/** The env a headless turn runs with. */\nexport const codexEnv = (env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv => jobEnv(env);\n\nexport const LOGIN_HINT = \"Codex isn't signed in on this machine: run `codex login --device-auth` there.\";\n\n/** Whether Codex can run as this process: CODEX_API_KEY in the env is enough; else\n * `codex login status` (exit 0 signed in, exit 1 \"Not logged in\"). Anything else \u2014\n * it didn't run, it timed out \u2014 is null, never a reason to refuse. */\nexport function codexLogin(bin: string, env: NodeJS.ProcessEnv = process.env): Promise<Login> {\n if (env.CODEX_API_KEY) return Promise.resolve({ loggedIn: true, method: \"api key\" });\n return new Promise((resolve) => {\n execFile(\n bin,\n [\"login\", \"status\"],\n { encoding: \"utf8\", timeout: 20_000, env: codexEnv(env), maxBuffer: 256 * 1024 },\n (err) => {\n if (!err) return resolve({ loggedIn: true });\n const code = (err as { code?: unknown }).code;\n resolve(code === 1 ? { loggedIn: false } : { loggedIn: null });\n },\n );\n });\n}\n\n/** One `--json` line, as much of it as the daemon uses. */\nexport interface CodexPiece {\n /** `thread.started`: the session's id, which Codex chose. */\n session?: string;\n /** A finished `agent_message`: one part of the answer. */\n message?: string;\n /** `turn.completed` (or `turn.failed`). */\n done?: boolean;\n /** `turn.failed`: why. */\n failed?: string;\n /** A top-level `error` (\"Reconnecting... 2/5\"): transient, the reason only if the run then fails. */\n note?: string;\n /** An `error` item: a warning Codex printed and carried on after (hook trust, a clamped timeout). */\n warning?: string;\n}\n\nexport function codexLine(line: string): CodexPiece | null {\n let j: {\n type?: unknown;\n thread_id?: unknown;\n message?: unknown;\n item?: { type?: unknown; text?: unknown; message?: unknown };\n error?: { message?: unknown };\n };\n try {\n j = JSON.parse(line);\n } catch {\n return null;\n }\n if (!j || typeof j !== \"object\") return null;\n const str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n switch (j.type) {\n case \"thread.started\":\n return str(j.thread_id) ? { session: str(j.thread_id) } : null;\n case \"item.completed\": {\n const it = j.item;\n if (it?.type === \"agent_message\" && str(it.text)) return { message: str(it.text) };\n if (it?.type === \"error\" && str(it.message)) return { warning: str(it.message) };\n return null;\n }\n case \"turn.completed\":\n return { done: true };\n case \"turn.failed\":\n return { done: true, failed: str(j.error?.message) || \"Codex reported an error\" };\n case \"error\":\n return str(j.message) ? { note: str(j.message) } : null;\n default:\n return null;\n }\n}\n\n/** A Codex run read as it streams: the answer is its finished agent messages. */\nexport class CodexReading implements Reading {\n session: string | null = null;\n lines = 0;\n readonly warnings: string[] = [];\n private readonly messages: string[] = [];\n private done = false;\n private failed: string | null = null;\n private note: string | null = null;\n\n get text(): string {\n return this.messages.join(\"\\n\\n\");\n }\n\n feed(line: string): boolean {\n this.lines++;\n const p = codexLine(line);\n if (!p) return false;\n if (p.session && !this.session) this.session = p.session;\n if (p.note) this.note = p.note;\n if (p.warning && this.warnings.length < 20) this.warnings.push(p.warning);\n if (p.failed) this.failed = p.failed;\n if (p.done) this.done = true;\n if (p.message?.trim()) {\n this.messages.push(p.message.trim());\n return true;\n }\n return false;\n }\n\n /** A failure is `turn.failed`, or a run that exits non-zero having said nothing; an\n * `error` item before a turn that then succeeds is only a warning. */\n outcome(res: RunResult): { failed: string } | { reply: string } {\n const broke = runFailure(LABEL, res);\n if (broke) return { failed: broke };\n if (this.failed) return { failed: this.failed };\n if (this.done || res.code === 0 || this.messages.length)\n return { reply: this.text || \"(Codex finished without a written reply.)\" };\n const why = this.note || codexStderr(res.stderr) || this.warnings.at(-1) || \"\";\n return { failed: `Codex exited (${res.signal || `code ${res.code}`}) without an answer${why ? `: ${why}` : \"\"}` };\n }\n}\n\n/** stderr's tail without the line Codex prints even with stdin closed. */\nfunction codexStderr(stderr: string | undefined): string {\n return stderrTail(\n String(stderr || \"\")\n .split(\"\\n\")\n .filter((l) => !/^Reading additional input from stdin/.test(l.trim()))\n .join(\"\\n\"),\n );\n}\n\nexport const reading = (): CodexReading => new CodexReading();\n", "// SPDX-License-Identifier: Apache-2.0\n// Devin CLI (Cognition) \u2014 docs: https://docs.devin.ai/cli/extensibility/hooks/overview\n// Config: the `hooks` key of the user config file \u2014 `~/.config/devin/config.json`\n// (`$XDG_CONFIG_HOME/devin/config.json` when that is set), `%APPDATA%\\devin\\config.json`\n// on Windows. Claude-shaped, matcher a REGEX on the tool name, timeouts in SECONDS.\n// That file is the only user-level location Devin reads hooks from; `hooks.v1.json` is\n// project-level only.\n//\n// Devin accepts exactly eight event names and rejects the WHOLE file on one it does not\n// know (\"unknown variant `Notification`, expected one of \u2026\"), which silently disables\n// every hook in it. DEVIN_EVENTS is that set, and nothing else may be added to it.\n//\n// The payload carries no `cwd`, no `transcript_path` and no `model`: the folder comes\n// from DEVIN_PROJECT_DIR in the hook's environment, and the transcript, the model, the\n// title and the times come from Devin's own session store \u2014 one SQLite file under the\n// data directory, read only, through readers/sqlite.ts. A session's transcript is\n// addressed as \"<database>#<session id>\", because readTranscript is given a file.\n//\n// stdout stays empty for every event: Devin reads a decision from stdout, and silence\n// plus exit 0 is \"carry on\" (printing nothing, printing `{}`, exiting 1 and blowing the\n// timeout were all measured as non-blocking; only exit 2 or an explicit\n// {\"decision\":\"block\"} blocks a tool).\nimport { createHash } from \"node:crypto\";\nimport { existsSync, readlinkSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { querySqlite } from \"../readers/sqlite.js\";\nimport { pairTurns } from \"../readers/transcripts.js\";\nimport { installClaudeShaped, installedClaudeShaped, readJson, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport type {\n Adapter,\n BackfillRow,\n HookInput,\n HookResult,\n InstallOptions,\n SessionFacts,\n TranscriptRead,\n} from \"./types.js\";\n\nconst NAME = \"devin\";\n/** The eight event names Devin accepts. One it does not know makes it drop the whole\n * hooks file, so this list is exact, not a superset \u2014 see devin.test.ts. */\nexport const DEVIN_EVENTS = [\n \"SessionStart\",\n \"UserPromptSubmit\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PermissionRequest\",\n \"Stop\",\n \"PostCompaction\",\n \"SessionEnd\",\n] as const;\nconst OPTS = { matcherFor: (e: string) => (/Tool|Permission/.test(e) ? \"\" : undefined), timeout: 5 };\nconst eventsFor = (lean?: boolean) => (lean ? DEVIN_EVENTS.filter((e) => e !== \"PreToolUse\") : [...DEVIN_EVENTS]);\nconst INSTALL_NOTE =\n \"Devin drops a whole hooks file on one event name it doesn't know; `/hooks` in `devin` lists what loaded\";\nconst CLAUDE_NOTE =\n \"Devin also reads ~/.claude/settings.json hooks (read_config_from.claude); a Claude-only event name there makes it ignore that file whole\";\n\nconst deadFileNote = (bad: string) =>\n `Devin loads NO hooks from this file: \"${bad}\" is not one of its event names and it rejects the file whole \u2014 remove that key (\\`/hooks\\` in \\`devin\\` lists what loaded)`;\n\n/** The first `hooks` key in the file that Devin does not accept, if there is one.\n * One such key disables every hook in the file, ours and any other tool's. */\nexport function foreignEvent(file: string): string | undefined {\n const hooks = readJson(file).hooks;\n if (!hooks || typeof hooks !== \"object\" || Array.isArray(hooks)) return undefined;\n const ok = DEVIN_EVENTS as readonly string[];\n return Object.keys(hooks).find((k) => !ok.includes(k));\n}\n\nconst homeOf = (env: NodeJS.ProcessEnv) => env.HOME || homeDir();\nconst appData = (env: NodeJS.ProcessEnv) => env.APPDATA || path.join(homeOf(env), \"AppData\", \"Roaming\");\n/** `~/.config/devin`, `$XDG_CONFIG_HOME/devin`, or `%APPDATA%\\devin`. */\nexport const devinConfigDir = (env: NodeJS.ProcessEnv = process.env): string =>\n process.platform === \"win32\"\n ? path.join(appData(env), \"devin\")\n : path.join(env.XDG_CONFIG_HOME || path.join(homeOf(env), \".config\"), \"devin\");\nconst configFile = (env: NodeJS.ProcessEnv) => path.join(devinConfigDir(env), \"config.json\");\n/** `~/.local/share/devin/cli`, `$XDG_DATA_HOME/devin/cli`, or `%APPDATA%\\devin\\cli`. */\nexport const devinDataDir = (env: NodeJS.ProcessEnv = process.env): string =>\n process.platform === \"win32\"\n ? path.join(appData(env), \"devin\", \"cli\")\n : path.join(env.XDG_DATA_HOME || path.join(homeOf(env), \".local\", \"share\"), \"devin\", \"cli\");\nconst sessionsDb = (env: NodeJS.ProcessEnv) => path.join(devinDataDir(env), \"sessions.db\");\n\nconst SESSION_ID = /^[A-Za-z0-9._:-]{1,128}$/;\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst endReason = (r: unknown): \"clear\" | \"logout\" | \"exit\" | \"other\" =>\n r === \"clear\" || r === \"logout\" || r === \"exit\" ? r : \"other\";\nconst pickSource = (v: unknown): string =>\n typeof v === \"string\" && [\"startup\", \"resume\", \"clear\", \"compact\", \"fork\"].includes(v) ? v : \"unknown\";\nfunction errText(v: unknown): string | undefined {\n if (typeof v === \"string\" && v) return v.slice(0, 2000);\n if (v && typeof v === \"object\") {\n const e = v as { message?: unknown; error?: unknown };\n if (typeof e.message === \"string\" && e.message) return e.message.slice(0, 2000);\n if (typeof e.error === \"string\" && e.error) return e.error.slice(0, 2000);\n }\n return undefined;\n}\nconst cut = (s: string, n: number): string => (s.length > n ? `${s.slice(0, n).replace(/\\s+\\S*$/, \"\")}\u2026` : s);\n\nexport const devin: Adapter = {\n name: NAME,\n events: DEVIN_EVENTS,\n detect: (env = process.env) => existsSync(devinConfigDir(env)) || existsSync(devinDataDir(env)),\n configFiles: (env = process.env) => [configFile(env)],\n install: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const file = configFile(env);\n const r = installClaudeShaped(file, NAME, eventsFor(opts.lean), cmd, OPTS);\n if (r.skipped) return [r];\n const bad = foreignEvent(file);\n return [{ ...r, note: bad ? deadFileNote(bad) : INSTALL_NOTE }];\n },\n uninstall: (env = process.env, opts: InstallOptions = {}) => [\n uninstallClaudeShaped(configFile(env), DEVIN_EVENTS, { created: opts.created?.includes(configFile(env)) }),\n ],\n installed: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const file = configFile(env);\n const state = installedClaudeShaped(file, NAME, eventsFor(opts.lean), cmd, OPTS);\n // Our entries can be present and current and still report nothing: one event name\n // Devin does not know makes it drop the whole file, ours with it. `status` has to\n // say so, or it tells the person reporting is on while it is dead.\n const bad = state === \"missing\" ? undefined : foreignEvent(file);\n return [{ file, state: bad ? \"inactive\" : state, note: bad ? deadFileNote(bad) : CLAUDE_NOTE }];\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = typeof s.session_id === \"string\" ? s.session_id : \"\";\n if (!id) return null;\n // Nothing in the payload names the folder; DEVIN_PROJECT_DIR is the only thing that does.\n const session: HookResult[\"session\"] = { id, cwd: input.env.DEVIN_PROJECT_DIR ?? input.cwd };\n const turn_id = typeof s.prompt_id === \"string\" ? s.prompt_id : undefined;\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const call_id = typeof s.tool_use_id === \"string\" ? s.tool_use_id : undefined;\n // Every recorded payload has an object here, but the field is free-form: a Devin\n // version or an MCP-style tool could send a bare string, and then there is no\n // `success` and no `output` to read \u2014 the whole value IS the output.\n const response =\n s.tool_response && typeof s.tool_response === \"object\" && !Array.isArray(s.tool_response)\n ? (s.tool_response as { success?: unknown; output?: unknown; error?: unknown })\n : undefined;\n // The same prompt must always name the same attention (CONTROL.md \u00A76). Devin's\n // PermissionRequest does carry tool_use_id; the hash is the fallback for one that\n // doesn't, and is the bytes ADAPTERS.md's common conventions prescribe.\n const permissionId = () =>\n `perm-${createHash(\"sha256\")\n .update(`${turn_id ?? \"\"}|${tool ?? \"\"}|${JSON.stringify(s.tool_input ?? null)}`)\n .digest(\"hex\")\n .slice(0, 16)}`;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(ev(\"session.started\", { source: pickSource(s.source) }));\n break;\n case \"UserPromptSubmit\":\n events.push(\n ev(\"turn.started\", {\n turn_id,\n prompt_chars: typeof s.prompt === \"string\" ? [...s.prompt].length : undefined,\n }),\n );\n break;\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, call_id, turn_id, input: s.tool_input }));\n break;\n case \"PostToolUse\":\n // Devin is the one harness that says so outright: tool_response.success.\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n call_id,\n turn_id,\n // `ok` is required on tool.ended (PROTOCOL.md \u00A7events), so a response\n // that carries no success flag at all reads as \"nothing said it failed\".\n ok: response?.success !== false,\n error: errText(response?.error),\n input: s.tool_input,\n output: response ? response.output : s.tool_response,\n }),\n );\n break;\n case \"PermissionRequest\":\n events.push(ev(\"attention.needed\", { attention_id: call_id ?? permissionId(), kind: \"permission\", tool }));\n break;\n case \"Stop\":\n events.push(ev(\"turn.ended\", { turn_id, reason: \"stop\" }));\n break;\n case \"PostCompaction\":\n // Devin has no pre-compaction event; the payload carries only the summary.\n events.push(ev(\"context.compacted\", { trigger: \"auto\" }));\n break;\n case \"SessionEnd\":\n events.push(ev(\"session.ended\", { reason: endReason(s.reason) }));\n break;\n default:\n return null;\n }\n return {\n session,\n events,\n hints: {},\n transcript: transcriptRef(sessionsDb(input.env as NodeJS.ProcessEnv), id),\n };\n },\n\n readTranscript(file, fromLine) {\n const ref = splitRef(file);\n if (!ref) return { turns: [], line: fromLine };\n return readDevinChain(ref.db, ref.session, fromLine);\n },\n\n facts(session, transcript, _hints, _state, env = process.env): SessionFacts {\n const out: SessionFacts = {};\n const version = devinVersion(env);\n if (version) out.harness_version = version;\n const account = devinAccount(env);\n if (account) out.account_id = account;\n const ref = splitRef(transcript) ?? { db: sessionsDb(env), session: session.id };\n if (!SESSION_ID.test(ref.session)) return out;\n const rows = querySqlite(ref.db, SESSION_SQL, [ref.session]);\n const row = rows?.[0];\n if (!row) return out;\n Object.assign(out, sessionFacts(row));\n return out;\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows = querySqlite(sessionsDb(env), BACKFILL_SQL, [\"text\", Math.floor(sinceMs / 1000)]);\n if (!rows) return [];\n const out: BackfillRow[] = [];\n for (const row of rows) {\n const id = String(row.id); // text, the query says\n if (!SESSION_ID.test(id)) continue;\n const { started_at, last_at, ...rest } = sessionFacts(row);\n if (!started_at || !last_at) continue;\n out.push({ session: { id, ...rest }, started_at, last_at });\n }\n return out;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n\n// --- the session store ---------------------------------------------------------------\n\n/** `<database>#<session id>`: readTranscript is given a file, and Devin keeps every\n * session in one database, so the session has to ride in the string. */\nexport const transcriptRef = (db: string, session: string): string => `${db}#${session}`;\nexport function splitRef(ref: string | undefined): { db: string; session: string } | null {\n if (!ref) return null;\n const at = ref.lastIndexOf(\"#\");\n if (at <= 0) return null;\n const db = ref.slice(0, at);\n const session = ref.slice(at + 1);\n return db && SESSION_ID.test(session) ? { db, session } : null;\n}\n\n/** `message_nodes` is a forest: it keeps abandoned branches too (27 nodes for a\n * two-turn session). The transcript is the one chain that ends at\n * `sessions.main_chain_id`, walked up through `parent_node_id` \u2014 never every node. */\n/** The walk stops at the cursor (`m.node_id >= ?`): everything below it has been read\n * already, and without that bound every Stop pulled `chat_message` for every ancestor\n * \u2014 the root of a real chain carries a 17 kB system prompt and four more system\n * blocks, re-read on every event, and past 32 MB the child and CLI engines give up\n * and return nothing. The cap keeps the NEWEST rows (`DESC`), re-sorted below: an\n * ascending cap would have kept the oldest and delivered no new turn ever again. */\nconst CHAIN_LIMIT = 4000;\nexport const CHAIN_SQL = `WITH RECURSIVE chain(node_id, parent_node_id, chat_message, created_at) AS (\n SELECT node_id, parent_node_id, chat_message, created_at FROM message_nodes\n WHERE session_id = ? AND node_id = (SELECT main_chain_id FROM sessions WHERE id = ?)\n UNION ALL\n SELECT m.node_id, m.parent_node_id, m.chat_message, m.created_at FROM message_nodes m\n JOIN chain c ON m.node_id = c.parent_node_id AND m.session_id = ? AND m.node_id >= ?\n)\nSELECT node_id, chat_message, created_at FROM chain ORDER BY node_id DESC LIMIT ${CHAIN_LIMIT}`;\n\n/** Times are unix SECONDS in this store. The first ask comes from `prompt_history`,\n * because `sessions.title` holds whatever the titler last produced \u2014 a backticked\n * command, or a raw `functions.Shell:0{\u2026}` mid-turn. */\nconst SESSION_FIELDS = `s.model, s.working_directory, s.created_at, s.last_activity_at,\n (SELECT p.content FROM prompt_history p WHERE p.session_id = s.id AND p.is_shell = 0\n ORDER BY p.timestamp ASC, p.id ASC LIMIT 1) AS first_ask`;\nconst SESSION_SQL = `SELECT ${SESSION_FIELDS} FROM sessions s WHERE s.id = ? LIMIT 1`;\n// typeof(id) = 'text' (the literal rides as a parameter: the CLI engine takes no quote\n// in the SQL): an id a session ref could carry. A blob id comes back from the sqlite3\n// CLI as a string shaped by its version, so the database says what it is.\nconst BACKFILL_SQL = `SELECT s.id, ${SESSION_FIELDS} FROM sessions s\n WHERE s.hidden = 0 AND typeof(s.id) = ? AND s.last_activity_at >= ?\n ORDER BY s.last_activity_at DESC LIMIT 500`;\n\nfunction sessionFacts(row: Record<string, unknown>): SessionFacts {\n const out: SessionFacts = {};\n if (typeof row.model === \"string\" && row.model) out.model = row.model;\n if (typeof row.working_directory === \"string\" && path.isAbsolute(row.working_directory))\n out.cwd = row.working_directory;\n const started = Number(row.created_at);\n const last = Number(row.last_activity_at);\n if (Number.isFinite(started) && started > 0) out.started_at = Math.round(started * 1000);\n if (Number.isFinite(last) && last > 0) out.last_at = Math.round(last * 1000);\n if (typeof row.first_ask === \"string\") {\n const line = row.first_ask.split(\"\\n\").find((l) => l.trim()) ?? \"\";\n if (line.trim()) {\n out.title = cut(line.trim(), 80);\n out.title_source = \"first-ask\";\n }\n }\n return out;\n}\n\ninterface ChatMessage {\n role?: unknown;\n content?: unknown;\n metadata?: { is_user_input?: unknown; created_at?: unknown } | null;\n}\n\n/** The canonical chain as turns. `node_id` is the cursor: it rises along the chain and\n * is stable across a resume, so a later read starts where the last one stopped.\n * `role: \"system\"` is Cognition's own prompt (and the skills manifest, and the\n * generated system_info block), never the person's words \u2014 it is skipped at every\n * tier, as is `role: \"tool\"`. */\nexport function readDevinChain(db: string, session: string, fromLine: number): TranscriptRead {\n if (!SESSION_ID.test(session)) return { turns: [], line: fromLine };\n const floor = Number.isFinite(fromLine) && fromLine > 0 ? Math.floor(fromLine) : 0;\n const rows = querySqlite(db, CHAIN_SQL, [session, session, session, floor]);\n if (!rows?.length) return { turns: [], line: fromLine };\n const msgs: { role: \"user\" | \"assistant\"; text: string; at: number; line: number }[] = [];\n let end = fromLine;\n for (const row of rows) {\n const node = Number(row.node_id);\n if (!Number.isFinite(node)) continue;\n if (node + 1 > end) end = node + 1;\n if (node < fromLine) continue;\n let j: ChatMessage;\n try {\n j = JSON.parse(String(row.chat_message ?? \"\")) as ChatMessage;\n } catch {\n continue;\n }\n const text = typeof j.content === \"string\" ? j.content.trim() : \"\";\n if (!text) continue;\n // The message's own time, not the row's. `message_nodes.created_at` is when the row\n // batch was last WRITTEN: Devin rewrites it on every save of the chain, so every\n // node of a chain usually carries one identical value, and it is not even monotonic\n // along the chain. Measured on a live store 2026-10-08: a two-turn session had all\n // four of its chain nodes at 23:33:10 while their own `metadata.created_at` read\n // 23:32:29, :34, 23:33:08 and :10 (turn 1 reported 41 s late, both turns at the same\n // instant); one node's row time was rewritten 12 s later between two reads; and a\n // descendant's row time was 27 s EARLIER than its ancestor's. The column is only the\n // fallback for a row whose message has no time of its own.\n const secs = Number(row.created_at);\n const at =\n Date.parse(String(j.metadata?.created_at ?? \"\")) ||\n (Number.isFinite(secs) && secs > 0 ? Math.round(secs * 1000) : 0) ||\n Date.now();\n if (j.role === \"user\" && j.metadata?.is_user_input === true) msgs.push({ role: \"user\", text, at, line: node });\n else if (j.role === \"assistant\") msgs.push({ role: \"assistant\", text, at, line: node });\n }\n // The rows come newest first (the cap keeps the newest); a transcript runs the other way.\n msgs.sort((a, b) => a.line - b.line);\n return pairTurns(msgs, end);\n}\n\n/** `<data dir>/_versions/current` is a symlink to the running version's folder. */\nexport function devinVersion(env: NodeJS.ProcessEnv = process.env): string | undefined {\n try {\n const target = readlinkSync(path.join(devinDataDir(env), \"_versions\", \"current\"));\n const name = path.basename(target);\n return /^[0-9][0-9A-Za-z.+-]{0,63}$/.test(name) ? name : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The organisation the CLI is signed in to, from the user config \u2014 the only account id\n * Devin keeps in a plain local file. Never the email, and never credentials.toml. */\nexport function devinAccount(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const d = readJson(configFile(env)).devin as { org_id?: unknown } | undefined;\n const id = d && typeof d === \"object\" ? d.org_id : undefined;\n return typeof id === \"string\" && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Read-only SQLite, for a harness that keeps its sessions in a database instead of a\n// JSONL file. Three ways in, tried in order, because `node:sqlite` does not exist on\n// Node 20 (the floor this package builds for) and is behind --experimental-sqlite on\n// 22.5\u201322.12:\n// \"node\" in this process, through createRequire \u2014 no static import, so the bundle\n// still loads on a Node without the module;\n// \"child\" one `node --experimental-sqlite -e \u2026` run through execFileSync: no shell,\n// arguments passed as argv, a short timeout;\n// \"cli\" the `sqlite3` binary, when it is on PATH and every parameter is a plain\n// scalar that can be written as a literal.\n// Every path opens the file read-only, is bounded in time, and returns null instead of\n// throwing: a database that is busy, missing, locked or unreadable costs the caller\n// nothing but an empty read.\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\n\nexport type SqliteParam = string | number;\nexport type SqliteRow = Record<string, unknown>;\nexport type SqliteEngine = \"auto\" | \"node\" | \"child\" | \"cli\";\n\nexport interface SqliteOptions {\n /** Busy timeout and the child's wall clock, in ms (default 2000). */\n timeoutMs?: number;\n /** Force one way in; \"auto\" tries node, then child, then cli (default). */\n engine?: SqliteEngine;\n /** Largest reply a child or the CLI may print (default 32 MB). */\n maxBuffer?: number;\n}\n\ninterface Statement {\n all(...params: SqliteParam[]): unknown[];\n}\ninterface Db {\n prepare(sql: string): Statement;\n exec(sql: string): void;\n close(): void;\n}\ntype DbCtor = new (path: string, options?: Record<string, unknown>) => Db;\n\n/** `node:sqlite` is still experimental, and Node says so on stderr the first time it is\n * used. A reader has no business writing to a harness's terminal, so that one warning\n * is swallowed while the module is loaded and used \u2014 nothing else is, and the original\n * emitter is back before this returns. (The child path passes --no-warnings instead.)\n * Exported for its test: Node emits that warning once per process. */\nexport function quiet<T>(fn: () => T): T {\n const original = process.emitWarning;\n try {\n process.emitWarning = ((warning: unknown, ...rest: unknown[]) => {\n const kind = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string } | undefined)?.type;\n if (kind === \"ExperimentalWarning\" && /sqlite/i.test(String(warning))) return;\n (original as (...a: unknown[]) => void).call(process, warning, ...rest);\n }) as typeof process.emitWarning;\n return fn();\n } finally {\n process.emitWarning = original;\n }\n}\n\nlet ctorCache: DbCtor | null | undefined;\n/** `node:sqlite` if this Node has it; null if it does not (Node 20, or 22.x unflagged). */\nfunction dbCtor(): DbCtor | null {\n if (ctorCache !== undefined) return ctorCache;\n ctorCache = null;\n try {\n const req = createRequire(import.meta.url);\n const m = quiet(() => req(\"node:sqlite\")) as { DatabaseSync?: unknown };\n if (typeof m?.DatabaseSync === \"function\") ctorCache = m.DatabaseSync as DbCtor;\n } catch {}\n return ctorCache;\n}\n\n/** SQLite gives back strings, numbers, null, BigInt and Uint8Array; the protocol takes JSON. */\nfunction plain(row: unknown): SqliteRow | null {\n if (!row || typeof row !== \"object\") return null;\n const out: SqliteRow = {};\n for (const [k, v] of Object.entries(row as SqliteRow)) {\n if (typeof v === \"bigint\") out[k] = Number(v);\n else if (v instanceof Uint8Array) out[k] = null;\n else out[k] = v;\n }\n return out;\n}\nconst rows = (v: unknown): SqliteRow[] | null => {\n if (!Array.isArray(v)) return null;\n const out: SqliteRow[] = [];\n for (const r of v) {\n const p = plain(r);\n if (p) out.push(p);\n }\n return out;\n};\n\nfunction viaNode(file: string, sql: string, params: SqliteParam[], o: Required<SqliteOptions>): SqliteRow[] | null {\n const C = dbCtor();\n if (!C) return null;\n let db: Db;\n try {\n db = quiet(() => new C(file, { readOnly: true, timeout: o.timeoutMs }));\n } catch {\n return null;\n }\n try {\n try {\n db.exec(`PRAGMA busy_timeout = ${Math.round(o.timeoutMs)}`);\n } catch {}\n return quiet(() => rows(db.prepare(sql).all(...params)));\n } catch {\n return null;\n } finally {\n try {\n db.close();\n } catch {}\n }\n}\n\n/** Runs in a child Node, with the file, the SQL, the parameters and the timeout as argv. */\nconst CHILD = `const { DatabaseSync } = require(\"node:sqlite\");\nconst [, file, sql, params, ms] = process.argv;\nconst db = new DatabaseSync(file, { readOnly: true, timeout: Number(ms) });\ntry { db.exec(\"PRAGMA busy_timeout = \" + Number(ms)); } catch {}\nconst out = db.prepare(sql).all(...JSON.parse(params));\ndb.close();\nprocess.stdout.write(JSON.stringify(out));`;\n\nfunction viaChild(file: string, sql: string, params: SqliteParam[], o: Required<SqliteOptions>): SqliteRow[] | null {\n try {\n const out = execFileSync(\n process.execPath,\n [\"--experimental-sqlite\", \"--no-warnings\", \"-e\", CHILD, file, sql, JSON.stringify(params), String(o.timeoutMs)],\n {\n encoding: \"utf8\",\n timeout: o.timeoutMs + 3000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n maxBuffer: o.maxBuffer,\n windowsHide: true,\n },\n );\n return rows(JSON.parse(out || \"null\"));\n } catch {\n return null;\n }\n}\n\n/** A parameter safe to write into SQL as a literal: no quote, no backslash, no newline. */\nconst SAFE = /^[A-Za-z0-9 ._:@/+-]{0,256}$/;\nexport function inlineParams(sql: string, params: SqliteParam[]): string | null {\n if (sql.includes(\"'\")) return null; // a literal in the SQL would make the `?` count a guess\n const holes = sql.split(\"?\").length - 1;\n if (holes !== params.length) return null;\n let i = 0;\n let bad = false;\n const out = sql.replace(/\\?/g, () => {\n const p = params[i++];\n if (typeof p === \"number\") {\n if (!Number.isFinite(p)) {\n bad = true;\n return \"NULL\";\n }\n return String(p);\n }\n if (typeof p !== \"string\" || !SAFE.test(p)) {\n bad = true;\n return \"NULL\";\n }\n return `'${p}'`;\n });\n return bad ? null : out;\n}\n\nfunction viaCli(file: string, sql: string, params: SqliteParam[], o: Required<SqliteOptions>): SqliteRow[] | null {\n const text = inlineParams(sql, params);\n if (!text) return null;\n try {\n const out = execFileSync(\"sqlite3\", [\"-readonly\", \"-json\", file, text], {\n encoding: \"utf8\",\n timeout: o.timeoutMs + 3000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n maxBuffer: o.maxBuffer,\n windowsHide: true,\n }).trim();\n if (!out) return [];\n return rows(JSON.parse(out));\n } catch {\n return null;\n }\n}\n\n/** One read-only query. Null means \"could not read it\", never an exception. */\nexport function querySqlite(\n file: string,\n sql: string,\n params: SqliteParam[] = [],\n opts: SqliteOptions = {},\n): SqliteRow[] | null {\n const o: Required<SqliteOptions> = {\n timeoutMs: opts.timeoutMs ?? 2000,\n engine: opts.engine ?? \"auto\",\n maxBuffer: opts.maxBuffer ?? 32 * 1024 * 1024,\n };\n if (!file) return null;\n try {\n if (!existsSync(file)) return null;\n } catch {\n return null;\n }\n const ways =\n o.engine === \"auto\"\n ? ([viaNode, viaChild, viaCli] as const)\n : o.engine === \"node\"\n ? ([viaNode] as const)\n : o.engine === \"child\"\n ? ([viaChild] as const)\n : ([viaCli] as const);\n for (const way of ways) {\n const r = way(file, sql, params, o);\n if (r) return r;\n }\n return null;\n}\n\n/** Is `node:sqlite` in this process? (Tests skip what they cannot set up.) */\nexport const sqliteInProcess = (): boolean => dbCtor() !== null;\n", "// SPDX-License-Identifier: Apache-2.0\n// Gemini CLI (Google) \u2014 docs: https://geminicli.com/docs/hooks/reference\n// Config: ~/.gemini/settings.json `hooks` key, same array-of-groups shape as Claude\n// Code but timeouts in MILLISECONDS and a `name` per handler. stdout must be JSON or\n// empty. Its own telemetry defaults logPrompts on; the installer says so once.\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines } from \"../readers/files.js\";\nimport { readGemini } from \"../readers/transcripts.js\";\nimport { installClaudeShaped, installedClaudeShaped, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport type { Adapter, HookInput, HookResult, InstallOptions, SessionFacts } from \"./types.js\";\n\nconst NAME = \"gemini-cli\";\nexport const GEMINI_EVENTS = [\n \"SessionStart\",\n \"BeforeAgent\",\n \"BeforeTool\",\n \"AfterTool\",\n \"Notification\",\n \"AfterAgent\",\n \"PreCompress\",\n \"SessionEnd\",\n] as const;\nconst OPTS = { matcherFor: (e: string) => (/Tool/.test(e) ? \".*\" : undefined), timeout: 5000 };\nconst geminiDir = (env: NodeJS.ProcessEnv) => env.GEMINI_CLI_HOME || path.join(homeDir(), \".gemini\");\nconst settings = (env: NodeJS.ProcessEnv) => path.join(geminiDir(env), \"settings.json\");\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst eventsFor = (lean?: boolean) => (lean ? GEMINI_EVENTS.filter((e) => e !== \"BeforeTool\") : [...GEMINI_EVENTS]);\n\n/** Before 0.46 the hooks system is off unless tools.enableHooks is true (issue #11). */\nexport function geminiHooksActive(settingsFile: string): { active: boolean; note?: string } {\n let tools: { enableHooks?: unknown } | undefined;\n try {\n tools = (JSON.parse(readFileSync(settingsFile, \"utf8\")) as { tools?: { enableHooks?: unknown } }).tools;\n } catch {}\n if (tools?.enableHooks === true) return { active: true };\n if (tools?.enableHooks === false)\n return { active: false, note: \"inactive: tools.enableHooks is false in settings.json\" };\n let version = \"\";\n try {\n version = execFileSync(\"gemini\", [\"--version\"], {\n encoding: \"utf8\",\n timeout: 4000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return {\n active: true,\n note: \"could not run `gemini --version`; hooks need tools.enableHooks on versions before 0.46\",\n };\n }\n const m = /(\\d+)\\.(\\d+)/.exec(version);\n if (m && (Number(m[1]) > 0 || Number(m[2]) >= 46)) return { active: true };\n return {\n active: false,\n note: `inactive: Gemini CLI ${version || \"?\"} runs hooks only with \"tools\": {\"enableHooks\": true} in settings.json`,\n };\n}\n\nexport const geminiCli: Adapter = {\n name: NAME,\n events: GEMINI_EVENTS,\n // ~/.gemini also belongs to Antigravity; Gemini CLI is here when its settings or its chat logs exist.\n detect: (env = process.env) => existsSync(settings(env)) || existsSync(path.join(geminiDir(env), \"tmp\")),\n configFiles: (env = process.env) => [settings(env)],\n install: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const r = installClaudeShaped(settings(env), NAME, eventsFor(opts.lean), cmd, OPTS);\n const a = geminiHooksActive(settings(env));\n return [a.note && !r.skipped ? { ...r, note: [r.note, a.note].filter(Boolean).join(\"; \") } : r];\n },\n uninstall: (env = process.env, opts: InstallOptions = {}) => [\n uninstallClaudeShaped(settings(env), GEMINI_EVENTS, { created: opts.created?.includes(settings(env)) }),\n ],\n installed: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const state = installedClaudeShaped(settings(env), NAME, eventsFor(opts.lean), cmd, OPTS);\n const a = geminiHooksActive(settings(env));\n return [\n {\n file: settings(env),\n state: state === \"current\" && !a.active ? \"inactive\" : state,\n ...(a.note ? { note: a.note } : {}),\n },\n ];\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = s.session_id as string | undefined;\n if (!id) return null;\n const session: HookResult[\"session\"] = { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd };\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(\n ev(\"session.started\", {\n source:\n typeof s.source === \"string\" && [\"startup\", \"resume\", \"clear\"].includes(s.source) ? s.source : \"unknown\",\n }),\n );\n break;\n case \"BeforeAgent\":\n events.push(\n ev(\"turn.started\", { prompt_chars: typeof s.prompt === \"string\" ? [...s.prompt].length : undefined }),\n );\n break;\n case \"BeforeTool\":\n if (tool) events.push(ev(\"tool.started\", { tool, input: s.tool_input }));\n break;\n case \"AfterTool\": {\n const resp = s.tool_response as { error?: unknown; llmContent?: unknown } | undefined;\n const err =\n resp && typeof resp === \"object\" && resp.error\n ? String(typeof resp.error === \"string\" ? resp.error : JSON.stringify(resp.error)).slice(0, 2000)\n : undefined;\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n ok: !err,\n error: err,\n input: s.tool_input,\n output: resp?.llmContent ?? s.tool_response,\n }),\n );\n break;\n }\n case \"Notification\":\n events.push(\n ev(\"attention.needed\", {\n attention_id: `notif-${Date.now()}`,\n kind: s.notification_type === \"ToolPermission\" ? \"permission\" : \"question\",\n message: typeof s.message === \"string\" ? s.message.slice(0, 200) : undefined,\n }),\n );\n break;\n case \"AfterAgent\":\n events.push(ev(\"turn.ended\", { reason: \"stop\" }));\n break;\n case \"PreCompress\":\n events.push(ev(\"context.compacted\", { trigger: s.trigger === \"manual\" ? \"manual\" : \"auto\" }));\n break;\n case \"SessionEnd\":\n events.push(\n ev(\"session.ended\", {\n reason:\n s.reason === \"clear\" || s.reason === \"logout\" || s.reason === \"exit\"\n ? s.reason\n : s.reason === \"prompt_input_exit\"\n ? \"exit\"\n : \"other\",\n }),\n );\n break;\n default:\n return null;\n }\n const r: HookResult = { session, events, hints: {} };\n if (typeof s.transcript_path === \"string\") r.transcript = s.transcript_path;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readGemini(text.split(\"\\n\"), fromLine);\n },\n\n facts(_session, transcript): SessionFacts {\n const out: SessionFacts = {};\n if (!transcript) return out;\n const { head, tail } = ends(transcript, 64 * 1024, 64 * 1024);\n const H = parseLines(head);\n const T = parseLines(tail);\n const first = H.find((j) => j.type === \"user\");\n const raw = first ? (first.content ?? first.message ?? first.text) : undefined;\n const text = typeof raw === \"string\" ? raw.trim() : \"\";\n if (text) {\n const line = text.split(\"\\n\")[0] as string; // trimmed, so its first line is its first non-blank one\n out.title = line.length > 80 ? `${line.slice(0, 80).replace(/\\s+\\S*$/, \"\")}\u2026` : line;\n out.title_source = \"first-ask\";\n }\n const times = H.concat(T)\n .map((j) => Date.parse(String(j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n return out;\n },\n\n backfill: () => [], // chat logs are keyed by a project hash, not a session id we can name; the first hook of a resumed session reports it\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The registry: the only place that lists vendors. A new harness is one file here\n// plus its fixtures and its row in spec/ADAPTERS.md.\nimport { antigravity } from \"./antigravity.js\";\nimport { findAgy } from \"./antigravity-control.js\";\nimport { claudeCode } from \"./claude-code.js\";\nimport { findClaude } from \"./claude-code-control.js\";\nimport { codex } from \"./codex.js\";\nimport { findCodex } from \"./codex-control.js\";\nimport { devin } from \"./devin.js\";\nimport { geminiCli } from \"./gemini-cli.js\";\nimport type { Adapter } from \"./types.js\";\n\nexport const ADAPTERS: readonly Adapter[] = [claudeCode, codex, geminiCli, antigravity, devin];\nexport const adapterByName = (name: string): Adapter | undefined => ADAPTERS.find((a) => a.name === name);\nexport { AG_STALE_PRETOOL, antigravityAnswer } from \"./antigravity.js\";\nexport * as antigravityControl from \"./antigravity-control.js\";\nexport { claudeAccounts, claudeDirs, notClaudeCode } from \"./claude-code.js\";\nexport * as claudeControl from \"./claude-code-control.js\";\nexport * as codexControl from \"./codex-control.js\";\nexport { DEVIN_EVENTS, devinConfigDir, devinDataDir, readDevinChain } from \"./devin.js\";\nexport {\n deniedNote,\n JOB_TIMEOUT_MS,\n jobEnv,\n type Login,\n type Reading,\n type RunOptions,\n type RunResult,\n runHeadless,\n} from \"./headless.js\";\n\n/** The harnesses a control daemon here can drive headlessly (CONTROL.md \u00A76): each whose\n * CLI is installed on this machine. What `control pair` and every hello advertise. */\nexport function drivableHarnesses(env: NodeJS.ProcessEnv = process.env): string[] {\n return [\n ...(findClaude(env) ? [\"claude-code\"] : []),\n ...(findCodex(env) ? [\"codex\"] : []),\n ...(findAgy(env) ? [\"antigravity\"] : []),\n ];\n}\nexport type {\n Adapter,\n AdapterEvent,\n BackfillRow,\n FactsState,\n HookCommand,\n HookInput,\n HookResult,\n InstallReport,\n SessionFacts,\n TranscriptRead,\n Turn,\n} from \"./types.js\";\nexport { antigravity, claudeCode, codex, devin, geminiCli };\n", "// SPDX-License-Identifier: Apache-2.0\n// ~/.config/sessionpipe/config.json, mode 0600: the machine's name, the sinks with\n// their tier and token, per-harness switches, the update check.\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { configFile } from \"./paths.js\";\nimport type { Tier } from \"./types.js\";\n\nexport interface SinkConfig {\n name: string;\n /** https://\u2026, file:PATH, stdout, otlp:URL */\n url: string;\n tier: Tier;\n pii?: boolean;\n /** @deprecated Never set: control is per machine (spec/CONTROL.md \u00A72). Kept so an\n * older config still reads. */\n control?: boolean;\n token?: string;\n /** whsec_\u2026 for Standard Webhooks signatures. */\n secret?: string;\n /** The token (and secret) live in this store instead of in this file; the client\n * reads them from it when it sends. */\n token_in?: \"keychain\" | \"secret-service\";\n /** Learned from the receiver's well-known file; re-read daily. */\n max_tier?: Tier;\n well_known_at?: string;\n paused?: string;\n}\n\nexport interface Config {\n machine?: string;\n sinks: SinkConfig[];\n harnesses: Record<string, { enabled?: boolean; created?: string[] }>;\n update_check?: boolean;\n keep_days?: number;\n}\n\nexport const DEFAULT_CONFIG: Config = { sinks: [], harnesses: {}, update_check: true, keep_days: 30 };\n\nexport function readConfig(file: string = configFile()): Config {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as Partial<Config>;\n return {\n ...DEFAULT_CONFIG,\n ...j,\n sinks: Array.isArray(j.sinks) ? j.sinks : [],\n harnesses: j.harnesses && typeof j.harnesses === \"object\" ? j.harnesses : {},\n };\n } catch {\n return { ...DEFAULT_CONFIG, sinks: [], harnesses: {} };\n }\n}\n\nexport function writeConfig(c: Config, file: string = configFile()): void {\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n writeFileSync(file, `${JSON.stringify(c, null, 2)}\\n`, { mode: 0o600 });\n if (process.platform !== \"win32\" && existsSync(file)) {\n try {\n chmodSync(file, 0o600);\n } catch {}\n }\n}\n\n/** The machine's name: what the person configured, else the hostname without a\n * local suffix. Never guessed from anything else (a hand-typed name once linked 64\n * versions to nothing). */\nexport function machineName(c: Config, hostname: string): string {\n if (c.machine) return String(c.machine).slice(0, 80);\n return hostname.replace(/\\.(local|lan|home)$/i, \"\");\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// ULID: 48-bit ms timestamp + 80 random bits, Crockford base32. Monotonic within a\n// process so two events in the same millisecond still sort in emit order.\nimport { randomBytes } from \"node:crypto\";\n\nconst ALPHABET = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\nlet lastTime = 0;\nlet lastRand: number[] = [];\n\nfunction encodeTime(t: number): string {\n let out = \"\";\n let n = t;\n for (let i = 0; i < 10; i++) {\n out = ALPHABET[n % 32] + out;\n n = Math.floor(n / 32);\n }\n return out;\n}\n\nexport function ulid(now: number = Date.now()): string {\n if (now === lastTime) {\n // increment the random part\n for (let i = lastRand.length - 1; i >= 0; i--) {\n const v = (lastRand[i] as number) + 1;\n if (v < 32) {\n lastRand[i] = v;\n break;\n }\n lastRand[i] = 0;\n }\n } else {\n lastTime = now;\n lastRand = Array.from(randomBytes(16), (b) => b % 32);\n }\n return encodeTime(now) + lastRand.map((v) => ALPHABET[v]).join(\"\");\n}\n\nexport const isUlid = (s: string): boolean => /^[0-9A-HJKMNP-TV-Z]{26}$/.test(s);\n", "// SPDX-License-Identifier: Apache-2.0\n// From an adapter's output to a protocol event: id, time, the full session block\n// as known now, and the raw (tier 3) data. Filtering per sink happens later.\nimport type { AdapterEvent } from \"./adapters/types.js\";\nimport type { Event, Session } from \"./types.js\";\nimport { ulid } from \"./ulid.js\";\n\nexport interface EventContext {\n harness: { name: string; version?: string };\n session: Session;\n now?: number;\n}\n\nexport function makeEvent(a: AdapterEvent, ctx: EventContext): Event {\n const now = ctx.now ?? Date.now();\n const harness: Event[\"harness\"] = { name: ctx.harness.name, event: a.harnessEvent };\n if (ctx.harness.version) harness.version = ctx.harness.version;\n return {\n protocol: 1,\n id: ulid(now),\n type: a.type,\n time: new Date(now).toISOString(),\n tier: 3,\n harness,\n session: ctx.session,\n privacy: { rulesets: [], pii: false },\n data: a.data,\n };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The outbox: append-only JSONL per (harness, session) under\n// <state>/outbox/<harness>/<session>.jsonl, a per-session seq counter, a per-sink\n// cursor that moves only when the sink acknowledged, and a per-session lock so two\n// workers never interleave. Never lose, never duplicate.\nimport {\n appendFileSync,\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readdirSync,\n readFileSync,\n readSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport { safeId } from \"./paths.js\";\nimport type { Event } from \"./types.js\";\n\nexport interface OutboxRef {\n harness: string;\n session: string;\n}\n\nconst READ_CHUNK = 1024 * 1024;\nconst READ_MAX = 8 * 1024 * 1024;\n\nexport class Outbox {\n constructor(readonly root: string) {}\n\n dir(harness: string): string {\n return path.join(this.root, \"outbox\", safeId(harness));\n }\n file(ref: OutboxRef): string {\n return path.join(this.dir(ref.harness), `${safeId(ref.session)}.jsonl`);\n }\n private seqFile(ref: OutboxRef): string {\n return path.join(this.dir(ref.harness), `${safeId(ref.session)}.seq`);\n }\n\n /** The next seq for a session, persisted (survives a hibernating machine and a\n * restart; an in-memory counter would restart at 0 and collide). */\n nextSeq(ref: OutboxRef): number {\n const f = this.seqFile(ref);\n let n = -1;\n try {\n const t = readFileSync(f, \"utf8\").trim();\n if (/^\\d+$/.test(t)) n = Number(t);\n } catch {}\n // A missing or unreadable counter (a crash between truncate and write leaves it\n // empty) with an existing outbox: recover from the file's last line.\n if (n < 0) n = this.lastSeqInFile(ref) + 1;\n mkdirSync(path.dirname(f), { recursive: true, mode: 0o700 });\n writeFileSync(f, String(n + 1), { mode: 0o600 });\n return n;\n }\n\n private lastSeqInFile(ref: OutboxRef): number {\n const f = this.file(ref);\n if (!existsSync(f)) return -1;\n const lines = readFileSync(f, \"utf8\").trim().split(\"\\n\");\n for (let i = lines.length - 1; i >= 0; i--) {\n try {\n const j = JSON.parse(lines[i] as string) as Event;\n if (typeof j.session?.seq === \"number\") return j.session.seq;\n } catch {}\n }\n return -1;\n }\n\n append(ref: OutboxRef, events: Event[]): void {\n if (!events.length) return;\n mkdirSync(this.dir(ref.harness), { recursive: true, mode: 0o700 });\n appendFileSync(this.file(ref), `${events.map((e) => JSON.stringify(e)).join(\"\\n\")}\\n`, { mode: 0o600 });\n }\n\n /** Every session file, newest first. */\n sessions(): OutboxRef[] {\n const out: { ref: OutboxRef; mtime: number }[] = [];\n const base = path.join(this.root, \"outbox\");\n if (!existsSync(base)) return [];\n for (const h of readdirSync(base)) {\n const d = path.join(base, h);\n let names: string[] = [];\n try {\n names = readdirSync(d).filter((n) => n.endsWith(\".jsonl\"));\n } catch {\n continue;\n }\n for (const n of names) {\n try {\n out.push({ ref: { harness: h, session: n.slice(0, -6) }, mtime: statSync(path.join(d, n)).mtimeMs });\n } catch {}\n }\n }\n return out.sort((a, b) => b.mtime - a.mtime).map((x) => x.ref);\n }\n\n /** Read events after byte offset `from`; returns them and the new offset. Lines\n * are read whole; a partial trailing line (a write in progress) is left. A read\n * takes READ_CHUNK bytes at a time, not the rest of the file: a session file grows\n * to tens of MB and a drain takes it in batches of 50. It reads on until the batch\n * is full or the file ends, so lines that parse to nothing never stop a drain; one\n * line longer than the chunk gets a larger one, up to READ_MAX. */\n read(ref: OutboxRef, from: number, maxEvents = 500): { events: Event[]; offset: number } {\n const f = this.file(ref);\n if (!existsSync(f)) return { events: [], offset: from };\n const size = statSync(f).size;\n if (from >= size) return { events: [], offset: from };\n const fd = openSync(f, \"r\");\n try {\n const events: Event[] = [];\n let offset = from;\n let chunk = READ_CHUNK;\n while (events.length < maxEvents && offset < size) {\n const buf = Buffer.alloc(Math.min(size - offset, chunk));\n const n = readSync(fd, buf, 0, buf.length, offset);\n const text = buf.subarray(0, n).toString(\"utf8\");\n let pos = 0;\n let used = 0;\n while (events.length < maxEvents) {\n const nl = text.indexOf(\"\\n\", pos);\n if (nl < 0) break;\n const line = text.slice(pos, nl);\n pos = nl + 1;\n used += Buffer.byteLength(line, \"utf8\") + 1;\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as Event);\n } catch {}\n }\n offset += used;\n if (used) continue;\n // No whole line in this chunk: a line longer than it, or a write in progress.\n if (offset + n >= size || chunk >= READ_MAX) break;\n chunk *= 2;\n }\n return { events, offset };\n } finally {\n closeSync(fd);\n }\n }\n\n /** Files older than `days` are pruned; the cursor files with them. */\n prune(days: number, now = Date.now()): number {\n let n = 0;\n const cutoff = now - days * 86_400_000;\n for (const ref of this.sessions()) {\n const f = this.file(ref);\n try {\n if (statSync(f).mtimeMs < cutoff) {\n unlinkSync(f);\n try {\n unlinkSync(this.seqFile(ref));\n } catch {}\n n++;\n }\n } catch {}\n }\n return n;\n }\n\n delete(ref: OutboxRef): void {\n for (const f of [this.file(ref), this.seqFile(ref)]) {\n try {\n unlinkSync(f);\n } catch {}\n }\n }\n}\n\n/** Per-sink cursor: byte offset per session file, moved only on a 2xx. */\nexport class Cursors {\n constructor(\n readonly root: string,\n readonly sink: string,\n ) {}\n private file(): string {\n return path.join(this.root, \"cursors\", `${safeId(this.sink)}.json`);\n }\n read(): Record<string, number> {\n try {\n return JSON.parse(readFileSync(this.file(), \"utf8\")) as Record<string, number>;\n } catch {\n return {};\n }\n }\n write(c: Record<string, number>): void {\n const f = this.file();\n mkdirSync(path.dirname(f), { recursive: true, mode: 0o700 });\n const tmp = `${f}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(c), { mode: 0o600 });\n renameSync(tmp, f);\n }\n key(ref: OutboxRef): string {\n return `${ref.harness}/${ref.session}`;\n }\n}\n\n/** A lock per session so two workers never interleave. Stale once the worker that\n * took it is gone (its 15 s deadline ends it without a release), or after 5 min. */\nexport function takeLock(root: string, ref: OutboxRef, staleMs = 5 * 60_000): (() => void) | null {\n return takeNamedLock(root, `${safeId(ref.harness)}-${safeId(ref.session)}`, staleMs);\n}\n\n/** A named lock under <root>/locks, held by one process at a time: the file names\n * its pid. Stale once that process is gone, or after `staleMs`. */\nexport function takeNamedLock(root: string, name: string, staleMs = 5 * 60_000): (() => void) | null {\n const dir = path.join(root, \"locks\");\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n const f = path.join(dir, `${name}.lock`);\n try {\n if (Date.now() - statSync(f).mtimeMs > staleMs || !processAlive(Number(readFileSync(f, \"utf8\")))) unlinkSync(f);\n else return null;\n } catch {}\n try {\n writeFileSync(f, String(process.pid), { flag: \"wx\" });\n } catch {\n return null;\n }\n return () => {\n try {\n unlinkSync(f);\n } catch {}\n };\n}\n\n/** Whether the process a lock or a claimed job names is still running. A pid that\n * can't be read counts as running: the age rule decides then. */\nexport function processAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return true;\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n return (e as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// pii@1 \u2014 an opt-in second pass that reduces identifiers (spec/PRIVACY.md \u00A72). It\n// does not promise anonymity; it removes the obvious.\nimport { createHash } from \"node:crypto\";\n\nexport const RULESET_PII = \"pii@1\";\n\nconst EMAIL = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g;\n/** E.164 and common national forms: an optional +, 7\u201315 digits with separators,\n * optional area-code parentheses. A version number (22.23.1) or an IP never matches:\n * the run must not sit between dots, and needs \u2265 7 digits. */\nconst PHONE = /(?<![\\w.])(?:\\+\\d{1,3}[ .-]?)?(?:\\(\\d{2,4}\\)[ .-]?)?\\d{2,4}(?:[ .-]?\\d{2,4}){1,3}(?!\\w)/g;\n\nfunction looksPhone(s: string): boolean {\n const digits = s.replace(/\\D/g, \"\");\n if (digits.length < 7 || digits.length > 15) return false;\n // \"port 8891, pr 12345\": a bare run with no separator or + is a number, not a phone.\n if (!/[+() .-]/.test(s)) return false;\n // \"22.23.1\", \"185.199.108.153\": dots alone are a version or an address.\n if (!/[+() -]/.test(s)) return false;\n return true;\n}\n\n/** Replace emails and phone numbers, and write `home` as `~`. */\nexport function reducePii(text: string, home?: string): string {\n if (!text) return text;\n let out = text.replace(EMAIL, \"[email]\");\n out = out.replace(PHONE, (m) => (looksPhone(m) ? \"[phone]\" : m));\n if (home) {\n const h = home.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n out = out.replace(new RegExp(`(?<![A-Za-z0-9_])${h}(?=/|$|\\\\s|[\"'\\`])`, \"g\"), \"~\");\n }\n return out;\n}\n\n/** The machine's name under pii@1: the first 8 hex of its SHA-256. */\nexport function hashMachine(name: string): string {\n return createHash(\"sha256\").update(name).digest(\"hex\").slice(0, 8);\n}\n\n/** Apply pii@1 to every string in a value; `home` becomes `~`. */\nexport function reducePiiDeep<T>(v: T, home?: string): T {\n if (typeof v === \"string\") return reducePii(v, home) as T;\n if (Array.isArray(v)) return v.map((x) => reducePiiDeep(x, home)) as T;\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v as Record<string, unknown>)) out[k] = reducePiiDeep(x, home);\n return out as T;\n }\n return v;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// secrets@1 \u2014 credentials out of every string, on the person's machine, before an\n// event reaches the outbox. Ported from spacesheep-cli lib/redact.js (Michael\n// Makarov, MIT \u2192 Apache-2.0, see NOTICE). The ruleset is defined in\n// spec/PRIVACY.md \u00A72 and pinned by conformance/redaction/secrets.json.\n//\n// Every pattern is linear: bounded repetition, no nested quantifiers. The\n// adversarial vectors (password_ \u00D7 5000, a 50 000-space run) pin that.\n\nexport const RULESET_SECRETS = \"secrets@1\";\nexport const REDACTED = \"[redacted]\";\n\n/** Token formats that are a credential by their shape alone. Each is anchored on a\n * vendor prefix, so a commit sha or a UUID never matches. */\nconst TOKEN_PATTERNS: RegExp[] = [\n /-----BEGIN [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----[\\s\\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----|$)/g,\n /\\b(?:AKIA|ASIA|ABIA|ACCA)[0-9A-Z]{16}\\b/g, // AWS access key id\n /\\bgh[pousr]_[A-Za-z0-9]{30,}\\b/g, // GitHub\n /\\bgithub_pat_[A-Za-z0-9_]{30,}\\b/g,\n /\\bglpat-[A-Za-z0-9_-]{20,}\\b/g, // GitLab\n /\\bxox[abposre]-[A-Za-z0-9-]{10,}\\b/g, // Slack\n /\\bhttps:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]+/g,\n /\\bhttps:\\/\\/(?:ptb\\.|canary\\.)?discord(?:app)?\\.com\\/api\\/webhooks\\/[0-9]+\\/[A-Za-z0-9_-]+/g,\n /\\bsk-(?:ant-|proj-|svcacct-|admin-|or-v1-)?[A-Za-z0-9_-]{20,}\\b/g, // Anthropic, OpenAI, DeepSeek, OpenRouter\n /\\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\\b/g, // Stripe secret / restricted\n /\\bwhsec_[A-Za-z0-9+/=]{20,}/g, // Stripe / Svix / Standard Webhooks secret\n /\\bAIza[0-9A-Za-z_-]{35}\\b/g, // Google API key\n /\\bya29\\.[0-9A-Za-z_-]{20,}/g, // Google OAuth access token\n /\\b1\\/\\/0[0-9A-Za-z_-]{30,}/g, // Google OAuth refresh token\n /\\bGOCSPX-[0-9A-Za-z_-]{20,}/g, // Google OAuth client secret\n /\\bxai-[A-Za-z0-9]{30,}\\b/g,\n /\\bgsk_[A-Za-z0-9]{30,}\\b/g, // Groq\n /\\bpplx-[A-Za-z0-9]{30,}\\b/g, // Perplexity\n /\\bhf_[A-Za-z0-9]{30,}\\b/g, // Hugging Face\n /\\bpcsk_[A-Za-z0-9_]{30,}\\b/g, // Pinecone\n /\\bnpm_[A-Za-z0-9]{30,}\\b/g,\n /\\bpypi-[A-Za-z0-9_-]{50,}/g,\n /\\bSG\\.[A-Za-z0-9_-]{16,}\\.[A-Za-z0-9_-]{16,}/g, // SendGrid\n /\\bshp(?:at|ss|ca|pa)_[a-fA-F0-9]{32}\\b/g, // Shopify\n /\\bdop_v1_[a-f0-9]{64}\\b/g, // DigitalOcean\n /\\b(?:lin_api|lin_oauth)_[A-Za-z0-9]{30,}\\b/g, // Linear\n /\\b(?:ntn|secret)_[A-Za-z0-9]{40,}\\b/g, // Notion\n /\\bsbp_[a-f0-9]{40}\\b/g, // Supabase\n /\\bfigd_[A-Za-z0-9_-]{30,}/g, // Figma\n /\\bdp\\.(?:pt|st|sa|ct)\\.[A-Za-z0-9]{30,}/g, // Doppler\n /\\bgrn_[A-Za-z0-9_-]{20,}/g, // Granola\n /\\bss_[a-f0-9]{32,}\\b/g, // spacesheep API keys\n /\\b[0-9]{8,10}:AA[A-Za-z0-9_-]{33}\\b/g, // Telegram bot token\n /\\beyJ[A-Za-z0-9_-]{10,}\\.eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}/g, // JWT\n];\n/** `scheme://user:password@host` \u2014 the password goes, the user and host stay. */\nconst URL_CREDENTIALS = /\\b([a-z][a-z0-9+.-]{1,20}:\\/\\/[^\\s:/@'\"`<>]{1,100}:)([^\\s@/'\"`<>]{1,200})(@)/gi;\n/** `Authorization: Bearer \u2026` / `Basic \u2026`, and a bare `Bearer <token>` in a curl line. */\nconst AUTH_HEADER = /\\b((?:Bearer|Basic|Token)\\s+)([A-Za-z0-9._~+/=-]{16,})/g;\n// The words that name a secret, in prose. `key` alone is too common (\"the key\n// point\"), so it only counts with a qualifier.\nconst SECRET_WORD =\n \"(?:pass(?:word|wd|phrase|code)?s?|pwd|secret(?:[ _-]?key)?s?|client[ _-]?secret|api[ _-]?keys?|apikeys?|access[ _-]?keys?|access[ _-]?tokens?|auth[ _-]?tokens?|refresh[ _-]?tokens?|private[ _-]?keys?|tokens?|credentials?|creds)\";\n/** Strict form: a NAME, an explicit separator (`=`, `:`, `=>`), a value. The name is\n * one flat run of identifier characters judged in code (isSecretName), never by a\n * nested pattern. Only a secret name goes on to consume its value \u2014 otherwise\n * `https:` would swallow the `?token=\u2026` behind it. */\nconst NAME_SEP = /(?<![A-Za-z0-9_])([A-Za-z][A-Za-z0-9_-]{1,79})([\"']?\\s{0,3}(?::=|=>|=|:)\\s{0,3})/g;\nconst VALUE = /\"([^\"\\n]{1,300})\"|'([^'\\n]{1,300})'|`([^`\\n]{1,300})`|([^\\s\"'`,;&)}\\]]{1,300})/y;\n\nfunction redactAssignments(text: string): string {\n let out = \"\";\n let last = 0;\n NAME_SEP.lastIndex = 0;\n for (let m = NAME_SEP.exec(text); m; m = NAME_SEP.exec(text)) {\n const name = m[1] as string;\n if (!isSecretName(name)) continue;\n VALUE.lastIndex = NAME_SEP.lastIndex;\n const v = VALUE.exec(text);\n if (!v) continue;\n const value = (v[1] ?? v[2] ?? v[3] ?? v[4]) as string;\n NAME_SEP.lastIndex = VALUE.lastIndex;\n if (isPlaceholder(value) || value.includes(REDACTED)) continue;\n // `max_tokens: 4096`, `input_tokens=12k` \u2014 a token COUNT, not a token.\n if (/tokens?$/i.test(name) && /^\\d+(?:[.,]\\d+)*[km]?$/i.test(value)) continue;\n const q = v[1] != null ? '\"' : v[2] != null ? \"'\" : v[3] != null ? \"`\" : \"\";\n out += text.slice(last, v.index) + q + REDACTED + q;\n last = VALUE.lastIndex;\n }\n return last ? out + text.slice(last) : text;\n}\n\n/** Is this identifier the name of a secret? `DB_PASSWORD`, `apiKey`, `client-secret`,\n * `AWS_SECRET_ACCESS_KEY`, `GITHUB_TOKEN`; an env-style `STRIPE_KEY` too. Not\n * `password_hash`, `tokenizer`, `sort_key`. */\nexport function isSecretName(name: string): boolean {\n if (/^[A-Z0-9_]+_KEY$/.test(name)) return true;\n const flat = name.toLowerCase().replace(/[_-]/g, \"\");\n return /(?:pass(?:word|wd|phrase|code)|pwd|secret|secretkey|secretaccesskey|clientsecret|apikey|accesskey|accesstoken|authtoken|refreshtoken|privatekey|token|credential|creds)s?$/.test(\n flat,\n );\n}\n\n/** Loose form: prose. \"password is Hunter2!\", \"the token was ghx\u2026\". Only a value\n * that looks generated counts, so \"the password is wrong\" passes untouched.\n * Whitespace runs are bounded so a long run can't make the match quadratic. */\nconst PROSE = new RegExp(\n `(\\\\b${SECRET_WORD}(?:[ \\\\t]{1,3}(?:is|was|=|:|to|as|of|for[ \\\\t]{1,3}\\\\S{1,40}[ \\\\t]{1,3}is))?[ \\\\t]{1,3})([\"'\\`]?)([^\\\\s\"'\\`]{6,200})\\\\2`,\n \"gi\",\n);\n\n/** A value that is plainly not the secret itself: a type, a variable, a template, an\n * already-redacted marker, an env lookup. */\nfunction isPlaceholder(v: string): boolean {\n const s = v.replace(/[.,;:!?]+$/, \"\");\n if (!s) return true;\n if (\n /^(?:string|number|boolean|bool|str|int|any|unknown|null|undefined|none|nil|true|false|optional|required|text|varchar|password|secret|token|env|string\\[\\]|object|bytes)$/i.test(\n s,\n )\n )\n return true;\n if (/^\\[?redacted\\]?$/i.test(s) || /^\\*+$/.test(s) || /^x{3,}$/i.test(s) || /^\\.{3}$|^\u2026$/.test(s)) return true;\n if (/^[<{$%]/.test(s)) return true; // <your-key>, ${VAR}, {{var}}, $VAR, %VAR%\n if (\n /^(?:process\\.env|env|os\\.environ|c\\.env|this\\.env|import\\.meta\\.env|getenv|config|settings|secrets|args|opts|options|req|request|body|params|input|data|user|self|this)\\b/i.test(\n s,\n )\n )\n return true;\n if (/^[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)+$/.test(s)) return true; // a member path: form.password\n if (/[(]/.test(s)) return true; // a call: hash(pw), getSecret()\n if (/^(?:your|my|the|a|an|some|new|old)[-_ ]/i.test(s)) return true; // your-api-key\n return false;\n}\n\n/** Does a prose value look like something generated, rather than an English word? */\nfunction looksSecret(v: string): boolean {\n const s = v.replace(/[.,;:!?)]+$/, \"\");\n if (s.length < 6) return false;\n if (isPlaceholder(s)) return false;\n if (/^https?:\\/\\//i.test(s)) return false; // a link, handled by URL_CREDENTIALS if it carries one\n if (/^[a-z]+(?:[-'][a-z]+)*$/.test(s)) return false; // a lowercase word\n if (/^[A-Z][a-z]+$/.test(s)) return false; // a capitalised word\n if (/^\\d+(?:[.,]\\d+)*[a-z%]*$/i.test(s)) return false; // a count: 4096, 128k, 3.5, 50%\n if (/^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/.test(s)) return false; // an env var's NAME\n const kinds = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^A-Za-z0-9]/].filter((r) => r.test(s)).length;\n return kinds >= 3 || (/[0-9]/.test(s) && /[A-Za-z]/.test(s));\n}\n\n/** Redact every credential in `text`. Returns the same string when there is none. */\nexport function redactSecrets(text: string): string {\n if (!text) return text;\n let out = text;\n for (const re of TOKEN_PATTERNS) out = out.replace(re, REDACTED);\n out = out.replace(URL_CREDENTIALS, (_m, head: string, _pw: string, at: string) => `${head}${REDACTED}${at}`);\n out = out.replace(AUTH_HEADER, (_m, head: string) => `${head}${REDACTED}`);\n out = redactAssignments(out);\n out = out.replace(PROSE, (m, head: string, q: string, v: string) =>\n !looksSecret(v) || v.includes(REDACTED) ? m : `${head}${q}${REDACTED}${q}`,\n );\n return out;\n}\n\n/** Did redaction change anything? */\nexport function hasSecret(text: string): boolean {\n return !!text && redactSecrets(text) !== text;\n}\n\n/** Redact every string in a JSON-able value (keys are left alone). */\nexport function redactDeep<T>(v: T): T {\n if (typeof v === \"string\") return redactSecrets(v) as T;\n if (Array.isArray(v)) return v.map(redactDeep) as T;\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v as Record<string, unknown>)) out[k] = redactDeep(x);\n return out as T;\n }\n return v;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// filter(event, tier, pii): the pure function every sink runs an event through.\n// Removes by ALLOWLIST per type and tier (spec/PRIVACY.md \u00A71), redacts every string\n// above tier 0 with secrets@1, and runs pii@1 when asked. Returns null when the\n// type is not carried at the tier. The conformance runner runs the same function.\nimport type { Event, Tier } from \"../types.js\";\nimport { hashMachine, RULESET_PII, reducePiiDeep } from \"./pii.js\";\nimport { RULESET_SECRETS, redactDeep } from \"./secrets.js\";\n\n/** The lowest tier that carries each known type (kept in step with schema/v1.ts). */\nexport const TYPE_TIER: Record<string, Tier> = {\n \"session.started\": 0,\n \"session.heartbeat\": 0,\n \"session.ended\": 0,\n \"session.backfill\": 0,\n \"session.forgotten\": 0,\n \"turn.started\": 0,\n \"turn.ended\": 0,\n \"turn.transcript\": 2,\n \"turn.progress\": 2,\n \"tool.started\": 1,\n \"tool.ended\": 1,\n \"files.changed\": 1,\n \"attention.needed\": 0,\n \"attention.cleared\": 0,\n \"subagent.started\": 1,\n \"subagent.ended\": 1,\n \"context.compacted\": 1,\n native: 3,\n};\n\n/** data keys allowed per type at tier N (cumulative: tier 1 includes tier 0's). */\nconst DATA_ALLOW: Record<string, Partial<Record<Tier, string[]>>> = {\n \"session.started\": { 0: [\"source\"] },\n \"session.heartbeat\": { 0: [] },\n \"session.ended\": { 0: [\"reason\"] },\n \"session.backfill\": { 0: [\"started_at\", \"last_at\", \"turns\"] },\n \"session.forgotten\": { 0: [] },\n \"turn.started\": { 0: [\"turn_id\"], 1: [\"prompt_chars\"] },\n \"turn.ended\": { 0: [\"turn_id\", \"reason\", \"ms\"], 1: [\"error\"] },\n \"turn.transcript\": { 2: [\"turn\", \"user\", \"assistant\", \"at\"] },\n \"turn.progress\": { 2: [\"turn\", \"user\", \"assistant\", \"at\"] },\n \"tool.started\": { 1: [\"tool\", \"call_id\", \"turn_id\", \"agent_id\"], 3: [\"input\"] },\n \"tool.ended\": { 1: [\"tool\", \"call_id\", \"turn_id\", \"agent_id\", \"ms\", \"ok\", \"error\"], 3: [\"input\", \"output\"] },\n \"files.changed\": { 1: [\"paths\"] },\n \"attention.needed\": { 0: [\"attention_id\", \"kind\"], 1: [\"tool\", \"message\"] },\n \"attention.cleared\": { 0: [\"attention_id\", \"how\"] },\n \"subagent.started\": { 1: [\"agent_id\", \"agent_type\"] },\n \"subagent.ended\": { 1: [\"agent_id\", \"agent_type\"] },\n \"context.compacted\": { 1: [\"trigger\"] },\n};\n\nconst SESSION_ALLOW = [\n \"id\",\n \"seq\",\n \"machine\",\n \"cwd\",\n \"repo\",\n \"branch\",\n \"model\",\n \"title\",\n \"title_source\",\n \"url\",\n \"account_id\",\n \"parent_id\",\n];\nconst MAX_SIDE = 20_000;\nconst MAX_IO = 64 * 1024;\n\nfunction allowedKeys(type: string, tier: Tier): string[] | null {\n const table = DATA_ALLOW[type];\n if (!table) return null; // unknown type: kept whole (receivers keep extra keys), redacted\n const out: string[] = [];\n for (let t = 0; t <= tier; t++) for (const k of table[t as Tier] ?? []) out.push(k);\n return out;\n}\n\nfunction cap(v: unknown, max: number): unknown {\n if (typeof v === \"string\") return v.length > max ? `${v.slice(0, max)}\u2026` : v;\n if (v && typeof v === \"object\") {\n const s = JSON.stringify(v);\n return s.length > max ? `${s.slice(0, max)}\u2026` : v;\n }\n return v;\n}\n\n/** At most `max` characters, keeping the end: an ellipsis, then the last max \u2212 1. */\nexport function capTail(v: string, max: number): string {\n return v.length > max ? `\u2026${v.slice(v.length - max + 1)}` : v;\n}\n\nexport interface FilterOptions {\n /** The person's home directory, for pii@1's `~` rewrite. */\n home?: string;\n}\n\n/** The event as a sink at `tier` may see it, or null when the type is above the tier. */\nexport function filterEvent(event: Event, tier: Tier, pii: boolean, opts: FilterOptions = {}): Event | null {\n const minTier = TYPE_TIER[event.type];\n if (minTier !== undefined && minTier > tier) return null;\n\n const session: Record<string, unknown> = {};\n for (const k of SESSION_ALLOW)\n if (event.session[k as keyof typeof event.session] !== undefined)\n session[k] = event.session[k as keyof typeof event.session];\n\n let data: Record<string, unknown> = {};\n const keys = allowedKeys(event.type, tier);\n if (keys === null) data = { ...event.data };\n else for (const k of keys) if (event.data[k] !== undefined) data[k] = event.data[k];\n if (typeof data.user === \"string\") data.user = cap(data.user, MAX_SIDE);\n // A turn still running is read for where it is now: its reply keeps the end.\n if (typeof data.assistant === \"string\")\n data.assistant = event.type === \"turn.progress\" ? capTail(data.assistant, MAX_SIDE) : cap(data.assistant, MAX_SIDE);\n if (data.input !== undefined) data.input = cap(data.input, MAX_IO);\n if (data.output !== undefined) data.output = cap(data.output, MAX_IO);\n if (typeof data.message === \"string\") data.message = cap(data.message, 200);\n\n const rulesets: string[] = [];\n let out: Event = { ...event, tier, session: session as Event[\"session\"], data, privacy: { rulesets, pii } };\n if (tier > 0) {\n // Redact, then the caps above already applied: a cut before redaction could leave half a key.\n out = { ...out, session: redactDeep(out.session), data: redactDeep(out.data) };\n rulesets.push(RULESET_SECRETS);\n }\n if (pii) {\n const s = reducePiiDeep(out.session, opts.home) as Record<string, unknown>;\n if (typeof s.machine === \"string\") s.machine = hashMachine(s.machine);\n delete s.account_id;\n out = { ...out, session: s as Event[\"session\"], data: reducePiiDeep(out.data, opts.home) };\n rulesets.push(RULESET_PII);\n }\n out.privacy = { rulesets, pii };\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// A session's short id (spec/PROTOCOL.md \u00A73): the first 8 hex digits of\n// sha256(\"sessionpipe.session:\" + harness + \":\" + id). What a person reads in a log\n// line, a notification, a search box; derived, never sent. Not a prefix of the id\n// itself: Codex ids are time-ordered (UUIDv7), and two sessions started in the same\n// minute share their first eight characters.\nimport { createHash } from \"node:crypto\";\n\nexport function shortId(harness: string, id: string): string {\n return createHash(\"sha256\").update(`sessionpipe.session:${harness}:${id}`).digest(\"hex\").slice(0, 8);\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// file:PATH \u2014 append filtered events as JSONL. The zero-server sink.\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Event, Tier } from \"../types.js\";\nimport type { DeliveryResult, Sink } from \"./types.js\";\n\nexport class FileSink implements Sink {\n constructor(\n readonly name: string,\n readonly file: string,\n readonly tier: Tier,\n readonly pii: boolean,\n ) {}\n async send(events: Event[]): Promise<DeliveryResult> {\n try {\n mkdirSync(path.dirname(this.file), { recursive: true });\n appendFileSync(this.file, `${events.map((e) => JSON.stringify(e)).join(\"\\n\")}\\n`);\n return { ok: true, acknowledged: events.length, accepted: events.length, duplicates: 0, rejected: [] };\n } catch (e) {\n return { ok: false, acknowledged: 0, error: String((e as Error).message), action: \"retry\" };\n }\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// stdout \u2014 one JSON line per event to a writable (the worker's stdout is ignored\n// when spawned by a hook, so this sink is for `sessionpipe tail` and tests).\nimport type { Event, Tier } from \"../types.js\";\nimport type { DeliveryResult, Sink } from \"./types.js\";\n\nexport class StdoutSink implements Sink {\n constructor(\n readonly name: string,\n readonly tier: Tier,\n readonly pii: boolean,\n private readonly write: (line: string) => void = (l) => process.stdout.write(`${l}\\n`),\n ) {}\n async send(events: Event[]): Promise<DeliveryResult> {\n try {\n for (const e of events) this.write(JSON.stringify(e));\n return { ok: true, acknowledged: events.length, accepted: events.length, duplicates: 0, rejected: [] };\n } catch (e) {\n // A closed pipe (`sessionpipe tail | head`): a result, like every other sink.\n return { ok: false, acknowledged: 0, error: String((e as Error).message ?? e), action: \"retry\" };\n }\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The pure half of `sessionpipe connect`: which folders a machine allows sessions you\n// message to run in, when nobody said. Never the home folder or anything above it:\n// \"allow everything I own\" is not a default anyone should find out about later.\nimport path from \"node:path\";\n\n/** The home folder, or a folder that contains it (/, /Users), or the filesystem root. */\nexport function isBroad(dir: string, home: string): boolean {\n const d = path.resolve(dir);\n const h = path.resolve(home);\n if (d === path.parse(d).root) return true;\n // A resolved path ends with the separator only when it is the root, answered above.\n return d === h || h.startsWith(/* v8 ignore next */ d.endsWith(path.sep) ? d : d + path.sep);\n}\n\n// `parent` is a resolved, non-root folder (isBroad keeps the root out): it never ends with the separator.\nconst inside = (child: string, parent: string): boolean =>\n child !== parent && child.startsWith(/* v8 ignore next */ parent.endsWith(path.sep) ? parent : parent + path.sep);\n\nexport interface FolderChoice {\n folders: string[];\n /** Where they came from: the flags, the machine's own list, the folder this ran in,\n * the folders recent sessions ran in, or nowhere. */\n from: \"flags\" | \"existing\" | \"here\" | \"recent\" | \"none\";\n}\n\n/** `recent`: the folders this machine's sessions ran in, newest first. */\nexport function connectFolders(o: {\n cwd: string;\n home: string;\n flags: string[];\n existing: string[];\n recent: string[];\n exists?: (dir: string) => boolean;\n max?: number;\n}): FolderChoice {\n if (o.flags.length) return { folders: o.flags.map((d) => path.resolve(d)), from: \"flags\" };\n if (o.existing.length) return { folders: [], from: \"existing\" };\n if (!isBroad(o.cwd, o.home)) return { folders: [path.resolve(o.cwd)], from: \"here\" };\n const exists = o.exists ?? (() => true);\n const picked: string[] = [];\n for (const raw of o.recent) {\n if (!raw || !path.isAbsolute(raw)) continue;\n const d = path.resolve(raw);\n if (isBroad(d, o.home) || picked.includes(d) || !exists(d)) continue;\n if (picked.some((p) => inside(d, p))) continue;\n // A wider folder replaces the narrower ones already picked under it.\n for (let i = picked.length - 1; i >= 0; i--) if (inside(picked[i] as string, d)) picked.splice(i, 1);\n picked.push(d);\n if (picked.length >= (o.max ?? 8)) break;\n }\n return picked.length ? { folders: picked, from: \"recent\" } : { folders: [], from: \"none\" };\n}\n\n/** The tier `connect` reports at: --tier when given; otherwise 2 (what a session board\n * needs: the asks and the answers, secrets removed), never lowering a sink set higher. */\nexport function connectTier(flag: string | undefined, current: number | undefined): 0 | 1 | 2 | 3 {\n if (flag !== undefined && flag !== \"\")\n return Math.max(0, Math.min(3, Math.trunc(Number(flag)) || 0)) as 0 | 1 | 2 | 3;\n return Math.max(2, Math.min(3, current ?? 0)) as 2 | 3;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The control daemon keeps its own copy current. About a minute after it starts, and\n// then once a day by the wall clock (state/control/update.json remembers the last\n// check, so a restart or a machine that slept doesn't ask twice in a day), it reads\n// npm's `latest`. When that is newer it waits until the daemon has nothing in hand \u2014\n// no message being delivered, no headless run or start, no held SDK session mid-turn,\n// no permission prompt open, no session on the machine mid-turn, no acks being sent \u2014\n// stops taking new messages, installs the release into the prefix it runs from\n// (update.ts), and restarts onto it:\n//\n// launchd / systemd exit UPDATE_EXIT; the service restarts it on the new code\n// (every plist and unit sessionpipe ever wrote restarts on a\n// non-zero exit).\n// anything else this process stops being the daemon and becomes its parent:\n// it runs the new `control run` as its child with the same env\n// and output, restarts it on UPDATE_EXIT, and exits with it\n// otherwise. Whatever waits on this process (a terminal, a\n// container's init, a setsid'd shell) keeps waiting.\n//\n// Off with SESSIONPIPE_NO_UPDATE_CHECK, `update_check: false` in config.json\n// (`sessionpipe update off`), or when the running copy isn't a global npm install.\nimport { type ChildProcess, spawn } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Config } from \"@sessionpipe/core\";\nimport { compareVersions, globalPrefix, isNewer, unwritable } from \"../update.js\";\nimport { controlState, writePrivate } from \"./store.js\";\n\n/** EX_TEMPFAIL: \"start me again, on the code now on disk\". */\nexport const UPDATE_EXIT = 75;\nexport const DAY_MS = 24 * 3600_000;\nconst LABEL = \"org.sessionpipe.control\";\nconst UNIT = \"sessionpipe-control.service\";\n\n/** What the daemon remembers about updating, in state/control/update.json. */\nexport interface UpdateRecord {\n /** The last time it asked npm, whatever the answer. */\n checked_at?: string;\n /** What npm said was `latest` then; null when the check failed. */\n latest?: string | null;\n error?: string | null;\n /** The version that checked. */\n running?: string;\n /** Why the daemon's auto-update is off, as the daemon sees it (its own env), or null. */\n off?: string | null;\n /** A newer release waiting for the daemon to be idle. */\n pending?: string | null;\n updated?: { from: string; to: string; at: string; ms: number } | null;\n failed?: { version: string; at: string; error: string } | null;\n}\n\nexport const updateFile = (env: NodeJS.ProcessEnv = process.env): string => path.join(controlState(env), \"update.json\");\n\nexport function readUpdate(file: string): UpdateRecord {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as UpdateRecord;\n return j && typeof j === \"object\" ? j : {};\n } catch {\n return {};\n }\n}\n\n/** Due when it never checked, last checked a day or more ago, or the clock went back. */\nexport function isDue(rec: UpdateRecord, now: number): boolean {\n const t = Date.parse(rec.checked_at ?? \"\");\n if (!Number.isFinite(t)) return true;\n if (t > now + 5 * 60_000) return true;\n return now - t >= DAY_MS;\n}\n\n/** Why auto-update is off for this copy, or null when it is on. */\nexport function autoUpdateOff(o: {\n env: NodeJS.ProcessEnv;\n config: Pick<Config, \"update_check\">;\n distDir: string;\n platform?: NodeJS.Platform;\n}): string | null {\n if (o.env.SESSIONPIPE_NO_UPDATE_CHECK) return \"SESSIONPIPE_NO_UPDATE_CHECK is set\";\n if (o.config.update_check === false) return \"update_check is false in config.json (`sessionpipe update on`)\";\n const prefix = globalPrefix(o.distDir, o.platform);\n if (!prefix) return \"this copy isn't a global npm install (npx, a checkout or a dev build)\";\n return unwritable(prefix, o.platform);\n}\n\n/** What `status` and `doctor` say about updating. */\nexport interface UpdateSummary {\n auto: boolean;\n /** Why updates are by hand only, or null. */\n off: string | null;\n last_check: string | null;\n latest: string | null;\n last_error: string | null;\n pending: string | null;\n updated: UpdateRecord[\"updated\"] | null;\n failed: UpdateRecord[\"failed\"] | null;\n}\n\nexport function updateSummary(o: {\n /** autoUpdateOff() for this copy, from this shell (its env aside: the daemon's counts). */\n off: string | null;\n paired: boolean;\n rec: UpdateRecord;\n}): UpdateSummary {\n const daemonEnv = o.rec.off?.startsWith(\"SESSIONPIPE_NO_UPDATE_CHECK\")\n ? \"SESSIONPIPE_NO_UPDATE_CHECK is set in the daemon's environment\"\n : null;\n const off =\n o.off ?? (o.paired ? daemonEnv : \"it runs in the control daemon, which isn't set up here (`sessionpipe connect`)\");\n return {\n auto: !off,\n off,\n last_check: o.rec.checked_at ?? null,\n latest: o.rec.latest ?? null,\n last_error: o.rec.error ?? null,\n pending: o.rec.pending ?? null,\n updated: o.rec.updated ?? null,\n failed: o.rec.failed ?? null,\n };\n}\n\nexport function ago(iso: string, now: number): string {\n const ms = now - Date.parse(iso);\n if (!Number.isFinite(ms)) return \"at an unreadable time\";\n if (ms < 90_000) return \"just now\";\n if (ms < 90 * 60_000) return `${Math.round(ms / 60_000)} min ago`;\n if (ms < 36 * 3600_000) return `${Math.round(ms / 3600_000)} h ago`;\n return `${Math.round(ms / DAY_MS)} days ago`;\n}\n\n/** One line: whether it's automatic, when it last looked, what it found. */\nexport function updateLine(s: UpdateSummary, now: number): string {\n const parts = [\n s.auto\n ? \"automatic (the control daemon checks npm once a day and installs when idle; `sessionpipe update off` stops it)\"\n : `not automatic: ${s.off}`,\n ];\n if (s.last_check)\n parts.push(\n s.last_error\n ? `last check ${ago(s.last_check, now)} failed: ${s.last_error}`\n : `last check ${ago(s.last_check, now)}: latest ${s.latest ?? \"?\"}`,\n );\n else if (s.auto) parts.push(\"not checked yet (a minute after the daemon starts)\");\n if (s.pending) parts.push(`${s.pending} waits for the daemon to be idle`);\n if (s.failed) parts.push(`installing ${s.failed.version} failed ${ago(s.failed.at, now)}: ${s.failed.error}`);\n else if (s.updated) parts.push(`updated ${s.updated.from} \u2192 ${s.updated.to} ${ago(s.updated.at, now)}`);\n return parts.join(\" \u00B7 \");\n}\n\nexport type RestartVia = \"launchd\" | \"systemd\" | \"supervisor\";\n\n/** Who restarts this process when it exits UPDATE_EXIT, or null when nobody will (it\n * then supervises the new daemon itself). A wrong \"nobody\" costs one extra process; a\n * wrong \"somebody\" would leave the machine without a daemon, so each answer is checked\n * against the process's own parentage \u2014 a variable inherited by a child of the daemon\n * (a session it started) never counts. */\nexport function restartVia(o: {\n env: NodeJS.ProcessEnv;\n platform: NodeJS.Platform;\n pid: number;\n ppid: number;\n /** /proc/self/cgroup (Linux). */\n cgroup?: () => string;\n}): RestartVia | null {\n const s = o.env.SESSIONPIPE_SERVICE ?? \"\";\n if (s.startsWith(\"supervisor:\") && s === `supervisor:${o.ppid}`) return \"supervisor\";\n if (o.platform === \"darwin\" && o.ppid === 1 && (s === \"launchd\" || o.env.XPC_SERVICE_NAME === LABEL))\n return \"launchd\";\n if (o.platform === \"linux\") {\n let cg = \"\";\n try {\n cg = (o.cgroup ?? (() => readFileSync(\"/proc/self/cgroup\", \"utf8\")))();\n } catch {}\n const inUnit = cg.split(\"\\n\").some((l) => l.endsWith(`/${UNIT}`) || l.includes(`/${UNIT}/`));\n const mainPid = !o.env.SYSTEMD_EXEC_PID || o.env.SYSTEMD_EXEC_PID === String(o.pid);\n if (inUnit && mainPid) return \"systemd\";\n }\n return null;\n}\n\n/** What the daemon offers the updater. */\nexport interface Quiescent {\n /** Null when nothing is in hand; otherwise what is. */\n busy(): string | null;\n /** Stop taking new messages (in-flight long-polls end); the receiver keeps them. */\n pauseIntake(): void;\n resumeIntake(): void;\n}\n\nexport interface UpdaterDeps {\n now: () => number;\n log: (line: string) => void;\n /** The running version. */\n version: string;\n file: string;\n /** Why it is off right now (re-read every tick: config.json may have changed). */\n off: () => string | null;\n latest: () => Promise<string>;\n /** The version of the copy on disk. */\n installed: () => Promise<string | null>;\n install: (version: string) => Promise<{ ok: true; ms: number; hooks?: string } | { ok: false; error: string }>;\n daemon: Quiescent;\n /** Stop the daemon and come back on the code on disk. Doesn't return in production. */\n restart: (from: string, to: string) => Promise<void>;\n firstCheckMs?: number;\n /** How often it looks at the clock; a check runs only when one is due. */\n tickMs?: number;\n idlePollMs?: number;\n}\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms).unref?.());\n\nexport class AutoUpdater {\n private first: NodeJS.Timeout | null = null;\n private every: NodeJS.Timeout | null = null;\n private stopped = false;\n private busyWith: Promise<void> | null = null;\n private lastOff: string | null | undefined = undefined;\n\n constructor(private readonly d: UpdaterDeps) {}\n\n start(): void {\n // A wait that a restart cut short is picked up again from `latest` by tick().\n if (this.record().pending) this.save({ pending: null });\n this.first = setTimeout(() => void this.tick(), this.d.firstCheckMs ?? 60_000);\n this.first.unref?.();\n // A look at the clock every ten minutes (one small file read): a machine that\n // sleeps catches up soon after it wakes, not up to an hour of awake time later.\n this.every = setInterval(() => void this.tick(), this.d.tickMs ?? 10 * 60_000);\n this.every.unref?.();\n }\n\n stop(): void {\n this.stopped = true;\n if (this.first) clearTimeout(this.first);\n if (this.every) clearInterval(this.every);\n }\n\n record(): UpdateRecord {\n return readUpdate(this.d.file);\n }\n\n private save(patch: Partial<UpdateRecord>): void {\n try {\n writePrivate(this.d.file, { ...readUpdate(this.d.file), ...patch });\n } catch {}\n }\n\n /** One look at the clock: check when a check is due and nothing is under way. */\n async tick(): Promise<void> {\n if (this.stopped || this.busyWith) return;\n const off = this.d.off();\n if (off !== this.lastOff) {\n if (off) this.d.log(`auto-update off: ${off}`);\n else if (this.lastOff) this.d.log(\"auto-update on\");\n this.lastOff = off;\n this.save({ off });\n }\n if (off) return;\n const rec = this.record();\n if (isDue(rec, this.d.now())) return this.check();\n // Not due, but the last check found a release this daemon never got to (it was\n // restarted while it waited to be idle): carry on. One that failed waits a day.\n const known = rec.latest;\n if (known && isNewer(known, this.d.version) && rec.failed?.version !== known)\n return this.guard(() => this.apply(known));\n }\n\n /** One update job at a time; whatever it throws is logged, never left unhandled. */\n private guard(job: () => Promise<void>): Promise<void> {\n if (this.busyWith) return this.busyWith;\n this.busyWith = job()\n .catch((e) => {\n if (!this.stopped) this.d.log(`update: ${String((e as Error)?.message || e)}`);\n })\n .finally(() => {\n this.busyWith = null;\n });\n return this.busyWith;\n }\n\n /** Ask npm now; when it has a newer release, install it once idle and restart. */\n check(): Promise<void> {\n return this.guard(async () => {\n const t0 = this.d.now();\n let latest: string;\n try {\n latest = await this.d.latest();\n } catch (e) {\n const error = String((e as Error)?.message || e).slice(0, 200);\n this.save({ checked_at: new Date(t0).toISOString(), latest: null, error, running: this.d.version });\n this.d.log(`update check: failed after ${this.d.now() - t0} ms: ${error}`);\n return;\n }\n const ms = this.d.now() - t0;\n this.save({ checked_at: new Date(t0).toISOString(), latest, error: null, running: this.d.version });\n if (!isNewer(latest, this.d.version)) {\n this.save({ pending: null });\n this.d.log(`update check: ${this.d.version} is current (npm latest ${latest}, ${ms} ms)`);\n return;\n }\n this.d.log(`update check: ${latest} is out (running ${this.d.version}, ${ms} ms); updating once idle`);\n await this.apply(latest);\n });\n }\n\n /** Restart onto the copy on disk once idle (`sessionpipe update` installed it). */\n restartWhenIdle(): boolean {\n if (this.stopped) return false;\n // An update under way ends the same way: on the newest copy on disk.\n if (this.busyWith) return true;\n void this.guard(async () => {\n const onDisk = await this.d.installed();\n if (!onDisk || onDisk === this.d.version) {\n this.d.log(`restart asked: the copy on disk is ${onDisk ?? \"unreadable\"}, the one running; staying`);\n return;\n }\n await this.quiesce(onDisk, false);\n await this.resumeOnError(async () => {\n this.d.log(`restart: ${this.d.version} \u2192 ${onDisk} (installed by hand)`);\n this.save({ updated: { from: this.d.version, to: onDisk, at: new Date(this.d.now()).toISOString(), ms: 0 } });\n await this.d.restart(this.d.version, onDisk);\n });\n });\n return true;\n }\n\n /** Wait until the daemon has nothing in hand, then stop its intake. A message that\n * slipped in between is let through and waited for. An automatic update turned off\n * meanwhile (`sessionpipe update off`) stops waiting. */\n private async quiesce(target: string, auto = true): Promise<void> {\n let said = false;\n for (;;) {\n let why = this.d.daemon.busy();\n while (why) {\n if (this.stopped) throw new Error(\"stopped\");\n const off = auto ? this.d.off() : null;\n if (off) {\n this.save({ pending: null });\n throw new Error(`${target} not installed: auto-update was turned off (${off})`);\n }\n if (!said) {\n this.d.log(`update: ${target} waits until the daemon is idle (${why})`);\n said = true;\n }\n await sleep(this.d.idlePollMs ?? 15_000);\n why = this.d.daemon.busy();\n }\n this.d.daemon.pauseIntake();\n if (!this.d.daemon.busy()) return;\n this.d.daemon.resumeIntake();\n }\n }\n\n /** Intake is paused from quiesce() on: whatever goes wrong after it lets it go. */\n private async resumeOnError(fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (e) {\n this.d.daemon.resumeIntake();\n throw e;\n }\n }\n\n private async apply(target: string): Promise<void> {\n this.save({ pending: target });\n await this.quiesce(target);\n await this.resumeOnError(() => this.installAndRestart(target));\n }\n\n private async installAndRestart(target: string): Promise<void> {\n const from = this.d.version;\n const t0 = this.d.now();\n const onDisk = await this.d.installed();\n let note = \"\";\n // Someone already installed it (or something newer) by hand: never install over a\n // newer copy, just restart onto what is there.\n const c = onDisk ? compareVersions(onDisk, target) : null;\n if (onDisk && c !== null && c >= 0) {\n target = onDisk;\n note = \" (already on disk)\";\n } else {\n const r = await this.d.install(target);\n if (!r.ok) {\n this.d.daemon.resumeIntake();\n const ms = this.d.now() - t0;\n this.save({\n pending: null,\n failed: { version: target, at: new Date(this.d.now()).toISOString(), error: r.error },\n });\n this.d.log(`update: ${from} \u2192 ${target} failed after ${ms} ms: ${r.error}; still running ${from}`);\n return;\n }\n if (r.hooks) note = `; ${r.hooks}`;\n }\n const ms = this.d.now() - t0;\n // Anything that came in over the socket while npm ran (a permission prompt) ends\n // first. The new copy is on disk by now, so it is restarted onto whatever happens.\n if (this.d.daemon.busy()) {\n this.d.daemon.resumeIntake();\n await this.quiesce(target, false);\n }\n this.save({\n pending: null,\n failed: null,\n updated: { from, to: target, at: new Date(this.d.now()).toISOString(), ms },\n });\n this.d.log(`update: ${from} \u2192 ${target} in ${ms} ms${note}; restarting`);\n await this.d.restart(from, target);\n }\n}\n\n/** The parent left behind when no service manager will restart the daemon: runs\n * `control run` as a child with the same env and output, starts it again when it exits\n * UPDATE_EXIT (an update) or fails (after 5 s, like the service files), and exits\n * with it when it exits cleanly or is told to stop. */\nexport function supervise(o: {\n node: string;\n args: string[];\n env: NodeJS.ProcessEnv;\n log: (line: string) => void;\n spawn?: typeof spawn;\n exit?: (code: number) => void;\n failDelayMs?: number;\n}): { stop: (sig?: NodeJS.Signals) => void } {\n const run = o.spawn ?? spawn;\n const exit = o.exit ?? ((c: number) => process.exit(c));\n const env = { ...o.env, SESSIONPIPE_SERVICE: `supervisor:${process.pid}` };\n let child: ChildProcess | null = null;\n let stopping = false;\n let later: NodeJS.Timeout | null = null;\n const start = () => {\n later = null;\n const c = run(o.node, o.args, { env, stdio: \"inherit\", windowsHide: true });\n child = c;\n let done = false;\n const ended = (code: number | null, signal: NodeJS.Signals | null) => {\n if (done) return;\n done = true;\n child = null;\n if (stopping) return exit(code ?? 0);\n if (code === UPDATE_EXIT) {\n o.log(\"the daemon is restarting onto its new version\");\n return start();\n }\n if (code === 0) return exit(0);\n o.log(`the daemon exited (${signal ?? `code ${code}`}); starting it again in 5 s`);\n later = setTimeout(start, o.failDelayMs ?? 5000);\n };\n c.on(\"exit\", ended);\n c.on(\"error\", (e) => {\n o.log(`couldn't start the daemon: ${e.message}`);\n ended(1, null);\n });\n };\n const stop = (sig: NodeJS.Signals = \"SIGTERM\") => {\n stopping = true;\n if (later) clearTimeout(later);\n if (child) child.kill(sig);\n else exit(0);\n };\n start();\n return { stop };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Updating this copy of sessionpipe from npm: what the latest release is, whether this\n// copy is one npm can update in place, and the install itself. `sessionpipe update`\n// runs it by hand; the control daemon runs it once a day (control/autoupdate.ts).\n//\n// Only a global npm install updates itself. A copy in the npx cache, a git checkout or\n// a dev build is somebody's deliberate choice of code, and npm installing over it\n// would be wrong or impossible: for those `globalPrefix` is null and nothing happens.\nimport { spawn } from \"node:child_process\";\nimport { accessSync, constants, existsSync, realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { viaNpx } from \"./runtime.js\";\n\nexport const REGISTRY_LATEST = \"https://registry.npmjs.org/sessionpipe/latest\";\n\nconst VERSION_RE = /^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/;\n\ninterface Parsed {\n n: [number, number, number];\n pre: string | null;\n}\nfunction parse(v: string): Parsed | null {\n const m = VERSION_RE.exec(String(v).trim());\n if (!m) return null;\n return { n: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] ?? null };\n}\n\n/** Order two versions: <0, 0, >0, or null if either isn't one. A release sorts above\n * its own prereleases; prereleases compare by their tag. */\nexport function compareVersions(a: string, b: string): number | null {\n const x = parse(a);\n const y = parse(b);\n if (!x || !y) return null;\n for (let i = 0; i < 3; i++) if (x.n[i] !== y.n[i]) return (x.n[i] as number) - (y.n[i] as number);\n if (x.pre === y.pre) return 0;\n if (x.pre === null) return 1;\n if (y.pre === null) return -1;\n return x.pre.localeCompare(y.pre, \"en\", { numeric: true });\n}\n\n/** `a` is a release newer than `b`. A prerelease is never offered as an update: the\n * `latest` dist-tag is a release, and anything else is someone's experiment.\n * Setup opts into prereleases when checking whether an installed build is newer. */\nexport function isNewer(a: string, b: string, includePrereleases = false): boolean {\n const x = parse(a);\n if (!x || (!includePrereleases && x.pre !== null)) return false;\n const c = compareVersions(a, b);\n return c !== null && c > 0;\n}\n\n/** The registry's `latest` for sessionpipe: one GET, nothing sent but the request. */\nexport async function latestVersion(f: typeof fetch = fetch, timeoutMs = 8000): Promise<string> {\n const r = await f(REGISTRY_LATEST, {\n signal: AbortSignal.timeout(timeoutMs),\n headers: { accept: \"application/json\" },\n });\n if (!r.ok) throw new Error(`the npm registry answered HTTP ${r.status}`);\n const j = (await r.json()) as { version?: unknown };\n if (typeof j.version !== \"string\" || !parse(j.version)) throw new Error(\"the npm registry named no version\");\n return j.version;\n}\n\n/** The prefix a global npm install of sessionpipe lives under, from the running copy's\n * dist folder (`<prefix>/lib/node_modules/sessionpipe/dist`, on Windows\n * `<prefix>\\node_modules\\sessionpipe\\dist`). */\nexport function prefixOf(distDir: string, platform: NodeJS.Platform = process.platform): string | null {\n const re =\n platform === \"win32\" ? /^(.*?)[\\\\/]node_modules[\\\\/]sessionpipe[\\\\/]/ : /^(.*)\\/lib\\/node_modules\\/sessionpipe\\//;\n return re.exec(`${distDir}/`)?.[1] ?? null;\n}\n\n/** The npm prefix this copy was installed into with `npm install -g`, or null when it\n * isn't a global npm install (the npx cache, a git checkout, a project's\n * node_modules, a dev build). A global install always has its bin link in the prefix. */\nexport function globalPrefix(distDir: string, platform: NodeJS.Platform = process.platform): string | null {\n if (viaNpx(distDir)) return null;\n const prefix = prefixOf(distDir, platform);\n if (!prefix) return null;\n const bin = platform === \"win32\" ? path.join(prefix, \"sessionpipe.cmd\") : path.join(prefix, \"bin\", \"sessionpipe\");\n return existsSync(bin) ? prefix : null;\n}\n\n/** Why npm can't write this prefix (installed with sudo, a read-only image), or null. */\nexport function unwritable(prefix: string, platform: NodeJS.Platform = process.platform): string | null {\n const dir = platform === \"win32\" ? path.join(prefix, \"node_modules\") : path.join(prefix, \"lib\", \"node_modules\");\n try {\n accessSync(dir, constants.W_OK);\n return null;\n } catch {\n return `${dir} isn't writable by this user (installed with sudo?)`;\n }\n}\n\n/** npm, run by this very node: under launchd PATH is /usr/bin:/bin, so neither `npm`\n * nor the `node` its shebang asks for is on it. Its npm-cli.js sits beside the node\n * binary (nvm, Homebrew, the official builds, the node Docker images). */\nexport function npmArgv(node: string, platform: NodeJS.Platform = process.platform): string[] {\n const dir = path.dirname(node);\n const candidates =\n platform === \"win32\"\n ? [path.join(dir, \"node_modules\", \"npm\", \"bin\", \"npm-cli.js\")]\n : [path.join(dir, \"npm\"), path.join(dir, \"..\", \"lib\", \"node_modules\", \"npm\", \"bin\", \"npm-cli.js\")];\n for (const c of candidates) {\n try {\n const real = realpathSync(c);\n if (real.endsWith(\".js\")) return [node, real];\n } catch {}\n }\n return [platform === \"win32\" ? \"npm.cmd\" : \"npm\"];\n}\n\nexport interface ExecResult {\n code: number | null;\n stdout: string;\n stderr: string;\n error?: string;\n}\nexport type Exec = (argv: string[], o: { env: NodeJS.ProcessEnv; timeoutMs: number }) => Promise<ExecResult>;\n\n/** Run a command to the end, keeping the tail of its output. */\nexport const execCapture: Exec = (argv, o) =>\n new Promise((resolve) => {\n const [cmd, ...rest] = argv as [string, ...string[]];\n let stdout = \"\";\n let stderr = \"\";\n const keep = (s: string, b: Buffer) => (s + b.toString(\"utf8\")).slice(-16_000);\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn(cmd, rest, {\n env: o.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n shell: process.platform === \"win32\" && cmd.endsWith(\".cmd\"),\n });\n } catch (e) {\n resolve({ code: null, stdout, stderr, error: (e as Error).message });\n return;\n }\n const t = setTimeout(() => child.kill(\"SIGTERM\"), o.timeoutMs);\n child.stdout?.on(\"data\", (b: Buffer) => {\n stdout = keep(stdout, b);\n });\n child.stderr?.on(\"data\", (b: Buffer) => {\n stderr = keep(stderr, b);\n });\n child.on(\"error\", (e) => {\n clearTimeout(t);\n resolve({ code: null, stdout, stderr, error: e.message });\n });\n child.on(\"close\", (code) => {\n clearTimeout(t);\n resolve({ code, stdout, stderr });\n });\n });\n\nexport interface InstallOptions {\n /** The node running this copy (process.execPath). */\n node: string;\n /** The running copy's dist folder: where the new one lands, under the same prefix. */\n distDir: string;\n /** Harnesses whose hooks to re-arm afterwards (config.harnesses that are enabled). */\n harnesses: string[];\n env?: NodeJS.ProcessEnv;\n exec?: Exec;\n platform?: NodeJS.Platform;\n}\n\nexport type InstallResult =\n | { ok: true; ms: number; hooks: string }\n | { ok: false; ms: number; error: string; stage: \"prefix\" | \"npm\" | \"verify\" };\n\nconst lastLine = (r: ExecResult): string =>\n (r.error || r.stderr.trim().split(\"\\n\").filter(Boolean).slice(-2).join(\" \") || `exit ${r.code}`).slice(0, 300);\n\n/** The version of the copy on disk (which may not be the one running). */\nexport async function installedVersion(o: {\n node: string;\n distDir: string;\n env?: NodeJS.ProcessEnv;\n exec?: Exec;\n}): Promise<string | null> {\n const r = await (o.exec ?? execCapture)([o.node, path.join(o.distDir, \"cli.js\"), \"--version\"], {\n env: o.env ?? process.env,\n timeoutMs: 30_000,\n });\n const v = r.stdout.trim();\n return r.code === 0 && parse(v) ? v : null;\n}\n\n/** `npm install -g sessionpipe@<version>` into the prefix the running copy came from,\n * check the copy on disk says that version, then re-copy the hook launcher's files\n * (the hooks run copies in ~/.local/share/sessionpipe, which npm never touches) for\n * the harnesses already set up here. Lifecycle scripts are off: sessionpipe has none,\n * and an unattended install runs nothing it fetched. */\nexport async function installVersion(version: string, o: InstallOptions): Promise<InstallResult> {\n const t0 = Date.now();\n const platform = o.platform ?? process.platform;\n const exec = o.exec ?? execCapture;\n const base = o.env ?? process.env;\n // npm and anything it starts find this node first.\n const env = { ...base, PATH: [path.dirname(o.node), base.PATH].filter(Boolean).join(path.delimiter) };\n const prefix = globalPrefix(o.distDir, platform);\n if (!prefix)\n return { ok: false, ms: Date.now() - t0, stage: \"prefix\", error: \"this copy isn't a global npm install\" };\n const npm = npmArgv(o.node, platform);\n const r = await exec(\n [\n ...npm,\n \"install\",\n \"--global\",\n \"--prefix\",\n prefix,\n \"--ignore-scripts\",\n \"--no-audit\",\n \"--no-fund\",\n `sessionpipe@${version}`,\n ],\n { env, timeoutMs: 5 * 60_000 },\n );\n if (r.code !== 0) return { ok: false, ms: Date.now() - t0, stage: \"npm\", error: `npm install: ${lastLine(r)}` };\n const now = await installedVersion({ node: o.node, distDir: o.distDir, env, exec });\n if (now !== version)\n return {\n ok: false,\n ms: Date.now() - t0,\n stage: \"verify\",\n error: `npm finished, but the copy in ${prefix} says ${now ?? \"nothing\"}, not ${version}`,\n };\n let hooks = \"no harness set up here; nothing to re-arm\";\n if (o.harnesses.length) {\n const h = await exec(\n [o.node, path.join(o.distDir, \"cli.js\"), \"install\", \"--backfill\", \"0\", ...o.harnesses.map((n) => `--${n}`)],\n { env, timeoutMs: 2 * 60_000 },\n );\n hooks =\n h.code === 0\n ? `hooks re-armed for ${o.harnesses.join(\", \")}`\n : `re-arming the hooks failed (${lastLine(h)}); \\`sessionpipe install\\` does it`;\n }\n return { ok: true, ms: Date.now() - t0, hooks };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Persistent paths shared by hook installation and control pairing.\nimport { execFileSync } from \"node:child_process\";\nimport { readFileSync, realpathSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { launcherState } from \"./launcher.js\";\nimport { VERSION } from \"./run.js\";\nimport { isNewer } from \"./update.js\";\n\n/** Homebrew's versioned Cellar path dies on `brew upgrade node`; its stable links survive. */\nexport function stableNode(exe: string): string {\n const m = /^(.*)\\/Cellar\\/(node(?:@\\d+)?)\\/[^/]+\\/bin\\/node$/.exec(exe);\n if (!m) return exe;\n let real: string;\n try {\n real = realpathSync(exe);\n } catch {\n return exe;\n }\n for (const c of [`${m[1]}/opt/${m[2]}/bin/node`, `${m[1]}/bin/node`]) {\n try {\n if (realpathSync(c) === real) return c;\n } catch {}\n }\n return exe;\n}\n\nexport function viaNpx(distDir: string): boolean {\n return /[\\\\/]_npx[\\\\/]/.test(distDir) || /[\\\\/]\\.npm[\\\\/]/.test(distDir);\n}\n\n/** Homebrew's default prefix disappears on a node upgrade; use the persistent one. */\nfunction installLocation(): { prefix: string; target: string } {\n let prefix = \"\";\n try {\n prefix = execFileSync(\"npm\", [\"prefix\", \"-g\"], {\n encoding: \"utf8\",\n timeout: 15000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {}\n return {\n prefix,\n target: /\\/Cellar\\/node(?:@\\d+)?\\/[^/]+/.test(prefix) ? path.join(os.homedir(), \".local\") : prefix,\n };\n}\n\n/** Refuse before npm, config or hook writes, including hooks left by another prefix. */\nexport function assertSetupVersion(allowDowngrade: boolean, target?: string): void {\n if (allowDowngrade) return;\n const check = (installed: string | null, where: string): void => {\n if (installed && isNewer(installed, VERSION, true))\n throw new Error(\n `refusing to downgrade sessionpipe: ${installed} is installed at ${where}; this command would install ${VERSION}. Use the installed newer CLI, or pass --allow-downgrade to force ${VERSION}.`,\n );\n };\n const hooks = launcherState(VERSION);\n check(hooks.version, hooks.file);\n const prefix = target ?? installLocation().target;\n if (!prefix) return;\n const pkg = path.join(\n prefix,\n ...(process.platform === \"win32\" ? [] : [\"lib\"]),\n \"node_modules\",\n \"sessionpipe\",\n \"package.json\",\n );\n let installed: unknown;\n try {\n installed = (JSON.parse(readFileSync(pkg, \"utf8\")) as { version?: unknown }).version;\n } catch {}\n if (typeof installed === \"string\") check(installed, pkg);\n}\n\n/** Install the running version persistently and hand off the original command before side effects. */\nexport function rerunGlobally(argv: string[], out: (s: string) => void, setup?: { allowDowngrade: boolean }): void {\n const { prefix, target } = installLocation();\n if (setup) assertSetupVersion(setup.allowDowngrade, target);\n out(` Installing sessionpipe@${VERSION} globally, so hooks and services use a persistent copy\u2026`);\n let bin: string;\n try {\n execFileSync(\"npm\", [\"install\", \"-g\", `sessionpipe@${VERSION}`, ...(target ? [\"--prefix\", target] : [])], {\n stdio: [\"ignore\", \"ignore\", \"inherit\"],\n });\n bin =\n process.platform === \"win32\"\n ? path.join(target, \"sessionpipe.cmd\")\n : target\n ? path.join(target, \"bin\", \"sessionpipe\")\n : \"sessionpipe\";\n if (target && target !== prefix)\n out(` Installed into ${target}; make sure ${path.join(target, \"bin\")} is on your PATH.`);\n } catch {\n out(\n \" ! couldn't install globally (`npm install -g sessionpipe` failed). Run it yourself, then retry this command.\",\n );\n process.exit(1);\n }\n // The command's own failure (a pairing that expired) is its own to report, not an\n // install that failed: it has said why; pass its exit status on.\n try {\n execFileSync(bin, argv, { stdio: \"inherit\", shell: process.platform === \"win32\" });\n } catch (e) {\n process.exit(typeof (e as { status?: unknown }).status === \"number\" ? (e as { status: number }).status : 1);\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The hook's own home, outside every npm prefix: a copy of hook.js and worker.js and a\n// small sh launcher, which is what the harnesses run. A hook entry that named node and\n// hook.js by their install paths died with them \u2014 `nvm uninstall`, a Volta or asdf\n// switch, a moved npm prefix \u2014 and the harness said nothing; the machine just stopped\n// reporting. The launcher runs the node sessionpipe was installed with and, once that\n// one is gone, any node on PATH. Windows keeps the direct entry (it has no sh).\n// ~/.local/share/sessionpipe/ SESSIONPIPE_DATA, else $XDG_DATA_HOME/sessionpipe\nimport { accessSync, chmodSync, constants, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { AG_STALE_PRETOOL } from \"@sessionpipe/core\";\n\nexport const LAUNCHER = \"sessionpipe-hook\";\nconst COPIED = [\"worker.js\", \"hook.js\"] as const;\n\nexport function dataDir(env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_DATA) return path.resolve(env.SESSIONPIPE_DATA);\n return path.join(env.XDG_DATA_HOME || path.join(os.homedir(), \".local\", \"share\"), \"sessionpipe\");\n}\nexport const launcherPath = (env: NodeJS.ProcessEnv = process.env): string => path.join(dataDir(env), LAUNCHER);\nexport const usesLauncher = (platform: NodeJS.Platform = process.platform): boolean => platform !== \"win32\";\n\nconst sq = (s: string): string => `'${s.replace(/'/g, `'\\\\''`)}'`;\n\n/** The launcher, in sh. No node at all prints what Antigravity needs and exits 0: the\n * hook must stay invisible to the harness whatever is missing (and a PreToolUse entry\n * an older install left must not turn into a silent deny). */\nexport function launcherScript(node: string, hook: string, version: string): string {\n return `#!/bin/sh\n# sessionpipe ${version} hook launcher, written by \\`sessionpipe install\\`. Harnesses run\n# this; it runs hook.js beside it with the node sessionpipe was installed with, or with\n# any node on PATH once that one is gone (an nvm uninstall, a Homebrew upgrade).\nn=${sq(node)}\n[ -x \"$n\" ] || n=$(command -v node) || { [ \"$1\" = antigravity ] && if [ \"$2\" = PreToolUse ]; then echo ${sq(AG_STALE_PRETOOL.trim())}; else echo '{}'; fi; exit 0; }\nexec \"$n\" ${sq(hook)} \"$@\"\n`;\n}\n\nfunction writeIfChanged(file: string, body: Buffer | string, mode: number): boolean {\n try {\n const cur = readFileSync(file);\n if (cur.equals(Buffer.isBuffer(body) ? body : Buffer.from(body))) {\n chmodSync(file, mode);\n return false;\n }\n } catch {}\n // A hook may start while this runs: write beside it and rename, never half a file.\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, body, { mode });\n renameSync(tmp, file);\n chmodSync(file, mode);\n return true;\n}\n\n/** Copy the hook and worker out of the npm install and (re)write the launcher. The\n * worker goes first, so a hook that starts mid-copy never spawns a missing one. */\nexport function installLauncher(o: { distDir: string; node: string; version: string; env?: NodeJS.ProcessEnv }): {\n launcher: string;\n changed: boolean;\n} {\n const dir = dataDir(o.env);\n mkdirSync(dir, { recursive: true, mode: 0o755 });\n let changed = false;\n for (const f of COPIED)\n changed = writeIfChanged(path.join(dir, f), readFileSync(path.join(o.distDir, f)), 0o644) || changed;\n const launcher = path.join(dir, LAUNCHER);\n changed = writeIfChanged(launcher, launcherScript(o.node, path.join(dir, \"hook.js\"), o.version), 0o755) || changed;\n return { launcher, changed };\n}\n\nexport function removeLauncher(env: NodeJS.ProcessEnv = process.env): void {\n for (const f of [LAUNCHER, ...COPIED]) rmSync(path.join(dataDir(env), f), { force: true });\n}\n\nexport interface LauncherState {\n file: string;\n present: boolean;\n /** The node the launcher names, and whether it can still run. */\n node: string | null;\n nodeOk: boolean;\n version: string | null;\n problems: string[];\n}\n\n/** What `doctor` says about the launcher. */\nexport function launcherState(version: string, env: NodeJS.ProcessEnv = process.env): LauncherState {\n const file = launcherPath(env);\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return {\n file,\n present: false,\n node: null,\n nodeOk: false,\n version: null,\n problems: [\"the hook launcher is missing; run `sessionpipe install` again\"],\n };\n }\n const node = /^n='((?:[^']|'\\\\'')*)'$/m.exec(text)?.[1]?.replace(/'\\\\''/g, \"'\") ?? null;\n const v = /^# sessionpipe (\\S+) hook launcher/m.exec(text)?.[1] ?? null;\n let nodeOk = false;\n try {\n if (node) {\n accessSync(node, constants.X_OK);\n nodeOk = true;\n }\n } catch {}\n const problems: string[] = [];\n if (!nodeOk)\n problems.push(\n `the node the hook launcher names (${node ?? \"?\"}) is gone; it falls back to the node on PATH. \\`sessionpipe install\\` points it at this one.`,\n );\n for (const f of COPIED)\n try {\n accessSync(path.join(path.dirname(file), f), constants.R_OK);\n } catch {\n problems.push(`${f} is missing beside the hook launcher; run \\`sessionpipe install\\` again`);\n }\n if (v && v !== version)\n problems.push(\n `the hooks run sessionpipe ${v}, this is ${version}; run \\`sessionpipe install\\` to bring them up to date`,\n );\n return { file, present: true, node, nodeOk, version: v, problems };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// What a worker run does, as a function so tests and `sessionpipe replay` share it.\nimport {\n appendFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n adapterByName,\n Cursors,\n capTail,\n type DeliveryResult,\n type Event,\n type FactsState,\n FileSink,\n filterEvent,\n gitFacts,\n isInjected,\n machineName,\n makeEvent,\n Outbox,\n processAlive,\n readConfig,\n redactDeep,\n type Session,\n type Sink,\n type SinkConfig,\n StdoutSink,\n safeId,\n shortId,\n stateDir,\n type TranscriptRead,\n takeLock,\n takeNamedLock,\n tilde,\n writeConfig,\n} from \"@sessionpipe/core\";\nimport { aliasFile, readAliases, receiverIdOf } from \"./control/aliases.js\";\nimport { ask, socketPath } from \"./control/local.js\";\nimport { HttpSink } from \"./http-sink.js\";\nimport { sinkWithSecrets } from \"./secrets.js\";\n\nasync function tellDaemon(\n state: string,\n job: Job,\n session: string,\n cwd: string | undefined,\n transcript?: string,\n): Promise<void> {\n const sock = socketPath(state);\n if (process.platform !== \"win32\" && !existsSync(sock)) return;\n await ask(\n sock,\n {\n op: \"event\",\n session: `${job.harness}:${session}`,\n event: job.event,\n ...(cwd ? { cwd } : {}),\n ...(transcript ? { transcript } : {}),\n },\n 300,\n );\n}\n\ndeclare const __SESSIONPIPE_VERSION__: string;\nconst VERSION = typeof __SESSIONPIPE_VERSION__ === \"string\" ? __SESSIONPIPE_VERSION__ : \"0.0.0\";\n\nexport interface Job {\n harness: string;\n event: string;\n argv: string[];\n stdin: string;\n cwd: string;\n env: Record<string, string>;\n ppid?: number;\n at: number;\n /** How many times the session's lock held this job out (a fresh worker starts for\n * it each time, up to MAX_TRIES; after that a sweep picks it up). */\n tries?: number;\n}\n\nexport const MAX_TRIES = 10;\n\n/** A job file the worker will pick up: random suffix, 0600, in a 0700 dir. */\nexport function enqueueJob(state: string, job: Job): string {\n const jobs = jobsDir(state);\n mkdirSync(jobs, { recursive: true, mode: 0o700 });\n const f = path.join(jobs, `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.json`);\n writeFileSync(f, JSON.stringify(job), { mode: 0o600 });\n return f;\n}\n\n/** A job is claimed by renaming its file `<file>.<pid>.running`: of two workers that\n * race for it, one rename wins. The claim stays until the job's events are in the\n * outbox (or it went back to the queue), so a worker its deadline ended mid-run\n * leaves it behind for a sweep to give back (ground rule 4: no event lost). */\nexport function claimJob(file: string): { job: Job; file: string } | null {\n const claimed = `${file}.${process.pid}.running`;\n try {\n renameSync(file, claimed);\n } catch {\n return null;\n }\n try {\n return { job: JSON.parse(readFileSync(claimed, \"utf8\")) as Job, file: claimed };\n } catch {\n releaseJob(claimed);\n return null;\n }\n}\nexport function releaseJob(claimed: string | undefined): void {\n if (!claimed) return;\n try {\n unlinkSync(claimed);\n } catch {}\n}\n\n/** Jobs another worker left behind: a claim whose worker is gone (or older than any\n * worker lives, `abandonedMs`) goes back to the queue, then every queued job older\n * than `olderThanMs` (younger ones belong to the worker their hook just spawned)\n * is claimed and run. Every worker sweeps before it exits. */\nexport async function sweepJobs(state: string, olderThanMs = 3000, limit = 20, abandonedMs = 60_000): Promise<number> {\n const jobs = jobsDir(state);\n let names: string[] = [];\n try {\n names = readdirSync(jobs);\n } catch {\n return 0;\n }\n const queued = names.filter((n) => n.endsWith(\".json\"));\n for (const n of names) {\n const m = /^(.*\\.json)\\.(\\d+)\\.running$/.exec(n);\n if (!m) continue;\n const f = path.join(jobs, n);\n try {\n if (processAlive(Number(m[2])) && Date.now() - statSync(f).mtimeMs < abandonedMs) continue;\n renameSync(f, path.join(jobs, m[1] as string));\n queued.push(m[1] as string);\n } catch {}\n }\n let ran = 0;\n for (const n of queued.sort().slice(0, limit)) {\n const f = path.join(jobs, n);\n try {\n if (Date.now() - statSync(f).mtimeMs < olderThanMs) continue;\n } catch {\n continue;\n }\n const c = claimJob(f);\n if (!c) continue;\n try {\n await runJob(c.job, { state, claimed: c.file });\n } catch {\n } finally {\n releaseJob(c.file);\n }\n ran++;\n }\n return ran;\n}\n\nexport function log(state: string, line: string): void {\n try {\n mkdirSync(state, { recursive: true, mode: 0o700 });\n const f = path.join(state, \"log\");\n try {\n if (statSync(f).size > 1024 * 1024) renameSync(f, `${f}.1`);\n } catch {}\n appendFileSync(f, `${new Date().toISOString()} ${line}\\n`);\n } catch {}\n}\n\n/** <state>/facts/<harness>/<session>.json \u2014 what the machine learned about a session. */\nexport function factsState(state: string): FactsState {\n const file = (h: string, s: string) => path.join(state, \"facts\", safeId(h), `${safeId(s)}.json`);\n return {\n get(h, s) {\n try {\n return JSON.parse(readFileSync(file(h, s), \"utf8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n },\n save(h, s, patch) {\n const cur = this.get(h, s);\n const next = { ...cur, ...patch };\n if (JSON.stringify(next) === JSON.stringify(cur)) return;\n mkdirSync(path.dirname(file(h, s)), { recursive: true, mode: 0o700 });\n writeFileSync(file(h, s), JSON.stringify(next), { mode: 0o600 });\n },\n };\n}\n\nexport function buildSinks(sinks: SinkConfig[], o: { locked?: (name: string) => void } = {}): Sink[] {\n const out: Sink[] = [];\n for (const raw of sinks) {\n if (raw.paused) continue;\n // A token kept in a keychain is read now; one this process can't read (a keychain\n // locked in an ssh session) leaves the sink's events waiting, never sent unsigned.\n const s = sinkWithSecrets(raw);\n if (!s) {\n o.locked?.(raw.name);\n continue;\n }\n const tier = Math.min(s.tier, s.max_tier ?? 3) as 0 | 1 | 2 | 3;\n if (s.url === \"stdout\") out.push(new StdoutSink(s.name, tier, !!s.pii));\n else if (s.url.startsWith(\"file:\"))\n out.push(new FileSink(s.name, s.url.slice(5).replace(/^~(?=\\/|$)/, os.homedir()), tier, !!s.pii));\n else if (/^https?:\\/\\//.test(s.url)) out.push(new HttpSink(s, tier));\n }\n return out;\n}\n\n/** How often a running turn's words go out again (turn.progress), at most. */\nexport const PROGRESS_MS = 20_000;\n\n/** The turn still running in a transcript read from the delivery cursor: the last\n * turn with a reply so far, or a prompt nothing has answered yet (the hook's own\n * copy when the transcript doesn't hold it yet). `base` is the number the cursor's\n * first turn will get, so a turn keeps the number its turn.transcript will carry.\n * The reply keeps its end when it is long: where the turn is now. */\nexport function openTurn(\n read: TranscriptRead,\n o: { base: number; prompt?: string | undefined; at: number },\n): { turn: number; user: string; assistant: string; at: number } | null {\n const last = read.turns[read.turns.length - 1];\n const fresh = (user: string, at: number) => ({\n turn: o.base + read.turns.length,\n user: user.slice(0, MAX_TURN_SIDE),\n assistant: \"\",\n at,\n });\n if (read.open) return fresh(read.open.user, read.open.at);\n // The prompt the hook just reported, unless the transcript already has its reply.\n // Text the person never typed (a task notification, another session's message) opens\n // no turn: the readers skip it, so that turn would never be delivered, and its\n // reading would stand in for the turn that is running until the next one lands.\n const prompt = o.prompt?.trim();\n if (prompt && !isInjected(prompt) && !(last && last.user.includes(prompt.slice(0, 200)))) return fresh(prompt, o.at);\n if (!last) return null;\n return {\n turn: o.base + read.turns.length - 1,\n user: last.user.slice(0, MAX_TURN_SIDE),\n assistant: capTail(last.assistant, MAX_TURN_SIDE),\n at: last.at,\n };\n}\nconst MAX_TURN_SIDE = 20_000;\n\n/** Run one hook job end to end: events \u2192 outbox \u2192 sinks. Returns what happened.\n * `claimed` is the job file this run holds: released once the events are in the\n * outbox or the job is back in the queue (`requeued` names its new file). */\nexport async function runJob(\n job: Job,\n opts: { state?: string; now?: number; claimed?: string; lockWaitMs?: number } = {},\n): Promise<{ events: Event[]; delivered: Record<string, number>; requeued?: string }> {\n const state = opts.state ?? stateDir();\n const cfg = readConfig();\n const adapter = adapterByName(job.harness);\n // A hooks file can outlive the build that wrote it (an update to a sessionpipe without\n // that adapter, a hand-written entry): without this line the events are dropped in\n // silence, with nothing on the machine to say so.\n if (!adapter) {\n log(state, `${job.harness} ${job.event}: no adapter for harness \"${job.harness}\"; event dropped`);\n return { events: [], delivered: {} };\n }\n const r = adapter.fromHook({ argv: job.argv, stdin: job.stdin, env: { ...process.env, ...job.env }, cwd: job.cwd });\n // The adapter did not claim the payload (another harness ran our entry out of a\n // shared hooks file, an event name it does not map, a payload with no session id).\n // Dropped either way, but never in silence: this is where a wrongly-named event\n // lands, and the log is the only thing on the machine that can say so.\n if (!r || !r.session.id) {\n log(state, `${job.harness} ${job.event}: the ${job.harness} adapter did not claim this payload; event dropped`);\n return { events: [], delivered: {} };\n }\n // A session the control daemon started goes by the id its start command named, not\n // the one the harness picked (CONTROL.md \u00A76 `start`; control/aliases.ts): its events\n // say so, and so does everything below. The adapter's own reading of the session\n // (facts, a remote URL) keeps the harness's id.\n const id =\n receiverIdOf(readAliases(aliasFile(path.join(state, \"control\"))), job.harness, r.session.id) ?? r.session.id;\n const claudeEnd = job.harness === \"claude-code\" && r.events.some((e) => e.type === \"session.ended\");\n // The control daemon learns each session's turn state and folder from its events (a\n // message for a session mid-turn waits for its Stop; a pending permission prompt\n // closes when the tool runs). A local round trip, and nothing when no daemon runs.\n if (!claudeEnd) await tellDaemon(state, job, id, r.session.cwd, r.transcript);\n const outbox = new Outbox(state);\n const ref = { harness: job.harness, session: id };\n // Hooks of one session fire close together (parallel subagents, issue #9): poll\n // for the lock, often enough that its siblings can't keep taking it in between,\n // before giving the job back to the queue.\n let release = takeLock(state, ref);\n const lockWait = opts.lockWaitMs ?? LOCK_WAIT_MS;\n for (const until = Date.now() + lockWait; !release && Date.now() < until; ) {\n await new Promise((res) => setTimeout(res, 50));\n release = takeLock(state, ref);\n }\n if (!release) {\n log(state, `${job.harness} ${job.event}: session ${id} locked for ${lockWait / 1000} s, re-queued`);\n const requeued = enqueueJob(state, { ...job, tries: (job.tries ?? 0) + 1 });\n releaseJob(opts.claimed);\n return { events: [], delivered: {}, requeued };\n }\n const events: Event[] = [];\n try {\n const facts = factsState(state);\n const mem = facts.get(job.harness, id);\n // `claude mcp list` fires SessionEnd with a fresh id but no SessionStart or\n // transcript. Check under the session lock, before creating facts or a seq:\n // any existing outbox, facts or transcript is enough to preserve a real end.\n if (\n claudeEnd &&\n !existsSync(outbox.file(ref)) &&\n Object.keys(mem).length === 0 &&\n !(r.transcript && existsSync(r.transcript))\n ) {\n releaseJob(opts.claimed);\n return { events: [], delivered: {} };\n }\n if (claudeEnd) await tellDaemon(state, job, id, r.session.cwd, r.transcript);\n // Heartbeat-class events read no facts (they fire every tool call); the rest refresh them.\n const heavy = !/^(PreToolUse|PostToolUse|PostToolUseFailure|BeforeTool|AfterTool|PostInvocation)$/.test(job.event);\n let learned: Partial<Session> = {};\n if (heavy) {\n // The hook's environment, not the worker's: a swept job may be run by a worker\n // another harness's hook spawned, whose env names none of this harness's homes.\n const f = adapter.facts(r.session, r.transcript, r.hints ?? {}, facts, { ...process.env, ...job.env });\n const { started_at: _s, last_at: _l, first_ask: _fa, harness_version, ...rest } = f;\n learned = rest;\n if (harness_version) facts.save(job.harness, id, { harness_version });\n facts.save(job.harness, id, { session: { ...(mem.session as object), ...learned } });\n // Antigravity's transcript never says which folder a conversation runs in, and\n // Devin's payload names none either (only DEVIN_PROJECT_DIR in the hook's env);\n // the hooks do. Kept raw (this file is the machine's own, 0600), so the control\n // daemon still knows where to resume it after a restart.\n if (CWD_FROM_HOOKS.has(job.harness) && r.session.cwd && path.isAbsolute(r.session.cwd))\n facts.save(job.harness, id, { cwd: r.session.cwd });\n }\n const known = (mem.session as Partial<Session> | undefined) ?? {};\n const cwdRaw = learned.cwd ?? r.session.cwd ?? known.cwd;\n const git = heavy ? gitFacts(cwdRaw) : {};\n const session: Session = {\n ...known,\n ...learned,\n ...git,\n ...(learned.branch ? { branch: learned.branch } : {}),\n id,\n seq: 0,\n machine: machineName(cfg, os.hostname()),\n ...(cwdRaw ? { cwd: tilde(cwdRaw) } : {}),\n ...(r.session.model ? { model: r.session.model } : {}),\n };\n const version = (facts.get(job.harness, id).harness_version as string | undefined) ?? undefined;\n for (const a of r.events) {\n const e = makeEvent(a, {\n harness: { name: job.harness, ...(version ? { version } : {}) },\n session: { ...session, seq: outbox.nextSeq(ref) },\n now: opts.now ?? job.at,\n });\n events.push(e);\n }\n const wantsTranscript = cfg.sinks.some((s) => !s.paused && Math.min(s.tier, s.max_tier ?? 3) >= 2);\n // Tier 2, while a turn runs: what it has said so far, so a receiver can show a long\n // turn before it ends. On the prompt, then at most every PROGRESS_MS on a tool call,\n // and only when it changed. The cursor stays where it is: turn.transcript still\n // delivers the whole turn when it ends.\n const ending = r.events.some((e) => e.type === \"turn.ended\" || e.type === \"session.ended\");\n const starting = r.events.some((e) => e.type === \"turn.started\");\n // A message sent while a turn runs is absorbed by that turn, and Claude Code reports\n // it as a prompt with the running turn's own id. It is not a new turn: where it\n // belongs is the transcript's to say, so its text is no reading of its own.\n const startedId = r.events.find((e) => e.type === \"turn.started\")?.data.turn_id;\n const absorbed = starting && typeof startedId === \"string\" && facts.get(job.harness, id).open_turn === startedId;\n if (wantsTranscript && r.transcript && !ending && (starting || r.events.some((e) => e.type === \"tool.ended\"))) {\n const cur = facts.get(job.harness, id);\n const at = opts.now ?? job.at;\n if (starting || at - (Number(cur.progress_at) || 0) >= PROGRESS_MS) {\n const p = openTurn(adapter.readTranscript(r.transcript, Number(cur.transcript_line) || 0), {\n base: Number(cur.transcript_turns) || 0,\n prompt: !absorbed && typeof r.hints?.prompt === \"string\" ? r.hints.prompt : undefined,\n at,\n });\n const sig = p && `${p.turn}:${p.user.length}:${p.assistant.length}`;\n if (p && (starting || sig !== cur.progress_sig)) {\n events.push(\n makeEvent(\n { type: \"turn.progress\", harnessEvent: job.event, data: { ...p, at: new Date(p.at).toISOString() } },\n {\n harness: { name: job.harness, ...(version ? { version } : {}) },\n session: { ...session, seq: outbox.nextSeq(ref) },\n now: at,\n },\n ),\n );\n facts.save(job.harness, id, { progress_at: at, progress_sig: sig });\n }\n }\n }\n // The turn running now, by its prompt's id, until it ends (for `absorbed`).\n if (starting && typeof startedId === \"string\" && !absorbed) facts.save(job.harness, id, { open_turn: startedId });\n if (ending) facts.save(job.harness, id, { open_turn: null });\n // Tier 2: after a turn ends, the transcript's new turns become turn.transcript events.\n if (\n wantsTranscript &&\n r.transcript &&\n r.events.some((e) => e.type === \"turn.ended\" || e.type === \"session.ended\")\n ) {\n const cur = facts.get(job.harness, id);\n const fromLine = Number(cur.transcript_line) || 0;\n let turnNo = Number(cur.transcript_turns) || 0;\n const read = adapter.readTranscript(r.transcript, fromLine);\n for (const t of read.turns) {\n events.push(\n makeEvent(\n {\n type: \"turn.transcript\",\n harnessEvent: job.event,\n data: { turn: turnNo++, user: t.user, assistant: t.assistant, at: new Date(t.at).toISOString() },\n },\n {\n harness: { name: job.harness, ...(version ? { version } : {}) },\n session: { ...session, seq: outbox.nextSeq(ref) },\n now: opts.now ?? job.at,\n },\n ),\n );\n }\n if (read.turns.length) facts.save(job.harness, id, { transcript_line: read.line, transcript_turns: turnNo });\n }\n // At rest the outbox holds redacted strings (advisory GHSA-8f6f-c3c9-j5p6): the\n // tier-3 fields stay, with their secrets already gone; filterEvent runs the same\n // idempotent pass again per sink.\n outbox.append(\n ref,\n events.map((e) => ({ ...e, session: redactDeep(e.session), data: redactDeep(e.data) })),\n );\n releaseJob(opts.claimed);\n log(\n state,\n `${job.harness} ${job.event}: ${events.map((e) => e.type).join(\",\") || \"nothing\"} (${shortId(job.harness, id)})`,\n );\n } finally {\n release();\n }\n // The session's lock covered the append; the sinks drain without it (the outbox\n // reader leaves a line still being written), so a sibling hook isn't held out for\n // a round trip.\n const delivered = (await drain(state, cfg.sinks, outbox, ref)) ?? {};\n if (Math.random() < 0.02) outbox.prune(cfg.keep_days ?? 30);\n return { events, delivered };\n}\n\n/** One worker drains a machine's sinks at a time (the `flush` lock). Another whose\n * events are in the outbox meanwhile marks that there is more and leaves them to\n * it (null: nothing sent by this one). The one draining looks for the mark after\n * each pass, once it has let the lock go, so events appended during a pass go out\n * in its next pass or with the worker that appended them, never wait for a later\n * hook. Under a flood of hook events this is one uploader sending full batches,\n * not one per event, all refused together (mordast, 2026-10-14: 828 refusals in\n * two minutes, 5 192 jobs queued). */\nexport async function drain(\n state: string,\n sinkConfigs: SinkConfig[],\n outbox: Outbox,\n first?: { harness: string; session: string },\n): Promise<Record<string, number> | null> {\n const more = path.join(state, \"locks\", \"flush.more\");\n let release = takeNamedLock(state, \"flush\");\n if (!release) {\n try {\n writeFileSync(more, \"\", { mode: 0o600 });\n } catch {}\n release = takeNamedLock(state, \"flush\");\n if (!release) return null;\n }\n const delivered: Record<string, number> = {};\n for (;;) {\n try {\n unlinkSync(more);\n } catch {}\n try {\n for (const [k, v] of Object.entries(await flush(state, sinkConfigs, outbox, first)))\n delivered[k] = (delivered[k] ?? 0) + v;\n } finally {\n release();\n }\n if (!existsSync(more)) return delivered;\n release = takeNamedLock(state, \"flush\");\n if (!release) return delivered;\n }\n}\n\n/** HTTP.md \u00A72: a sink that answered 429 isn't tried again before its `retry-after`;\n * one that was unreachable (5xx, a timeout) waits 2 s \u00B7 10 s \u00B7 60 s \u00B7 5 min \u00B7 30 min,\n * then every 30 min. Kept in <state>/backoff/<sink>.json, so every worker on the\n * machine waits, not only the one that was refused. Cleared by the next batch the\n * sink takes. */\nexport interface Backoff {\n until: number;\n failures: number;\n why: string;\n}\nconst BACKOFF_MS = [2_000, 10_000, 60_000, 5 * 60_000, 30 * 60_000];\nconst backoffFile = (state: string, sink: string): string => path.join(state, \"backoff\", `${safeId(sink)}.json`);\nexport function readBackoff(state: string, sink: string): Backoff | null {\n try {\n const b = JSON.parse(readFileSync(backoffFile(state, sink), \"utf8\")) as Backoff;\n return typeof b.until === \"number\" ? b : null;\n } catch {\n return null;\n }\n}\nfunction noteFailure(state: string, sink: string, res: DeliveryResult, prev: Backoff | null): Backoff {\n const failures = (prev?.failures ?? 0) + 1;\n const ladder = BACKOFF_MS[Math.min(failures, BACKOFF_MS.length) - 1] as number;\n const wait = Number.isFinite(res.retryAfterMs) ? (res.retryAfterMs as number) : ladder;\n const b = { until: Date.now() + wait, failures, why: `${res.status ?? \"\"} ${res.error ?? \"\"}`.trim() };\n const f = backoffFile(state, sink);\n try {\n mkdirSync(path.dirname(f), { recursive: true, mode: 0o700 });\n writeFileSync(f, JSON.stringify(b), { mode: 0o600 });\n } catch {}\n return b;\n}\nfunction clearBackoff(state: string, sink: string): void {\n try {\n unlinkSync(backoffFile(state, sink));\n } catch {}\n}\n\n/** How long a job waits for its session's lock before it goes back to the queue. */\nconst LOCK_WAIT_MS = 6000;\n/** Harnesses whose own files do not name the session's folder: the hooks' cwd is kept. */\nconst CWD_FROM_HOOKS = new Set([\"antigravity\", \"devin\"]);\n\nconst BATCH = 50;\nconst MAX_PER_RUN = 500;\n\n/** Drain every sink from its cursor: this session first, then any backlog. Events\n * from many sessions are packed into one batch of up to BATCH, so a first\n * install's 400-session backfill is nine POSTs, not four hundred (the receiver's\n * write limit ended the first replay at 278 events, 2026-09-28). A cursor moves\n * only after its batch was acknowledged; a refused batch stops the sink for this\n * run and the next worker starts from the same cursors. The sinks drain at once:\n * the session's lock is held for the slowest round trip, not the sum of them (a\n * verdict's config write is synchronous, so two sinks' never interleave). */\nexport async function flush(\n state: string,\n sinkConfigs: SinkConfig[],\n outbox: Outbox,\n first?: { harness: string; session: string },\n o: { /** Try a sink in backoff anyway (`sessionpipe replay`). */ force?: boolean } = {},\n): Promise<Record<string, number>> {\n const delivered: Record<string, number> = {};\n const sinks = buildSinks(sinkConfigs, {\n locked: (name) => log(state, `sink ${name}: its token is in a keychain this process can't read; left for later`),\n });\n const refs = outbox.sessions();\n if (first) {\n const k = `${first.harness}/${safeId(first.session)}`;\n refs.sort((a, b) => (`${a.harness}/${a.session}` === k ? -1 : `${b.harness}/${b.session}` === k ? 1 : 0));\n }\n const drainSink = async (sink: Sink): Promise<void> => {\n let backoff = readBackoff(state, sink.name);\n if (backoff && !o.force && backoff.until > Date.now()) {\n delivered[sink.name] = 0;\n return;\n }\n const cursors = new Cursors(state, sink.name);\n const c = cursors.read();\n let sent = 0;\n let stalled = false;\n // Pull filtered events session by session into one batch; remember where each\n // session's offset would land if the batch goes through.\n let batch: Event[] = [];\n let pending: Record<string, number> = {};\n // HTTP.md \u00A72 413: halve the batch and try again; one event too large on its own\n // is dropped and logged. A half that is refused for another reason stops the\n // run like any refusal: the cursor stays, and the halves that went through are\n // sent again next time (the receiver counts them as duplicates).\n const deliver = async (events: Event[]): Promise<DeliveryResult> => {\n const res = await sink.send(events);\n if (res.ok || res.action !== \"split\") return res;\n if (events.length === 1) {\n const e = events[0] as Event;\n log(state, `sink ${sink.name}: 413 ${res.error ?? \"\"} \u2192 event ${e.id} (${e.type}) is too large alone, dropped`);\n return { ok: true, acknowledged: 0, accepted: 0, duplicates: 0, rejected: [{ id: e.id, reason: \"too_large\" }] };\n }\n const half = Math.ceil(events.length / 2);\n const a = await deliver(events.slice(0, half));\n if (!a.ok) return a;\n const b = await deliver(events.slice(half));\n if (!b.ok) return b;\n return {\n ok: true,\n acknowledged: a.acknowledged + b.acknowledged,\n accepted: (a.accepted ?? 0) + (b.accepted ?? 0),\n duplicates: (a.duplicates ?? 0) + (b.duplicates ?? 0),\n rejected: [...(a.rejected ?? []), ...(b.rejected ?? [])],\n };\n };\n const send = async (): Promise<boolean> => {\n if (!batch.length) {\n Object.assign(c, pending);\n pending = {};\n cursors.write(c);\n return true;\n }\n const res = await deliver(batch);\n if (!res.ok) {\n const action = res.action ?? \"retry\";\n let wait = \"\";\n if (action === \"retry\") {\n backoff = noteFailure(state, sink.name, res, backoff);\n wait = `, waits ${Math.round((backoff.until - Date.now()) / 1000)} s`;\n }\n log(state, `sink ${sink.name}: ${res.status ?? \"\"} ${res.error ?? \"\"} \u2192 ${action}${wait}`);\n if (res.action === \"pause\" || res.action === \"lower-tier\") applySinkVerdict(sink.name, res);\n if (res.action !== \"drop\") {\n batch = [];\n pending = {};\n return false;\n }\n } else if (backoff) {\n clearBackoff(state, sink.name);\n backoff = null;\n }\n sent += batch.length;\n Object.assign(c, pending);\n cursors.write(c);\n batch = [];\n pending = {};\n return true;\n };\n for (const ref of refs) {\n if (stalled || sent >= MAX_PER_RUN) break;\n let offset = pending[cursors.key(ref)] ?? c[cursors.key(ref)] ?? 0;\n for (;;) {\n const room = BATCH - batch.length;\n const { events, offset: next } = outbox.read(ref, offset, room);\n if (!events.length) break;\n for (const e of events) {\n const f = filterEvent(e, sink.tier, sink.pii, { home: os.homedir() });\n if (f) batch.push(f);\n }\n offset = next;\n pending[cursors.key(ref)] = offset;\n if (batch.length >= BATCH) {\n if (!(await send())) {\n stalled = true;\n break;\n }\n if (sent >= MAX_PER_RUN) break;\n }\n }\n }\n if (!stalled && (batch.length || Object.keys(pending).length)) if (!(await send())) stalled = true;\n delivered[sink.name] = sent;\n };\n await Promise.all(sinks.map(drainSink));\n return delivered;\n}\n\nfunction applySinkVerdict(name: string, res: { action?: string; max_tier?: number; error?: string }): void {\n try {\n const cfg = readConfig();\n const s = cfg.sinks.find((x) => x.name === name);\n if (!s) return;\n if (res.action === \"pause\") s.paused = `${new Date().toISOString()} ${res.error ?? \"unauthorized\"}`;\n if (res.action === \"lower-tier\" && typeof res.max_tier === \"number\") s.max_tier = res.max_tier as 0 | 1 | 2 | 3;\n writeConfig(cfg);\n } catch {}\n}\n\nexport { VERSION };\nexport const versionLine = (): string => `sessionpipe ${VERSION}`;\nexport const jobsDir = (state: string): string => path.join(state, \"jobs\");\nexport const hasJobs = (state: string): boolean => existsSync(jobsDir(state));\n", "// SPDX-License-Identifier: Apache-2.0\n// Sessions the daemon started under the command's name (spec/CONTROL.md \u00A76 `start`).\n// Codex and Antigravity pick a new session's id themselves, but a `start` names the\n// session (`codex:<id>`), and that name is what the person's receiver knows it by. So\n// the moment a run reveals the harness's own id, the daemon records it here:\n//\n// state/control/aliases.json {\"codex:<command's id>\": {\"id\": \"<harness's id>\",\n// \"cwd\": \"<folder>\", \"at\": \"<iso>\"}, \u2026} (0600)\n//\n// and everything the machine reports uses the command's id: the daemon's acks, a later\n// prompt (resumed under the harness's id), and the hook events, which the worker renames\n// before it builds them (run.ts). Small, so it is read whole wherever it is needed.\nimport { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface Alias {\n /** The harness's own session id. */\n id: string;\n /** The folder the session runs in (the start's). */\n cwd: string;\n at: string;\n}\nexport type Aliases = Record<string, Alias>;\n\nexport const aliasFile = (controlDir: string): string => path.join(controlDir, \"aliases.json\");\n\nexport function readAliases(file: string): Aliases {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as unknown;\n if (!j || typeof j !== \"object\" || Array.isArray(j)) return {};\n const out: Aliases = {};\n for (const [k, v] of Object.entries(j as Record<string, unknown>)) {\n const a = v as Partial<Alias> | null;\n if (a && typeof a.id === \"string\" && a.id && typeof a.cwd === \"string\")\n out[k] = { id: a.id, cwd: a.cwd, at: typeof a.at === \"string\" ? a.at : \"\" };\n }\n return out;\n } catch {\n return {};\n }\n}\n\n/** Written whole and renamed into place, 0600 in a 0700 folder. */\nexport function writeAliases(file: string, all: Aliases): void {\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(all, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, file);\n try {\n chmodSync(file, 0o600);\n } catch {}\n}\n\n/** The command's id a harness's own session goes by, or null when it was never renamed. */\nexport function receiverIdOf(all: Aliases, harness: string, id: string): string | null {\n const prefix = `${harness}:`;\n for (const [k, a] of Object.entries(all)) if (a.id === id && k.startsWith(prefix)) return k.slice(prefix.length);\n return null;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The daemon's local socket (spec/CONTROL.md \u00A78): how the waiter, the Stop and\n// PermissionRequest hooks and the worker talk to the one daemon on this machine.\n// Line-delimited JSON, one request per connection. A Unix socket in the state\n// directory (0600, in a 0700 dir); a per-user named pipe on Windows. Only node:\n// builtins \u2014 the hook bundle imports this.\nimport net from \"node:net\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nexport type LocalRequest =\n /** A waiter parks until a message for its session arrives. */\n | { op: \"wait\"; session: string; pid?: number }\n /** A Stop hook asks for a queued message (turn mode). */\n | { op: \"stop\"; session: string; active: boolean }\n /** A PermissionRequest hook parks until a verified answer, or until it's released. */\n | { op: \"permission\"; session: string; attention: string; tool?: string }\n /** The worker reports a hook event: turn state and attention closure. */\n | { op: \"event\"; session: string; event: string; transcript?: string; cwd?: string }\n /** `sessionpipe control status`. */\n | { op: \"status\" }\n /** `sessionpipe update` installed a new copy: restart onto it once nothing is in hand. */\n | { op: \"restart\" };\n\nexport type LocalReply =\n | { op: \"message\"; text: string; id: string }\n | { op: \"block\"; reason: string; id: string }\n | { op: \"decision\"; behavior: \"allow\" | \"deny\"; message?: string; id: string }\n | { op: \"none\" }\n /** A newer waiter for the same session took over; this one stops. */\n | { op: \"replaced\" }\n | { op: \"ok\" }\n | { op: \"status\"; status: unknown };\n\n/** Where the daemon listens. `SESSIONPIPE_SOCKET` overrides (tests). */\nexport function socketPath(state: string, env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_SOCKET) return env.SESSIONPIPE_SOCKET;\n if (process.platform === \"win32\") return `\\\\\\\\.\\\\pipe\\\\sessionpipe-control-${os.userInfo().username}`;\n return path.join(state, \"control.sock\");\n}\n\n/** One request, one reply. `timeoutMs` bounds the whole exchange; null on any\n * failure (no daemon, a timeout, a garbled reply) \u2014 callers treat that as \"none\". */\nexport function ask(sock: string, req: LocalRequest, timeoutMs: number): Promise<LocalReply | null> {\n return new Promise((resolve) => {\n let buf = \"\";\n let done = false;\n const s = net.connect(sock);\n const finish = (r: LocalReply | null) => {\n if (done) return;\n done = true;\n clearTimeout(t);\n s.destroy();\n resolve(r);\n };\n const t = setTimeout(() => finish(null), timeoutMs);\n s.on(\"connect\", () => s.write(`${JSON.stringify(req)}\\n`));\n s.on(\"data\", (d) => {\n buf += d.toString(\"utf8\");\n const i = buf.indexOf(\"\\n\");\n if (i < 0) return;\n try {\n finish(JSON.parse(buf.slice(0, i)) as LocalReply);\n } catch {\n finish(null);\n }\n });\n s.on(\"error\", () => finish(null));\n s.on(\"close\", () => finish(null));\n });\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The HTTP sink (spec/HTTP.md \u00A72): POST {events} with the protocol header, a bearer\n// token and optional Standard Webhooks signature; errors map to what the sender\n// does next. The cursor moves only on 202. Retry/backoff is the worker's cadence\n// (each hook run drains the backlog); this class reports, it does not sleep.\nimport { createHash, createHmac } from \"node:crypto\";\nimport type { DeliveryResult, Event, Sink, SinkConfig, Tier } from \"@sessionpipe/core\";\n\nconst TIMEOUT_MS = 15_000;\n\n/** The Standard Webhooks message id (HTTP.md \u00A72): the same batch sent again carries\n * the same id, so a receiver that dedupes on webhook-id sees a retry as one message.\n * Derived from the events' own ids, which the outbox keeps across retries. */\nexport function webhookId(events: Pick<Event, \"id\">[]): string {\n return `msg_${createHash(\"sha256\")\n .update(events.map((e) => e.id).join(\",\"))\n .digest(\"base64url\")\n .slice(0, 32)}`;\n}\n\n/** HTTP.md \u00A72 429: wait as `retry-after` says, seconds or an HTTP date (RFC 9110\n * \u00A710.2.3); a minute when the header is missing or unreadable. */\nexport function retryAfterMs(header: string | null, now = Date.now()): number {\n if (header === null || header.trim() === \"\") return 60_000;\n const secs = Number(header);\n if (Number.isFinite(secs)) return Math.max(0, secs) * 1000;\n const at = Date.parse(header);\n return Number.isFinite(at) ? Math.max(0, at - now) : 60_000;\n}\n\nexport class HttpSink implements Sink {\n readonly name: string;\n readonly pii: boolean;\n private readonly url: string;\n constructor(\n private readonly cfg: SinkConfig,\n readonly tier: Tier,\n ) {\n this.name = cfg.name;\n this.pii = !!cfg.pii;\n this.url = cfg.url.replace(/\\/$/, \"\");\n }\n\n private eventsUrl(): string {\n // The endpoint from the well-known file is stored beside the url at `sink add`;\n // until then the spec's default path.\n const ep = (this.cfg as { endpoints?: { events?: string } }).endpoints?.events ?? \"/api/sessionpipe/v1/events\";\n return /^https?:\\/\\//.test(ep) ? ep : this.url + ep;\n }\n\n async send(events: Event[]): Promise<DeliveryResult> {\n const body = JSON.stringify({ events });\n const headers: Record<string, string> = { \"content-type\": \"application/json\", \"sessionpipe-protocol\": \"1\" };\n if (this.cfg.token) headers.authorization = `Bearer ${this.cfg.token}`;\n if (this.cfg.secret?.startsWith(\"whsec_\")) {\n const id = webhookId(events);\n const ts = Math.floor(Date.now() / 1000);\n const key = Buffer.from(this.cfg.secret.slice(6), \"base64\");\n const sig = createHmac(\"sha256\", key).update(`${id}.${ts}.${body}`).digest(\"base64\");\n headers[\"webhook-id\"] = id;\n headers[\"webhook-timestamp\"] = String(ts);\n headers[\"webhook-signature\"] = `v1,${sig}`;\n }\n const ctl = new AbortController();\n const t = setTimeout(() => ctl.abort(), TIMEOUT_MS);\n try {\n const r = await fetch(this.eventsUrl(), { method: \"POST\", headers, body, signal: ctl.signal });\n const text = await r.text();\n let j: Record<string, unknown> = {};\n try {\n j = text ? (JSON.parse(text) as Record<string, unknown>) : {};\n } catch {}\n if (r.status === 202 || r.status === 200) {\n return {\n ok: true,\n acknowledged: events.length,\n accepted: Number(j.accepted ?? events.length),\n duplicates: Number(j.duplicates ?? 0),\n rejected: Array.isArray(j.rejected) ? (j.rejected as { id: string; reason: string }[]) : [],\n ...(typeof j.max_tier === \"number\" ? { max_tier: j.max_tier as Tier } : {}),\n status: r.status,\n };\n }\n const err = typeof j.reason === \"string\" ? j.reason : text.slice(0, 200);\n if (r.status === 400) return { ok: false, acknowledged: 0, status: 400, error: err, action: \"drop\" };\n if (r.status === 401) return { ok: false, acknowledged: 0, status: 401, error: err, action: \"pause\" };\n if (r.status === 403)\n return {\n ok: false,\n acknowledged: 0,\n status: 403,\n error: err,\n action: \"lower-tier\",\n ...(typeof j.max_tier === \"number\" ? { max_tier: j.max_tier as Tier } : {}),\n };\n if (r.status === 413) return { ok: false, acknowledged: 0, status: 413, error: err, action: \"split\" };\n if (r.status === 429)\n return {\n ok: false,\n acknowledged: 0,\n status: 429,\n error: err,\n action: \"retry\",\n retryAfterMs: retryAfterMs(r.headers.get(\"retry-after\")),\n };\n return { ok: false, acknowledged: 0, status: r.status, error: err, action: \"retry\" };\n } catch (e) {\n return { ok: false, acknowledged: 0, error: String((e as Error).message ?? e), action: \"retry\" };\n } finally {\n clearTimeout(t);\n }\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Where this machine's secrets live: each sink's token (and Webhooks secret) and each\n// paired receiver's machine token. In the operating system's keychain when this person\n// has one unlocked \u2014 the macOS Keychain, or the Secret Service (GNOME Keyring, KWallet)\n// in a Linux desktop session \u2014 and otherwise in config.json / control.json at mode\n// 0600, which is all a headless server has (the same as ~/.ssh). A secret in a store\n// leaves `token_in` in the file and no token.\n//\n// What a store protects against, plainly: a dotfiles repo, a backup, a synced\n// ~/.config, a `cat` over a shoulder. Not a program running as you: `security` hands an\n// item it wrote back without asking, which is also how the hook's worker reads it.\n\nimport { spawnSync } from \"node:child_process\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { configFile, readConfig, type SinkConfig, writeConfig } from \"@sessionpipe/core\";\n\nexport type SecretStore = \"keychain\" | \"secret-service\";\nexport type StoreName = SecretStore | \"file\";\n\nconst SERVICE = \"sessionpipe\";\n\nexport type Runner = (cmd: string, args: string[], input?: string) => { status: number | null; stdout: string };\nexport const defaultRunner: Runner = (cmd, args, input) => {\n const r = spawnSync(cmd, args, {\n input: input ?? \"\",\n encoding: \"utf8\",\n timeout: 8000,\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n return { status: r.error ? null : r.status, stdout: r.stdout ?? \"\" };\n};\n\n/** A sink's item. The machine has one config, so a sink's name is enough \u2014 except\n * where SESSIONPIPE_CONFIG points at another (a second profile, a test): then the\n * item names that config too, so two configs' sinks of one name never share a key. */\nexport const sinkAccount = (name: string, what: \"token\" | \"secret\" = \"token\"): string => {\n const scope = process.env.SESSIONPIPE_CONFIG\n ? `@${createHash(\"sha256\").update(configFile()).digest(\"hex\").slice(0, 8)}`\n : \"\";\n return `sink:${name}:${what}${scope}`;\n};\nexport const controlAccount = (machine: string): string => `control:${machine}`;\n\n/** `security -i` reads its commands from stdin, so the value never sits in argv (and in\n * `ps`). Its parser takes double-quoted words: a value with a quote, a backslash or a\n * space isn't stored there and stays in the file. */\nconst KC_SAFE = /^[\\x21\\x23-\\x5b\\x5d-\\x7e]{1,4096}$/;\nconst NAME_SAFE = /^[\\x20\\x21\\x23-\\x5b\\x5d-\\x7e]{1,200}$/;\n\nexport function secretGet(store: SecretStore, account: string, run: Runner = defaultRunner): string | null {\n const r =\n store === \"keychain\"\n ? run(\"security\", [\"find-generic-password\", \"-s\", SERVICE, \"-a\", account, \"-w\"])\n : run(\"secret-tool\", [\"lookup\", \"service\", SERVICE, \"account\", account]);\n if (r.status !== 0) return null;\n const v = r.stdout.replace(/\\r?\\n$/, \"\");\n return v || null;\n}\n\nexport function secretSet(store: SecretStore, account: string, value: string, run: Runner = defaultRunner): boolean {\n if (store === \"keychain\") {\n if (!KC_SAFE.test(value) || !NAME_SAFE.test(account)) return false;\n run(\n \"security\",\n [\"-i\"],\n `add-generic-password -U -s ${SERVICE} -a \"${account}\" -l \"${SERVICE} ${account}\" -w \"${value}\"\\n`,\n );\n } else {\n run(\"secret-tool\", [\"store\", \"--label\", `${SERVICE} ${account}`, \"service\", SERVICE, \"account\", account], value);\n }\n // Trust only a read-back: `security -i` exits 0 whatever its commands did.\n return secretGet(store, account, run) === value;\n}\n\nexport function secretDel(store: SecretStore, account: string, run: Runner = defaultRunner): void {\n if (store === \"keychain\") run(\"security\", [\"delete-generic-password\", \"-s\", SERVICE, \"-a\", account]);\n else run(\"secret-tool\", [\"clear\", \"service\", SERVICE, \"account\", account]);\n}\n\n/** Can this process write, read back and delete an item in the store right now? */\nexport function probe(store: SecretStore, run: Runner = defaultRunner): boolean {\n const account = `probe:${randomBytes(6).toString(\"hex\")}`;\n const ok = secretSet(store, account, randomBytes(12).toString(\"base64url\"), run);\n secretDel(store, account, run);\n return ok;\n}\n\n/** The best place for secrets on this machine, from this session. SESSIONPIPE_SECRETS\n * (file | keychain | secret-service) overrides. The Secret Service is used only in a\n * desktop session: on a server its keyring is locked whenever nobody is logged in,\n * which is exactly when the daemon needs its token. */\nexport function bestStore(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n run: Runner = defaultRunner,\n): StoreName {\n const want = env.SESSIONPIPE_SECRETS;\n if (want === \"file\") return \"file\";\n const candidates: SecretStore[] =\n want === \"keychain\" || want === \"secret-service\"\n ? [want]\n : platform === \"darwin\"\n ? [\"keychain\"]\n : platform === \"linux\" && env.DBUS_SESSION_BUS_ADDRESS && (env.DISPLAY || env.WAYLAND_DISPLAY)\n ? [\"secret-service\"]\n : [];\n for (const s of candidates) if (probe(s, run)) return s;\n return \"file\";\n}\n\nexport const storeLabel = (s: StoreName | undefined): string =>\n s === \"keychain\" ? \"the macOS Keychain\" : s === \"secret-service\" ? \"the Secret Service keyring\" : \"a 0600 file\";\n\n/** The sink with its token and secret filled in from its store. Null when they live in\n * a store this process can't read right now (a keychain locked in an ssh session):\n * the caller leaves the events in the outbox rather than sending them unsigned. */\nexport function sinkWithSecrets(s: SinkConfig, run: Runner = defaultRunner): SinkConfig | null {\n if (!s.token_in) return s;\n const token = secretGet(s.token_in, sinkAccount(s.name), run);\n if (!token) return null;\n const secret = secretGet(s.token_in, sinkAccount(s.name, \"secret\"), run);\n return { ...s, token, ...(secret ? { secret } : {}) };\n}\n\n/** Store a sink's secrets in `to` (or back in the file) and save the config. */\nexport function moveSinkSecrets(\n to: StoreName,\n o: { run?: Runner; file?: string } = {},\n): { moved: string[]; kept: string[] } {\n const run = o.run ?? defaultRunner;\n const cfg = o.file ? readConfig(o.file) : readConfig();\n const moved: string[] = [];\n const kept: string[] = [];\n for (const s of cfg.sinks) {\n const from = s.token_in;\n if ((from ?? \"file\") === to) continue;\n const full = sinkWithSecrets(s, run);\n if (!full) {\n kept.push(s.name);\n continue;\n }\n if (!full.token && !full.secret) continue;\n if (to === \"file\") {\n // From a store, so with a token (sinkWithSecrets is null without one); a sink\n // already in the file never gets here.\n /* v8 ignore else */\n if (full.token) s.token = full.token;\n if (full.secret) s.secret = full.secret;\n delete s.token_in;\n } else {\n const ok =\n (!full.token || secretSet(to, sinkAccount(s.name), full.token, run)) &&\n (!full.secret || secretSet(to, sinkAccount(s.name, \"secret\"), full.secret, run));\n if (!ok) {\n secretDel(to, sinkAccount(s.name), run);\n secretDel(to, sinkAccount(s.name, \"secret\"), run);\n kept.push(s.name);\n continue;\n }\n delete s.token;\n delete s.secret;\n s.token_in = to;\n }\n moved.push(s.name);\n if (from) {\n // Written first, then the file says where; only then is the old copy dropped.\n if (o.file) writeConfig(cfg, o.file);\n else writeConfig(cfg);\n secretDel(from, sinkAccount(s.name), run);\n secretDel(from, sinkAccount(s.name, \"secret\"), run);\n }\n }\n if (o.file) writeConfig(cfg, o.file);\n else writeConfig(cfg);\n return { moved, kept };\n}\n\n/** Forget a sink's secrets wherever they are (sink remove, uninstall). */\nexport function dropSinkSecrets(s: SinkConfig, run: Runner = defaultRunner): void {\n if (!s.token_in) return;\n secretDel(s.token_in, sinkAccount(s.name), run);\n secretDel(s.token_in, sinkAccount(s.name, \"secret\"), run);\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// What the control daemon keeps on disk:\n// config/control.json the receivers this machine is paired with: machine id,\n// the machine's own token, the enrolled keys, folders, mode (0600)\n// state/control/nonces.jsonl every verified nonce for 25 h, fsync'd before a\n// command runs (a failed write refuses it)\n// state/control/acks.jsonl acks not yet accepted by their receiver\n// state/control/state.json forks: which copy a message to a session goes to\nimport {\n appendFileSync,\n chmodSync,\n closeSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport { configFile, stateDir } from \"@sessionpipe/core\";\nimport { NONCE_TTL_MS, type TrustedKey } from \"@sessionpipe/core/control\";\nimport {\n controlAccount,\n defaultRunner,\n type Runner,\n type SecretStore,\n type StoreName,\n secretDel,\n secretGet,\n secretSet,\n} from \"../secrets.js\";\n\nexport interface PairedReceiver {\n /** The receiver's origin, as the person typed it. */\n url: string;\n /** Absolute control endpoint (from the well-known file). */\n control: string;\n rpId: string;\n machine: string;\n /** The machine's own bearer (polls, acks, hello, off): opens nothing else. Empty\n * when it lives in a store this process can't read right now. */\n token: string;\n /** The token lives in this store, not in control.json (secrets.ts). */\n token_in?: SecretStore;\n keys: (TrustedKey & { name?: string; added_at: string })[];\n paired_at: string;\n}\n\nexport interface ControlConfig {\n name: string;\n /** Folders sessions may run in; compared on whole path segments, real paths. */\n folders: string[];\n mode: \"safe\" | \"auto\";\n receivers: PairedReceiver[];\n /** Caps this machine keeps whatever a receiver sends (defaults in daemon.ts,\n * LIMITS): new sessions running at once and per hour, headless Claude Code runs\n * at once. */\n limits?: { start_concurrent?: number; start_per_hour?: number; headless?: number };\n}\n\nexport const controlFile = (env: NodeJS.ProcessEnv = process.env) =>\n path.join(path.dirname(configFile(env)), \"control.json\");\nexport const controlState = (env: NodeJS.ProcessEnv = process.env) => path.join(stateDir(env), \"control\");\n\nexport function writePrivate(file: string, value: unknown): void {\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, file);\n try {\n chmodSync(file, 0o600);\n } catch {}\n}\n\nexport function readControl(env: NodeJS.ProcessEnv = process.env, run: Runner = defaultRunner): ControlConfig | null {\n try {\n const j = JSON.parse(readFileSync(controlFile(env), \"utf8\")) as ControlConfig;\n if (!j || !Array.isArray(j.receivers)) return null;\n return {\n name: j.name || \"machine\",\n folders: j.folders ?? [],\n mode: j.mode === \"auto\" ? \"auto\" : \"safe\",\n receivers: j.receivers.map((r) =>\n r.token_in ? { ...r, token: secretGet(r.token_in, controlAccount(r.machine), run) ?? \"\" } : r,\n ),\n ...(j.limits ? { limits: j.limits } : {}),\n };\n } catch {\n return null;\n }\n}\n\n/** How many receivers this machine is paired with, from control.json alone (no\n * keychain read: `status` shouldn't ask one). */\nexport function pairedCount(env: NodeJS.ProcessEnv = process.env): number {\n try {\n const j = JSON.parse(readFileSync(controlFile(env), \"utf8\")) as { receivers?: unknown };\n return Array.isArray(j.receivers) ? j.receivers.length : 0;\n } catch {\n return 0;\n }\n}\n\n/** A token kept in a store is never written back into the file. */\nexport const writeControl = (c: ControlConfig, env: NodeJS.ProcessEnv = process.env) =>\n writePrivate(controlFile(env), {\n ...c,\n receivers: c.receivers.map((r) => {\n if (!r.token_in) return r;\n const { token: _t, ...rest } = r;\n return rest;\n }),\n });\n\n/** Move every paired receiver's token into `to` (or back into control.json). A token\n * this process can't read is left where it is. */\nexport function moveControlSecrets(\n to: StoreName,\n o: { env?: NodeJS.ProcessEnv; run?: Runner } = {},\n): { moved: string[]; kept: string[] } {\n const run = o.run ?? defaultRunner;\n const cfg = readControl(o.env, run);\n const moved: string[] = [];\n const kept: string[] = [];\n if (!cfg) return { moved, kept };\n const drop: { store: SecretStore; machine: string }[] = [];\n for (const r of cfg.receivers) {\n if ((r.token_in ?? \"file\") === to) continue;\n if (!r.token) {\n kept.push(r.url);\n continue;\n }\n if (to !== \"file\" && !secretSet(to, controlAccount(r.machine), r.token, run)) {\n secretDel(to, controlAccount(r.machine), run);\n kept.push(r.url);\n continue;\n }\n if (r.token_in) drop.push({ store: r.token_in, machine: r.machine });\n if (to === \"file\") delete r.token_in;\n else r.token_in = to;\n moved.push(r.url);\n }\n writeControl(cfg, o.env);\n for (const d of drop) secretDel(d.store, controlAccount(d.machine), run);\n return { moved, kept };\n}\n\n/** Forget a receiver's token wherever it is (control off). */\nexport function dropControlSecret(r: PairedReceiver, run: Runner = defaultRunner): void {\n if (r.token_in) secretDel(r.token_in, controlAccount(r.machine), run);\n}\n\n/** Nonces the machine has run, for NONCE_TTL_MS. `seen()` records a new nonce\n * durably BEFORE it answers false; a write that fails throws, and the verifier\n * refuses the command (`nonce_store`). */\nexport class NonceStore {\n private readonly seenAt = new Map<string, number>();\n constructor(\n private readonly file: string,\n private readonly now: () => number = Date.now,\n ) {\n let raw = \"\";\n try {\n raw = readFileSync(file, \"utf8\");\n } catch {}\n const cut = this.now() - NONCE_TTL_MS;\n for (const line of raw.split(\"\\n\")) {\n if (!line) continue;\n try {\n const { n, t } = JSON.parse(line) as { n: string; t: number };\n if (typeof n === \"string\" && t > cut) this.seenAt.set(n, t);\n } catch {}\n }\n this.compact();\n }\n\n seen = (nonce: string): boolean => {\n const t = this.seenAt.get(nonce);\n if (t !== undefined && t > this.now() - NONCE_TTL_MS) return true;\n const at = this.now();\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n const fd = openSync(this.file, \"a\", 0o600);\n try {\n appendFileSync(fd, `${JSON.stringify({ n: nonce, t: at })}\\n`);\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n this.seenAt.set(nonce, at);\n return false;\n };\n\n /** Rewrite the file with only the live window (on start, and daily). */\n compact(): void {\n const cut = this.now() - NONCE_TTL_MS;\n for (const [n, t] of this.seenAt) if (t <= cut) this.seenAt.delete(n);\n if (!existsSync(this.file) && !this.seenAt.size) return;\n const body = [...this.seenAt].map(([n, t]) => JSON.stringify({ n, t })).join(\"\\n\");\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n writeFileSync(`${this.file}.tmp`, body ? `${body}\\n` : \"\", { mode: 0o600 });\n renameSync(`${this.file}.tmp`, this.file);\n }\n\n get size(): number {\n return this.seenAt.size;\n }\n}\n\nexport interface Ack {\n receiver: string;\n id: string;\n outcome: \"taken\" | \"delivered\" | \"expired\" | \"unsupported\" | \"failed\" | \"refused\";\n at: string;\n mode?: string;\n session?: string;\n code?: string;\n detail?: string;\n reply?: string;\n}\n\n/** Acks not yet accepted: appended before they are sent, rewritten when sent, so a\n * daemon restart re-sends rather than forgets (every message is acked exactly once\n * with a final outcome; a duplicate is tolerated by the receiver). */\nexport class AckOutbox {\n constructor(private readonly file: string) {}\n all(): Ack[] {\n try {\n return readFileSync(this.file, \"utf8\")\n .split(\"\\n\")\n .filter(Boolean)\n .map((l) => JSON.parse(l) as Ack);\n } catch {\n return [];\n }\n }\n add(a: Ack): void {\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n appendFileSync(this.file, `${JSON.stringify(a)}\\n`, { mode: 0o600 });\n }\n keep(left: Ack[]): void {\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n writeFileSync(`${this.file}.tmp`, left.map((a) => JSON.stringify(a)).join(\"\\n\") + (left.length ? \"\\n\" : \"\"), {\n mode: 0o600,\n });\n renameSync(`${this.file}.tmp`, this.file);\n }\n}\n\nexport interface DaemonState {\n /** Original session \u2192 the fork its messages go to. */\n copies: Record<string, string>;\n}\n\nexport function readState(file: string): DaemonState {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as DaemonState;\n return { copies: j.copies && typeof j.copies === \"object\" ? j.copies : {} };\n } catch {\n return { copies: {} };\n }\n}\nexport const writeState = (file: string, s: DaemonState) => writePrivate(file, s);\n", "// SPDX-License-Identifier: Apache-2.0\n// The one verifier for signed control commands (spec/CONTROL.md \u00A74\u2013\u00A75). A machine\n// runs a command only when this says yes; a receiver MAY run it too, as an early\n// word, so a bad command is refused where the person can see why.\n//\n// WebCrypto only (globalThis.crypto.subtle), no node: imports, no clock of its own\n// (`now` is passed in): the same file runs in a Cloudflare Worker, in a browser and\n// in Node \u2265 20, and conformance/control-vectors/ pins its answers.\n//\n// Every signature covers the EXACT bytes as transmitted (`cmd`, `grant.str`): the\n// strings are parsed to read their fields and never re-serialized to verify.\n\n/** One passkey tap vouches for a day key for at most this long. */\nexport const GRANT_MAX_MS = 24 * 3600_000;\n/** Clock slack between the signing device, the receiver and the machine. */\nexport const SKEW_MS = 5 * 60_000;\n/** The machine judges a command by when it was SIGNED: a message sent while the lid\n * was shut still runs when the machine wakes, up to a day later. */\nexport const MACHINE_MAX_AGE_MS = 24 * 3600_000;\n/** A receiver's early check is stricter: a command is carried within ten minutes of\n * being signed, or not at all. */\nexport const RECEIVER_MAX_AGE_MS = 10 * 60_000;\n/** How long a machine remembers a nonce: longer than MACHINE_MAX_AGE_MS + SKEW_MS. */\nexport const NONCE_TTL_MS = 25 * 3600_000;\n/** The whole command string, in UTF-16 code units (what JSON.parse sees). */\nexport const CMD_MAX = 48_000;\n/** A prompt's text, in characters. */\nexport const TEXT_MAX = 20_000;\n/** A permission answer's note. */\nexport const NOTE_MAX = 2_000;\n/** A grant string. */\nexport const GRANT_STR_MAX = 2_000;\n/** Attachments on a `start` (CONTROL.md \u00A73.1): at most this many files, */\nexport const FILES_MAX = 10;\n/** each at most this many bytes, */\nexport const FILE_SIZE_MAX = 26_214_400;\n/** together at most this many, */\nexport const FILES_TOTAL_MAX = 52_428_800;\n/** with a name of at most this many characters (after NFC) */\nexport const FILE_NAME_MAX = 200;\n/** and a media type of at most this many. */\nexport const FILE_TYPE_MAX = 100;\n\nexport const COMMAND_TYPE = \"sessionpipe.control\";\nexport const GRANT_TYPE = \"sessionpipe.grant\";\nexport const CONTROL_KINDS = [\"prompt\", \"permission.answer\", \"cancel\", \"start\", \"key.add\"] as const;\n/** The session a `key.add` names: the machine's own key store, not a coding session. */\nexport const KEY_STORE_SESSION = \"sessionpipe:keys\";\nexport type ControlKind = (typeof CONTROL_KINDS)[number];\n\n/** COSE algorithm ids a trusted key may use. */\nexport const ES256 = -7;\nexport const RS256 = -257;\n\n/** A key enrolled on the machine: a passkey's credential id, COSE alg and SPKI (base64url). */\nexport interface TrustedKey {\n id: string;\n alg: number;\n spki: string;\n}\n/** A WebAuthn assertion: credential id, authenticatorData, clientDataJSON, signature (base64url). */\nexport interface Assertion {\n cred: string;\n ad: string;\n cd: string;\n sig: string;\n}\n/** The day's grant: a passkey's assertion over sha256(str), where str names the day key. */\nexport interface GrantBundle extends Assertion {\n str: string;\n}\n/** What a receiver carries for one command (control.json minus the receiver's envelope). */\nexport interface SignedCommand {\n cmd: string;\n csig?: string | null;\n grant?: GrantBundle | null;\n confirm?: Assertion | null;\n}\nexport interface Grant {\n v: 1;\n t: typeof GRANT_TYPE;\n pub: string;\n iat: number;\n exp: number;\n rp: string;\n}\n/** One file attached to a `start`: the bytes live on the receiver, named by their hash. */\nexport interface ControlFile {\n /** The file name the machine writes (NFC). */\n name: string;\n /** Media type, `type/subtype`. */\n type: string;\n /** Bytes. */\n size: number;\n /** SHA-256 of the bytes, base64url without padding (43 characters). */\n sha256: string;\n}\nexport interface ControlCommand {\n v: 1;\n t: typeof COMMAND_TYPE;\n machine: string;\n kind: ControlKind;\n /** `<harness>:<id>`, e.g. `claude-code:8c132906-\u2026`. */\n session: string;\n text?: string;\n for?: string;\n decision?: \"allow\" | \"deny\";\n note?: string;\n cwd?: string;\n /** key.add only: the passkey to trust from now on, as the receiver holds it. */\n key?: { id: string; alg: -7 | -257; spki: string };\n /** key.add only: what the person calls the device (\"iPhone\"), for `control keys`. */\n name?: string;\n /** start only: files to download, verify and write into the new session's folder. */\n files?: ControlFile[];\n nonce: string;\n iat: number;\n}\n\n/** Why a command was refused. Stable: conformance vectors and acks name these. */\nexport type RefusalCode =\n | \"malformed\"\n | \"not_a_command\"\n | \"wrong_machine\"\n | \"unknown_kind\"\n | \"bad_session\"\n | \"bad_fields\"\n | \"bad_nonce\"\n | \"too_old\"\n | \"future\"\n | \"unsigned\"\n | \"untrusted_key\"\n | \"bad_assertion\"\n | \"bad_grant\"\n | \"outside_grant\"\n | \"bad_csig\"\n | \"replay\"\n | \"nonce_store\";\n\nexport type Verdict =\n | { ok: true; cmd: ControlCommand; via: \"grant\" | \"confirm\"; key: string }\n | { ok: false; code: RefusalCode; why: string };\n\nexport interface VerifyOptions {\n /** This machine's id; a command for another machine is refused. */\n machine: string;\n /** The receiver's WebAuthn rp id the keys were enrolled for (well-known control.signing.rp_id). */\n rpId: string;\n /** The keys enrolled on this machine (or, for a receiver's early check, the account's). */\n trusted: TrustedKey[];\n /** Epoch ms. */\n now: number;\n /** MACHINE_MAX_AGE_MS on a machine (default), RECEIVER_MAX_AGE_MS on a receiver. */\n maxAgeMs?: number;\n /** Called once, last, only for a command whose signatures all verified: answer\n * true when the nonce was seen before, otherwise record it (durably) and answer\n * false. A throw refuses the command (`nonce_store`): never run what could not\n * be remembered. Omit it on a receiver's early check. */\n seenNonce?: (nonce: string) => boolean | Promise<boolean>;\n}\n\nconst NONCE_RE = /^[A-Za-z0-9_-]{22,64}$/;\nconst MACHINE_RE = /^m_[A-Za-z0-9_-]{16,40}$/;\nconst HARNESS_RE = /^[a-z][a-z0-9-]{0,39}$/;\nconst SESSION_ID_RE = /^[A-Za-z0-9._:-]{1,128}$/;\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst B64URL_RE = /^[A-Za-z0-9_-]*$/;\nconst SHA256_RE = /^[A-Za-z0-9_-]{43}$/;\nconst MEDIA_TYPE_RE = /^[a-z0-9][a-z0-9!#$&^_.+-]*\\/[a-z0-9][a-z0-9!#$&^_.+-]*$/i;\n// biome-ignore lint/suspicious/noControlCharactersInRegex: control characters are exactly what it rejects\nconst BAD_NAME_CHAR_RE = /[/\\\\\\x00-\\x1f\\x7f]/;\nconst UP = 0x01;\nconst UV = 0x04;\n\n// --- encodings ------------------------------------------------------------------\n\nconst enc = new TextEncoder();\nconst dec = new TextDecoder();\n\nexport function b64url(bytes: Uint8Array | ArrayBuffer): string {\n const u = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n let s = \"\";\n for (const b of u) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** base64url without padding, strictly; null for anything else. */\nexport function fromB64url(s: unknown): Uint8Array | null {\n if (typeof s !== \"string\" || !B64URL_RE.test(s) || s.length % 4 === 1) return null;\n try {\n const bin = atob(s.replace(/-/g, \"+\").replace(/_/g, \"/\") + \"===\".slice((s.length + 3) % 4));\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n } catch {\n return null;\n }\n}\n\nexport async function sha256(data: string | Uint8Array): Promise<Uint8Array> {\n const bytes = typeof data === \"string\" ? enc.encode(data) : data;\n return new Uint8Array(await crypto.subtle.digest(\"SHA-256\", bytes as Uint8Array<ArrayBuffer>));\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\n/** Equal, compared whole: a mismatch costs the same as a match. */\nexport function sameBytes(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let d = 0;\n for (let i = 0; i < a.length; i++) d |= (a[i] as number) ^ (b[i] as number);\n return d === 0;\n}\n\n/** A DER ECDSA signature (what WebAuthn returns) as the 64-byte r\u2016s WebCrypto verifies.\n * Strict: every length must match the bytes, so one signature has one encoding (a\n * P-256 signature is at most 72 bytes, so the short length form is the only one). */\nexport function derToRaw(der: Uint8Array): Uint8Array | null {\n if (der[0] !== 0x30 || der.length < 8 || der[1] !== der.length - 2) return null;\n let i = 2;\n const part = (): Uint8Array | null => {\n if (der[i] !== 0x02) return null;\n const len = der[i + 1] as number;\n if (len < 1 || len > 33) return null;\n let v = der.slice(i + 2, i + 2 + len);\n if (v.length !== len) return null;\n // Minimal integers only: no needless leading zero, and never negative.\n if ((v[0] as number) & 0x80) return null;\n if (len > 1 && v[0] === 0 && !((v[1] as number) & 0x80)) return null;\n i += 2 + len;\n while (v.length > 32 && v[0] === 0) v = v.slice(1);\n if (v.length > 32) return null;\n const out = new Uint8Array(32);\n out.set(v, 32 - v.length);\n return out;\n };\n const r = part();\n const s = part();\n return r && s && i === der.length ? concat(r, s) : null;\n}\n\nconst u8 = (b: Uint8Array) => b as Uint8Array<ArrayBuffer>;\n/** WebCrypto's key type, named without the DOM lib (Workers, Node and browsers all have it). */\ntype CryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>;\n\nasync function importKey(key: TrustedKey): Promise<CryptoKey | null> {\n const spki = fromB64url(key.spki);\n if (!spki?.length) return null;\n try {\n if (key.alg === ES256)\n return await crypto.subtle.importKey(\"spki\", u8(spki), { name: \"ECDSA\", namedCurve: \"P-256\" }, false, [\"verify\"]);\n if (key.alg === RS256) {\n const k = await crypto.subtle.importKey(\"spki\", u8(spki), { name: \"RSASSA-PKCS1-v1_5\", hash: \"SHA-256\" }, false, [\n \"verify\",\n ]);\n const bits = (k.algorithm as { modulusLength?: number }).modulusLength as number; // every RSA key has one\n return bits >= 2048 ? k : null;\n }\n } catch {}\n return null;\n}\n\n/** Can this key be enrolled at all? A machine refuses to trust a key it could never verify with. */\nexport async function keyUsable(key: TrustedKey): Promise<boolean> {\n return (\n !!key &&\n typeof key.id === \"string\" &&\n /^[A-Za-z0-9_-]{16,1400}$/.test(key.id) &&\n (key.alg === ES256 || key.alg === RS256) &&\n !!(await importKey(key))\n );\n}\n\n// --- WebAuthn -------------------------------------------------------------------\n\n/** A WebAuthn origin a key may have been used from: https on the rp id or a subdomain;\n * for rp id `localhost`, plain http on any port too. A bare origin, as a browser writes it. */\nexport function originAllowed(origin: unknown, rpId: string): boolean {\n if (typeof origin !== \"string\" || !rpId) return false;\n let u: URL;\n try {\n u = new URL(origin);\n } catch {\n return false;\n }\n if (u.origin !== origin) return false;\n if (u.hostname !== rpId && !u.hostname.endsWith(`.${rpId}`)) return false;\n if (u.protocol === \"https:\") return true;\n return u.protocol === \"http:\" && rpId === \"localhost\";\n}\n\ntype Check = { ok: true } | { ok: false; why: string };\nconst no = (why: string): Check => ({ ok: false, why });\n\n/** One passkey assertion over `challenge`, made with `key`, by a verified person. */\nexport async function verifyAssertion(\n challenge: Uint8Array,\n a: Assertion | null | undefined,\n key: TrustedKey,\n rpId: string,\n): Promise<Check> {\n if (!a || typeof a !== \"object\") return no(\"no passkey signature\");\n if (a.cred !== key.id) return no(\"signed with a key this machine doesn't trust\");\n const cdBytes = fromB64url(a.cd);\n const ad = fromB64url(a.ad);\n const sig = fromB64url(a.sig);\n if (!cdBytes || !ad || !sig?.length) return no(\"the passkey signature is malformed\");\n let cd: { type?: unknown; challenge?: unknown; origin?: unknown; crossOrigin?: unknown };\n try {\n cd = JSON.parse(dec.decode(cdBytes));\n } catch {\n return no(\"the passkey signature is malformed\");\n }\n if (!cd || typeof cd !== \"object\") return no(\"the passkey signature is malformed\");\n if (cd.type !== \"webauthn.get\") return no(\"the passkey answered a different question\");\n if (cd.challenge !== b64url(challenge)) return no(\"the passkey signed something else\");\n if (!originAllowed(cd.origin, rpId)) return no(`the passkey was used on another site, not ${rpId}`);\n if (cd.crossOrigin === true) return no(\"the passkey was used inside another site's frame\");\n if (ad.length < 37) return no(\"the passkey signature is malformed\");\n if (!sameBytes(ad.slice(0, 32), await sha256(rpId))) return no(`the passkey belongs to another site, not ${rpId}`);\n const flags = ad[32] as number;\n if (!(flags & UP) || !(flags & UV)) return no(\"the passkey signed without verifying the person\");\n const pub = await importKey(key);\n if (!pub) return no(\"a trusted key is unusable\");\n const signed = concat(ad, await sha256(cdBytes));\n let good = false;\n try {\n if (key.alg === ES256) {\n const raw = derToRaw(sig);\n good = !!raw && (await crypto.subtle.verify({ name: \"ECDSA\", hash: \"SHA-256\" }, pub, u8(raw), u8(signed)));\n } else {\n good = await crypto.subtle.verify({ name: \"RSASSA-PKCS1-v1_5\" }, pub, u8(sig), u8(signed));\n }\n } catch {\n good = false;\n }\n return good ? { ok: true } : no(\"the passkey signature doesn't verify\");\n}\n\n/** What a passkey signs to enroll on a machine: bound to that machine and that pairing code. */\nexport function pairChallenge(machine: string, code: string): Promise<Uint8Array> {\n return sha256(`sessionpipe.pair:${machine}:${code}`);\n}\n\n/** The enrollment proof: the new key's assertion over pairChallenge(machine, code).\n * Only after this verifies does the key go into the machine's trust store. */\nexport async function verifyEnrollment(o: {\n machine: string;\n code: string;\n key: TrustedKey;\n proof: Assertion;\n rpId: string;\n}): Promise<Check> {\n if (!(await keyUsable(o.key))) return no(\"the key is in a shape this machine can't use\");\n return verifyAssertion(await pairChallenge(o.machine, o.code), o.proof, o.key, o.rpId);\n}\n\n// --- the command ------------------------------------------------------------------\n\ntype Parsed = { ok: true; cmd: ControlCommand } | { ok: false; code: RefusalCode; why: string };\nconst bad = (code: RefusalCode, why: string): { ok: false; code: RefusalCode; why: string } => ({\n ok: false,\n code,\n why,\n});\nconst isNum = (n: unknown): n is number => typeof n === \"number\" && Number.isFinite(n);\n\n/** The session id rule per harness (ADAPTERS.md): Claude Code ids are UUIDs. */\nexport function sessionIdOk(harness: string, id: string): boolean {\n if (!SESSION_ID_RE.test(id)) return false;\n if (harness === \"claude-code\") return UUID_RE.test(id);\n return true;\n}\n\n/** Split `<harness>:<id>`; null when either half breaks its rule. */\nexport function parseSessionRef(ref: unknown): { harness: string; id: string } | null {\n if (typeof ref !== \"string\") return null;\n const i = ref.indexOf(\":\");\n if (i <= 0) return null;\n const harness = ref.slice(0, i);\n const id = ref.slice(i + 1);\n return HARNESS_RE.test(harness) && sessionIdOk(harness, id) ? { harness, id } : null;\n}\n\n/** Read the command's fields from the exact string. Structure only; no clock, no keys. */\nexport function parseCommand(str: unknown): Parsed {\n if (typeof str !== \"string\" || !str || str.length > CMD_MAX)\n return bad(\"malformed\", \"the command is missing or too long\");\n let c: Record<string, unknown>;\n try {\n c = JSON.parse(str);\n } catch {\n return bad(\"malformed\", \"the command is not JSON\");\n }\n if (!c || typeof c !== \"object\" || Array.isArray(c)) return bad(\"malformed\", \"the command is not an object\");\n if (c.v !== 1 || c.t !== COMMAND_TYPE) return bad(\"not_a_command\", \"not a sessionpipe control command\");\n if (typeof c.machine !== \"string\" || !MACHINE_RE.test(c.machine)) return bad(\"malformed\", \"which machine?\");\n if (!CONTROL_KINDS.includes(c.kind as ControlKind))\n return bad(\"unknown_kind\", \"the command asks for something unknown\");\n const ref = parseSessionRef(c.session);\n if (!ref) return bad(\"bad_session\", \"which session?\");\n if (typeof c.nonce !== \"string\" || !NONCE_RE.test(c.nonce))\n return bad(\"bad_nonce\", \"the nonce is missing or malformed\");\n if (!isNum(c.iat) || !Number.isInteger(c.iat) || c.iat <= 0)\n return bad(\"malformed\", \"the command has no signing time\");\n const has = (k: string) => c[k] !== undefined;\n const text = () => typeof c.text === \"string\" && c.text.trim().length > 0 && c.text.length <= TEXT_MAX;\n switch (c.kind as ControlKind) {\n case \"prompt\":\n if (!text()) return bad(\"bad_fields\", `a prompt needs text, at most ${TEXT_MAX} characters`);\n if (has(\"for\") || has(\"decision\") || has(\"cwd\")) return bad(\"bad_fields\", \"a prompt carries only text\");\n break;\n case \"start\":\n if (!text()) return bad(\"bad_fields\", `a new session needs text, at most ${TEXT_MAX} characters`);\n if (typeof c.cwd !== \"string\" || !isAbsolute(c.cwd) || c.cwd.length > 1024)\n return bad(\"bad_fields\", \"a new session needs an absolute folder\");\n if (has(\"for\") || has(\"decision\")) return bad(\"bad_fields\", \"a start carries text, cwd and files\");\n if (has(\"files\")) {\n const why = filesProblem(c.files);\n if (why) return bad(\"bad_fields\", why);\n }\n break;\n case \"permission.answer\":\n if (typeof c.for !== \"string\" || !c.for || c.for.length > 128) return bad(\"bad_fields\", \"which attention?\");\n if (c.decision !== \"allow\" && c.decision !== \"deny\") return bad(\"bad_fields\", \"allow or deny?\");\n if (has(\"text\") || has(\"cwd\")) return bad(\"bad_fields\", \"a permission answer carries for, decision and note\");\n break;\n case \"cancel\":\n if (has(\"text\") || has(\"for\") || has(\"decision\") || has(\"cwd\"))\n return bad(\"bad_fields\", \"a cancel carries nothing\");\n break;\n case \"key.add\": {\n // A device the machine already trusts vouches for a new one (CONTROL.md \u00A72): the\n // new passkey's id, algorithm and public key are inside the signed bytes.\n if (c.session !== KEY_STORE_SESSION) return bad(\"bad_session\", `a key.add names ${KEY_STORE_SESSION}`);\n const k = c.key as { id?: unknown; alg?: unknown; spki?: unknown } | undefined;\n const b64 = (v: unknown, min: number, max: number) =>\n typeof v === \"string\" && v.length >= min && v.length <= max && /^[A-Za-z0-9_-]+$/.test(v);\n if (\n !k ||\n typeof k !== \"object\" ||\n !b64(k.id, 16, 1400) ||\n (k.alg !== -7 && k.alg !== -257) ||\n !b64(k.spki, 40, 2000)\n )\n return bad(\"bad_fields\", \"a key.add carries the key: id, alg (-7 or -257) and spki\");\n if (has(\"name\") && (typeof c.name !== \"string\" || !c.name.trim() || c.name.length > 80))\n return bad(\"bad_fields\", \"a device name is text, at most 80 characters\");\n if (has(\"text\") || has(\"for\") || has(\"decision\") || has(\"cwd\"))\n return bad(\"bad_fields\", \"a key.add carries the key and a name\");\n break;\n }\n }\n if (c.kind !== \"key.add\" && (has(\"key\") || has(\"name\"))) return bad(\"bad_fields\", \"only a key.add carries a key\");\n if (c.kind !== \"start\" && has(\"files\")) return bad(\"bad_fields\", \"only a start carries files\");\n if (has(\"note\") && (typeof c.note !== \"string\" || c.note.length > NOTE_MAX))\n return bad(\"bad_fields\", `a note is text, at most ${NOTE_MAX} characters`);\n return { ok: true, cmd: c as unknown as ControlCommand };\n}\n\n/** Why a start's `files` breaks the rules (CONTROL.md \u00A73.1), or null when it doesn't. */\nexport function filesProblem(files: unknown): string | null {\n if (!Array.isArray(files) || files.length < 1 || files.length > FILES_MAX)\n return `files is a list of 1 to ${FILES_MAX} files`;\n const seen = new Set<string>();\n let total = 0;\n for (const f of files as unknown[]) {\n if (!f || typeof f !== \"object\" || Array.isArray(f)) return \"each file is an object\";\n const { name, type, size, sha256: hash } = f as Record<string, unknown>;\n const why = fileNameProblem(name);\n if (why) return why;\n const key = (name as string).normalize(\"NFC\").toLowerCase();\n if (seen.has(key)) return \"two files have the same name\";\n seen.add(key);\n if (typeof type !== \"string\" || type.length > FILE_TYPE_MAX || !MEDIA_TYPE_RE.test(type))\n return \"a file's type isn't a media type\";\n if (!isNum(size) || !Number.isInteger(size) || size < 1 || size > FILE_SIZE_MAX)\n return `a file is 1 byte to ${FILE_SIZE_MAX / 1_048_576} MiB`;\n total += size;\n if (typeof hash !== \"string\" || !SHA256_RE.test(hash)) return \"a file's sha256 isn't 43 base64url characters\";\n }\n if (total > FILES_TOTAL_MAX) return `the files add up to more than ${FILES_TOTAL_MAX / 1_048_576} MiB`;\n return null;\n}\n\n/** A file name the machine can write inside the session's folder and nowhere else. */\nfunction fileNameProblem(name: unknown): string | null {\n if (typeof name !== \"string\") return \"a file has no name\";\n const n = name.normalize(\"NFC\");\n if (n.length < 1 || n.length > FILE_NAME_MAX) return `a file name is 1 to ${FILE_NAME_MAX} characters`;\n if (BAD_NAME_CHAR_RE.test(n)) return \"a file name has a slash, a backslash or a control character\";\n if (n.startsWith(\".\")) return \"a file name can't start with a dot\";\n return null;\n}\n\nfunction isAbsolute(p: string): boolean {\n return p.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(p);\n}\n\n/** The grant's fields, read from its exact string. */\nexport function parseGrant(str: unknown, rpId: string): { ok: true; grant: Grant } | { ok: false; why: string } {\n if (typeof str !== \"string\" || !str || str.length > GRANT_STR_MAX)\n return { ok: false, why: \"the grant is missing or too long\" };\n let g: Record<string, unknown>;\n try {\n g = JSON.parse(str);\n } catch {\n return { ok: false, why: \"the grant is not JSON\" };\n }\n if (!g || typeof g !== \"object\" || Array.isArray(g)) return { ok: false, why: \"the grant is not an object\" };\n if (g.v !== 1 || g.t !== GRANT_TYPE) return { ok: false, why: \"not a sessionpipe grant\" };\n if (g.rp !== rpId) return { ok: false, why: `the grant is for another site, not ${rpId}` };\n if (typeof g.pub !== \"string\" || !fromB64url(g.pub)?.length || !isNum(g.iat) || !isNum(g.exp))\n return { ok: false, why: \"the grant is missing parts\" };\n if (g.exp <= g.iat) return { ok: false, why: \"the grant ends before it starts\" };\n if (g.exp - g.iat > GRANT_MAX_MS + SKEW_MS) return { ok: false, why: \"the grant lasts longer than a day\" };\n return { ok: true, grant: g as unknown as Grant };\n}\n\nasync function verifyCsig(cmd: string, csig: unknown, pub: string): Promise<boolean> {\n const sig = fromB64url(csig);\n const spki = fromB64url(pub);\n if (sig?.length !== 64 || !spki) return false;\n try {\n const key = await crypto.subtle.importKey(\"spki\", u8(spki), { name: \"ECDSA\", namedCurve: \"P-256\" }, false, [\n \"verify\",\n ]);\n return await crypto.subtle.verify({ name: \"ECDSA\", hash: \"SHA-256\" }, key, u8(sig), u8(enc.encode(cmd)));\n } catch {\n return false;\n }\n}\n\n/**\n * Is this a command this machine may run? The checks, in the spec's order\n * (CONTROL.md \u00A75): the exact bytes parse; the command is for this machine; it is\n * signed \u2014 a grant from a trusted key plus the day key's signature, or a confirm\n * over sha256(cmd); it was signed within the age window; its nonce is new.\n * The folder and open-attention checks that follow are the daemon's (they read\n * the machine, not the command).\n */\nexport async function verifyCommand(s: SignedCommand | null | undefined, o: VerifyOptions): Promise<Verdict> {\n if (!s || typeof s !== \"object\") return bad(\"malformed\", \"nothing to verify\");\n const p = parseCommand(s.cmd);\n if (!p.ok) return p;\n const c = p.cmd;\n if (c.machine !== o.machine) return bad(\"wrong_machine\", \"the command is for another machine\");\n\n let via: \"grant\" | \"confirm\" | null = null;\n let keyId = \"\";\n let refusal: { code: RefusalCode; why: string } | null = null;\n if (s.grant && s.csig) {\n const r = await checkGrantPath(s, c, o);\n if (r.ok) {\n via = \"grant\";\n keyId = r.key;\n } else refusal = r;\n }\n if (!via && s.confirm) {\n const key = o.trusted.find((k) => k && k.id === s.confirm?.cred);\n if (!key) refusal = { code: \"untrusted_key\", why: \"confirmed with a key this machine doesn't trust\" };\n else {\n const a = await verifyAssertion(await sha256(s.cmd), s.confirm, key, o.rpId);\n if (a.ok) {\n via = \"confirm\";\n keyId = key.id;\n } else refusal = { code: \"bad_assertion\", why: a.why };\n }\n }\n if (!via) {\n if (refusal) return bad(refusal.code, refusal.why);\n return bad(\"unsigned\", \"the command isn't signed\");\n }\n if (c.iat > o.now + SKEW_MS) return bad(\"future\", \"the command is dated in the future (is this clock right?)\");\n if (o.now - c.iat > (o.maxAgeMs ?? MACHINE_MAX_AGE_MS)) return bad(\"too_old\", \"the command was signed too long ago\");\n if (o.seenNonce) {\n let seen: boolean;\n try {\n seen = await o.seenNonce(c.nonce);\n } catch {\n return bad(\"nonce_store\", \"the nonce couldn't be recorded, so the command didn't run\");\n }\n if (seen) return bad(\"replay\", \"this command was already used once\");\n }\n return { ok: true, cmd: c, via, key: keyId };\n}\n\nasync function checkGrantPath(\n s: SignedCommand,\n c: ControlCommand,\n o: VerifyOptions,\n): Promise<{ ok: true; key: string } | { ok: false; code: RefusalCode; why: string }> {\n const bundle = s.grant as GrantBundle;\n const g = parseGrant(bundle.str, o.rpId);\n if (!g.ok) return bad(\"bad_grant\", g.why);\n const key = o.trusted.find((k) => k && k.id === bundle.cred);\n if (!key) return bad(\"untrusted_key\", \"the grant was signed with a key this machine doesn't trust\");\n const a = await verifyAssertion(await sha256(bundle.str), bundle, key, o.rpId);\n if (!a.ok) return bad(\"bad_assertion\", a.why);\n if (!(await verifyCsig(s.cmd, s.csig, g.grant.pub)))\n return bad(\"bad_csig\", \"the command's signature doesn't verify \u2014 it was changed after it was signed\");\n if (c.iat < g.grant.iat - SKEW_MS || c.iat > g.grant.exp)\n return bad(\"outside_grant\", \"the command was signed outside its grant's window\");\n return { ok: true, key: key.id };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// `sessionpipe control pair | mode | folders | keys | off | run | status` and `sessionpipe wait`.\nimport { existsSync, realpathSync, statSync, unwatchFile, watchFile } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n antigravityControl,\n claudeControl,\n claudeDirs,\n codexControl,\n drivableHarnesses,\n machineName,\n Outbox,\n readConfig,\n stateDir,\n type Tier,\n writeConfig,\n} from \"@sessionpipe/core\";\n\nconst { claudeLogin, detectCaps, findClaude, runClaude } = claudeControl;\n\nimport { isBroad } from \"../connect.js\";\nimport { drain, VERSION } from \"../run.js\";\nimport { rerunGlobally, stableNode, viaNpx } from \"../runtime.js\";\nimport { controlAccount, secretGet, sinkWithSecrets } from \"../secrets.js\";\nimport { installedVersion, installVersion, latestVersion } from \"../update.js\";\nimport { AutoUpdater, autoUpdateOff, restartVia, supervise, UPDATE_EXIT, updateFile } from \"./autoupdate.js\";\nimport { ControlDaemon, DaemonRunning } from \"./daemon.js\";\nimport { ask, socketPath } from \"./local.js\";\nimport { installService, off, pair, removeKey, uninstallService } from \"./pair.js\";\nimport { loadSdk } from \"./sdk.js\";\nimport { controlFile, controlState, readControl, writeControl } from \"./store.js\";\nimport { waitForMessage, waitSession } from \"./wait.js\";\n\nexport const CONTROL_HELP = ` sessionpipe control pair <receiver> [--folder DIR]\u2026 [--mode safe|auto] [--tier 0-3] [--token T] [--name N] [--no-service]\n sessionpipe control mode auto|safe (how sessions run when you message them)\n sessionpipe control folders [add|remove DIR\u2026] (where sessions you message may run)\n sessionpipe control status | keys [remove <id>] | off [<receiver>] | run\n sessionpipe wait [--session <harness>:<id>] (a session runs this in the background)`;\n\nconst MODE_TEXT = ` auto Claude Code's auto mode: the session reads, edits and runs commands, and Claude Code's\n own safety check stops what looks dangerous. Pick this to get work done from your phone.\n (Codex runs with --approve-for-me, Antigravity with --mode accept-edits.)\n safe Only what each folder's Claude Code settings already allow: with no allow rules, a\n session can't even read a file. Pick this if this machine holds things no agent\n should touch unattended. (Codex runs in its workspace-write sandbox and never\n escalates; Antigravity is denied every tool call that would need approval.)`;\n\n/** Ask the person at this machine, once: auto or safe. Not a terminal (an agent ran the\n * pair command): safe, and say how to change it. */\nasync function askMode(out: (s?: string) => void): Promise<\"safe\" | \"auto\"> {\n if (!process.stdin.isTTY) {\n out(\" Mode: safe for now. Run `sessionpipe control mode auto` to let sessions you message work unattended.\");\n return \"safe\";\n }\n out(\"\");\n out(\" When you message a session on this machine from your phone, how may it run?\");\n out(MODE_TEXT);\n const { createInterface } = await import(\"node:readline/promises\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n for (;;) {\n const a = (await rl.question(\" auto or safe? [auto] \")).trim().toLowerCase();\n if (a === \"\" || a === \"a\" || a === \"auto\") return \"auto\";\n if (a === \"s\" || a === \"safe\") return \"safe\";\n }\n } finally {\n rl.close();\n }\n}\n\n/** `control folders add|remove`: the new list, and a line per folder saying what became\n * of it. A folder to add must exist and be a project, never the home folder or above\n * it (pair's rule); folders are compared as real paths, as the daemon compares them. */\nexport function changeFolders(\n folders: string[],\n op: \"add\" | \"remove\",\n dirs: string[],\n home = os.homedir(),\n): { folders: string[]; said: string[] } {\n const real = (d: string) => {\n try {\n return realpathSync.native(d);\n } catch {\n return path.resolve(d);\n }\n };\n const next = [...folders];\n const said: string[] = [];\n for (const d of dirs) {\n const abs = path.resolve(d);\n const at = next.findIndex((f) => real(f) === real(abs));\n if (op === \"remove\") {\n if (at < 0) said.push(` \u00B7 ${abs} wasn't allowed`);\n else said.push(` \u2713 No longer allowed: ${next.splice(at, 1)[0]}`);\n continue;\n }\n let dir = false;\n try {\n dir = statSync(abs).isDirectory();\n } catch {}\n if (!dir) said.push(` \u2717 ${abs} isn't a folder on this machine`);\n else if (isBroad(abs, home))\n said.push(\n ` \u2717 Not allowing all of ${abs}: name a project folder inside it, so a message can't run anywhere you own`,\n );\n else if (at >= 0) said.push(` \u00B7 ${abs} is already allowed`);\n else {\n next.push(abs);\n said.push(` \u2713 Allowed ${abs}`);\n }\n }\n return { folders: next, said };\n}\n\nexport async function controlMain(argv: string[], out: (s?: string) => void, distDir: string): Promise<void> {\n const flag = (n: string) => {\n const i = argv.indexOf(n);\n return i >= 0 ? argv[i + 1] : undefined;\n };\n const flags = (n: string) => argv.flatMap((a, i) => (a === n && argv[i + 1] ? [argv[i + 1] as string] : []));\n const sub = argv[1];\n switch (sub) {\n case \"pair\": {\n // `spacesheep.dev` is enough: a bare host means https.\n const raw = argv[2];\n if (!raw || raw.startsWith(\"-\")) return out(`usage:\\n${CONTROL_HELP}`);\n if (viaNpx(distDir)) return rerunGlobally(argv, out);\n const url = (/^https?:\\/\\//.test(raw) ? raw : `https://${raw}`).replace(/\\/$/, \"\");\n const cfg = readConfig();\n const sink = cfg.sinks.find((s) => s.url.replace(/\\/$/, \"\") === url);\n // No token is fine where the receiver offers open pairing: the person approves the\n // link signed in, and that is the whole setup.\n const token = flag(\"--token\") ?? (sink ? sinkWithSecrets(sink)?.token : undefined) ?? null;\n if (token !== null && !/^[\\x21-\\x7e]+$/.test(token))\n return out(\n \" That token has a character a key never has (a placeholder like ss_\u2026 pasted as is?). Leave --token out to pair with a link instead.\",\n );\n const folders = flags(\"--folder\");\n const existing = readControl();\n // The folder this ran in \u2014 unless that is the home folder or above it, which\n // would let a message start a session anywhere you own.\n if (!folders.length && !existing?.folders.length) {\n if (!isBroad(process.cwd(), os.homedir())) folders.push(process.cwd());\n else\n out(\n ` ! Not allowing all of ${process.cwd()}: sessions you message may run only in folders you name. Pass --folder <project>, or run this from inside one.`,\n );\n }\n // How sessions run when a message arrives is the person's call, asked once here at\n // the machine \u2014 never a default they find out about when a session can't read a file.\n const mode: \"safe\" | \"auto\" =\n flag(\"--mode\") === \"auto\" || flag(\"--mode\") === \"safe\"\n ? (flag(\"--mode\") as \"safe\" | \"auto\")\n : existing?.mode && existing.receivers.length\n ? existing.mode\n : await askMode(out);\n const tier = argv.includes(\"--tier\") ? (Math.max(0, Math.min(3, Number(flag(\"--tier\")) || 0)) as Tier) : 0;\n await pair({\n url,\n token,\n // The key the receiver handed over at pairing becomes this machine's sink for it,\n // at --tier (0 \u2014 session state only \u2014 unless given), unless one is configured.\n addSink: (t) => {\n const r = adoptSinkToken(url, t, tier);\n if (r === \"kept\") return;\n out(\n r === \"filled\"\n ? ` \u2713 Sink ${new URL(url).host} now carries the key the receiver handed over.`\n : tier >= 2\n ? ` \u2713 Sink ${new URL(url).host} added at tier ${tier}.`\n : ` \u2713 Sink ${new URL(url).host} added (tier ${tier}: ${tier ? \"tool activity\" : \"session state\"}, no conversation text). \\`sessionpipe sink add ${url} --tier 2\\` sends transcripts too.`,\n );\n },\n folders,\n mode,\n name: flag(\"--name\") ?? existing?.name ?? machineName(cfg, os.hostname()),\n out,\n });\n const c = readControl()!;\n out(` Folders sessions may run in: ${c.folders.join(\", \")}`);\n out(\n ` Mode: ${c.mode} (${c.mode === \"safe\" ? \"nothing that needs approval runs unattended\" : \"Claude Code's auto mode\"})`,\n );\n let cli = path.join(distDir, \"cli.js\");\n try {\n cli = realpathSync(cli);\n } catch {}\n if (argv.includes(\"--no-service\"))\n out(\" Daemon: not installed as a service (--no-service); run `sessionpipe control run` yourself\");\n else out(` Daemon: ${installService({ node: stableNode(process.execPath), cli })}`);\n return;\n }\n case \"mode\": {\n const want = argv[2];\n if (want !== \"auto\" && want !== \"safe\") {\n const c = readControl();\n return out(` mode: ${c?.mode ?? \"not set up\"}\\n usage: sessionpipe control mode auto|safe\\n${MODE_TEXT}`);\n }\n const c = readControl();\n if (!c) return out(\" control isn't set up on this machine: run `sessionpipe control pair <receiver>` first\");\n c.mode = want;\n writeControl(c);\n // The running daemon reads control.json again within seconds; the next run uses it.\n return out(\n ` \u2713 Sessions you message now run in ${want} mode${want === \"auto\" ? \" (Claude Code's auto mode decides what's safe)\" : \" (only what each folder's settings already allow)\"}.`,\n );\n }\n case \"folders\": {\n // The folders are the machine's own list, so they change here, at its keyboard, as\n // at pairing: no new pairing and no passkey. A message to a session in any other\n // folder is refused (\"that session's folder isn't one this machine allows\").\n const op = argv[2];\n const usage = \" usage: sessionpipe control folders [add|remove <folder>\u2026]\";\n if (op !== undefined && op !== \"add\" && op !== \"remove\") return out(usage);\n const c = readControl();\n if (!c) return out(\" control isn't set up on this machine: run `sessionpipe control pair <receiver>` first\");\n if (op) {\n const dirs = argv.slice(3);\n if (!dirs.length) return out(usage);\n const r = changeFolders(c.folders, op, dirs);\n for (const l of r.said) out(l);\n if (r.folders.join(\"\\n\") !== c.folders.join(\"\\n\")) {\n c.folders = r.folders;\n writeControl(c);\n // The running daemon reads control.json again within seconds and tells the\n // receiver the new list in a hello then.\n out(\" The control daemon uses the new list within seconds.\");\n }\n }\n return out(\n c.folders.length\n ? ` Sessions you message may run in:\\n${c.folders.map((f) => ` ${f}`).join(\"\\n\")}`\n : \" No folder is allowed: a message to a session here is refused until you add one.\",\n );\n }\n case \"keys\": {\n const c = readControl();\n if (argv[2] === \"remove\" && argv[3]) {\n const n = removeKey(argv[3]);\n return out(n ? ` removed ${n} key(s)` : \" no such key\");\n }\n if (!c?.receivers.length)\n return out(\" control isn't paired on this machine (`sessionpipe control pair <receiver>`)\");\n for (const r of c.receivers) {\n out(` ${r.url} \u00B7 machine ${r.machine}`);\n for (const k of r.keys)\n out(` ${k.id.slice(0, 16)}\u2026 ${k.alg === -7 ? \"ES256\" : \"RS256\"} added ${k.added_at.slice(0, 10)}`);\n }\n return;\n }\n case \"off\": {\n const c = await off({ out, ...(argv[2] ? { url: argv[2] } : {}) });\n if (c && !c.receivers.length) uninstallService();\n return;\n }\n case \"status\": {\n const r = await ask(socketPath(stateDir()), { op: \"status\" }, 2000);\n if (r?.op !== \"status\") return out(\" the control daemon isn't running\");\n return out(JSON.stringify(r.status, null, 2));\n }\n case \"run\":\n return runDaemon(out, distDir);\n default:\n return out(CONTROL_HELP);\n }\n}\n\n/** The harnesses set up on this machine, whose hooks an update re-arms. */\nexport function enabledHarnesses(harnesses: Record<string, { enabled?: boolean }>): string[] {\n return Object.entries(harnesses)\n .filter(([, h]) => h?.enabled !== false)\n .map(([n]) => n)\n .filter((n) => /^[a-z][a-z0-9-]{0,40}$/.test(n));\n}\n\nasync function runDaemon(out: (s?: string) => void, distDir: string): Promise<void> {\n const cfg = readControl();\n if (!cfg?.receivers.length) {\n out(\"control isn't paired on this machine; nothing to do (`sessionpipe control pair <receiver>`)\");\n return;\n }\n const log = (s: string) => out(`${new Date().toISOString()} ${s}`);\n let claude: { bin: string; caps: ReturnType<typeof detectCaps>; sig: string } | null = null;\n const claudeNow = () => {\n const bin = findClaude();\n if (!bin) return null;\n const sig = `${bin}:${existsSync(bin) ? realpathSync(bin) : \"\"}`;\n if (claude?.sig !== sig) claude = { bin, caps: detectCaps(bin), sig };\n return claude;\n };\n const sdk = await loadSdk({ claudeBin: findClaude(), env: process.env, log });\n let updater: AutoUpdater | null = null;\n const d = new ControlDaemon(cfg, controlState(), socketPath(stateDir()), {\n now: Date.now,\n fetch,\n log,\n claudeDirs: () => claudeDirs(),\n claude: claudeNow,\n codex: () => codexControl.findCodex(),\n agy: () => antigravityControl.findAgy(),\n codexLogin: (bin) => codexControl.codexLogin(bin),\n harnesses: () => drivableHarnesses(),\n run: runClaude,\n sdk,\n login: async (configDir) => {\n const c = claudeNow();\n return c ? claudeLogin(c.bin, configDir) : { loggedIn: null };\n },\n token: (r) => (r.token_in ? secretGet(r.token_in, controlAccount(r.machine)) : null),\n onRestart: () => updater?.restartWhenIdle() ?? false,\n updateStatus: () => (updater ? updater.record() : null),\n // Two daemons started at once and the other one holds the socket: leave it to it.\n onLostSocket: () => process.exit(0),\n });\n try {\n await d.start();\n } catch (e) {\n if (!(e instanceof DaemonRunning)) throw e;\n // Exit 0: no service manager restarts a daemon that stepped aside on purpose.\n log(`${e.message}; this one exits`);\n process.exit(0);\n }\n // Retry pending events even when a session has no more hooks. This also drains\n // what workers with a locked keychain left. The shared drain honours each sink's\n // wait and the machine-wide delivery lock, wherever its token lives.\n const drainTimer = setInterval(() => {\n const sinks = readConfig().sinks.filter((s) => !s.paused);\n if (sinks.length) void drain(stateDir(), sinks, new Outbox(stateDir())).catch(() => {});\n }, 60_000);\n drainTimer.unref();\n watchFile(controlFile(), { interval: 5000 }, () => {\n const next = readControl();\n if (next) d.reload(next);\n });\n let stopping = false;\n const bye = async () => {\n if (stopping) return;\n stopping = true;\n updater?.stop();\n await d.stop();\n process.exit(0);\n };\n const signals = [\"SIGTERM\", \"SIGINT\"] as const;\n for (const sig of signals) process.on(sig, bye);\n\n // Restart onto the code now on disk. The daemon is stopped first (its socket closed,\n // its long-polls ended), so two never poll at once.\n const restart = async (_from: string, to: string): Promise<void> => {\n stopping = true;\n updater?.stop();\n clearInterval(drainTimer);\n unwatchFile(controlFile());\n for (const sig of signals) process.off(sig, bye);\n await d.stop();\n const via = restartVia({ env: process.env, platform: process.platform, pid: process.pid, ppid: process.ppid });\n if (via) {\n log(`exiting ${UPDATE_EXIT} so ${via === \"supervisor\" ? \"the supervising sessionpipe\" : via} starts ${to}`);\n process.exit(UPDATE_EXIT);\n }\n // Nobody restarts this process: it stays, as the new daemon's parent.\n let cli = path.join(distDir, \"cli.js\");\n try {\n cli = realpathSync(cli);\n } catch {}\n log(`no service manager restarts this daemon: pid ${process.pid} now runs ${to} as its child`);\n const sup = supervise({ node: process.execPath, args: [cli, \"control\", \"run\"], env: process.env, log });\n for (const sig of [...signals, \"SIGHUP\"] as const) process.on(sig, () => sup.stop(sig));\n };\n updater = new AutoUpdater({\n now: Date.now,\n log,\n version: VERSION,\n file: updateFile(),\n off: () => autoUpdateOff({ env: process.env, config: readConfig(), distDir }),\n latest: () => latestVersion(fetch),\n installed: () => installedVersion({ node: process.execPath, distDir }),\n install: (v) =>\n installVersion(v, { node: process.execPath, distDir, harnesses: enabledHarnesses(readConfig().harnesses) }),\n daemon: d,\n restart,\n });\n updater.start();\n}\n\nexport async function waitMain(argv: string[], out: (s?: string) => void): Promise<void> {\n const i = argv.indexOf(\"--session\");\n const session = waitSession(i >= 0 ? argv[i + 1] : undefined);\n if (!session) {\n out(\"sessionpipe wait: which session? Pass --session <harness>:<id> (Claude Code sets CLAUDE_CODE_SESSION_ID).\");\n process.exitCode = 2;\n return;\n }\n out(await waitForMessage(session));\n}\n\n/** Give a sink the key a receiver handed over at pairing. A sink for the receiver that\n * has a key keeps it (\"kept\"); one without a key gets this one (\"filled\"); otherwise a\n * new sink at `tier` (\"added\"). */\nexport function adoptSinkToken(url: string, token: string, tier: Tier, file?: string): \"kept\" | \"filled\" | \"added\" {\n const now = file ? readConfig(file) : readConfig();\n const same = now.sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n if (same && (same.token || same.token_in)) return \"kept\";\n if (same) same.token = token;\n else now.sinks.push({ name: new URL(url).host, url, tier, pii: false, token });\n if (file) writeConfig(now, file);\n else writeConfig(now);\n return same ? \"filled\" : \"added\";\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The control daemon (spec/CONTROL.md): one process per computer. It holds one\n// long-poll per paired receiver, verifies every command itself against the keys\n// enrolled at this terminal, and delivers each one the cheapest way the session\n// allows \u2014 to a parked waiter, at the session's next Stop, to a session it holds\n// through the Agent SDK, or by a headless resume or fork \u2014 then acks how. Claude Code,\n// Codex (`codex exec`) and Antigravity (`agy`) sessions can be resumed and started\n// headlessly; the Agent SDK, waiters, Stop blocks and forks are Claude Code's.\n//\n// A receiver can queue a message; it can never make this process run one.\nimport { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, statSync, unlinkSync } from \"node:fs\";\nimport net from \"node:net\";\nimport path from \"node:path\";\nimport {\n antigravityControl,\n claudeAccounts,\n claudeControl,\n codexControl,\n deniedNote,\n type HarnessAccount,\n JOB_TIMEOUT_MS,\n jobEnv,\n type Login,\n type Reading,\n type RunOptions,\n type RunResult,\n redactSecrets,\n safeId,\n shortId,\n} from \"@sessionpipe/core\";\nimport { type ControlCommand, parseSessionRef, verifyCommand } from \"@sessionpipe/core/control\";\nimport { type Alias, type Aliases, aliasFile, readAliases, receiverIdOf, writeAliases } from \"./aliases.js\";\nimport { fetchFiles, withFiles, writeFiles } from \"./files.js\";\nimport { ask, type LocalReply, type LocalRequest } from \"./local.js\";\nimport { awaitAnswer, transcriptEnd } from \"./reply.js\";\nimport { type DeliveryMode, frame, frameStart, IN_PLACE_ANSWER, kindPath, routePrompt } from \"./route.js\";\nimport {\n type Ack,\n AckOutbox,\n type ControlConfig,\n type DaemonState,\n NonceStore,\n type PairedReceiver,\n readState,\n writeControl,\n writeState,\n} from \"./store.js\";\nimport { AnswerStream } from \"./stream.js\";\n\nconst {\n claudeEnv,\n findTranscript,\n isUuid,\n liveProcess,\n loginHint,\n modeFlags,\n parseResult,\n recentlyWritten,\n sessionFolder,\n} = claudeControl;\ntype Caps = claudeControl.Caps;\ntype Transcript = claudeControl.Transcript;\n\n/** Where a session lives: its folder, and how the harness names it. */\ninterface Placed {\n folder: string;\n /** Claude Code's transcript. */\n transcript: Transcript | null;\n /** Codex / Antigravity: the harness's own id to resume (an alias's, else the command's). */\n target?: string;\n /** Codex: the session's rollout file, whose writes say whether it is in use. */\n file?: string | null;\n}\n\n/** A harness the daemon runs headlessly besides Claude Code (codex-control.ts,\n * antigravity-control.ts). */\ninterface Driver {\n label: string;\n cmd: string;\n bin: () => string | null;\n args: (o: { mode: \"safe\" | \"auto\"; prompt: string; cwd: string; resume?: string }) => string[];\n reading: () => Reading & { warnings?: string[] };\n login?: (bin: string) => Promise<Login>;\n loginHint?: string;\n}\n\n/** A start, read from the command before it is verified: only ever used to order a\n * prompt behind it, never to run anything. */\nfunction startNamed(cmd: unknown): string | null {\n if (typeof cmd !== \"string\" || cmd.length > 64 * 1024 || !cmd.includes('\"start\"')) return null;\n try {\n const c = JSON.parse(cmd) as { kind?: unknown; session?: unknown };\n return c?.kind === \"start\" && typeof c.session === \"string\" ? c.session : null;\n } catch {\n return null;\n }\n}\n\ndeclare const __SESSIONPIPE_VERSION__: string;\nconst VERSION = typeof __SESSIONPIPE_VERSION__ === \"string\" ? __SESSIONPIPE_VERSION__ : \"0.0.0\";\n\nconst MAX_REPLY = 20_000;\nconst HELLO_EVERY_MS = 10 * 60_000;\n/** A message waiting for a Stop that never comes goes another way after this. */\nconst TURN_FALLBACK_MS = 30 * 60_000;\n/** How long the daemon follows a session's turn for the answer to an in-place\n * message before acking it delivered without one. */\nconst ANSWER_WAIT_MS = 30 * 60_000;\n/** How long a Stop hook may take to be answered. */\nconst RECENT_ACKS_MS = 25 * 3600_000;\n/** Events that prove a pending permission prompt was resolved some other way. */\nconst CLOSES_ATTENTION = new Set([\n \"PostToolUse\",\n \"PostToolUseFailure\",\n \"Stop\",\n \"StopFailure\",\n \"UserPromptSubmit\",\n \"SessionEnd\",\n]);\n\n/** The message as the receiver carried it (control.json). */\nexport interface Carried {\n id: string;\n cmd: string;\n csig?: string | null;\n grant?: { str: string; cred: string; ad: string; cd: string; sig: string } | null;\n confirm?: { cred: string; ad: string; cd: string; sig: string } | null;\n at: string;\n expires_at: string;\n}\n\n/** A session the Agent SDK holds for the daemon (sdk.ts; a fake in tests). */\nexport interface SdkSession {\n /** Deliver one message; resolves with the agent's reply when the turn ends. */\n send(text: string): Promise<{ reply: string; error?: string }>;\n interrupt(): Promise<void>;\n close(): void;\n readonly busy: boolean;\n readonly lastUsed: number;\n}\nexport interface SdkHost {\n start(o: {\n session: string;\n cwd: string;\n mode: \"safe\" | \"auto\";\n configDir?: string;\n allowedTools?: string[];\n }): SdkSession;\n}\n\nexport interface DaemonDeps {\n now: () => number;\n fetch: typeof fetch;\n log: (line: string) => void;\n claudeDirs: () => string[];\n claude: () => { bin: string; caps: Caps } | null;\n /** Codex CLI's `codex` and Antigravity's `agy` on this machine (null: not installed).\n * Absent: this daemon doesn't drive that harness. */\n codex?: () => string | null;\n agy?: () => string | null;\n /** Is Codex signed in as this process sees it? Asked before a run. */\n codexLogin?: (bin: string) => Promise<Login>;\n /** The harnesses every hello advertises (core's drivableHarnesses); by default, the\n * ones the finders above find. */\n harnesses?: () => string[];\n /** The harness accounts every hello names; by default, those signed in across\n * `claudeDirs`, read again for each hello. */\n accounts?: () => HarnessAccount[];\n run: (bin: string, args: string[], o: RunOptions) => Promise<RunResult>;\n sdk?: SdkHost | null;\n /** How long to follow a live session's turn for an in-place answer (tests shorten it). */\n answerWaitMs?: number;\n /** Close an SDK session idle this long (a held session costs ~300 MB). */\n sdkIdleMs?: number;\n /** How long one of a start's files may take to download (tests shorten it). */\n fileTimeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n /** Is Claude Code signed in for this account, as this process sees it? Asked before\n * a headless run, so a login the daemon can't read (a macOS keychain with nobody at\n * the screen) fails with what to do, not with Claude Code's \"please run /login\". */\n login?: (configDir?: string) => Promise<Login>;\n /** Read a receiver's machine token again: it may live in a keychain that was\n * locked when the daemon started and has unlocked since. */\n token?: (r: PairedReceiver) => string | null;\n platform?: NodeJS.Platform;\n /** `sessionpipe update` installed a new copy: restart onto it once idle. True when\n * accepted (autoupdate.ts). */\n onRestart?: () => boolean;\n /** The updater's view, for `control status`. */\n updateStatus?: () => unknown;\n /** Another daemon took the socket path: this one has stopped and should exit. */\n onLostSocket?: () => void;\n}\n\n/** Another daemon already answers on the socket: this one must not start. */\nexport class DaemonRunning extends Error {\n constructor(readonly other: { pid?: number; version?: string }) {\n super(\n `another control daemon already serves this machine (${other.pid ? `pid ${other.pid}, ` : \"\"}sessionpipe ${other.version ?? \"?\"})`,\n );\n }\n}\n\ninterface TurnPending {\n receiver: PairedReceiver;\n msgId: string;\n text: string;\n session: string;\n queuedAt: number;\n}\n\ninterface Live {\n midTurn: boolean;\n /** The Stop hook just delivered a block: the next Stop event continues the turn. */\n continued: boolean;\n waiter: net.Socket | null;\n turnQueue: TurnPending[];\n attentions: Map<string, net.Socket>;\n cwd?: string;\n transcript?: string;\n lastEvent: number;\n}\n\ninterface PollState {\n started: number;\n last: number | null;\n error: string | null;\n on: boolean;\n unauthorized: boolean;\n authBackoff: number;\n wake: (() => void) | null;\n}\n\nexport interface Status {\n version: string;\n pid: number;\n name: string;\n receivers: {\n url: string;\n machine: string;\n keys: number;\n polling: boolean;\n /** Last successful poll; failed responses must not conceal a control outage. */\n last_poll: number | null;\n /** Time since success, or since this loop started if it has never succeeded. */\n last_poll_age_ms: number;\n last_error: string | null;\n }[];\n waiting: string[];\n mid_turn: string[];\n attentions: { session: string; id: string }[];\n sdk: string[];\n nonces: number;\n acks_pending: number;\n delivered: Record<string, number>;\n /** Null when the daemon could restart now (nothing in hand); otherwise what it holds. */\n busy: string | null;\n update?: unknown;\n}\n\n/** The machine's own caps (CONTROL.md \u00A76 `start`): every command is the owner's,\n * signed, but a burst of them must not start a crowd of agents. A start beyond the\n * caps is refused `start_limit`; a headless run beyond `headless` waits its turn. */\n/** What a receiver may let its sessions use without asking (CONTROL.md \u00A76): its own MCP\n * servers, by name \u2014 never a built-in tool. The receiver is where the message came\n * from, so answering it there (publishing a page, replying) is the job; anything else\n * still needs the person's approval rule. */\nexport function sessionToolsFrom(v: unknown): string[] {\n if (!Array.isArray(v)) return [];\n return [\n ...new Set(v.filter((t): t is string => typeof t === \"string\" && /^mcp__[A-Za-z0-9_-]{1,64}$/.test(t))),\n ].slice(0, 8);\n}\n\nexport const LIMITS = { startConcurrent: 2, startPerHour: 10, headless: 3 } as const;\n\nexport class ControlDaemon {\n private server: net.Server | null = null;\n private readonly live = new Map<string, Live>();\n private readonly sdkSessions = new Map<string, SdkSession>();\n private readonly nonces: NonceStore;\n private readonly acks: AckOutbox;\n private readonly recentAcks = new Map<string, { ack: Ack; at: number }>();\n private readonly inflight = new Set<string>();\n private readonly queues = new Map<string, Promise<unknown>>();\n private readonly lastEnd = new Map<string, number>();\n private state: DaemonState;\n private running = false;\n private readonly polling = new Map<string, PollState>();\n private readonly delivered: Record<string, number> = {};\n private helloTimer: NodeJS.Timeout | null = null;\n private helloSoon: NodeJS.Timeout | null = null;\n private readonly aborts = new Set<AbortController>();\n /** Per receiver: the MCP servers its sessions may use unattended (its well-known). */\n private readonly sessionTools = new Map<string, string[]>();\n /** Sessions a run of the daemon's own is working on right now (a start, a resume):\n * a message for one waits for that run and resumes it \u2014 never a copy, which would\n * set two agents on one task (2026-10-02: a \"just merge when ready\" sent while the\n * start still ran forked a second agent that raced the first toward main). */\n private readonly ownRuns = new Map<string, number>();\n private startsRunning = 0;\n private startTimes: number[] = [];\n private procs = 0;\n private readonly procWaiters: (() => void)[] = [];\n /** configDir \u2192 the last login answer and when (a yes is kept 10 minutes, a no 30 s). */\n private readonly logins = new Map<string, { at: number; login: Login }>();\n /** Intake paused for an update: the long-polls end and wait for this. */\n private paused: { until: Promise<void>; go: () => void } | null = null;\n /** Poll answers whose messages are being read and handed out. */\n private receiving = 0;\n /** The socket file this daemon created (dev:ino): stop() removes only that one, and a\n * different file at the path means another daemon took over. */\n private sockId: string | null = null;\n private ownTimer: NodeJS.Timeout | null = null;\n /** Every open local connection: stop() ends them, or the server's close would wait\n * on a client that never says anything. */\n private readonly conns = new Set<net.Socket>();\n /** Codex and Antigravity sessions the daemon started, under the start's id (aliases.ts). */\n private aliases: Aliases;\n /** Starts in hand, by the session they name, from the moment they arrive: a prompt\n * for that session that came in the same poll waits for its start rather than\n * finding no session (2026-10-04: a start and a prompt queued back to back). */\n private readonly startsPending = new Map<string, Promise<void>>();\n\n constructor(\n private cfg: ControlConfig,\n private readonly dir: string,\n private readonly sock: string,\n private readonly deps: DaemonDeps,\n ) {\n this.nonces = new NonceStore(path.join(dir, \"nonces.jsonl\"), deps.now);\n this.acks = new AckOutbox(path.join(dir, \"acks.jsonl\"));\n this.state = readState(path.join(dir, \"state.json\"));\n this.aliases = readAliases(aliasFile(dir));\n }\n\n // --- lifecycle ------------------------------------------------------------------\n\n async start(): Promise<void> {\n this.running = true;\n mkdirSync(this.dir, { recursive: true, mode: 0o700 });\n await this.listen();\n for (const r of this.cfg.receivers) void this.pollLoop(r);\n this.helloTimer = setInterval(() => void this.helloAll(), HELLO_EVERY_MS);\n this.helloTimer.unref();\n void this.helloAll();\n void this.flushAcks();\n const idle = setInterval(() => this.closeIdleSdk(), 60_000);\n idle.unref();\n if (this.sockId) {\n this.ownTimer = setInterval(() => void this.checkSocket(), 10_000);\n this.ownTimer.unref();\n }\n this.deps.log(\n `control daemon ${VERSION} up \u00B7 pid ${process.pid} \u00B7 ${this.cfg.receivers.length} receiver(s) \u00B7 socket ${this.sock}`,\n );\n }\n\n /** `leaveSocket`: the socket path is another daemon's now. Closing a Unix-socket\n * server makes Node unlink its path whoever holds it, so this one's server is left\n * open for the process's exit to drop. */\n async stop(o: { leaveSocket?: boolean } = {}): Promise<void> {\n this.running = false;\n this.paused?.go();\n for (const a of this.aborts) a.abort();\n for (const st of this.polling.values()) st.wake?.();\n if (this.helloTimer) clearInterval(this.helloTimer);\n if (this.helloSoon) clearTimeout(this.helloSoon);\n if (this.ownTimer) clearInterval(this.ownTimer);\n for (const s of this.sdkSessions.values()) s.close();\n for (const l of this.live.values()) {\n l.waiter?.destroy();\n for (const a of l.attentions.values()) a.destroy();\n }\n for (const c of this.conns) c.destroy();\n if (o.leaveSocket) {\n this.sockId = null;\n return;\n }\n await new Promise<void>((r) => (this.server ? this.server.close(() => r()) : r()));\n this.server = null;\n // Only the socket file this daemon made: after a hand-over the path is someone else's.\n /* v8 ignore next -- Node unlinks a listening Unix socket's path in server.close(), so the file is gone by here; kept for a runtime that doesn't */\n if (process.platform !== \"win32\" && this.sockId && socketId(this.sock) === this.sockId)\n try {\n unlinkSync(this.sock);\n } catch {}\n this.sockId = null;\n }\n\n /** Null when nothing is in hand, so a restart would interrupt nothing; otherwise what\n * is. Parked waiters don't count: a waiter reconnects in silence (CONTROL.md \u00A78). A\n * session someone is working in mid-turn does (a restart forgets it is mid-turn, so a\n * message to it would fork rather than wait for its Stop), unless it has been silent\n * for ten minutes: a session killed mid-turn never sends its Stop. */\n busy(): string | null {\n if (this.inflight.size) return `${this.inflight.size} message(s) in hand`;\n if (this.procs || this.ownRuns.size) return \"a headless agent run\";\n if (this.startsRunning) return \"a session starting\";\n for (const s of this.sdkSessions.values()) if (s.busy) return \"an Agent SDK session mid-turn\";\n for (const l of this.live.values()) if (l.attentions.size) return \"a permission prompt waiting for an answer\";\n const now = this.deps.now();\n for (const l of this.live.values())\n if (l.midTurn && now - l.lastEvent < 10 * 60_000) return \"a session on this machine mid-turn\";\n if (this.receiving) return \"messages just received\";\n if (this.flushing) return \"acks being sent\";\n return null;\n }\n\n /** Stop taking messages: every long-poll ends now and waits for resumeIntake(). The\n * receiver keeps what arrives meanwhile; the local socket keeps answering. */\n pauseIntake(): void {\n if (this.paused) return;\n let go!: () => void;\n const until = new Promise<void>((r) => {\n go = r;\n });\n this.paused = { until, go };\n for (const a of this.aborts) a.abort();\n }\n\n resumeIntake(): void {\n const p = this.paused;\n this.paused = null;\n p?.go();\n }\n\n /** The socket path still holds this daemon's file. Gone: listen again. Replaced:\n * another daemon took over (two started at once), so this one steps aside. */\n private async checkSocket(): Promise<void> {\n if (!this.running || !this.sockId) return;\n const now = socketId(this.sock);\n if (now === this.sockId) return;\n if (now === null) {\n // Someone deleted the file. The old server keeps the connections it has (closing\n // it would wait on parked waiters, and unlink the path again); a new one takes it.\n this.deps.log(`the socket ${this.sock} vanished; listening again`);\n this.server?.unref();\n this.server = null;\n try {\n await this.listen();\n } catch (e) {\n this.deps.log(\n `couldn't listen again: ${String(/* v8 ignore next -- listen() throws Errors (net, DaemonRunning) */ (e as Error)?.message || e)}`,\n );\n }\n return;\n }\n this.deps.log(\"another control daemon took over the socket; this one stops\");\n await this.stop({ leaveSocket: true });\n this.deps.onLostSocket?.();\n }\n\n reload(cfg: ControlConfig): void {\n const known = new Set(this.cfg.receivers.map((r) => r.control + r.machine));\n const told = JSON.stringify([this.cfg.folders, this.cfg.mode, this.cfg.name]);\n this.cfg = cfg;\n for (const r of cfg.receivers) if (!known.has(r.control + r.machine)) void this.pollLoop(r);\n // `control folders`, `control mode` or a `--rename-machine` changed what a hello says:\n // say it now, so the receiver doesn't wait up to ten minutes for the next one.\n if (this.running && JSON.stringify([cfg.folders, cfg.mode, cfg.name]) !== told) void this.helloAll();\n }\n\n status(): Status {\n return {\n version: VERSION,\n pid: process.pid,\n name: this.cfg.name,\n receivers: this.cfg.receivers.map((r) => {\n const p = this.polling.get(r.control + r.machine);\n return {\n url: r.url,\n machine: r.machine,\n keys: r.keys.length,\n polling: !!p?.on,\n last_poll: p?.last ?? null,\n last_poll_age_ms: p ? Math.max(0, this.deps.now() - (p.last ?? p.started)) : 0,\n last_error: p?.error ?? null,\n };\n }),\n waiting: [...this.live].filter(([, l]) => l.waiter).map(([k]) => k),\n mid_turn: [...this.live].filter(([, l]) => l.midTurn).map(([k]) => k),\n attentions: [...this.live].flatMap(([k, l]) => [...l.attentions.keys()].map((id) => ({ session: k, id }))),\n sdk: [...this.sdkSessions.keys()],\n nonces: this.nonces.size,\n acks_pending: this.acks.all().length,\n delivered: { ...this.delivered },\n busy: this.busy(),\n ...(this.deps.updateStatus ? { update: this.deps.updateStatus() } : {}),\n };\n }\n\n // --- the local socket -----------------------------------------------------------\n\n /** One daemon per machine: a daemon that answers on the socket keeps it, and this\n * one doesn't start. A socket file nobody answers on is a dead daemon's; it goes. */\n private async listen(): Promise<void> {\n const other = await ask(this.sock, { op: \"status\" }, 1500);\n if (other?.op === \"status\") throw new DaemonRunning((other.status ?? {}) as { pid?: number; version?: string });\n if (process.platform !== \"win32\") {\n try {\n if (existsSync(this.sock)) unlinkSync(this.sock);\n } catch {}\n }\n this.server = net.createServer((s) => this.onConn(s));\n await new Promise<void>((resolve, reject) => {\n this.server!.once(\"error\", reject);\n this.server!.listen(this.sock, () => resolve());\n });\n if (process.platform !== \"win32\") {\n // The socket is this user's alone (CONTROL.md \u00A78: mode 0600), whatever the umask.\n chmodSync(this.sock, 0o600);\n this.sockId = socketId(this.sock);\n }\n }\n\n private onConn(s: net.Socket): void {\n let buf = \"\";\n let handled = false;\n this.conns.add(s);\n s.on(\"close\", () => this.conns.delete(s));\n s.on(\"error\", () => {});\n s.on(\"data\", (d) => {\n if (handled) return;\n buf += d.toString(\"utf8\");\n if (buf.length > 64 * 1024) return s.destroy();\n const i = buf.indexOf(\"\\n\");\n if (i < 0) return;\n handled = true;\n let req: LocalRequest;\n try {\n req = JSON.parse(buf.slice(0, i)) as LocalRequest;\n } catch {\n return s.destroy();\n }\n this.onRequest(req, s);\n });\n }\n\n private reply(s: net.Socket, r: LocalReply): void {\n try {\n s.end(`${JSON.stringify(r)}\\n`);\n } catch {}\n }\n\n private liveOf(session: string): Live {\n let l = this.live.get(session);\n if (!l) {\n l = {\n midTurn: false,\n continued: false,\n waiter: null,\n turnQueue: [],\n attentions: new Map(),\n lastEvent: this.deps.now(),\n };\n this.live.set(session, l);\n }\n return l;\n }\n\n private onRequest(req: LocalRequest, s: net.Socket): void {\n switch (req.op) {\n case \"status\":\n this.reply(s, { op: \"status\", status: this.status() });\n return;\n case \"wait\": {\n if (!parseSessionRef(req.session)) {\n this.reply(s, { op: \"none\" });\n return;\n }\n const l = this.liveOf(req.session);\n if (l.waiter && l.waiter !== s) this.reply(l.waiter, { op: \"replaced\" });\n l.waiter = s;\n s.on(\"close\", () => {\n if (l.waiter === s) {\n l.waiter = null;\n this.scheduleHello();\n }\n });\n this.scheduleHello();\n return;\n }\n case \"stop\": {\n const l = this.liveOf(req.session);\n l.lastEvent = this.deps.now();\n const p = this.takeTurn(l);\n if (!p) {\n this.reply(s, { op: \"none\" });\n return;\n }\n l.continued = true;\n const from = this.answerFrom(req.session);\n this.reply(s, { op: \"block\", reason: `${frame(p.text, p.receiver.url)}\\n\\n${IN_PLACE_ANSWER}`, id: p.msgId });\n this.followAnswer(p.receiver, p.msgId, \"turn\", req.session, from, p.queuedAt);\n return;\n }\n case \"permission\": {\n const l = this.liveOf(req.session);\n const prev = l.attentions.get(req.attention);\n if (prev && prev !== s) this.reply(prev, { op: \"none\" });\n l.attentions.set(req.attention, s);\n s.on(\"close\", () => {\n if (l.attentions.get(req.attention) === s) l.attentions.delete(req.attention);\n });\n return;\n }\n case \"event\":\n this.onEvent(req);\n this.reply(s, { op: \"ok\" });\n return;\n case \"restart\":\n this.reply(s, this.deps.onRestart?.() ? { op: \"ok\" } : { op: \"none\" });\n return;\n default:\n s.destroy();\n }\n }\n\n /** A queued turn message that hasn't expired. */\n private takeTurn(l: Live): TurnPending | null {\n while (l.turnQueue.length) {\n const p = l.turnQueue.shift()!;\n if (!this.inflight.has(p.msgId)) continue;\n return p;\n }\n return null;\n }\n\n private onEvent(e: Extract<LocalRequest, { op: \"event\" }>): void {\n // A worker that read the aliases a moment before a start recorded its session still\n // names the harness's own id; this daemon knows the start's.\n const l = this.liveOf(this.named(e.session));\n l.lastEvent = this.deps.now();\n if (e.cwd) l.cwd = e.cwd;\n if (e.transcript) l.transcript = e.transcript;\n if (CLOSES_ATTENTION.has(e.event) && l.attentions.size) {\n for (const s of l.attentions.values()) this.reply(s, { op: \"none\" });\n l.attentions.clear();\n }\n if (e.event === \"UserPromptSubmit\" || e.event === \"SessionStart\") {\n if (e.event === \"UserPromptSubmit\") l.midTurn = true;\n return;\n }\n if (e.event === \"Stop\" && l.continued) {\n l.continued = false;\n return;\n }\n if (e.event === \"Stop\" || e.event === \"StopFailure\" || e.event === \"SessionEnd\") {\n l.midTurn = false;\n l.continued = false;\n // A message queued for a Stop that came and went without taking it (it\n // arrived after the hook asked, or the turn failed) goes another way.\n const left = l.turnQueue.splice(0);\n for (const p of left) if (this.inflight.has(p.msgId)) void this.reroute(p);\n }\n }\n\n // --- receivers ------------------------------------------------------------------\n\n private async pollLoop(first: PairedReceiver): Promise<void> {\n const key = first.control + first.machine;\n const st: PollState = {\n started: this.deps.now(),\n last: null,\n error: null,\n on: true,\n unauthorized: false,\n authBackoff: 0,\n wake: null,\n };\n this.polling.set(key, st);\n // Unlike a bare sleep, this wait can end as soon as a hello proves the token\n // works, or the daemon stops. Keep exactly one poll loop per receiver.\n const retry = (ms: number) =>\n new Promise<void>((resolve) => {\n st.on = false;\n if (!this.running) {\n resolve();\n return;\n }\n const timer = setTimeout(() => st.wake?.(), ms);\n timer.unref();\n st.wake = () => {\n clearTimeout(timer);\n st.wake = null;\n resolve();\n };\n });\n let backoff = 0;\n let downSince = 0;\n // A deploy takes the receiver away for seconds, not minutes: retry soon, capped at\n // 15 s (one request per machine), with jitter so every machine a deploy dropped\n // doesn't come back in the same instant. The old 60 s / 5 min steps left a\n // machine blind for minutes after a 30-second outage.\n const steps = [1000, 2000, 5000, 10_000, 15_000];\n const pause = (n: number) => (steps[Math.min(n, steps.length - 1)] as number) * (0.75 + Math.random() * 0.5);\n for (;;) {\n // The current record every round: `control pair` may have added a key since.\n const r = this.cfg.receivers.find((x) => x.control + x.machine === key);\n if (!this.running || !r) break;\n if (this.paused) {\n st.on = false;\n await this.paused.until;\n continue;\n }\n if (!r.token) {\n // Its token lives in a keychain this process can't read yet (locked, or nobody\n // logged in): ask again every 30 s rather than poll with no bearer.\n const t = this.deps.token?.(r) ?? null;\n if (t) {\n r.token = t;\n this.deps.log(`${r.url}: machine token readable again`);\n } else {\n if (!st.error?.startsWith(\"can't read\"))\n this.deps.log(`${r.url}: can't read this machine's token from ${r.token_in ?? \"its store\"}; retrying`);\n st.error = `can't read this machine's token from ${r.token_in ?? \"its store\"} (locked?); retrying every 30 s`;\n await retry(30_000);\n continue;\n }\n }\n const ctl = new AbortController();\n st.on = true;\n this.aborts.add(ctl);\n // A poll held past wait + 10 s is a dead connection (a laptop that slept, a\n // network that changed): give up on it and ask again.\n const t = setTimeout(() => ctl.abort(), 35_000);\n try {\n const u = new URL(r.control);\n u.searchParams.set(\"machine\", r.machine);\n u.searchParams.set(\"wait\", \"25\");\n const asked = this.deps.now();\n const res = await this.deps.fetch(u, { headers: { authorization: `Bearer ${r.token}` }, signal: ctl.signal });\n // The request deadline applies to reading the response, never to a retry\n // delay (which can be much longer than a long-poll).\n if (res.status !== 200) clearTimeout(t);\n st.unauthorized = res.status === 401;\n if (downSince && (res.status === 200 || res.status === 204)) {\n // Timed to when this poll was sent: a long-poll that reconnected is then held\n // up to `wait` before it answers.\n this.deps.log(`${r.url}: back after ${Math.round((asked - downSince) / 1000)} s (${backoff} failed tries)`);\n downSince = 0;\n }\n if (res.status === 401) {\n st.error = \"the receiver no longer knows this machine (401); run `sessionpipe control pair` again\";\n this.deps.log(`${r.url}: ${st.error}`);\n downSince ||= this.deps.now();\n backoff++;\n const delay = Math.min(60_000 * 2 ** st.authBackoff, 30 * 60_000);\n st.authBackoff = Math.min(st.authBackoff + 1, 5);\n await retry(delay);\n continue;\n }\n if (res.status === 200) {\n let fresh = 0;\n this.receiving++;\n try {\n const body = (await res.json()) as { messages?: Carried[] };\n // Looked up again: a key may have been added while this poll was parked.\n const cur = this.cfg.receivers.find((x) => x.control + x.machine === key) ?? r;\n // Not awaited: a headless turn can run for half an hour, and the next\n // message (for another session, or a permission answer) must not wait\n // behind it. handle() orders what must be ordered (one session's prompts).\n for (const m of body.messages ?? []) {\n if (m && !this.inflight.has(m.id)) fresh++;\n void this.handle(cur, m).catch((e) =>\n this.deps.log(\n `handle ${String(m?.id).slice(-8)}: ${String(/* v8 ignore next -- handle() rejects with an Error (the ack file) */ (e as Error)?.message || e)}`,\n ),\n );\n }\n } finally {\n this.receiving--;\n }\n clearTimeout(t);\n st.last = this.deps.now();\n st.error = null;\n st.authBackoff = 0;\n backoff = 0;\n // Only messages already in hand (a receiver that ignores `taken`): don't\n // turn the long-poll into a spin.\n if (!fresh) await sleep(2000);\n } else if (res.status === 204) {\n st.last = this.deps.now();\n st.error = null;\n st.authBackoff = 0;\n backoff = 0;\n } else {\n st.error = `HTTP ${res.status}`;\n downSince ||= this.deps.now();\n let delay = pause(backoff++);\n if (res.status === 503) {\n const after = res.headers.get(\"retry-after\");\n const ms = after && /^\\d+$/.test(after) ? Number(after) * 1000 : Date.parse(after ?? \"\") - this.deps.now();\n if (Number.isFinite(ms)) delay = Math.max(delay, ms);\n }\n // Node treats an overflowing timeout as 1 ms; a long Retry-After must\n // not accidentally become a tight loop.\n await retry(Math.min(delay, 2_147_483_647));\n }\n } catch (e) {\n if (!this.running) break;\n // Paused for an update: the abort was ours, not the network's.\n if (this.paused) continue;\n st.error = String((e as Error)?.message || e).slice(0, 120);\n st.unauthorized = false;\n downSince ||= this.deps.now();\n clearTimeout(t);\n await retry(pause(backoff++));\n } finally {\n clearTimeout(t);\n this.aborts.delete(ctl);\n }\n }\n st.on = false;\n }\n\n private scheduleHello(): void {\n if (this.helloSoon) return;\n this.helloSoon = setTimeout(() => {\n this.helloSoon = null;\n void this.helloAll();\n }, 1500);\n this.helloSoon.unref();\n }\n\n /** Read each receiver's well-known for its session tools (at start, then with every hello). */\n private async refreshSessionTools(): Promise<void> {\n for (const r of this.cfg.receivers) {\n try {\n const res = await this.deps.fetch(`${r.url.replace(/\\/$/, \"\")}/.well-known/sessionpipe`, {\n signal: AbortSignal.timeout(8000),\n });\n if (!res.ok) continue;\n const wk = (await res.json()) as { control?: { session_tools?: unknown } };\n const tools = sessionToolsFrom(wk.control?.session_tools);\n const key = r.control + r.machine;\n if (JSON.stringify(tools) !== JSON.stringify(this.sessionTools.get(key) ?? []))\n this.deps.log(\n `${r.url}: sessions it messages may use ${tools.length ? tools.join(\", \") : \"nothing extra\"} without asking`,\n );\n this.sessionTools.set(key, tools);\n } catch {}\n }\n }\n\n private allowedFor(r: PairedReceiver): string[] {\n return this.sessionTools.get(r.control + r.machine) ?? [];\n }\n\n private async helloAll(): Promise<void> {\n void this.refreshSessionTools();\n const waiting = [...this.live].filter(([, l]) => l.waiter).map(([k]) => k);\n const modes: DeliveryMode[] = [\"waiter\", \"turn\", \"resume\", \"fork\", ...(this.deps.sdk ? ([\"sdk\"] as const) : [])];\n const harnesses = this.harnesses();\n const accounts = this.accounts();\n for (const r of this.cfg.receivers) {\n const body = {\n name: this.cfg.name,\n harnesses,\n modes,\n keys: r.keys.map((k) => k.id),\n version: VERSION,\n waiting,\n folders: this.cfg.folders,\n mode: this.cfg.mode,\n ...(accounts.length ? { accounts } : {}),\n // This daemon takes `files` on a start (an older one would start without them).\n files: true,\n };\n const res = await this.post(r, \"/hello\", body).catch(() => null);\n const st = this.polling.get(r.control + r.machine);\n if (res?.ok && st?.unauthorized) {\n st.unauthorized = false;\n st.authBackoff = 0;\n st.error = null;\n this.deps.log(`${r.url}: hello accepted; retrying control poll now`);\n st.wake?.();\n }\n }\n }\n\n private async post(r: PairedReceiver, sub: string, body: unknown): Promise<Response> {\n const ctl = new AbortController();\n const t = setTimeout(() => ctl.abort(), 15_000);\n try {\n return await this.deps.fetch(`${r.control.replace(/\\/$/, \"\")}${sub}`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${r.token}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: ctl.signal,\n });\n } finally {\n clearTimeout(t);\n }\n }\n\n // --- acks -----------------------------------------------------------------------\n\n private finish(r: PairedReceiver, id: string, a: Omit<Ack, \"receiver\" | \"id\" | \"at\">, since?: number): void {\n const ack: Ack = { receiver: r.control + r.machine, id, at: new Date(this.deps.now()).toISOString(), ...a };\n if (ack.reply) ack.reply = redactSecrets(ack.reply).slice(0, MAX_REPLY);\n if (ack.detail) ack.detail = redactSecrets(ack.detail).slice(0, 500);\n if (a.outcome !== \"taken\") {\n this.inflight.delete(id);\n this.recentAcks.set(id, { ack, at: this.deps.now() });\n this.delivered[a.mode ?? a.outcome] = (this.delivered[a.mode ?? a.outcome] ?? 0) + 1;\n this.deps.log(\n `ack ${id.slice(-8)} ${a.outcome}${a.mode ? ` via ${a.mode}` : \"\"}${a.code ? ` (${a.code})` : \"\"}${since ? ` send\u2192${a.outcome} ${this.deps.now() - since} ms` : \"\"}`,\n );\n }\n this.acks.add(ack);\n void this.flushAcks();\n }\n\n private flushing = false;\n private async flushAcks(): Promise<void> {\n if (this.flushing) return;\n this.flushing = true;\n try {\n for (let round = 0; round < 5; round++) {\n const all = this.acks.all();\n if (!all.length) return;\n const left: Ack[] = [];\n for (const r of this.cfg.receivers) {\n const mine = all.filter((a) => a.receiver === r.control + r.machine);\n if (!mine.length) continue;\n const acks = mine.map(({ receiver: _r, ...a }) => a);\n const ok = await this.post(r, \"/ack\", { acks })\n .then((res) => res.status >= 200 && res.status < 300)\n .catch(() => false);\n if (!ok) left.push(...mine);\n }\n // Acks for a receiver no longer paired are dropped.\n const now = this.acks.all();\n const added = now.slice(all.length);\n this.acks.keep([...left, ...added]);\n if (!left.length && !added.length) return;\n if (left.length) await sleep(2000 * (round + 1));\n }\n } finally {\n this.flushing = false;\n }\n }\n\n // --- one message ----------------------------------------------------------------\n\n async handle(r: PairedReceiver, m: Carried): Promise<void> {\n if (!m || typeof m.id !== \"string\") return;\n if (this.inflight.has(m.id)) return; // redelivered while we work on it\n const prior = this.recentAcks.get(m.id);\n if (prior && this.deps.now() - prior.at < RECENT_ACKS_MS) {\n this.acks.add(prior.ack);\n void this.flushAcks();\n return;\n }\n // In hand from here, before anything is awaited: a redelivery that arrives while\n // this one verifies must not verify too and come back `replay`. Every path below\n // ends in finish(), which lets go of it.\n this.inflight.add(m.id);\n // A start is marked now too, before its verification: messages of one poll are\n // handled side by side, and a prompt queued right behind its start may finish\n // verifying first. Marked unverified, it only ever makes such a prompt wait.\n const starting = startNamed(m.cmd);\n let done = (): void => {};\n if (starting) {\n const mine = new Promise<void>((res) => {\n done = res;\n });\n const before = this.startsPending.get(starting);\n const all = before ? Promise.all([before, mine]).then(() => undefined) : mine;\n this.startsPending.set(starting, all);\n void all.then(() => {\n if (this.startsPending.get(starting) === all) this.startsPending.delete(starting);\n });\n }\n try {\n await this.handleVerified(r, m);\n } finally {\n done();\n }\n }\n\n private async handleVerified(r: PairedReceiver, m: Carried): Promise<void> {\n const sent = Date.parse(m.at) || this.deps.now();\n if (Date.parse(m.expires_at) <= this.deps.now()) return this.finish(r, m.id, { outcome: \"expired\" });\n const v = await verifyCommand(\n { cmd: m.cmd, csig: m.csig ?? null, grant: m.grant ?? null, confirm: m.confirm ?? null },\n { machine: r.machine, rpId: r.rpId, trusted: r.keys, now: this.deps.now(), seenNonce: this.nonces.seen },\n );\n if (!v.ok) {\n this.deps.log(`refused ${m.id.slice(-8)}: ${v.code} \u2014 ${v.why}`);\n return this.finish(r, m.id, { outcome: \"refused\", code: v.code, detail: v.why });\n }\n const cmd = v.cmd;\n // A device this machine already trusts vouched for a new one (CONTROL.md \u00A72): the\n // signature just verified against an enrolled key, so the new key joins the store.\n if (cmd.kind === \"key.add\") return this.addKey(r, m.id, cmd, sent);\n const ref = parseSessionRef(cmd.session)!;\n const kp = kindPath(cmd.kind, ref.harness);\n if (typeof kp === \"object\") return this.finish(r, m.id, { outcome: \"unsupported\", detail: kp.unsupported });\n try {\n if (kp === \"start\") return await this.startSession(r, m.id, cmd, sent);\n let place = this.place(cmd.session);\n // A session the daemon is still starting may have no transcript (or, for Codex and\n // Antigravity, no name) yet: wait for that start, then place it again.\n const starting = kp === \"prompt\" ? this.startsPending.get(cmd.session) : undefined;\n if (\"refused\" in place && (starting || this.ownRuns.has(ref.id))) {\n this.finish(r, m.id, { outcome: \"taken\" });\n await starting;\n await this.serial(ref.id, async () => {});\n place = this.place(cmd.session);\n }\n if (\"refused\" in place)\n return this.finish(r, m.id, { outcome: \"refused\", code: place.refused, detail: place.why });\n if (kp === \"permission\") return this.permission(r, m.id, cmd, sent);\n if (kp === \"cancel\") return await this.cancel(r, m.id, cmd, sent);\n // One session's prompts in the order they came, each routed only once the one\n // before it has landed (a second message to a session the first one forked\n // goes to the copy). Other sessions don't wait.\n return await this.serial(`deliver:${cmd.session}`, async () => {\n // Read again: the message before this one may have moved the session (a fork).\n const now = this.place(cmd.session);\n if (\"refused\" in now) return this.finish(r, m.id, { outcome: \"refused\", code: now.refused, detail: now.why });\n return this.prompt(r, m.id, cmd, now, sent);\n });\n } catch (e) {\n this.finish(r, m.id, { outcome: \"failed\", detail: String((e as Error)?.message || e) });\n }\n }\n\n /** Where the session lives, and whether its folder is allowed \u2014 read from the\n * session's own transcript (Claude Code, Codex), the folder its start recorded, or\n * the hooks' cwd, never the command. */\n private place(session: string): { refused: string; why: string } | Placed {\n const ref = parseSessionRef(session)!;\n if (ref.harness === \"codex\" || ref.harness === \"antigravity\") return this.placeDriven(session, ref);\n if (ref.harness === \"claude-code\") {\n const target = this.state.copies[ref.id] ?? ref.id;\n const t = findTranscript(target, this.deps.claudeDirs()) ?? findTranscript(ref.id, this.deps.claudeDirs());\n if (!t)\n return { refused: \"no_session\", why: `no Claude Code session ${shortId(ref.harness, ref.id)} on this machine` };\n const folder = sessionFolder(t);\n const ok = folder && this.allowed(folder);\n if (!ok) return { refused: \"folder\", why: \"that session's folder isn't one this machine allows\" };\n return { folder: ok, transcript: t };\n }\n const cwd = this.live.get(session)?.cwd;\n const ok = cwd && this.allowed(cwd);\n if (!ok) return { refused: cwd ? \"folder\" : \"no_session\", why: \"no allowed folder known for that session\" };\n return { folder: ok, transcript: null };\n }\n\n /** A Codex or Antigravity session: one the daemon started is its alias (the harness's\n * id and the start's folder); one the hooks reported is Codex's rollout (its\n * `session_meta` cwd) or, for Antigravity, the folder its hooks gave. */\n private placeDriven(\n session: string,\n ref: { harness: string; id: string },\n ): { refused: string; why: string } | Placed {\n const a = this.aliasOf(ref.harness, ref.id);\n const target = a?.id ?? ref.id;\n let cwd: string | undefined = a?.cwd || undefined;\n let file: string | null = null;\n if (ref.harness === \"codex\") {\n file = isUuid(target) ? codexControl.findRollout(target, this.deps.env ?? process.env) : null;\n if (!a && !file)\n return { refused: \"no_session\", why: `no Codex session ${shortId(ref.harness, ref.id)} on this machine` };\n cwd ||= file ? codexControl.codexFacts(file).cwd : undefined;\n } else cwd ||= this.live.get(session)?.cwd || this.factsCwd(ref.harness, ref.id);\n if (!cwd)\n return {\n refused: \"no_session\",\n why: `no folder known for ${ref.harness === \"codex\" ? \"Codex\" : \"Antigravity\"} session ${shortId(ref.harness, ref.id)}`,\n };\n const ok = this.allowed(cwd);\n if (!ok) return { refused: \"folder\", why: \"that session's folder isn't one this machine allows\" };\n return { folder: ok, transcript: null, target, file };\n }\n\n /** The folder the worker recorded for a session from its hooks (run.ts, facts). */\n private factsCwd(harness: string, id: string): string | undefined {\n try {\n const f = path.join(path.dirname(this.dir), \"facts\", safeId(harness), `${safeId(id)}.json`);\n const cwd = (JSON.parse(readFileSync(f, \"utf8\")) as { cwd?: unknown }).cwd;\n return typeof cwd === \"string\" && path.isAbsolute(cwd) ? cwd : undefined;\n } catch {\n return undefined;\n }\n }\n\n private aliasOf(harness: string, id: string): Alias | null {\n return this.aliases[`${harness}:${id}`] ?? null;\n }\n\n /** The harness revealed its own id for a session the command named: from now on that\n * is where the command's id leads (aliases.ts). Written before anything else reads it. */\n private setAlias(harness: string, id: string, real: string, cwd: string): void {\n this.aliases = {\n ...this.aliases,\n [`${harness}:${id}`]: { id: real, cwd, at: new Date(this.deps.now()).toISOString() },\n };\n try {\n writeAliases(aliasFile(this.dir), this.aliases);\n } catch (e) {\n this.deps.log(\n `couldn't record ${harness}:${id.slice(0, 8)} \u2192 ${real.slice(0, 8)}: ${String(/* v8 ignore next -- writeAliases throws fs Errors */ (e as Error)?.message || e)}`,\n );\n }\n }\n\n /** `<harness>:<harness's id>` \u2192 `<harness>:<the start's id>` for a session the daemon named. */\n private named(session: string): string {\n const i = session.indexOf(\":\");\n if (i <= 0) return session;\n const harness = session.slice(0, i);\n const as = receiverIdOf(this.aliases, harness, session.slice(i + 1));\n return as ? `${harness}:${as}` : session;\n }\n\n private driver(harness: string): Driver | null {\n if (harness === \"codex\")\n return {\n label: \"Codex\",\n cmd: \"codex\",\n bin: () => this.deps.codex?.() ?? null,\n args: ({ mode, prompt, cwd, resume }) =>\n resume ? codexControl.codexArgs({ mode, prompt, resume }) : codexControl.codexArgs({ mode, prompt, cwd }),\n reading: () => codexControl.reading(),\n ...(this.deps.codexLogin ? { login: this.deps.codexLogin } : {}),\n loginHint: codexControl.LOGIN_HINT,\n };\n /* v8 ignore else -- only a HEADLESS harness gets here (route.ts): Claude Code never asks for a driver */\n if (harness === \"antigravity\")\n return {\n label: \"Antigravity\",\n cmd: \"agy\",\n bin: () => this.deps.agy?.() ?? null,\n args: ({ mode, prompt, resume }) =>\n resume ? antigravityControl.agyArgs({ mode, prompt, resume }) : antigravityControl.agyArgs({ mode, prompt }),\n reading: () => antigravityControl.reading(),\n };\n /* v8 ignore next -- see above */\n return null;\n }\n\n /** Who is signed in here, for hello. A bad .claude.json names nobody, never fails a hello. */\n private accounts(): HarnessAccount[] {\n try {\n return this.deps.accounts ? this.deps.accounts() : claudeAccounts(this.deps.claudeDirs());\n } catch {\n return [];\n }\n }\n\n /** The harnesses this machine can run a message in, for hello. */\n private harnesses(): string[] {\n if (this.deps.harnesses) return this.deps.harnesses();\n return [\n ...(this.deps.claude() ? [\"claude-code\"] : []),\n ...(this.deps.codex?.() ? [\"codex\"] : []),\n ...(this.deps.agy?.() ? [\"antigravity\"] : []),\n ];\n }\n\n private allowed(dir: string): string | null {\n if (!path.isAbsolute(dir)) return null;\n let r: string;\n try {\n r = realpathSync.native(dir);\n if (!statSync(r).isDirectory()) return null;\n } catch {\n return null;\n }\n for (const f of this.cfg.folders) {\n let rf = f;\n try {\n rf = realpathSync.native(f);\n } catch {}\n if (r === rf || r.startsWith(rf.endsWith(path.sep) ? rf : rf + path.sep)) return r;\n }\n return null;\n }\n\n private permission(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number) {\n const l = this.live.get(cmd.session);\n const hook = l?.attentions.get(cmd.for as string);\n if (!hook) {\n // Nothing is ever auto-allowed: an allow needs a prompt open right now.\n if (cmd.decision === \"allow\")\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"no_attention\",\n detail: \"no permission prompt open for that id\",\n });\n this.finish(r, id, { outcome: \"expired\", detail: \"the prompt was already answered or closed\" });\n return;\n }\n l!.attentions.delete(cmd.for as string);\n this.reply(hook, {\n op: \"decision\",\n behavior: cmd.decision as \"allow\" | \"deny\",\n ...(cmd.note ? { message: cmd.note } : {}),\n id,\n });\n this.finish(r, id, { outcome: \"delivered\", mode: \"turn\" }, sent);\n }\n\n private async cancel(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number): Promise<void> {\n const ref = parseSessionRef(cmd.session)!;\n const held = this.sdkSessions.get(ref.id);\n if (!held)\n return this.finish(r, id, {\n outcome: \"unsupported\",\n detail: \"no cancel path for a session the daemon doesn't hold\",\n });\n await held.interrupt();\n this.finish(r, id, { outcome: \"delivered\", mode: \"sdk\" }, sent);\n }\n\n private view(session: string, place: Placed) {\n const ref = parseSessionRef(session)!;\n const l = this.live.get(session);\n if (ref.harness !== \"claude-code\") {\n // Codex: a rollout someone else wrote in the last 90 s is a session in use.\n // Antigravity keeps no file that says so: only the daemon's own run (whose\n // messages wait in line behind it) holds one.\n const live =\n !this.ownRuns.has(ref.id) &&\n !!place.file &&\n recentlyWritten(place.file, this.lastEnd.get(ref.id), this.deps.now());\n return {\n harness: ref.harness,\n sdk: false,\n waiter: !!l?.waiter && !l.waiter.destroyed,\n midTurn: !!l?.midTurn,\n live,\n known: true,\n canFork: false,\n api: false,\n };\n }\n const transcript = place.transcript;\n const claude =\n ref.harness === \"claude-code\"\n ? this.deps.claude()\n : /* v8 ignore next -- every other harness returned above */ null;\n const target = this.state.copies[ref.id] ?? ref.id;\n const t = transcript;\n // The daemon's own run holding it is not \"someone else's live process\": the message\n // queues behind that run (serial per session) and resumes it.\n const live =\n !this.ownRuns.has(target) &&\n !!t &&\n (liveProcess(target, t.configDir) || recentlyWritten(t.file, this.lastEnd.get(target), this.deps.now()));\n return {\n harness: ref.harness,\n sdk: this.sdkSessions.has(ref.id),\n waiter: !!l?.waiter && !l.waiter.destroyed,\n midTurn: !!l?.midTurn,\n live,\n known: !!t,\n canFork: !!claude?.caps.fork,\n api: false,\n };\n }\n\n private async prompt(r: PairedReceiver, id: string, cmd: ControlCommand, place: Placed, sent: number): Promise<void> {\n const route = routePrompt(this.view(cmd.session, place));\n if (\"unsupported\" in route) return this.finish(r, id, { outcome: \"unsupported\", detail: route.unsupported });\n /* v8 ignore next -- place() already refused a session with no transcript (`known` is never false here) */\n if (\"refused\" in route) return this.finish(r, id, { outcome: \"refused\", code: route.refused });\n const ref = parseSessionRef(cmd.session)!;\n const text = cmd.text as string;\n switch (route.mode) {\n case \"waiter\": {\n const l = this.live.get(cmd.session)!;\n const w = l.waiter!;\n l.waiter = null;\n const from = this.answerFrom(cmd.session);\n this.reply(w, { op: \"message\", text: frame(text, r.url), id });\n this.scheduleHello();\n return this.followAnswer(r, id, \"waiter\", cmd.session, from, sent);\n }\n case \"turn\": {\n const l = this.liveOf(cmd.session);\n const p: TurnPending = { receiver: r, msgId: id, text, session: cmd.session, queuedAt: sent };\n l.turnQueue.push(p);\n // It waits for the session's Stop: the receiver must not keep handing it back.\n this.finish(r, id, { outcome: \"taken\" });\n const t = setTimeout(() => {\n if (this.inflight.has(id) && l.turnQueue.includes(p)) {\n l.turnQueue.splice(l.turnQueue.indexOf(p), 1);\n void this.reroute(p);\n }\n }, TURN_FALLBACK_MS);\n t.unref();\n return;\n }\n case \"sdk\": {\n const s = this.sdkSessions.get(ref.id)!;\n this.finish(r, id, { outcome: \"taken\" });\n const out = await s.send(frame(text, r.url));\n return this.finish(\n r,\n id,\n out.error\n ? { outcome: \"failed\", detail: out.error }\n : { outcome: \"delivered\", mode: \"sdk\", reply: out.reply },\n sent,\n );\n }\n case \"resume\":\n case \"fork\":\n return this.headless(r, id, cmd, place, route.mode, sent);\n /* v8 ignore next -- no harness has an input API wired yet (view() says api: false) */\n case \"api\":\n return this.finish(r, id, { outcome: \"unsupported\", detail: \"no input API wired for this harness\" });\n }\n }\n\n /** A turn message whose Stop never took it: route again, now that it isn't mid-turn. */\n private async reroute(p: TurnPending): Promise<void> {\n const l = this.liveOf(p.session);\n l.midTurn = false;\n const place = this.place(p.session);\n if (\"refused\" in place) return this.finish(p.receiver, p.msgId, { outcome: \"refused\", code: place.refused });\n const cmd = { kind: \"prompt\", session: p.session, text: p.text } as ControlCommand;\n this.inflight.delete(p.msgId);\n this.inflight.add(p.msgId);\n await this.prompt(p.receiver, p.msgId, cmd, place, p.queuedAt).catch((e) =>\n this.finish(p.receiver, p.msgId, { outcome: \"failed\", detail: String((e as Error)?.message || e) }),\n );\n }\n\n /** Jobs for one session (and its copy) run one at a time, in order. */\n private serial<T>(key: string, task: () => Promise<T>): Promise<T> {\n const prev = this.queues.get(key) ?? Promise.resolve();\n const next = prev.then(task, task);\n this.queues.set(\n key,\n next.catch(() => {}),\n );\n return next;\n }\n\n /** Null when Claude Code is signed in for this account (or can't say); otherwise what\n * to tell the person. */\n private async loginProblem(configDir?: string): Promise<string | null> {\n const login = this.deps.login;\n if (!login) return null;\n if (await this.signedIn(configDir ?? \"\", () => login(configDir))) return null;\n this.deps.log(`claude isn't signed in for ${configDir ?? \"the default account\"} as the daemon sees it`);\n return loginHint(configDir, this.deps.platform ?? process.platform);\n }\n\n /** One harness account's login, asked at most every 10 minutes (30 s after a no). */\n private async signedIn(key: string, ask: () => Promise<Login>): Promise<boolean> {\n const now = this.deps.now();\n const hit = this.logins.get(key);\n let login = hit && now - hit.at < (hit.login.loggedIn === false ? 30_000 : 600_000) ? hit.login : null;\n if (!login) {\n login = await ask().catch((): Login => ({ loggedIn: null }));\n this.logins.set(key, { at: now, login });\n }\n return login.loggedIn !== false;\n }\n\n /** Null when a Codex or Antigravity run may go ahead; otherwise what to tell the person. */\n private async drivenProblem(drv: Driver): Promise<{ bin: string } | { failed: string }> {\n const bin = drv.bin();\n if (!bin) return { failed: `${drv.label} isn't installed on this machine` };\n const login = drv.login;\n if (login && !(await this.signedIn(`${drv.cmd}:`, () => login(bin)))) {\n this.deps.log(`${drv.cmd} isn't signed in as the daemon sees it`);\n return {\n failed:\n /* v8 ignore next -- only Codex has a login check, and it has a hint */ drv.loginHint ??\n `${drv.label} isn't signed in on this machine`,\n };\n }\n return { bin };\n }\n\n /** A Codex or Antigravity session's next message: a headless turn resumed under the\n * harness's own id, after any run of the daemon's own that holds it. */\n private async resumeDriven(r: PairedReceiver, id: string, cmd: ControlCommand, place: Placed, sent: number) {\n const ref = parseSessionRef(cmd.session)!;\n const drv = this.driver(ref.harness)!;\n const ready = await this.drivenProblem(drv);\n if (\"failed\" in ready) return this.finish(r, id, { outcome: \"failed\", detail: ready.failed });\n this.finish(r, id, { outcome: \"taken\" });\n await this.serial(ref.id, async () => {\n // Read again: the start this waited for may have named the session meanwhile.\n /* v8 ignore next -- placeDriven() always names a target; the last fallback is for the type */\n const target = this.aliasOf(ref.harness, ref.id)?.id ?? place.target ?? ref.id;\n const args = drv.args({\n mode: this.cfg.mode,\n prompt: frame(cmd.text as string, r.url),\n cwd: place.folder,\n resume: target,\n });\n this.deps.log(`${id.slice(-8)}: ${drv.cmd} resume ${target.slice(0, 8)} (${this.cfg.mode}) in ${place.folder}`);\n await this.drive(r, id, ref, drv, ready.bin, args, place.folder, sent, target);\n });\n }\n\n /** Run one Codex or Antigravity turn and ack it: `progress` as its answer grows, then\n * `delivered` (mode `resume`) with the reply. The moment the harness names the session\n * \u2014 a start's new one, or a fresh one for an id it didn't know \u2014 the command's id\n * becomes its alias, so the next message resumes it. */\n private async drive(\n r: PairedReceiver,\n id: string,\n ref: { harness: string; id: string },\n drv: Driver,\n bin: string,\n args: string[],\n cwd: string,\n sent: number,\n asked: string | null,\n ): Promise<void> {\n const stream = this.answerStream(r, id);\n const reading = drv.reading();\n let named: string | null = null;\n const name = () => {\n const s = reading.session;\n if (!s || s === named) return;\n named = s;\n if (s !== asked) this.setAlias(ref.harness, ref.id, s, cwd);\n };\n const onLine = (l: string) => {\n if (reading.feed(l)) stream.set(reading.text);\n name();\n };\n const res = await this.owning(ref.id, () =>\n this.slot(() =>\n this.deps.run(bin, args, {\n cwd,\n env: jobEnv(this.deps.env),\n timeoutMs: JOB_TIMEOUT_MS,\n onLine,\n keep: () => false,\n }),\n ),\n );\n // A runner that doesn't stream hands the whole output over at the end.\n if (!reading.lines && res.stdout) for (const l of res.stdout.split(\"\\n\")) if (l.trim()) onLine(l);\n stream.close();\n this.lastEnd.set(ref.id, this.deps.now());\n if (reading.warnings?.length)\n this.deps.log(`${id.slice(-8)}: ${drv.cmd} warned: ${reading.warnings.join(\" \u00B7 \").slice(0, 400)}`);\n const out = reading.outcome(res);\n if (\"failed\" in out) return this.finish(r, id, { outcome: \"failed\", detail: out.failed });\n const moved =\n asked && named && named !== asked\n ? `\\n\\n(${drv.label} didn't find that session on this machine, so this ran in a new one; later messages continue there.)`\n : \"\";\n this.finish(r, id, { outcome: \"delivered\", mode: \"resume\", reply: out.reply + moved }, sent);\n }\n\n private async headless(\n r: PairedReceiver,\n id: string,\n cmd: ControlCommand,\n place: Placed,\n mode: \"resume\" | \"fork\",\n sent: number,\n ): Promise<void> {\n if (parseSessionRef(cmd.session)?.harness !== \"claude-code\") return this.resumeDriven(r, id, cmd, place, sent);\n const claude = this.deps.claude();\n if (!claude)\n return this.finish(r, id, { outcome: \"failed\", detail: \"Claude Code isn't installed on this machine\" });\n const mf = modeFlags(this.cfg.mode, claude.caps);\n if (\"error\" in mf) return this.finish(r, id, { outcome: \"refused\", code: \"mode\", detail: mf.error });\n const signedOut = await this.loginProblem(place.transcript?.configDir);\n if (signedOut) return this.finish(r, id, { outcome: \"failed\", detail: signedOut });\n const ref = parseSessionRef(cmd.session)!;\n this.finish(r, id, { outcome: \"taken\" });\n await this.serial(ref.id, async () => {\n const target = this.state.copies[ref.id] ?? ref.id;\n const resume = mode === \"fork\" ? [\"--resume\", target, \"--fork-session\"] : [\"--resume\", target];\n const allow = this.allowedFor(r);\n const args = [\n \"-p\",\n ...this.outputArgs(claude.caps),\n ...mf.args,\n ...(allow.length ? [`--allowedTools=${allow.join(\",\")}`] : []),\n ...resume,\n frame(cmd.text as string, r.url),\n ];\n this.deps.log(`${id.slice(-8)}: claude -p ${[...mf.args, ...resume].join(\" \")} in ${place.folder}`);\n const stream = this.answerStream(r, id);\n const res = await this.owning(target, () =>\n this.slot(() =>\n this.deps.run(claude.bin, args, {\n cwd: place.folder,\n env: claudeEnv(place.transcript?.configDir, this.deps.env),\n timeoutMs: JOB_TIMEOUT_MS,\n ...(claude.caps.stream ? { onLine: (l: string) => stream.feed(l) } : {}),\n }),\n ),\n );\n stream.close();\n this.lastEnd.set(target, this.deps.now());\n const out = this.outcome(res);\n if (\"failed\" in out) return this.finish(r, id, { outcome: \"failed\", detail: out.failed });\n const ran = isUuid(out.session) ? out.session : target;\n if (mode === \"fork\" && ran !== target) {\n this.state.copies[ref.id] = ran;\n writeState(path.join(this.dir, \"state.json\"), this.state);\n this.lastEnd.set(ran, this.deps.now());\n }\n this.finish(\n r,\n id,\n { outcome: \"delivered\", mode, reply: out.reply, ...(ran !== ref.id ? { session: `claude-code:${ran}` } : {}) },\n sent,\n );\n });\n }\n\n private outcome(res: RunResult): { failed: string } | { reply: string; session?: string } {\n if (res.error) return { failed: `couldn't start Claude Code: ${res.error}` };\n if (res.timedOut) return { failed: \"Claude Code was still working after 30 minutes, so it was stopped\" };\n if (res.tooBig) return { failed: \"Claude Code's answer was too large to read\" };\n const j = parseResult(res.stdout);\n if (!j) {\n const why = String(res.stderr || \"\")\n .trim()\n .split(\"\\n\")\n .slice(-3)\n .join(\" \");\n return {\n failed: `Claude Code exited (${res.signal || `code ${res.code}`}) without an answer${why ? `: ${why}` : \"\"}`,\n };\n }\n if (j.is_error) return { failed: String(j.result || j.subtype || \"Claude Code reported an error\") };\n const denials = Array.isArray(j.permission_denials) ? j.permission_denials : [];\n const names = [...new Set(denials.map((d) => d?.tool_name).filter((n): n is string => typeof n === \"string\"))];\n const tail = deniedNote(names, denials.length);\n const text =\n typeof j.result === \"string\" && j.result.trim() ? j.result : \"(Claude Code finished without a written reply.)\";\n return { reply: text + tail, ...(typeof j.session_id === \"string\" ? { session: j.session_id } : {}) };\n }\n\n private addKey(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number) {\n const k = cmd.key!;\n const name = typeof cmd.name === \"string\" ? cmd.name.trim().slice(0, 80) : undefined;\n /* v8 ignore next -- the receiver that handed the message over is in cfg, unless `control off` ran mid-flight */\n const rec = this.cfg.receivers.find((x) => x.control === r.control && x.machine === r.machine) ?? r;\n if (rec.keys.some((x) => x.id === k.id))\n return this.finish(r, id, { outcome: \"delivered\", detail: \"that device was already trusted\" }, sent);\n rec.keys.push({\n id: k.id,\n alg: k.alg,\n spki: k.spki,\n ...(name ? { name } : {}),\n added_at: new Date(this.deps.now()).toISOString(),\n });\n try {\n writeControl(this.cfg, this.deps.env);\n } catch (e) {\n rec.keys = rec.keys.filter((x) => x.id !== k.id);\n return this.finish(r, id, {\n outcome: \"failed\",\n detail: `couldn't save the key: ${String(/* v8 ignore next -- writeControl throws fs Errors */ (e as Error)?.message || e)}`,\n });\n }\n this.deps.log(\n `trusted a new device${name ? ` (${name})` : \"\"} on ${r.url}: ${k.id.slice(0, 12)}\u2026, vouched for by a key it already trusted`,\n );\n this.finish(r, id, { outcome: \"delivered\", detail: `trusted ${name || \"a new device\"}` }, sent);\n }\n\n /** Where the session's transcript ends right now: its answer starts after this. */\n private answerFrom(session: string): { file: string; offset: number } | null {\n const ref = parseSessionRef(session);\n if (!ref || ref.harness !== \"claude-code\") return null;\n const t = findTranscript(this.state.copies[ref.id] ?? ref.id, this.deps.claudeDirs());\n return t ? { file: t.file, offset: transcriptEnd(t.file) } : null;\n }\n\n /** A message handed to a live session (a waiter, a Stop block) is `taken` now; the\n * session answers in its own turn, which the daemon reads from the transcript and\n * sends back as the final ack's `reply` \u2014 so the person sees the answer where they\n * asked. A turn that doesn't end within ANSWER_WAIT_MS is acked delivered without. */\n private followAnswer(\n r: PairedReceiver,\n id: string,\n mode: \"waiter\" | \"turn\",\n session: string,\n from: { file: string; offset: number } | null,\n sent: number,\n ): void {\n this.deps.log(`${id.slice(-8)}: in ${session.slice(0, 24)} via ${mode} ${this.deps.now() - sent} ms after send`);\n this.finish(r, id, { outcome: \"taken\" });\n const stream = this.answerStream(r, id);\n void (async () => {\n const answer = from\n ? await awaitAnswer(from.file, from.offset, {\n timeoutMs: this.deps.answerWaitMs ?? ANSWER_WAIT_MS,\n now: this.deps.now,\n onText: (t) => stream.set(t),\n })\n : null;\n stream.close();\n this.finish(r, id, { outcome: \"delivered\", mode, ...(answer ? { reply: answer } : {}) }, sent);\n })().catch((e) =>\n this.finish(r, id, {\n outcome: \"delivered\",\n mode,\n detail: String(/* v8 ignore next -- awaitAnswer throws fs Errors */ (e as Error)?.message || e),\n }),\n );\n }\n\n /** The answer so far, sent as a `progress` ack: whole, with a rising seq, at most\n * one in flight. Fire-and-forget \u2014 the final ack carries everything. */\n private answerStream(r: PairedReceiver, id: string): AnswerStream {\n return new AnswerStream(async (text, seq) => {\n await this.post(r, \"/ack\", {\n acks: [\n {\n id,\n outcome: \"progress\",\n at: new Date(this.deps.now()).toISOString(),\n seq,\n reply: redactSecrets(text).slice(0, MAX_REPLY),\n },\n ],\n });\n });\n }\n\n /** How a headless run prints: streamed where this Claude Code can, else one JSON at the end. */\n private outputArgs(caps: { stream?: boolean }): string[] {\n return caps.stream\n ? [\"--output-format\", \"stream-json\", \"--verbose\", \"--include-partial-messages\"]\n : [\"--output-format\", \"json\"];\n }\n\n /** Mark a session as held by one of the daemon's runs while `fn` runs. */\n private async owning<T>(session: string, fn: () => Promise<T>): Promise<T> {\n this.ownRuns.set(session, (this.ownRuns.get(session) ?? 0) + 1);\n try {\n return await fn();\n } finally {\n /* v8 ignore next -- a session being let go of was always held */\n const n = (this.ownRuns.get(session) ?? 1) - 1;\n if (n > 0) this.ownRuns.set(session, n);\n else this.ownRuns.delete(session);\n }\n }\n\n private limits() {\n const l = this.cfg.limits ?? {};\n const n = (v: unknown, d: number) => (typeof v === \"number\" && Number.isInteger(v) && v >= 0 ? v : d);\n return {\n startConcurrent: n(l.start_concurrent, LIMITS.startConcurrent),\n startPerHour: n(l.start_per_hour, LIMITS.startPerHour),\n headless: Math.max(1, n(l.headless, LIMITS.headless)),\n };\n }\n\n /** One headless Claude Code process at a time per slot; the rest wait in order. */\n private async slot<T>(fn: () => Promise<T>): Promise<T> {\n while (this.procs >= this.limits().headless) await new Promise<void>((r) => this.procWaiters.push(r));\n this.procs++;\n try {\n return await fn();\n } finally {\n this.procs--;\n this.procWaiters.shift()?.();\n }\n }\n\n private async startSession(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number): Promise<void> {\n const lim = this.limits();\n const now = this.deps.now();\n this.startTimes = this.startTimes.filter((t) => now - t < 3_600_000);\n if (this.startsRunning >= lim.startConcurrent || this.startTimes.length >= lim.startPerHour) {\n const detail =\n this.startsRunning >= lim.startConcurrent\n ? `this machine is already starting ${this.startsRunning} new session(s); it starts at most ${lim.startConcurrent} at once`\n : `this machine started ${this.startTimes.length} new sessions in the last hour, its limit`;\n this.deps.log(`refused ${id.slice(-8)}: start_limit \u2014 ${detail}`);\n return this.finish(r, id, { outcome: \"refused\", code: \"start_limit\", detail });\n }\n this.startsRunning++;\n this.startTimes.push(now);\n const sid = parseSessionRef(cmd.session)!.id;\n try {\n // On the session's own queue, and held as the daemon's own: a message sent while\n // the start still runs waits for it and resumes the session, never forks it.\n await this.serial(sid, () => this.owning(sid, () => this.startOne(r, id, cmd, sent)));\n } finally {\n this.startsRunning--;\n }\n }\n\n private async startOne(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number): Promise<void> {\n const ref = parseSessionRef(cmd.session)!;\n const cwd = this.allowed(cmd.cwd as string);\n if (!cwd)\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"folder\",\n detail: \"that folder isn't one this machine allows\",\n });\n if (ref.harness !== \"claude-code\") return this.startDriven(r, id, cmd, ref, cwd, sent);\n if (findTranscript(ref.id, this.deps.claudeDirs()) || this.sdkSessions.has(ref.id))\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"bad_session\",\n detail: \"that new session's id is already taken\",\n });\n const signedOut = await this.loginProblem(this.deps.env?.CLAUDE_CONFIG_DIR);\n if (signedOut) return this.finish(r, id, { outcome: \"failed\", detail: signedOut });\n this.finish(r, id, { outcome: \"taken\" });\n const text = await this.attached(r, id, cmd, ref, cwd);\n if (text === null) return;\n if (this.deps.sdk) {\n const sdk = this.deps.sdk;\n const out = await this.slot(async () => {\n const s = sdk.start({ session: ref.id, cwd, mode: this.cfg.mode, allowedTools: this.allowedFor(r) });\n this.sdkSessions.set(ref.id, s);\n return s.send(frameStart(text, r.url));\n });\n return this.finish(\n r,\n id,\n out.error ? { outcome: \"failed\", detail: out.error } : { outcome: \"delivered\", mode: \"sdk\", reply: out.reply },\n sent,\n );\n }\n const claude = this.deps.claude();\n if (!claude)\n return this.finish(r, id, { outcome: \"failed\", detail: \"Claude Code isn't installed on this machine\" });\n const mf = modeFlags(this.cfg.mode, claude.caps);\n if (\"error\" in mf) return this.finish(r, id, { outcome: \"refused\", code: \"mode\", detail: mf.error });\n const stream = this.answerStream(r, id);\n const res = await this.slot(() =>\n this.deps.run(\n claude.bin,\n [\n \"-p\",\n ...this.outputArgs(claude.caps),\n ...mf.args,\n ...(this.allowedFor(r).length ? [`--allowedTools=${this.allowedFor(r).join(\",\")}`] : []),\n \"--session-id\",\n ref.id,\n frameStart(text, r.url),\n ],\n {\n cwd,\n env: claudeEnv(undefined, this.deps.env),\n timeoutMs: JOB_TIMEOUT_MS,\n ...(claude.caps.stream ? { onLine: (l: string) => stream.feed(l) } : {}),\n },\n ),\n );\n stream.close();\n // The transcript this run just wrote is ours: the next message must not read it as a\n // live session (a fork instead of a resume).\n this.lastEnd.set(ref.id, this.deps.now());\n const out = this.outcome(res);\n if (\"failed\" in out) return this.finish(r, id, { outcome: \"failed\", detail: out.failed });\n this.finish(r, id, { outcome: \"delivered\", mode: \"resume\", reply: out.reply }, sent);\n }\n\n /** A new Codex or Antigravity session: the harness picks its id, and the start's id\n * becomes its name (aliases.ts) as soon as the run says what it picked. */\n private async startDriven(\n r: PairedReceiver,\n id: string,\n cmd: ControlCommand,\n ref: { harness: string; id: string },\n cwd: string,\n sent: number,\n ): Promise<void> {\n const drv = this.driver(ref.harness)!;\n const env = this.deps.env ?? process.env;\n if (\n this.aliasOf(ref.harness, ref.id) ||\n this.live.get(cmd.session)?.cwd ||\n (ref.harness === \"codex\" && isUuid(ref.id) && codexControl.findRollout(ref.id, env))\n )\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"bad_session\",\n detail: \"that new session's id is already taken\",\n });\n const ready = await this.drivenProblem(drv);\n if (\"failed\" in ready) return this.finish(r, id, { outcome: \"failed\", detail: ready.failed });\n this.finish(r, id, { outcome: \"taken\" });\n const text = await this.attached(r, id, cmd, ref, cwd);\n if (text === null) return;\n const args = drv.args({ mode: this.cfg.mode, prompt: frameStart(text, r.url), cwd });\n this.deps.log(\n `${id.slice(-8)}: ${drv.cmd} new session for ${shortId(ref.harness, ref.id)} (${this.cfg.mode}) in ${cwd}`,\n );\n await this.drive(r, id, ref, drv, ready.bin, args, cwd, sent, null);\n }\n\n /** A start's text, with its files (CONTROL.md \u00A76) fetched, checked and written under\n * `cwd` first \u2014 every check in \u00A75 passed and the nonce is recorded by now, so the\n * `taken` ack is out and the download may take its time. Null when a file failed:\n * the command is acked `failed` with code `file`, nothing is kept, no session starts. */\n private async attached(\n r: PairedReceiver,\n id: string,\n cmd: ControlCommand,\n ref: { id: string },\n cwd: string,\n ): Promise<string | null> {\n const text = cmd.text as string;\n if (!cmd.files) return text;\n try {\n const got = await fetchFiles(cmd.files, {\n control: r.control,\n token: r.token,\n fetch: this.deps.fetch,\n timeoutMs: this.deps.fileTimeoutMs,\n });\n const rel = writeFiles(cwd, ref.id, got);\n this.deps.log(`${id.slice(-8)}: ${got.length} file(s) saved in ${cwd}/.sessionpipe/files/${ref.id}`);\n return withFiles(text, got, rel);\n } catch (e) {\n // fetchFiles and writeFiles throw nothing but a FileProblem, and its message is the detail.\n const detail = (e as Error).message;\n this.deps.log(`${id.slice(-8)}: file \u2014 ${detail}`);\n this.finish(r, id, { outcome: \"failed\", code: \"file\", detail });\n return null;\n }\n }\n\n private closeIdleSdk(): void {\n const idle = this.deps.sdkIdleMs ?? 10 * 60_000;\n for (const [id, s] of this.sdkSessions)\n if (!s.busy && this.deps.now() - s.lastUsed > idle) {\n s.close();\n this.sdkSessions.delete(id);\n this.deps.log(\n `sdk session ${id.slice(0, 8)} closed after ${Math.round(idle / 60_000)} min idle (it resumes on the next message)`,\n );\n }\n }\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms).unref?.());\n\n/** dev:ino of the file at `p`, or null when there is none. */\nfunction socketId(p: string): string | null {\n try {\n const st = statSync(p);\n return `${st.dev}:${st.ino}`;\n } catch {\n return null;\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Attachments on a `start` (spec/CONTROL.md \u00A73.1, \u00A76): the signed command names each\n// file by its SHA-256; the bytes wait on the receiver. The daemon fetches each one\n// with the machine's token, stops reading past the signed size, checks length and\n// hash, and only then writes it \u2014 under <cwd>/.sessionpipe/files/<session>/, never\n// through a symlink, never over an existing path, mode 0600. Any problem: nothing is\n// kept and the session doesn't start. The same for every harness the daemon starts:\n// the files are in `cwd` before the run, and nothing about them is the harness's.\nimport { createHash } from \"node:crypto\";\nimport { existsSync, lstatSync, mkdirSync, realpathSync, rmSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { ControlFile } from \"@sessionpipe/core/control\";\n\n/** One file's download may take this long (25 MiB on a slow link). */\nexport const FETCH_TIMEOUT_MS = 5 * 60_000;\n\n/** A file could not be fetched, checked or written: the ack's `detail`, code `file`. */\nexport class FileProblem extends Error {}\n\nexport interface Fetched {\n file: ControlFile;\n /** The name as written: NFC. */\n name: string;\n bytes: Uint8Array;\n}\n\nexport interface FetchOptions {\n control: string;\n token: string;\n fetch: typeof fetch;\n /** Per file; tests shorten it. */\n timeoutMs?: number | undefined;\n}\n\nconst b64url = (b: Buffer) => b.toString(\"base64\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\nconst reason = (e: unknown) => (e instanceof Error ? e.message : String(e)).slice(0, 160);\n\n/** Fetch every file, in order, and check each against the signed size and hash.\n * Every failure is a FileProblem naming the file. */\nexport async function fetchFiles(files: ControlFile[], o: FetchOptions): Promise<Fetched[]> {\n const out: Fetched[] = [];\n for (const file of files) {\n let bytes: Uint8Array;\n try {\n bytes = await fetchOne(file, o);\n } catch (e) {\n if (e instanceof FileProblem) throw e;\n throw new FileProblem(`couldn't download ${JSON.stringify(file.name)}: ${reason(e)}`);\n }\n out.push({ file, name: file.name.normalize(\"NFC\"), bytes });\n }\n return out;\n}\n\nasync function fetchOne(f: ControlFile, o: FetchOptions): Promise<Uint8Array> {\n const label = JSON.stringify(f.name);\n const ctl = new AbortController();\n const t = setTimeout(() => ctl.abort(), o.timeoutMs ?? FETCH_TIMEOUT_MS);\n try {\n const res = await o.fetch(`${o.control.replace(/\\/$/, \"\")}/files/${f.sha256}`, {\n headers: { authorization: `Bearer ${o.token}` },\n signal: ctl.signal,\n });\n if (res.status === 404) throw new FileProblem(`${label} isn't on the receiver (never uploaded, or expired)`);\n if (res.status !== 200) throw new FileProblem(`couldn't download ${label}: HTTP ${res.status}`);\n // A declared length past the signed size: not a byte of it is read.\n if (Number(res.headers.get(\"content-length\")) > f.size) throw tooLong(label, f);\n const buf = new Uint8Array(f.size);\n let got = 0;\n const reader = res.body!.getReader();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n // Past the signed size: stop reading, whatever the receiver keeps sending.\n if (got + value.length > f.size) throw tooLong(label, f);\n buf.set(value, got);\n got += value.length;\n }\n if (got !== f.size) throw new FileProblem(`${label} is ${got} bytes, not its signed ${f.size}`);\n const hash = b64url(createHash(\"sha256\").update(buf).digest());\n if (hash !== f.sha256) throw new FileProblem(`${label} doesn't match its signed hash: it was changed`);\n return buf;\n } finally {\n clearTimeout(t);\n // Done or failed: whatever the receiver is still sending is cut off here.\n ctl.abort();\n }\n}\n\nconst tooLong = (label: string, f: ControlFile) =>\n new FileProblem(`${label} is larger than its signed size (${f.size} bytes)`);\n\n/** A directory that must be real (not a symlink) \u2014 made when absent. Anything else in\n * the way (a file of that name) fails the mkdir, and the files with it. */\nfunction realDir(p: string, why: string): void {\n mkdirSync(p, { recursive: true, mode: 0o700 });\n if (lstatSync(p).isSymbolicLink()) throw new FileProblem(`${why} is a symlink`);\n}\n\n/**\n * Write the checked files to <cwd>/.sessionpipe/files/<session>/ and answer their\n * paths relative to cwd. `cwd` is already resolved (realpath) and allowed.\n * On any problem everything written here is removed and FileProblem thrown.\n */\nexport function writeFiles(cwd: string, session: string, files: Fetched[]): string[] {\n const top = path.join(cwd, \".sessionpipe\");\n const parent = path.join(top, \"files\");\n const dir = path.join(parent, session);\n let made = false;\n try {\n realDir(top, \".sessionpipe\");\n // The folder ignores itself, so a repository never picks it up.\n const ignore = path.join(top, \".gitignore\");\n if (!existsSync(ignore)) writeFileSync(ignore, \"*\\n\", { flag: \"wx\", mode: 0o600 });\n realDir(parent, \".sessionpipe/files\");\n if (existsSync(dir)) throw new FileProblem(`.sessionpipe/files/${session} already exists`);\n mkdirSync(dir, { mode: 0o700 });\n made = true;\n // Every parent between cwd and here is a real directory right now.\n if (realpathSync.native(dir) !== dir) throw new FileProblem(\".sessionpipe leads outside the session's folder\");\n const rel: string[] = [];\n for (const f of files) {\n // wx: exclusive create, which also refuses to open through a symlink.\n writeFileSync(path.join(dir, f.name), f.bytes, { flag: \"wx\", mode: 0o600 });\n rel.push(`.sessionpipe/files/${session}/${f.name}`);\n }\n return rel;\n } catch (e) {\n if (made) rmSync(dir, { recursive: true, force: true });\n if (e instanceof FileProblem) throw e;\n throw new FileProblem(`couldn't save the files: ${reason(e)}`);\n }\n}\n\n/** 183402 \u2192 \"179 KB\", 1258291 \u2192 \"1.2 MB\" (units of 1024). */\nexport function humanSize(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1_048_576) return `${Math.round(n / 1024)} KB`;\n return `${(n / 1_048_576).toFixed(1)} MB`;\n}\n\n/** The command's text followed by the list of files the session can read. */\nexport function withFiles(text: string, files: Fetched[], rel: string[]): string {\n const lines = files.map((f, i) => `- ${rel[i]} (${f.file.type}, ${humanSize(f.file.size)})`);\n return `${text}\\n\\nAttached files (saved in this folder):\\n${lines.join(\"\\n\")}`;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The answer to a message delivered in place (spec/CONTROL.md \u00A76 `prompt`). A waiter or\n// a Stop block hands the message to the live session, which answers in its own turn;\n// the daemon reads that turn from the session's own transcript and sends it back as the\n// ack's `reply`, so the person sees the answer where they asked. Only the bytes the\n// transcript gained after the delivery are read: a long session's file is never parsed\n// whole, and nothing from before the message can be mistaken for its answer.\nimport { closeSync, openSync, readSync, statSync } from \"node:fs\";\n\n/** The transcript's size now: where its answer will start. */\nexport function transcriptEnd(file: string): number {\n try {\n return statSync(file).size;\n } catch {\n return 0;\n }\n}\n\n/** Claude Code records after the delivery \u2192 the turn's answer once the turn ended\n * (an assistant record with `stop_reason: \"end_turn\"`), else null. The answer is the\n * turn's assistant text, in order; sidechains (subagents) are not the session's words. */\nexport function answerIn(lines: string[]): { done: boolean; text: string } {\n const parts: string[] = [];\n for (const line of lines) {\n let j: {\n type?: string;\n isSidechain?: boolean;\n message?: { stop_reason?: string; content?: unknown };\n };\n try {\n j = JSON.parse(line);\n } catch {\n continue;\n }\n if (j.type !== \"assistant\" || j.isSidechain) continue;\n const content = j.message?.content;\n if (Array.isArray(content))\n for (const c of content as { type?: string; text?: unknown }[])\n if (c?.type === \"text\" && typeof c.text === \"string\" && c.text.trim()) parts.push(c.text.trim());\n if (j.message?.stop_reason === \"end_turn\") return { done: true, text: parts.join(\"\\n\\n\") };\n }\n return { done: false, text: parts.join(\"\\n\\n\") };\n}\n\n/** Wait for the turn that follows a delivery to end, reading the transcript from\n * `from` (its size at delivery). Resolves the answer, or null when the turn doesn't\n * end within `timeoutMs` (an interrupted turn, a session closed mid-answer). */\nexport async function awaitAnswer(\n file: string,\n from: number,\n o: {\n timeoutMs: number;\n pollMs?: number;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n /** The turn's text so far, each time it grows (for the progress ack). */\n onText?: (text: string) => void;\n },\n): Promise<string | null> {\n const now = o.now ?? Date.now;\n const sleep = o.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms).unref?.()));\n const until = now() + o.timeoutMs;\n let offset = from;\n let partial = \"\";\n const lines: string[] = [];\n while (now() < until) {\n const size = transcriptEnd(file);\n if (size < offset) return null; // rewritten under us: nothing we can trust\n if (size > offset) {\n const fd = openSync(file, \"r\");\n try {\n const buf = Buffer.alloc(Math.min(size - offset, 4 * 1024 * 1024));\n const n = readSync(fd, buf, 0, buf.length, offset);\n offset += n;\n const chunk = partial + buf.subarray(0, n).toString(\"utf8\");\n const cut = chunk.lastIndexOf(\"\\n\");\n partial = cut < 0 ? chunk : chunk.slice(cut + 1);\n if (cut >= 0) lines.push(...chunk.slice(0, cut).split(\"\\n\").filter(Boolean));\n } finally {\n closeSync(fd);\n }\n const a = answerIn(lines);\n if (a.done) return a.text || null;\n if (a.text) o.onText?.(a.text);\n }\n await sleep(o.pollMs ?? 500);\n }\n return null;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The routing rule (spec/CONTROL.md \u00A76): the first delivery mode that fits, top to\n// bottom. Pure, so every branch is a unit test.\nimport type { ControlKind } from \"@sessionpipe/core/control\";\n\nexport type DeliveryMode = \"sdk\" | \"waiter\" | \"turn\" | \"api\" | \"resume\" | \"fork\";\n\nexport interface SessionView {\n harness: string;\n /** The daemon holds this session through the Agent SDK right now. */\n sdk: boolean;\n /** A `sessionpipe wait` for it is parked on the socket. */\n waiter: boolean;\n /** Between a turn's start and its Stop (the Stop hook will ask). */\n midTurn: boolean;\n /** A live process holds the session (registry entry or a fresh transcript write). */\n live: boolean;\n /** The transcript exists on this machine (Codex, Antigravity: the session was placed). */\n known: boolean;\n /** This Claude Code can copy a session (`--fork-session`); no other harness can. */\n canFork: boolean;\n /** The harness has an input API (OpenCode, Codex app-server) \u2014 none is wired yet. */\n api: boolean;\n}\n\nexport type Route = { mode: DeliveryMode } | { unsupported: string } | { refused: \"no_session\" };\n\n/** The harnesses the daemon can run a turn of by itself: resume an idle session, start a\n * new one (`claude -p`, `codex exec`, `agy -p`). */\nexport const HEADLESS = new Set([\"claude-code\", \"codex\", \"antigravity\"]);\n\n/** Where a prompt (or a start) goes. Never two writers on one transcript: a live\n * session gets a fork, never a resume. */\nexport function routePrompt(s: SessionView): Route {\n if (s.sdk) return { mode: \"sdk\" };\n if (s.waiter) return { mode: \"waiter\" };\n if (s.midTurn) return { mode: \"turn\" };\n if (s.api) return { mode: \"api\" };\n if (!HEADLESS.has(s.harness)) return { unsupported: `no idle delivery for ${s.harness} yet` };\n if (!s.known) return { refused: \"no_session\" };\n if (!s.live) return { mode: \"resume\" };\n if (s.canFork) return { mode: \"fork\" };\n return {\n unsupported:\n s.harness === \"claude-code\"\n ? \"the session is open and this Claude Code can't copy it (no --fork-session)\"\n : `the session is open in ${s.harness} right now, and a ${s.harness} session can't be copied: send it again once it has been idle a couple of minutes`,\n };\n}\n\n/** How each kind is delivered, before the session's state is looked at. */\nexport function kindPath(\n kind: ControlKind,\n harness: string,\n): \"prompt\" | \"permission\" | \"cancel\" | \"start\" | { unsupported: string } {\n switch (kind) {\n case \"prompt\":\n return \"prompt\";\n case \"permission.answer\":\n return harness === \"gemini-cli\"\n ? { unsupported: \"Gemini CLI has no permission answer channel\" }\n : harness === \"devin\"\n ? { unsupported: \"Devin has no permission answer channel\" }\n : \"permission\";\n case \"cancel\":\n return \"cancel\";\n case \"start\":\n return HEADLESS.has(harness) ? \"start\" : { unsupported: `can't start a ${harness} session` };\n default:\n return { unsupported: `unknown kind ${String(kind)}` };\n }\n}\n\n/** The framed text a session receives (CONTROL.md \u00A76): the model and the person can\n * tell where it came from. */\n/** Said with every message that reaches a live session: the answer goes back by\n * itself (the daemon reads it from the transcript), so the model never invents a\n * command to reply with (a real session tried \\`sessionpipe send\\`, 2026-10-01). */\nexport const IN_PLACE_ANSWER =\n \"Answer it right here, as you would answer the person at the keyboard: your reply is sent back to them automatically. Don't run a command or call a tool just to send it.\";\n\nexport function frame(text: string, receiver: string): string {\n let host = receiver;\n try {\n host = new URL(receiver).host;\n } catch {}\n return `Message via ${host} (sessionpipe control, signed on the sender's device):\\n\\n${text}`;\n}\n\n/** A new session's first message: the person's words first, where they come from after.\n * Claude Code names a session from the start of its first message, so a header in front\n * named every started session \"Message via spacesheep.dev (sessionpipe control, s\u2026\"\n * (2026-10-02). In a new session there is no one else's conversation to tell it apart\n * from, so the source line can follow the ask. */\nexport function frameStart(text: string, receiver: string): string {\n let host = receiver;\n try {\n host = new URL(receiver).host;\n } catch {}\n return `${text}\\n\\n(Sent via ${host} with sessionpipe control, signed on the sender's device.)`;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The answer as it is written (spec/CONTROL.md \u00A710, the `progress` ack). A headless run\n// streams Claude Code's output (`--output-format stream-json --include-partial-\n// messages`) and a live session's transcript grows message by message; either way the\n// daemon sends the receiver the answer SO FAR, whole, with a rising seq. Reliability\n// comes from that shape, not from delivery: a progress ack is fire-and-forget, a lost\n// one is covered by the next, and the final `delivered` ack always carries the full\n// answer. At most one is in flight, at most one every `everyMs`.\n\n/** One stream-json line \u2192 text to append, or a message boundary (a new assistant\n * message after a tool step: its text starts a new paragraph). */\nexport function streamJsonPiece(line: string): { text?: string; boundary?: boolean } | null {\n let j: {\n type?: string;\n parent_tool_use_id?: unknown;\n event?: { type?: string; delta?: { type?: string; text?: unknown } };\n };\n try {\n j = JSON.parse(line);\n } catch {\n return null;\n }\n if (j.type !== \"stream_event\" || !j.event) return null;\n // A subagent's stream (a Task tool's) is not the session's answer.\n if (j.parent_tool_use_id) return null;\n const e = j.event;\n if (e.type === \"content_block_delta\" && e.delta?.type === \"text_delta\" && typeof e.delta.text === \"string\")\n return { text: e.delta.text };\n if (e.type === \"message_start\") return { boundary: true };\n return null;\n}\n\nexport class AnswerStream {\n private text = \"\";\n private sent = \"\";\n private seq = 0;\n private timer: NodeJS.Timeout | null = null;\n private inFlight = false;\n private closed = false;\n\n constructor(\n private readonly send: (text: string, seq: number) => Promise<void>,\n private readonly everyMs = 400,\n ) {}\n\n /** A stream-json line from a headless run. */\n feed(line: string): void {\n const p = streamJsonPiece(line);\n if (!p) return;\n if (p.boundary) {\n if (this.text && !this.text.endsWith(\"\\n\\n\")) this.text += \"\\n\\n\";\n return;\n }\n if (p.text) {\n this.text += p.text;\n this.schedule();\n }\n }\n\n /** The whole answer so far (a live session's transcript). */\n set(text: string): void {\n if (text === this.text) return;\n this.text = text;\n this.schedule();\n }\n\n /** No more progress: the final ack follows. */\n close(): void {\n this.closed = true;\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n\n private schedule(): void {\n if (this.closed || this.timer || this.inFlight) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, this.everyMs);\n this.timer.unref?.();\n }\n\n private async flush(): Promise<void> {\n const t = this.text.trim();\n if (this.closed || !t || t === this.sent) return;\n this.inFlight = true;\n this.sent = t;\n try {\n await this.send(t, ++this.seq);\n } catch {\n // Best effort: the next one, or the final ack, carries everything.\n } finally {\n this.inFlight = false;\n }\n if (this.text.trim() !== this.sent) this.schedule();\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// `sessionpipe control pair <receiver>`: a key enters this machine's trust store only\n// from this terminal (spec/CONTROL.md \u00A72). The receiver hands back a passkey and a\n// proof over sha256(\"sessionpipe.pair:<machine>:<code>\"); the key is trusted only once\n// the proof verifies here. Also the service files (launchd / systemd) that keep the\n// daemon running, and `control off`.\nimport { execFileSync } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { existsSync, mkdirSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { claudeAccounts, claudeDirs, drivableHarnesses, type HarnessAccount } from \"@sessionpipe/core\";\nimport { type TrustedKey, verifyEnrollment } from \"@sessionpipe/core/control\";\nimport {\n type ControlConfig,\n controlState,\n dropControlSecret,\n type PairedReceiver,\n readControl,\n writeControl,\n} from \"./store.js\";\n\ndeclare const __SESSIONPIPE_VERSION__: string;\nconst VERSION = typeof __SESSIONPIPE_VERSION__ === \"string\" ? __SESSIONPIPE_VERSION__ : \"0.0.0\";\n\nexport interface PairOptions {\n url: string;\n /** The person's sink token for this receiver (from `sink add`, or --token). Null:\n * open pairing, where the receiver offers it \u2014 the person approves a link and that\n * is the whole setup (CONTROL.md \u00A72). */\n token: string | null;\n folders: string[];\n mode: \"safe\" | \"auto\";\n name: string;\n out: (s: string) => void;\n fetch?: typeof fetch;\n sleep?: (ms: number) => Promise<void>;\n env?: NodeJS.ProcessEnv;\n /** Called with a sessions key the receiver handed over at pairing. */\n addSink?: (token: string) => void;\n /** The harnesses this machine can run a message in (default: those installed here). */\n harnesses?: string[];\n /** The harness accounts signed in here (default: every Claude Code config dir's). */\n accounts?: HarnessAccount[];\n /** How long expired codes are renewed for (default RENEW_FOR_MS). */\n renewFor?: number;\n}\n\n/** How long `control pair` keeps asking for fresh codes when nobody approves one. */\nexport const RENEW_FOR_MS = 60 * 60_000;\n\nasync function json(r: Response): Promise<Record<string, unknown>> {\n try {\n return (await r.json()) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nexport async function discover(\n url: string,\n f: typeof fetch,\n): Promise<{ control: string; rpId: string; open: boolean; events: string | null }> {\n const base = url.replace(/\\/$/, \"\");\n const r = await f(`${base}/.well-known/sessionpipe`);\n if (!r.ok) throw new Error(`${base} has no sessionpipe well-known file (HTTP ${r.status})`);\n const wk = (await r.json()) as {\n capabilities?: string[];\n endpoints?: { control?: string; events?: string };\n control?: { signing?: { rp_id?: string }; open_pairing?: boolean };\n };\n if (!wk.capabilities?.includes(\"control\") || !wk.endpoints?.control || !wk.control?.signing?.rp_id)\n throw new Error(`${base} doesn't serve control yet (its well-known file lists no control.signing)`);\n const abs = (ep: string) => (/^https?:\\/\\//.test(ep) ? ep : base + ep);\n return {\n control: abs(wk.endpoints.control),\n rpId: wk.control.signing.rp_id,\n open: wk.control.open_pairing === true,\n events: wk.endpoints.events ? abs(wk.endpoints.events) : null,\n };\n}\n\n/** Pair (or add a key to) this machine with one receiver. Returns the saved config. */\nexport async function pair(o: PairOptions): Promise<ControlConfig> {\n const f = o.fetch ?? fetch;\n const sleep = o.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)));\n const { control, rpId, open } = await discover(o.url, f);\n if (!o.token && !open)\n throw new Error(\n `${o.url} needs a key to pair: add it as a sink first (\\`sessionpipe sink add ${o.url} --token \u2026\\`) or pass --token.`,\n );\n // Open pairing: a secret only this terminal knows. The receiver keeps its hash, and\n // the status poll that hands over the machine's token must present it \u2014 so the link,\n // which the person opens elsewhere, is not a credential by itself.\n const pollKey = o.token ? null : randomBytes(32).toString(\"base64url\");\n const cfg: ControlConfig = readControl(o.env) ?? { name: o.name, folders: [], mode: o.mode, receivers: [] };\n cfg.name = o.name || cfg.name;\n cfg.mode = o.mode;\n cfg.folders = [...new Set([...cfg.folders, ...o.folders.map((d) => path.resolve(d))])];\n const existing = cfg.receivers.find((r) => r.control === control);\n let accounts = o.accounts;\n if (!accounts)\n try {\n const e = o.env ?? process.env;\n accounts = claudeAccounts(claudeDirs(e), e.HOME);\n } catch {\n accounts = [];\n }\n const auth = { authorization: `Bearer ${o.token ?? pollKey}`, \"content-type\": \"application/json\" };\n const hello = {\n ...(pollKey ? { poll_key: pollKey } : {}),\n name: cfg.name,\n harnesses: o.harnesses ?? drivableHarnesses(o.env ?? process.env),\n modes: [\"waiter\", \"turn\", \"resume\", \"fork\"],\n version: VERSION,\n folders: cfg.folders,\n mode: cfg.mode,\n ...(accounts.length ? { accounts } : {}),\n // This daemon takes `files` on a start (an older one would start without them).\n files: true,\n };\n /** One pairing code from the receiver. `machine` names the row a previous code\n * made, so a renewal adds no second machine. */\n const start = async (machine: string | undefined) => {\n const started = await f(`${control}/pair`, {\n method: \"POST\",\n headers: o.token ? auth : { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ...hello, ...(machine ? { machine } : {}) }),\n });\n const s = await json(started);\n if (started.status !== 201 && started.status !== 200)\n throw new Error(\n `the receiver refused to start pairing (HTTP ${started.status}${s.reason ? `: ${String(s.reason)}` : \"\"})`,\n );\n return {\n machine: String(s.machine),\n code: String(s.code),\n url: String(s.url),\n check: String(s.check),\n until: Date.parse(String(s.expires_at)) || Date.now() + 10 * 60_000,\n };\n };\n const host = new URL(o.url).host;\n const announce = (p: { url: string; check: string; until: number }) => {\n const spaced = /^\\d{6}$/.test(p.check) ? `${p.check.slice(0, 3)} ${p.check.slice(3)}` : p.check;\n o.out(\"\");\n // The approval happens on whatever device holds the person's passkey, which is\n // rarely the machine being paired (a server may have no screen at all): say so, or\n // the \"Touch ID\" line reads as \"do it here\" (2026-10-02, four machines, one headless).\n o.out(` On any phone or computer where you're signed in to ${host} (it doesn't have to be this one),`);\n if (pollKey) {\n // Open pairing: one address for everyone, and the digits are what the person types.\n o.out(` open ${p.url} and enter: ${spaced}`);\n o.out(\" then approve with that device's passkey (Touch ID, Face ID, a security key).\");\n o.out(\" Pairing several machines? Run this on each one: every machine shows its own digits.\");\n } else {\n o.out(\" open this link and approve with that device's passkey (Touch ID, Face ID, a security key):\");\n o.out(` ${p.url}`);\n o.out(` The page shows these digits too: ${p.check}`);\n }\n const mins = Math.max(1, Math.round((p.until - Date.now()) / 60_000));\n o.out(` This code is good for ${mins} minute${mins === 1 ? \"\" : \"s\"}; if it runs out, a fresh one appears here.`);\n o.out(\"\");\n };\n // A code lives ten minutes on the receiver. A person approving three headless\n // machines from a phone ran out of them (2026-10-08). A code nobody approved in time\n // is renewed from this terminal, with fresh digits, for up to RENEW_FOR_MS: the old\n // code is dead on the receiver, so no code lives longer than it did.\n const renewUntil = Date.now() + (o.renewFor ?? RENEW_FOR_MS);\n let cur = await start(existing?.machine);\n announce(cur);\n for (;;) {\n await sleep(2000);\n let p: Record<string, unknown> = {};\n let expired = Date.now() > cur.until;\n if (!expired) {\n const r = await f(`${control}/pair?code=${encodeURIComponent(cur.code)}`, { headers: auth }).catch(() => null);\n if (!r) continue;\n if (r.status === 404) throw new Error(\"the receiver lost the pairing; run `sessionpipe control pair` again\");\n p = await json(r);\n if (p.status === \"expired\") expired = true;\n else if (p.status !== \"paired\") continue;\n }\n if (expired) {\n if (Date.now() >= renewUntil) throw new Error(\"the pairing link expired; run `sessionpipe control pair` again\");\n // A keyed pairing keeps the machine row its first code made; an open one starts\n // clean under the same poll key (the receiver names the machine at approval).\n cur = await start(o.token ? cur.machine : existing?.machine);\n o.out(\" Nobody approved that code before it expired. Here is a fresh one; the old digits no longer work.\");\n announce(cur);\n continue;\n }\n const { machine, code } = cur;\n const key = p.key as TrustedKey;\n const proof = p.proof as { cred: string; ad: string; cd: string; sig: string };\n const v = await verifyEnrollment({ machine, code, key, proof, rpId });\n if (!v.ok) throw new Error(`the receiver's key didn't prove itself (${v.why}); nothing was trusted`);\n const token = existing?.token || (typeof p.token === \"string\" ? p.token : \"\");\n if (!token) throw new Error(\"the receiver didn't hand this machine its token\");\n const rec: PairedReceiver = existing ?? {\n url: o.url.replace(/\\/$/, \"\"),\n control,\n rpId,\n machine,\n token,\n keys: [],\n paired_at: new Date().toISOString(),\n };\n if (!rec.keys.some((k) => k.id === key.id)) rec.keys.push({ ...key, added_at: new Date().toISOString() });\n if (!existing) cfg.receivers.push(rec);\n writeControl(cfg, o.env);\n o.out(` \u2713 Paired with ${rec.url} as ${machine} \u00B7 ${rec.keys.length} key(s) trusted on this machine`);\n const named = accounts.flatMap((a) => (a.email ? [a.email] : []));\n if (named.length)\n o.out(` Its session board names your Claude Code account${named.length > 1 ? \"s\" : \"\"}: ${named.join(\", \")}`);\n // Whose passkey this machine now trusts: with open pairing, whoever approved the link.\n if (typeof p.account === \"string\")\n o.out(` Approved by ${p.account}. If that isn't you, run \\`sessionpipe control off\\` now.`);\n // The receiver may hand over a sessions-only key for the events lane, so its session\n // board shows this machine without a second step.\n if (typeof p.sink_token === \"string\" && o.addSink) o.addSink(p.sink_token);\n return cfg;\n }\n}\n\n/** `control off [<receiver>]`: tell the receiver, forget its token and keys. */\nexport async function off(o: {\n url?: string;\n out: (s: string) => void;\n fetch?: typeof fetch;\n env?: NodeJS.ProcessEnv;\n}) {\n const f = o.fetch ?? fetch;\n const cfg = readControl(o.env);\n if (!cfg) return o.out(\" control isn't set up on this machine\");\n const gone = cfg.receivers.filter((r) => !o.url || r.url === o.url.replace(/\\/$/, \"\"));\n for (const r of gone) {\n await f(`${r.control}/off`, { method: \"POST\", headers: { authorization: `Bearer ${r.token}` } }).catch(() => null);\n dropControlSecret(r);\n o.out(` removed ${r.url} (${r.machine}, ${r.keys.length} key(s))`);\n }\n cfg.receivers = cfg.receivers.filter((r) => !gone.includes(r));\n writeControl(cfg, o.env);\n return cfg;\n}\n\nexport function removeKey(id: string, env?: NodeJS.ProcessEnv): number {\n const cfg = readControl(env);\n if (!cfg) return 0;\n let n = 0;\n for (const r of cfg.receivers) {\n const before = r.keys.length;\n r.keys = r.keys.filter((k) => k.id !== id && !k.id.startsWith(id));\n n += before - r.keys.length;\n }\n writeControl(cfg, env);\n return n;\n}\n\n// --- the service -------------------------------------------------------------------\n\nconst LABEL = \"org.sessionpipe.control\";\nconst UNIT = \"sessionpipe-control.service\";\n\n/** Both files restart the daemon when it exits non-zero; an update exits UPDATE_EXIT\n * (75, autoupdate.ts) to come back on the new code. SESSIONPIPE_SERVICE tells the\n * daemon which manager that is (files from before it are recognized without it). */\nexport function serviceFiles(o: { node: string; cli: string; logDir: string; home?: string }) {\n const home = o.home ?? os.homedir();\n const xml = (s: string) => s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>${LABEL}</string>\n <key>ProgramArguments</key>\n <array><string>${xml(o.node)}</string><string>${xml(o.cli)}</string><string>control</string><string>run</string></array>\n <key>EnvironmentVariables</key><dict><key>SESSIONPIPE_SERVICE</key><string>launchd</string></dict>\n <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>ProcessType</key><string>Background</string>\n <key>StandardOutPath</key><string>${xml(path.join(o.logDir, \"daemon.log\"))}</string>\n <key>StandardErrorPath</key><string>${xml(path.join(o.logDir, \"daemon.log\"))}</string>\n</dict>\n</plist>\n`;\n const q = (s: string) => `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/%/g, \"%%\")}\"`;\n const unit = `[Unit]\nDescription=sessionpipe control daemon (signed messages to your coding sessions)\nAfter=network-online.target\n\n[Service]\nExecStart=${q(o.node)} ${q(o.cli)} control run\nEnvironment=SESSIONPIPE_SERVICE=systemd\nRestart=on-failure\nRestartForceExitStatus=75\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n`;\n return {\n plist: { file: path.join(home, \"Library\", \"LaunchAgents\", `${LABEL}.plist`), body: plist },\n unit: { file: path.join(home, \".config\", \"systemd\", \"user\", UNIT), body: unit },\n };\n}\n\nexport type Exec = (cmd: string, args: string[]) => string;\nconst execQuiet: Exec = (cmd, args) =>\n execFileSync(cmd, args, { encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"], timeout: 15_000 });\n\n/** A systemd user service stops when its person's last login ends \u2014 closing the ssh\n * session to a lab workstation or a cloud machine stopped the daemon with it \u2014 unless\n * the user lingers. `loginctl enable-linger` for yourself needs no root on systemd's\n * default policy; where it does, say the one command that does it. */\nexport function ensureLinger(user: string, exec: Exec = execQuiet): { on: boolean; note: string } {\n const lingering = () => {\n try {\n return /^Linger=yes/m.test(exec(\"loginctl\", [\"show-user\", user, \"--property=Linger\"]));\n } catch {\n return false;\n }\n };\n if (lingering()) return { on: true, note: \"it keeps running after you log out (linger was already on)\" };\n try {\n exec(\"loginctl\", [\"enable-linger\", user]);\n } catch {}\n if (lingering()) return { on: true, note: \"it keeps running after you log out (turned linger on)\" };\n return {\n on: false,\n note: `it stops when you log out: run \\`sudo loginctl enable-linger ${user}\\` once to keep it running`,\n };\n}\n\n/** Write and start the service for this platform. Returns what it did, in words. */\nexport function installService(o: {\n node: string;\n cli: string;\n env?: NodeJS.ProcessEnv;\n exec?: Exec;\n platform?: NodeJS.Platform;\n}): string {\n const logDir = controlState(o.env);\n mkdirSync(logDir, { recursive: true, mode: 0o700 });\n const f = serviceFiles({ node: o.node, cli: o.cli, logDir });\n const run = o.exec ?? execQuiet;\n const platform = o.platform ?? process.platform;\n if (platform === \"darwin\") {\n mkdirSync(path.dirname(f.plist.file), { recursive: true });\n writeFileSync(f.plist.file, f.plist.body);\n const uid = String(process.getuid?.() ?? \"\");\n for (const d of [\"gui\", \"user\"])\n try {\n run(\"launchctl\", [\"bootout\", `${d}/${uid}/${LABEL}`]);\n } catch {}\n try {\n run(\"launchctl\", [\"bootstrap\", `gui/${uid}`, f.plist.file]);\n return `launchd agent ${LABEL} (log: ${path.join(logDir, \"daemon.log\")})`;\n } catch {}\n // No one logged in at the screen (an ssh session to a Mac mini): the gui domain\n // doesn't exist. The user domain runs it now; after a restart it starts again at\n // the next login at the screen.\n run(\"launchctl\", [\"bootstrap\", `user/${uid}`, f.plist.file]);\n return `launchd agent ${LABEL} in the background domain, since nobody is logged in at this Mac's screen; after a restart it starts again when someone logs in there (log: ${path.join(logDir, \"daemon.log\")})`;\n }\n if (platform === \"linux\") {\n mkdirSync(path.dirname(f.unit.file), { recursive: true });\n writeFileSync(f.unit.file, f.unit.body);\n try {\n run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n run(\"systemctl\", [\"--user\", \"enable\", \"--now\", UNIT]);\n } catch {\n return `wrote ${f.unit.file}, but systemd --user isn't reachable here; run \\`sessionpipe control run\\` yourself (tmux, screen)`;\n }\n const linger = ensureLinger(os.userInfo().username, run);\n return `systemd user unit ${UNIT}; ${linger.note} (journalctl --user -u ${UNIT})`;\n }\n return \"no service manager for this platform yet; run `sessionpipe control run` yourself\";\n}\n\nexport function uninstallService(env?: NodeJS.ProcessEnv): void {\n const f = serviceFiles({ node: \"\", cli: \"\", logDir: controlState(env) });\n const run = (cmd: string, args: string[]) => {\n try {\n execFileSync(cmd, args, { stdio: \"ignore\", timeout: 15_000 });\n } catch {}\n };\n if (process.platform === \"darwin\" && existsSync(f.plist.file)) {\n run(\"launchctl\", [\"bootout\", `gui/${process.getuid?.() ?? \"\"}/${LABEL}`]);\n run(\"launchctl\", [\"bootout\", `user/${process.getuid?.() ?? \"\"}/${LABEL}`]);\n unlinkSync(f.plist.file);\n }\n if (process.platform === \"linux\" && existsSync(f.unit.file)) {\n run(\"systemctl\", [\"--user\", \"disable\", \"--now\", UNIT]);\n unlinkSync(f.unit.file);\n run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The `sdk` delivery mode (spec/CONTROL.md \u00A76): a session the daemon starts itself\n// through the Claude Agent SDK's streaming input, and keeps while it is in use, so\n// the next message lands in the same process with no cold start. Optional: the SDK\n// is a large package with its own binary, so sessionpipe does not depend on it. When\n// it can be imported (installed beside sessionpipe, or SESSIONPIPE_AGENT_SDK names\n// it), `start` goes through it; otherwise `start` is a headless `claude -p`.\n//\n// Measured (P1 spike 4, Claude Code 2.1.286): first token 1.5 s cold, 1.1 s warm;\n// zero turns while idle; but ~300 MB resident per held session, so the daemon\n// closes one that has been idle for ten minutes and a later message resumes it.\nimport type { SdkHost, SdkSession } from \"./daemon.js\";\n\ntype SdkQuery = AsyncIterable<{ type: string; subtype?: string; result?: unknown; is_error?: boolean }> & {\n interrupt(): Promise<void>;\n close(): void;\n};\ntype QueryFn = (p: { prompt: AsyncIterable<unknown>; options: Record<string, unknown> }) => SdkQuery;\n\nexport async function loadSdk(o: {\n claudeBin: string | null;\n env?: NodeJS.ProcessEnv;\n log: (s: string) => void;\n}): Promise<SdkHost | null> {\n const spec = o.env?.SESSIONPIPE_AGENT_SDK || \"@anthropic-ai/claude-agent-sdk\";\n let query: QueryFn;\n try {\n const mod = (await import(/* @vite-ignore */ spec)) as { query?: QueryFn };\n if (typeof mod.query !== \"function\") return null;\n query = mod.query;\n } catch {\n return null;\n }\n o.log(`Agent SDK found (${spec}): new sessions start in place`);\n return {\n start({\n session,\n cwd,\n mode,\n allowedTools,\n }: {\n session: string;\n cwd: string;\n mode: \"safe\" | \"auto\";\n configDir?: string;\n allowedTools?: string[];\n }): SdkSession {\n const queue: unknown[] = [];\n let wake: (() => void) | null = null;\n let closed = false;\n async function* input() {\n while (!closed) {\n while (queue.length) yield queue.shift();\n await new Promise<void>((r) => {\n wake = r;\n });\n }\n }\n const q = query({\n prompt: input(),\n options: {\n sessionId: session,\n cwd,\n permissionMode: mode === \"auto\" ? \"auto\" : \"dontAsk\",\n ...(allowedTools?.length ? { allowedTools } : {}),\n ...(o.claudeBin ? { pathToClaudeCodeExecutable: o.claudeBin } : {}),\n env: { ...(o.env ?? process.env), SESSIONPIPE_CONTROL_JOB: \"1\" },\n },\n });\n const waiting: { resolve: (v: { reply: string; error?: string }) => void }[] = [];\n let busy = false;\n let lastUsed = Date.now();\n void (async () => {\n try {\n for await (const m of q) {\n if (m.type !== \"result\") continue;\n busy = waiting.length > 1;\n lastUsed = Date.now();\n const w = waiting.shift();\n const text =\n typeof m.result === \"string\" && m.result.trim() ? m.result : \"(finished without a written reply)\";\n w?.resolve(m.is_error ? { reply: \"\", error: text } : { reply: text });\n }\n } catch (e) {\n for (const w of waiting.splice(0)) w.resolve({ reply: \"\", error: String((e as Error)?.message || e) });\n }\n })();\n return {\n send(text: string) {\n busy = true;\n lastUsed = Date.now();\n return new Promise((resolve) => {\n waiting.push({ resolve });\n queue.push({ type: \"user\", message: { role: \"user\", content: text }, parent_tool_use_id: null });\n wake?.();\n });\n },\n interrupt: () => q.interrupt(),\n close() {\n closed = true;\n wake?.();\n try {\n q.close();\n } catch {}\n },\n get busy() {\n return busy;\n },\n get lastUsed() {\n return lastUsed;\n },\n };\n },\n };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// `sessionpipe wait` (spec/CONTROL.md \u00A78): run by a session as a BACKGROUND command.\n// It blocks on the daemon's local socket \u2014 no network, no polling, no output \u2014 until\n// a verified message for this session arrives, prints it and exits 0; the harness\n// then wakes the session with it. If the daemon restarts, it reconnects in silence.\nimport { stateDir } from \"@sessionpipe/core\";\nimport { parseSessionRef } from \"@sessionpipe/core/control\";\nimport { ask, socketPath } from \"./local.js\";\n\nexport const RE_ARM =\n \"(Answer it right here, as you would answer the person at the keyboard: your reply is sent back to them automatically, so don't run a command or call a tool just to send it. Then, without mentioning it, start `sessionpipe wait` again as a background command, with the longest timeout your harness allows, to keep receiving messages.)\";\n\n/** The session to wait for: --session, else the harness's own env. */\nexport function waitSession(flag: string | undefined, env: NodeJS.ProcessEnv = process.env): string | null {\n if (flag) return parseSessionRef(flag) ? flag : null;\n if (env.CLAUDE_CODE_SESSION_ID) return `claude-code:${env.CLAUDE_CODE_SESSION_ID}`;\n if (env.CODEX_SESSION_ID) return `codex:${env.CODEX_SESSION_ID}`;\n return null;\n}\n\nexport async function waitForMessage(\n session: string,\n o: { env?: NodeJS.ProcessEnv; retryMs?: number } = {},\n): Promise<string> {\n const sock = socketPath(stateDir(o.env), o.env);\n for (;;) {\n // No timeout of our own: the harness's background deadline is the only clock.\n const r = await ask(sock, { op: \"wait\", session, pid: process.pid }, 2 ** 31 - 1);\n if (r?.op === \"message\") return `${r.text}\\n\\n${RE_ARM}`;\n if (r?.op === \"replaced\")\n return \"(Another `sessionpipe wait` for this session took over; this one stopped. Nothing to do.)\";\n await new Promise((res) => setTimeout(res, o.retryMs ?? 1000));\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Usage is data: asking for it must never enter a command's implementation. The site's\n// docs page reads the same table, so a command's usage is written in one place.\nexport function usageTable(harnesses: readonly string[]): Record<string, string> {\n return {\n connect:\n \"connect <receiver> [--machine NAME] [--rename-machine] [--allow-downgrade] [--tier 0-3] [--mode safe|auto] [--folder DIR]\u2026 [--no-service]\",\n install: `install [${harnesses.map((h) => `--${h}`).join(\" \")}] [--machine NAME] [--rename-machine] [--allow-downgrade] [--backfill DAYS] [--sink URL --tier N]`,\n sink: \"sink add|list|remove|test (use --help after a subcommand for its options)\",\n \"sink add\": \"sink add <url|file:PATH|stdout> [--tier 0-3] [--token T] [--secret S] [--pii] [--name N]\",\n \"sink list\": \"sink list\",\n \"sink remove\": \"sink remove <name>\",\n \"sink test\": \"sink test <name>\",\n secrets: \"secrets [move keychain|secret-service|file]\",\n \"secrets move\": \"secrets move keychain|secret-service|file\",\n status: \"status [--json]\",\n doctor: \"doctor [--json]\",\n tail: \"tail [--session ID] [--tier 0-3] [--harness NAME] [--all] [--json]\",\n backfill: `backfill [--days 30] [${harnesses.map((h) => `--${h}`).join(\" \")}]`,\n forget: \"forget <harness> <session>\",\n replay: \"replay [--sink NAME] [--from-start]\",\n update: \"update [off|on] (install the latest now; off/on: the daemon's daily update)\",\n \"update off\": \"update off\",\n \"update on\": \"update on\",\n control: \"control pair|mode|status|keys|off|run (use --help after a subcommand for its options)\",\n \"control pair\":\n \"control pair <receiver> [--folder DIR]\u2026 [--mode safe|auto] [--tier 0-3] [--token T] [--name N] [--no-service]\",\n \"control mode\": \"control mode auto|safe\",\n \"control status\": \"control status\",\n \"control keys\": \"control keys [remove <id>]\",\n \"control keys remove\": \"control keys remove <id>\",\n \"control off\": \"control off [<receiver>]\",\n \"control run\": \"control run\",\n wait: \"wait [--session <harness>:<id>]\",\n worker: \"worker <job-file> (internal: process one queued job)\",\n hook: \"hook (internal: harnesses run dist/hook.js directly)\",\n version: \"version (print the installed version)\",\n \"--version\": \"--version (print the installed version)\",\n \"-v\": \"-v (print the installed version)\",\n };\n}\n\nexport function commandHelp(args: string[], harnesses: readonly string[]): string | undefined {\n const usage = usageTable(harnesses);\n for (let n = Math.min(args.length, 3); n > 0; n--) {\n const line = usage[args.slice(0, n).join(\" \")];\n if (line) return `Usage: sessionpipe ${line}\\n\\n -h, --help Show help without running the command.`;\n }\n return undefined;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["execFileSync", "spawnSync", "existsSync", "readdirSync", "readFileSync", "realpathSync", "rmSync", "statSync", "unlinkSync", "os", "path", "existsSync", "mkdirSync", "readdirSync", "readFileSync", "statSync", "unlinkSync", "writeFileSync", "path", "path", "tail", "cap", "out", "out", "path", "settings", "entry", "path", "out", "existsSync", "mkdirSync", "writeFileSync", "unlinkSync", "readFileSync", "rows", "readdirSync", "statSync", "tail", "
|
|
3
|
+
"sources": ["../src/cli.ts", "../../core/src/adapters/acp-control.ts", "../../core/src/adapters/headless.ts", "../../core/src/adapters/antigravity.ts", "../../core/src/paths.ts", "../../core/src/readers/files.ts", "../../core/src/adapters/codex-rollout.ts", "../../core/src/readers/transcripts.ts", "../../core/src/adapters/claude-shaped.ts", "../../core/src/adapters/antigravity-control.ts", "../../core/src/adapters/claude-code.ts", "../../core/src/readers/git.ts", "../../core/src/adapters/claude-code-control.ts", "../../core/src/control/verify.ts", "../../core/src/adapters/codex.ts", "../../core/src/adapters/codex-config.ts", "../../core/src/adapters/codex-control.ts", "../../core/src/adapters/devin.ts", "../../core/src/readers/sqlite.ts", "../../core/src/adapters/gemini-cli.ts", "../../core/src/adapters/index.ts", "../../core/src/config.ts", "../../core/src/ulid.ts", "../../core/src/events.ts", "../../core/src/launched-by.ts", "../../core/src/outbox.ts", "../../core/src/privacy/pii.ts", "../../core/src/privacy/secrets.ts", "../../core/src/privacy/filter.ts", "../../core/src/short-id.ts", "../../core/src/sinks/file.ts", "../../core/src/sinks/stdout.ts", "../src/connect.ts", "../src/control/autoupdate.ts", "../src/update.ts", "../src/runtime.ts", "../src/launcher.ts", "../src/run.ts", "../src/control/aliases.ts", "../src/control/store.ts", "../src/secrets.ts", "../src/control/local.ts", "../src/http-sink.ts", "../../core/src/version.ts", "../src/control/cli.ts", "../src/control/daemon.ts", "../src/control/files.ts", "../src/control/reply.ts", "../src/control/route.ts", "../src/control/stream.ts", "../src/control/pair.ts", "../../core/src/service/index.ts", "../src/control/sdk.ts", "../src/control/wait.ts", "../src/help.ts"],
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n// SPDX-License-Identifier: Apache-2.0\n// sessionpipe: install once, hook everything, choose per sink what leaves.\n// connect \u00B7 install \u00B7 uninstall \u00B7 sink add|list|remove|test \u00B7 secrets \u00B7 status \u00B7\n// doctor \u00B7 tail \u00B7 backfill \u00B7 forget \u00B7 replay \u00B7 update \u00B7 hook \u00B7 worker\nimport { execFileSync, spawnSync } from \"node:child_process\";\nimport {\n existsSync,\n mkdtempSync,\n readdirSync,\n readFileSync,\n realpathSync,\n rmSync,\n statSync,\n unlinkSync,\n} from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n ADAPTERS,\n adapterByName,\n type BackfillRow,\n type Config,\n Cursors,\n claudeControl,\n claudeDirs,\n configFile,\n type Event,\n filterEvent,\n type HookCommand,\n machineName,\n makeEvent,\n Outbox,\n readConfig,\n type SinkConfig,\n stateDir,\n type Tier,\n tilde,\n writeConfig,\n} from \"@sessionpipe/core\";\nimport { connectFolders, connectTier } from \"./connect.js\";\nimport { autoUpdateOff, readUpdate, updateFile, updateLine, updateSummary } from \"./control/autoupdate.js\";\nimport { CONTROL_HELP, controlMain, enabledHarnesses, waitMain } from \"./control/cli.js\";\nimport type { Status } from \"./control/daemon.js\";\nimport { ask, socketPath } from \"./control/local.js\";\nimport { moveControlSecrets, pairedCount, parseMode, readControl, writeControl } from \"./control/store.js\";\nimport { commandHelp } from \"./help.js\";\nimport { installLauncher, launcherPath, launcherState, removeLauncher, usesLauncher } from \"./launcher.js\";\nimport { buildSinks, drain, factsState, flush, jobsDir, runJob, VERSION } from \"./run.js\";\nimport { assertSetupVersion, rerunGlobally, stableNode, viaNpx } from \"./runtime.js\";\nimport { bestStore, dropSinkSecrets, moveSinkSecrets, type StoreName, sinkWithSecrets, storeLabel } from \"./secrets.js\";\nimport { globalPrefix, installVersion, isNewer, latestVersion } from \"./update.js\";\n\nconst print = (s = \"\"): void => {\n process.stdout.write(`${s}\\n`);\n};\n// One command per process: `main` sets these for the run, every command reads them.\nlet args: string[] = [];\nlet out: (s?: string) => void = print;\nlet state = \"\";\nconst flag = (name: string): string | undefined => {\n const i = args.indexOf(name);\n return i >= 0 ? args[i + 1] : undefined;\n};\nconst has = (name: string): boolean => args.includes(name);\nconst distDir = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface Io {\n /** One line of output. */\n out: (s?: string) => void;\n /** What a failed command says, then `exit(1)`. */\n err: (s: string) => void;\n exit: (code: number) => void;\n}\n\n/** Run one command: `argv` is what follows `sessionpipe`; `io` is this process by default. */\nexport async function main(\n argv: string[],\n io: Io = { out: print, err: (s) => void process.stderr.write(s), exit: (c) => process.exit(c) },\n): Promise<void> {\n args = argv;\n out = io.out;\n state = stateDir();\n try {\n await command(args[0] ?? \"help\");\n } catch (e) {\n io.err(`sessionpipe: ${(e as Error).message}\\n`);\n io.exit(1);\n }\n}\n\n/** Is this file the process entrypoint? By real path: npm's bin link to it counts. */\nexport function isEntrypoint(argv1: string | undefined, url: string): boolean {\n try {\n return !!argv1 && realpathSync(argv1) === fileURLToPath(url);\n } catch {\n return false;\n }\n}\n\n/** The command a hook entry runs: the launcher, which outlives node upgrades\n * (launcher.ts); on Windows, this node by a stable absolute path and hook.js by its\n * real path. */\nfunction hookCommand(): HookCommand {\n if (usesLauncher()) {\n const l = launcherPath();\n return (a) => ({ argv: [l, ...a], command: `${JSON.stringify(l)} ${a.join(\" \")}` });\n }\n const node = stableNode(process.execPath);\n let script = path.join(distDir, \"hook.js\");\n try {\n script = realpathSync(script);\n } catch {}\n return (a) => ({\n argv: [node, script, ...a],\n command: `${JSON.stringify(node)} ${JSON.stringify(script)} ${a.join(\" \")}`,\n });\n}\n\nfunction selectedAdapters(): typeof ADAPTERS {\n const named = ADAPTERS.filter((a) => has(`--${a.name}`));\n if (named.length) return named;\n return ADAPTERS.filter((a) => a.detect());\n}\n\nasync function command(cmd: string): Promise<void> {\n // Help wins over every command and argument, before any command can do work.\n if (has(\"--help\") || has(\"-h\")) {\n const usage = commandHelp(\n args,\n ADAPTERS.map((a) => a.name),\n );\n return usage ? out(usage) : help();\n }\n switch (cmd) {\n case \"connect\":\n return connect();\n case \"install\":\n return install();\n case \"secrets\":\n return secrets();\n case \"uninstall\":\n return uninstall();\n case \"sink\":\n return sink();\n case \"status\":\n return status();\n case \"doctor\":\n return await doctor();\n case \"tail\":\n return tail();\n case \"backfill\":\n return backfill();\n case \"forget\":\n return forget();\n case \"replay\":\n return replay();\n case \"update\":\n return update();\n case \"worker\":\n return workerFromArgv();\n case \"control\":\n return controlMain(args, out, distDir);\n case \"wait\":\n return waitMain(args, out);\n case \"hook\":\n out(\"sessionpipe hook is dist/hook.js; harnesses run it directly\");\n return;\n case \"--version\":\n case \"-v\":\n case \"version\":\n out(VERSION);\n return;\n default:\n return help();\n }\n}\n\nfunction help(): void {\n out(`sessionpipe ${VERSION} \u2014 an open protocol for what your coding agents are doing\n\nUsage:\n sessionpipe connect <receiver> [--machine NAME] [--rename-machine] [--allow-downgrade] [--tier 0-3] [--mode safe|auto|inherit] [--folder DIR]\u2026\n (everything, in one go: hooks, a sink, signed messages, keys)\n sessionpipe install [--claude-code --codex --gemini-cli --antigravity --devin] [--machine NAME] [--rename-machine] [--allow-downgrade] [--backfill DAYS] [--sink URL --tier N]\n sessionpipe uninstall [--claude-code --codex --gemini-cli --antigravity --devin | --all] [--keep-state]\n sessionpipe sink add <url|file:PATH|stdout> [--tier 0-3] [--token T] [--pii] [--name N]\n sessionpipe sink list | remove <name> | test <name>\n sessionpipe secrets [move keychain|secret-service|file] (where the machine's keys live)\n sessionpipe status [--json] | doctor [--json]\n sessionpipe tail [--session ID] [--tier N] [--harness NAME]\n sessionpipe backfill [--days 30] | forget <harness> <session> | replay --sink NAME\n sessionpipe update [off|on] (install the latest now; off/on: the daemon's daily update)\n${CONTROL_HELP}\n\nDocs: https://sessionpipe.org \u00B7 nothing leaves this machine until you add a sink.`);\n}\n\n/** --machine names a first install. A repeat setup must not split sessions from control. */\nfunction setupConfig(): Config {\n const cfg = readConfig();\n const requested = flag(\"--machine\");\n if ((has(\"--machine\") || has(\"--rename-machine\")) && (!requested || requested.startsWith(\"-\")))\n throw new Error(\"--machine NAME is required when naming or renaming a machine\");\n const machine = requested?.slice(0, 80);\n const control = readControl();\n const hooksName = existsSync(configFile()) ? machineName(cfg, os.hostname()) : undefined;\n // A daemon paired as `<host>.local` (what `control pair` did before 0.9.0 on a Mac) is\n // this machine under the hooks' name, `<host>`: that name keeps a receiver's sessions\n // in one place, and the daemon is renamed to it below, which costs nothing since\n // receivers key a pairing by id. A daemon named on purpose keeps its name.\n const pairedName =\n control && hooksName && machineName({} as Config, control.name) === hooksName ? hooksName : control?.name;\n const current = cfg.machine || pairedName || hooksName;\n if (current && machine && machine !== current && !has(\"--rename-machine\")) {\n out(\n ` Keeping configured machine name ${current}; ignoring --machine ${machine}. Use --rename-machine with --machine NAME for an explicit rename.`,\n );\n cfg.machine = current;\n } else {\n const name = machine || current || machineName(cfg, os.hostname());\n // The daemon goes by the same name as the hooks, or a receiver shows one machine\n // twice. An explicit rename renames the paired daemon too: control.json carries the\n // name, the daemon re-reads it and says it in its next hello (receivers key machines\n // by id, so the pairing holds). receivers[].machine is that id, not the name.\n if (control && control.name !== name && (machine || name === pairedName)) {\n writeControl({ ...control, name });\n out(` Renamed the control daemon ${control.name} \u2192 ${name}; its next hello tells each receiver.`);\n }\n cfg.machine = name;\n }\n return cfg;\n}\n\nasync function install(): Promise<void> {\n const cfg = setupConfig();\n if (viaNpx(distDir)) return rerunGlobally(args, out, { allowDowngrade: has(\"--allow-downgrade\") });\n assertSetupVersion(has(\"--allow-downgrade\"));\n // A sink URL given here is added first, so the install knows whether it needs\n // every tool event or only the heartbeat's one.\n const sinkUrl = flag(\"--sink\");\n if (sinkUrl) await sinkAdd(sinkUrl, cfg);\n const adapters = selectedAdapters();\n if (!adapters.length) {\n out(\n \" No supported harness found on this machine (Claude Code, Codex, Gemini CLI, Antigravity, Devin). Pass --<harness> to force one.\",\n );\n return;\n }\n out(` Machine: ${machineName(cfg, os.hostname())}`);\n const lean = isLean(cfg);\n if (lean)\n out(\n \" No sink above tier 0: hooking one tool event per harness (the heartbeat's). `sink add \u2026 --tier 1` or higher hooks the rest.\",\n );\n installHarnesses(adapters, cfg, lean);\n writeConfig(cfg);\n const days = Number(flag(\"--backfill\") ?? 30);\n if (days > 0) backfillRows(adapters, days, cfg);\n out(\"\");\n const live = cfg.sinks.filter((s) => !s.paused);\n if (live.length) out(` Reporting to ${live.map((s) => `${s.name} (tier ${s.tier})`).join(\", \")}.`);\n else\n out(\n \" Nothing leaves this machine yet: events go to the local outbox. `sessionpipe tail` shows them; `sessionpipe sink add <url> --tier N` sends them.\",\n );\n out(\" Sessions already running pick up hooks on their next start (Claude Code \u2265 2.1.280 picks them up live).\");\n}\n\n/** No sink takes tier \u2265 1: the harness only needs one tool event (issue #12). */\nfunction isLean(cfg: Config): boolean {\n return !cfg.sinks.some((s) => !s.paused && Math.min(s.tier, s.max_tier ?? 3) >= 1);\n}\n\n/** Write the hooks for these harnesses; remember which files sessionpipe created. */\nfunction installHarnesses(adapters: readonly (typeof ADAPTERS)[number][], cfg: Config, lean: boolean): void {\n if (usesLauncher()) {\n const node = stableNode(process.execPath);\n const l = installLauncher({ distDir, node, version: VERSION });\n if (l.changed)\n out(` \u2713 hook launcher: ${tilde(l.launcher)} (node ${tilde(node)}, or any node on PATH once that one is gone)`);\n }\n const hc = hookCommand();\n for (const a of adapters) {\n const prev = cfg.harnesses[a.name] ?? {};\n const created = new Set(prev.created ?? []);\n const reports = a.install(hc, process.env, { lean, created: [...created] });\n for (const r of reports) {\n if (r.created) created.add(r.file);\n const mark = r.skipped ? \"!\" : r.changed ? \"\u2713\" : \"=\";\n out(\n ` ${mark} ${a.name}: ${tilde(r.file)}${r.note ? ` \u2014 ${r.note}` : r.changed ? \" written\" : \" already current\"}`,\n );\n }\n cfg.harnesses[a.name] = { enabled: true, ...(created.size ? { created: [...created] } : {}) };\n if (a.name === \"gemini-cli\")\n out(\" note: Gemini CLI's own telemetry defaults logPrompts on; that is Google's setting, not sessionpipe's.\");\n if (a.name === \"devin\" && !reports.some((r) => r.skipped))\n out(\n \" note: Devin ignores a hooks file whole if it holds one event name it doesn't know; run `/hooks` in `devin` to see what loaded.\",\n );\n if (a.name === \"codex\" && !reports.some((r) => r.skipped))\n out(\n \" note: Codex runs non-managed hooks only after you approve them: start `codex` and accept the hook review. The notify fallback reports turn ends meanwhile.\",\n );\n }\n}\n\n/** `sessionpipe connect <receiver>`: everything a machine needs, in one command and one\n * approval \u2014 the hooks for every agent and every Claude Code account here, a sink at\n * tier 2, signed messages (the daemon, paired with open pairing), the keys moved into\n * the keychain when there is one, the daemon kept running past logout, the last 30\n * days backfilled. Run it again and it only fixes what's missing. Asks nothing: the\n * mode is --mode or safe, the folders are --folder, this one, or where your recent\n * sessions ran \u2014 never the home folder. */\nasync function connect(): Promise<void> {\n const raw = args[1];\n if (!raw || raw.startsWith(\"-\"))\n return out(\n \"usage: sessionpipe connect <receiver> [--machine NAME] [--rename-machine] [--allow-downgrade] [--tier 0-3] [--mode safe|auto|inherit] [--folder DIR]\u2026 [--no-service]\",\n );\n const cfg = setupConfig();\n if (viaNpx(distDir)) return rerunGlobally(args, out, { allowDowngrade: has(\"--allow-downgrade\") });\n assertSetupVersion(has(\"--allow-downgrade\"));\n const url = (/^https?:\\/\\//.test(raw) ? raw : `https://${raw}`).replace(/\\/$/, \"\");\n const host = new URL(url).host;\n const name = machineName(cfg, os.hostname());\n const before = cfg.sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n const tier = connectTier(flag(\"--tier\"), before?.tier);\n out(` Connecting ${name} to ${host}.`);\n\n // 1. The hooks, for every agent on this machine (and every Claude Code account).\n const adapters = ADAPTERS.filter((a) => a.detect());\n if (!adapters.length)\n out(\n \" ! No coding agent here yet (Claude Code, Codex, Gemini CLI, Antigravity, Devin): run `sessionpipe install` once you have one.\",\n );\n else installHarnesses(adapters, cfg, tier < 1);\n writeConfig(cfg);\n await reportClaudeAccounts();\n const rows = collectRows(adapters, 30);\n\n // 2. One approval on any signed-in device: the machine's control token and its\n // sessions key together.\n const control = readControl();\n const paired = control?.receivers.find((r) => r.url === url);\n const sinkNow = readConfig().sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n if (paired && sinkNow && (sinkNow.token || sinkNow.token_in)) {\n out(` \u2713 Already paired with ${host} as ${paired.machine}: nothing to approve.`);\n } else {\n const recent = rows\n .slice()\n .sort((a, b) => b.row.last_at - a.row.last_at)\n .map((r) => r.row.session.cwd ?? \"\");\n const choice = connectFolders({\n cwd: process.cwd(),\n home: os.homedir(),\n flags: argsAll(\"--folder\"),\n existing: control?.folders ?? [],\n recent,\n exists: (d) => {\n try {\n return statSync(d).isDirectory();\n } catch {\n return false;\n }\n },\n });\n if (choice.from === \"recent\")\n out(` Folders from your recent sessions: ${choice.folders.map((d) => tilde(d)).join(\", \")}`);\n if (choice.from === \"none\")\n out(\n \" ! No folder for sessions you message yet (this ran from your home folder, and no recent session ran anywhere else). Run `sessionpipe control pair` again from a project folder, or with --folder.\",\n );\n const mode = parseMode(flag(\"--mode\")) ?? control?.mode ?? \"safe\";\n await controlMain(\n [\n \"control\",\n \"pair\",\n url,\n \"--mode\",\n mode,\n \"--tier\",\n String(tier),\n \"--name\",\n control?.name ?? name,\n ...choice.folders.flatMap((d) => [\"--folder\", d]),\n ...(has(\"--no-service\") ? [\"--no-service\"] : []),\n ],\n out,\n distDir,\n );\n if (mode === \"safe\")\n out(\n \" Safe mode: `sessionpipe control mode auto` lets sessions you message work unattended (Claude Code's auto mode).\",\n );\n }\n\n // 3. The sink at the tier asked for, with the receiver's cap and endpoints.\n const after = readConfig();\n const sink = after.sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n if (sink) {\n const old = sink.tier;\n sink.tier = tier;\n await learnReceiver(sink, tier);\n writeConfig(after);\n const eff = Math.min(sink.tier, sink.max_tier ?? 3) as Tier;\n out(` \u2713 Sink ${sink.name}: tier ${eff}${old !== tier ? ` (was ${old})` : \"\"} \u2014 sends ${TIER_TEXT[eff]}`);\n } else out(` ! No sink for ${host}: \\`sessionpipe sink add ${url} --token <key> --tier ${tier}\\``);\n\n // 4. Keys into the keychain, when this session has one unlocked.\n const store = bestStore();\n if (store !== \"file\") {\n const a = moveSinkSecrets(store);\n const b = moveControlSecrets(store);\n const kept = [...a.kept, ...b.kept];\n out(` \u2713 Keys: in ${storeLabel(store)}${kept.length ? ` (left in the file: ${kept.join(\", \")})` : \"\"}`);\n } else\n out(\n ` Keys: in ${tilde(path.dirname(configFile()))} at 0600 \u2014 no unlocked keychain in this session${process.env.SSH_CONNECTION ? \" (an ssh shell)\" : \"\"}`,\n );\n\n // 5. The last 30 days, now that there is somewhere to send them.\n if (rows.length) queueBackfill(rows, 30, readConfig());\n out(\"\");\n out(` Done: ${name} reports to ${host} and takes messages you sign on a device it trusts.`);\n out(\" Run this again any time; it only fixes what's missing. `sessionpipe doctor` checks everything.\");\n}\n\nfunction argsAll(name: string): string[] {\n return args.flatMap((a, i) => (a === name && args[i + 1] ? [args[i + 1] as string] : []));\n}\n\n/** Each Claude Code account on this machine, and whether Claude Code says it's signed\n * in from here (a message's headless run uses this login). */\nasync function reportClaudeAccounts(): Promise<void> {\n const bin = claudeControl.findClaude();\n if (!bin) return;\n const dirs = claudeDirs();\n const answers = await Promise.all(dirs.map((d) => claudeControl.claudeLogin(bin, d)));\n dirs.forEach((d, i) => {\n const l = answers[i] as claudeControl.Login;\n if (l.loggedIn === true)\n out(\n ` \u2713 Claude Code ${tilde(d)}: signed in${l.method ? ` (${[l.method, l.subscription].filter(Boolean).join(\", \")})` : \"\"}`,\n );\n else if (l.loggedIn === false)\n out(\n ` ! Claude Code ${tilde(d)}: not signed in as this shell sees it \u2014 ${claudeControl.loginCommand(d)}${process.platform === \"darwin\" && process.env.SSH_CONNECTION ? \" (over ssh a Mac's keychain login can't be read; log in at the screen)\" : \"\"}`,\n );\n });\n}\n\n/** `sessionpipe secrets [move <store>]`: where this machine's keys live. */\nfunction secrets(): void {\n const sub = args[1];\n if (sub === \"move\") {\n const to = args[2] as StoreName | undefined;\n if (to !== \"keychain\" && to !== \"secret-service\" && to !== \"file\") {\n out(\"usage: sessionpipe secrets move keychain|secret-service|file\");\n return;\n }\n const a = moveSinkSecrets(to);\n const b = moveControlSecrets(to);\n const moved = [...a.moved, ...b.moved];\n const kept = [...a.kept, ...b.kept];\n out(\n moved.length ? ` \u2713 moved to ${storeLabel(to)}: ${moved.join(\", \")}` : ` nothing to move to ${storeLabel(to)}`,\n );\n if (kept.length)\n out(` ! left where they are (unreadable here, or ${storeLabel(to)} refused them): ${kept.join(\", \")}`);\n return;\n }\n const cfg = readConfig();\n const where = (s: SinkConfig): string =>\n s.token_in\n ? `${storeLabel(s.token_in)}${sinkWithSecrets(s) ? \"\" : \" \u2014 can't be read from this session (locked?)\"}`\n : s.token || s.secret\n ? `${tilde(configFile())} (0600)`\n : \"no key\";\n for (const s of cfg.sinks) out(` sink ${s.name.padEnd(20)} ${where(s)}`);\n for (const r of readControl()?.receivers ?? [])\n out(\n ` control ${new URL(r.url).host.padEnd(17)} ${r.token_in ? `${storeLabel(r.token_in)}${r.token ? \"\" : \" \u2014 can't be read from this session (locked?)\"}` : \"control.json (0600)\"}`,\n );\n if (!cfg.sinks.length && !readControl()?.receivers.length) out(\" no keys on this machine\");\n out(` best store from this session: ${storeLabel(bestStore())}`);\n}\n\n/** The one env var that moves a harness's config off the real home (`antigravity`\n * lives under Gemini CLI's). A harness with none (null) can never be isolated. */\nconst AWAY_FROM_HOME: Record<string, string | null> = {\n \"claude-code\": \"CLAUDE_CONFIG_DIR\",\n codex: \"CODEX_HOME\",\n \"gemini-cli\": \"GEMINI_CLI_HOME\",\n antigravity: \"GEMINI_CLI_HOME\",\n devin: \"XDG_CONFIG_HOME\",\n};\n/** Harnesses this process would read out of the real home although SESSIONPIPE_CONFIG\n * or SESSIONPIPE_STATE say \"not this machine\". Setting those is how a test or an agent\n * sandboxes sessionpipe \u2014 but they only cover sessionpipe's own files, so an\n * all-harnesses uninstall under them still empties the live hooks files (measured\n * twice on a reporting machine, 8 Oct 2026: six config files rewritten, every `status`\n * row `missing`). */\nfunction unisolated(): string[] {\n if (!process.env.SESSIONPIPE_CONFIG && !process.env.SESSIONPIPE_STATE) return [];\n return ADAPTERS.filter((a) => {\n const v = AWAY_FROM_HOME[a.name];\n return v === null || (typeof v === \"string\" && !process.env[v]);\n }).map((a) => a.name);\n}\n\nfunction uninstall(): void {\n // `install` has had a per-harness selector all along; uninstall taking every harness\n // with no way to say otherwise is how one harness's test strips the other four.\n const named = ADAPTERS.filter((a) => has(`--${a.name}`));\n const all = !named.length;\n if (all && !has(\"--all\")) {\n const exposed = unisolated();\n if (exposed.length) {\n out(\n ` ! Refusing an uninstall of every harness: SESSIONPIPE_CONFIG/SESSIONPIPE_STATE point away from this machine, but ${exposed.join(\", \")} still resolve from ${tilde(os.homedir())}.`,\n );\n out(` Nothing was changed. Name what to remove (${exposed.map((n) => `--${n}`).join(\" \")}),`);\n out(\" pass --all if you do mean every harness on this machine, or unset SESSIONPIPE_CONFIG/SESSIONPIPE_STATE.\");\n process.exitCode = 2;\n return;\n }\n }\n const cfg = readConfig();\n for (const a of all ? ADAPTERS : named) {\n const created = cfg.harnesses[a.name]?.created ?? [];\n for (const r of a.uninstall(process.env, { created }))\n if (r.changed) out(` \u2713 ${a.name}: ${r.note ?? `hooks removed from ${tilde(r.file)}`}`);\n else if (r.skipped) out(` ! ${a.name}: ${tilde(r.file)} \u2014 ${r.note}`);\n delete cfg.harnesses[a.name];\n }\n writeConfig(cfg);\n // The launcher is shared: removing it while another harness still has hook entries\n // would leave that harness running a path that is gone.\n if (all && usesLauncher()) removeLauncher();\n if (!all) {\n out(` Still installed: ${Object.keys(cfg.harnesses).join(\", \") || \"nothing\"}.`);\n return;\n }\n if (!has(\"--keep-state\"))\n out(\n ` Outbox and state kept under ${tilde(state)} (delete it yourself, or pass nothing: it prunes after ${readConfig().keep_days ?? 30} days).`,\n );\n out(\" Done. Every config file is byte-identical except for the entries sessionpipe wrote.\");\n}\n\nasync function sink(): Promise<void> {\n const sub = args[1];\n const cfg = readConfig();\n if (sub === \"add\" && args[2]) return sinkAdd(args[2], cfg);\n if (sub === \"list\") {\n if (!cfg.sinks.length) out(\" no sinks\");\n for (const s of cfg.sinks)\n out(\n ` ${s.name.padEnd(16)} ${s.url.padEnd(44)} tier ${s.tier}${s.max_tier !== undefined && s.max_tier < s.tier ? ` (capped ${s.max_tier})` : \"\"}${s.pii ? \" pii\" : \"\"}${s.control ? \" control\" : \"\"}${s.paused ? ` PAUSED ${s.paused}` : \"\"}`,\n );\n return;\n }\n if (sub === \"remove\" && args[2]) {\n const n = cfg.sinks.length;\n for (const s of cfg.sinks) if (s.name === args[2]) dropSinkSecrets(s);\n cfg.sinks = cfg.sinks.filter((s) => s.name !== args[2]);\n writeConfig(cfg);\n out(cfg.sinks.length < n ? ` \u2713 removed ${args[2]}` : ` no sink named ${args[2]}`);\n return;\n }\n if (sub === \"test\" && args[2]) {\n const s = cfg.sinks.find((x) => x.name === args[2]);\n if (!s) return out(` no sink named ${args[2]}`);\n const [sk] = buildSinks([s]);\n if (!sk) return out(\" sink type not supported yet\");\n // One heartbeat, then its forget: the receiver sees the round trip and keeps no row.\n const session = { id: `test-${Date.now()}`, machine: machineName(cfg, os.hostname()) };\n const mk = (type: string, seq: number) =>\n makeEvent(\n { type, harnessEvent: \"test\", data: {} },\n { harness: { name: \"sessionpipe\" }, session: { ...session, seq } },\n );\n const r = await sk.send([\n filterEvent(mk(\"session.heartbeat\", 0), sk.tier, sk.pii) as Event,\n filterEvent(mk(\"session.forgotten\", 1), sk.tier, sk.pii) as Event,\n ]);\n out(\n r.ok\n ? ` \u2713 ${s.name}: ${r.status ?? \"ok\"} accepted ${r.accepted ?? 2} (a heartbeat and its forget)`\n : ` \u2717 ${s.name}: ${r.status ?? \"\"} ${r.error ?? \"\"} (${r.action})`,\n );\n return;\n }\n out(\n \"usage: sessionpipe sink add <url|file:PATH|stdout> [--tier N] [--token T] [--pii] [--name N] | list | remove <name> | test <name>\",\n );\n}\n\nasync function sinkAdd(url: string, cfg: Config): Promise<void> {\n const tier = Math.max(0, Math.min(3, Number(flag(\"--tier\") ?? 0))) as Tier;\n const name = flag(\"--name\") ?? (url === \"stdout\" ? \"stdout\" : url.startsWith(\"file:\") ? \"file\" : new URL(url).host);\n // Control is not a property of a sink: it is set up per machine, with keys enrolled\n // at this terminal (spec/CONTROL.md \u00A72, `sessionpipe control pair`). A sink never\n // carries `control: true`.\n if (has(\"--control\"))\n out(\" --control is ignored: control is set up per machine (`sessionpipe control pair <url>`, spec/CONTROL.md)\");\n const s: SinkConfig = { name, url, tier, pii: has(\"--pii\") };\n // Changing a sink's tier keeps the key it has (pairing may have handed it over, and\n // it may live in a keychain): only --token / --secret replace one.\n const prev = cfg.sinks.find((x) => x.name === name && x.url === url);\n const token = flag(\"--token\");\n const secret = flag(\"--secret\");\n if (prev?.token_in && !token && !secret) s.token_in = prev.token_in;\n else {\n const kept = prev ? sinkWithSecrets(prev) : null;\n const t = token ?? kept?.token;\n const sec = secret ?? kept?.secret;\n if (t) s.token = t;\n if (sec) s.secret = sec;\n if (prev?.token_in) dropSinkSecrets(prev);\n }\n await learnReceiver(s, tier);\n cfg.sinks = cfg.sinks.filter((x) => x.name !== name).concat([s]);\n writeConfig(cfg);\n out(` \u2713 sink ${name}: ${url} at tier ${Math.min(tier, s.max_tier ?? 3)}${s.pii ? \", pii\" : \"\"}`);\n out(` tier ${tier} sends: ${TIER_TEXT[Math.min(tier, s.max_tier ?? 3) as Tier]}`);\n}\n/** Read the receiver's well-known file onto the sink: its tier cap and endpoints. */\nasync function learnReceiver(s: SinkConfig, tier: Tier): Promise<void> {\n if (!/^https?:\\/\\//.test(s.url)) return;\n try {\n const r = await fetch(`${s.url.replace(/\\/$/, \"\")}/.well-known/sessionpipe`, { signal: AbortSignal.timeout(8000) });\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n const wk = (await r.json()) as { max_tier?: number; endpoints?: { events?: string }; capabilities?: string[] };\n if (typeof wk.max_tier === \"number\") {\n s.max_tier = wk.max_tier as Tier;\n if (wk.max_tier < tier) out(` receiver's max_tier is ${wk.max_tier}: sending tier ${wk.max_tier}, not ${tier}`);\n }\n if (wk.endpoints) (s as SinkConfig & { endpoints?: unknown }).endpoints = wk.endpoints;\n s.well_known_at = new Date().toISOString();\n } catch (e) {\n out(\n ` ! ${s.url} has no readable /.well-known/sessionpipe (${(e as Error).message}); added anyway, at tier ${tier}`,\n );\n }\n}\n\nconst TIER_TEXT: Record<Tier, string> = {\n 0: \"session state and timing, machine, folder, repo, branch, model, title, link, the KIND of attention needed \u2014 no tool names, no words\",\n 1: \"tier 0 + tool names, durations, ok/error, file paths, the attention message, subagents, compactions \u2014 no prompts\",\n 2: \"tier 1 + your prompts and the assistant's text, secrets removed\",\n 3: \"everything, including tool input and output\",\n};\n\n/** Each harness's sessions of the last `days` days, as the backfill reads them. */\nfunction collectRows(\n adapters: readonly (typeof ADAPTERS)[number][],\n days: number,\n): { harness: string; row: BackfillRow }[] {\n const since = Date.now() - days * 86_400_000;\n const rows: { harness: string; row: BackfillRow }[] = [];\n for (const a of adapters) {\n try {\n for (const row of a.backfill(since)) rows.push({ harness: a.name, row });\n } catch {}\n }\n return rows;\n}\n\nfunction backfillRows(adapters: readonly (typeof ADAPTERS)[number][], days: number, cfg: Config): void {\n queueBackfill(collectRows(adapters, days), days, cfg);\n}\n\nfunction queueBackfill(rows: { harness: string; row: BackfillRow }[], days: number, cfg: Config): void {\n const outbox = new Outbox(state);\n let n = 0;\n const machine = machineName(cfg, os.hostname());\n for (const { harness, row } of rows) {\n const ref = { harness, session: row.session.id };\n const facts = factsState(state).get(harness, row.session.id);\n if (facts.backfilled) continue;\n const { id, ...rest } = row.session;\n const e = makeEvent(\n {\n type: \"session.backfill\",\n harnessEvent: \"backfill\",\n data: {\n started_at: new Date(row.started_at).toISOString(),\n last_at: new Date(row.last_at).toISOString(),\n ...(row.turns !== undefined ? { turns: row.turns } : {}),\n },\n },\n {\n harness: { name: harness },\n session: { ...rest, id, seq: outbox.nextSeq(ref), machine, ...(rest.cwd ? { cwd: tilde(rest.cwd) } : {}) },\n now: row.last_at,\n },\n );\n outbox.append(ref, [e]);\n factsState(state).save(harness, row.session.id, { backfilled: true });\n n++;\n }\n out(` \u2713 Backfill: ${n} session${n === 1 ? \"\" : \"s\"} from the last ${days} days queued as session.backfill`);\n void drain(state, cfg.sinks, outbox);\n}\n\nfunction backfill(): void {\n backfillRows(selectedAdapters(), Number(flag(\"--days\") ?? 30), readConfig());\n}\n\nasync function forget(): Promise<void> {\n const [, harness, session] = args;\n if (!harness || !session) return out(\"usage: sessionpipe forget <harness> <session>\");\n const cfg = readConfig();\n const outbox = new Outbox(state);\n const ref = { harness, session };\n const e = makeEvent(\n { type: \"session.forgotten\", harnessEvent: \"forget\", data: {} },\n {\n harness: { name: harness },\n session: { id: session, seq: outbox.nextSeq(ref), machine: machineName(cfg, os.hostname()) },\n },\n );\n const sinks = buildSinks(cfg.sinks);\n for (const s of sinks) {\n const r = await s.send([filterEvent(e, s.tier, s.pii) as Event]);\n out(r.ok ? ` \u2713 ${s.name}: asked to delete ${harness}:${session}` : ` \u2717 ${s.name}: ${r.error ?? r.status}`);\n }\n outbox.delete(ref);\n out(\" local outbox for the session removed\");\n}\n\nasync function replay(): Promise<void> {\n const name = flag(\"--sink\");\n const cfg = readConfig();\n const sinks = name ? cfg.sinks.filter((s) => s.name === name) : cfg.sinks;\n if (!sinks.length) return out(\" no such sink\");\n for (const s of sinks) {\n if (has(\"--from-start\")) new Cursors(state, s.name).write({});\n }\n const d = await flush(state, sinks, new Outbox(state), undefined, { force: true });\n for (const [k, v] of Object.entries(d)) out(` ${k}: ${v} event${v === 1 ? \"\" : \"s\"} delivered`);\n}\n\ntype ControlHealth = {\n running: boolean;\n receivers: (Pick<Status[\"receivers\"][number], \"url\" | \"polling\" | \"last_poll\" | \"last_error\"> & {\n last_poll_age_ms: number | null;\n })[];\n};\n\nasync function controlHealth(): Promise<ControlHealth | null> {\n if (!pairedCount()) return null;\n const reply = await ask(socketPath(state), { op: \"status\" }, 1500);\n if (reply?.op !== \"status\") return { running: false, receivers: [] };\n const status = reply.status as Status;\n return {\n running: true,\n receivers: status.receivers.map((r) => ({\n url: r.url,\n polling: r.polling,\n last_poll: r.last_poll,\n last_error: r.last_error,\n // An older daemon has no age field. Its last_poll still exposes a loop\n // that stopped long ago, and polling=false catches the terminal 401.\n last_poll_age_ms: r.last_poll_age_ms ?? (r.last_poll === null ? null : Math.max(0, Date.now() - r.last_poll)),\n })),\n };\n}\n\nfunction controlLines(control: ControlHealth | null): void {\n if (!control) {\n out(\" control: not paired\");\n return;\n }\n if (!control.running) {\n out(\" control: daemon not running or not responding; polling: no\");\n return;\n }\n for (const r of control.receivers) {\n const age = r.last_poll_age_ms === null ? \"unknown\" : `${Math.floor(r.last_poll_age_ms / 60_000)} minutes`;\n out(\n ` control: ${r.url} \u00B7 polling: ${r.polling ? \"yes\" : \"no\"} \u00B7 last successful poll: ${r.last_poll === null ? `never (${age} since start)` : `${age} ago`} \u00B7 last error: ${r.last_error ?? \"none\"}`,\n );\n }\n}\n\nasync function status(): Promise<void> {\n const cfg = readConfig();\n const hc = hookCommand();\n const json = has(\"--json\");\n const harnesses: Record<string, { file: string; state: string; note?: string }[]> = {};\n const sinks = [];\n if (!json) out(` machine: ${machineName(cfg, os.hostname())} sessionpipe ${VERSION} state ${tilde(state)}`);\n for (const a of ADAPTERS) {\n if (!a.detect() && !cfg.harnesses[a.name]) continue;\n const installed = a.installed(hc, process.env, { lean: isLean(cfg) });\n harnesses[a.name] = installed.map((r) => ({\n file: tilde(r.file),\n state: r.state,\n ...(r.note ? { note: r.note } : {}),\n }));\n if (!json)\n for (const r of installed)\n out(\n ` ${a.name.padEnd(12)} ${tilde(r.file).padEnd(44)} ${r.state}${r.state !== \"current\" && r.note ? ` \u2014 ${r.note}` : \"\"}`,\n );\n }\n if (!json && !cfg.sinks.length) out(\" sinks: none (events stay in the local outbox)\");\n for (const s of cfg.sinks) {\n const c = new Cursors(state, s.name).read();\n const outbox = new Outbox(state);\n let pending = 0;\n for (const ref of outbox.sessions()) {\n const f = outbox.file(ref);\n try {\n pending += Math.max(0, statSync(f).size - (c[`${ref.harness}/${ref.session}`] ?? 0)) > 0 ? 1 : 0;\n } catch {}\n }\n sinks.push({\n name: s.name,\n url: s.url,\n tier: s.tier,\n max_tier: s.max_tier ?? null,\n pii: !!s.pii,\n control: !!s.control,\n paused: s.paused ?? null,\n pending_sessions: pending,\n });\n if (!json)\n out(\n ` sink ${s.name.padEnd(16)} tier ${Math.min(s.tier, s.max_tier ?? 3)} ${s.paused ? `PAUSED ${s.paused}` : pending ? `${pending} session file(s) with undelivered events` : \"up to date\"}`,\n );\n }\n const control = await controlHealth();\n if (!json) controlLines(control);\n const update = updateState(cfg);\n if (!json) out(` update: ${updateLine(update, Date.now())}`);\n const t = timing();\n if (!json && t)\n out(\n ` hook: in-process p50 ${t.p50} ms over ${t.n} runs (\\`sessionpipe doctor\\` measures the wall clock the harness waits)`,\n );\n let jobs = 0;\n try {\n jobs = readdirSync(jobsDir(state)).filter((n) => n.endsWith(\".json\")).length;\n } catch {}\n if (json)\n out(\n JSON.stringify(\n {\n version: VERSION,\n machine: machineName(cfg, os.hostname()),\n state,\n config: configFile(),\n harnesses,\n sinks,\n timing: t,\n control,\n update,\n jobs,\n },\n null,\n 2,\n ),\n );\n else if (jobs) out(` jobs: ${jobs} waiting`);\n}\n\n/** Spawn the hook the way a harness does and time the whole process (issue #12:\n * the in-process clock misses Node's startup, ~200 ms on an older Intel Mac). */\nfunction hookWall(runs = 8): { n: number; p50: number; p95: number } | null {\n const hook = path.join(distDir, \"hook.js\");\n const tmp = mkdtempSync(path.join(os.tmpdir(), \"sessionpipe-doctor-\"));\n const env = {\n ...process.env,\n SESSIONPIPE_STATE: tmp,\n SESSIONPIPE_CONFIG: path.join(tmp, \"config.json\"),\n SESSIONPIPE_NO_WORKER: \"1\",\n };\n const input = JSON.stringify({\n session_id: \"doctor\",\n hook_event_name: \"PostToolUse\",\n tool_name: \"Bash\",\n cwd: process.cwd(),\n });\n const times: number[] = [];\n try {\n for (let i = 0; i < runs; i++) {\n const t0 = process.hrtime.bigint();\n const r = spawnSync(process.execPath, [hook, \"claude-code\", \"PostToolUse\"], { input, env, encoding: \"utf8\" });\n if (r.status !== 0) return null;\n times.push(Number(process.hrtime.bigint() - t0) / 1e6);\n }\n } catch {\n return null;\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n times.sort((a, b) => a - b);\n // `?? 0` satisfies noUncheckedIndexedAccess: the index is clamped to the last of `runs` entries.\n const q = (p: number) =>\n Math.round(/* v8 ignore next */ times[Math.min(times.length - 1, Math.floor(p * times.length))] ?? 0);\n return { n: times.length, p50: q(0.5), p95: q(0.95) };\n}\n\nfunction timing(): { n: number; p50: number; p95: number } | null {\n try {\n const lines = readFileSync(path.join(state, \"timing.jsonl\"), \"utf8\").trim().split(\"\\n\").slice(-100);\n const ms = lines\n .map((l) => (JSON.parse(l) as { ms: number }).ms)\n .filter((x) => x >= 0)\n .sort((a, b) => a - b);\n if (!ms.length) return null;\n // `?? 0` satisfies noUncheckedIndexedAccess: the index is clamped to the last of a non-empty list.\n const q = (p: number) =>\n Math.round(/* v8 ignore next */ ms[Math.min(ms.length - 1, Math.floor(p * ms.length))] ?? 0);\n return { n: ms.length, p50: q(0.5), p95: q(0.95) };\n } catch {\n return null;\n }\n}\n\nasync function doctor(): Promise<void> {\n const cfg = readConfig();\n const hc = hookCommand();\n const report: Record<string, unknown> = {\n version: VERSION,\n node: process.version,\n node_path: stableNode(process.execPath),\n machine: machineName(cfg, os.hostname()),\n state: state,\n config: configFile(),\n harnesses: {},\n sinks: [],\n timing: timing(),\n hook_wall_ms: hookWall(),\n update: updateState(cfg),\n warnings: [] as string[],\n };\n const warnings = report.warnings as string[];\n const health = await controlHealth();\n report.control = health;\n if (health && !health.running)\n warnings.push(\"the control daemon is not running or not responding; polling is stopped\");\n for (const r of health?.receivers ?? []) {\n // A normal long-poll takes 25 s (35 s deadline). Allow one minute at startup\n // and between responses, but report a stopped/backing-off loop immediately.\n if (!r.polling || (r.last_poll_age_ms !== null && r.last_poll_age_ms >= 60_000)) {\n const age =\n r.last_poll_age_ms === null\n ? \"never polled\"\n : `not polled for ${Math.floor(r.last_poll_age_ms / 60_000)} minutes`;\n warnings.push(\n `${r.url}: the daemon has ${age}: ${r.last_error ?? (r.polling ? \"no successful poll response\" : \"polling stopped\")}`,\n );\n }\n }\n const upd = report.update as ReturnType<typeof updateState>;\n if (upd.failed)\n warnings.push(\n `the control daemon couldn't install sessionpipe ${upd.failed.version}: ${upd.failed.error}. It tries again tomorrow; \\`sessionpipe update\\` tries now.`,\n );\n if (usesLauncher()) {\n const l = launcherState(VERSION);\n report.launcher = { file: tilde(l.file), node: l.node, node_ok: l.nodeOk, version: l.version };\n if (Object.keys(cfg.harnesses).length) warnings.push(...l.problems);\n }\n // Where each key lives, and whether this session can read it.\n const keys: { what: string; where: string; readable: boolean }[] = [];\n for (const s of cfg.sinks)\n if (s.token_in || s.token || s.secret)\n keys.push({ what: `sink ${s.name}`, where: s.token_in ?? \"file\", readable: !!sinkWithSecrets(s) });\n const control = readControl();\n for (const r of control?.receivers ?? [])\n keys.push({ what: `control ${new URL(r.url).host}`, where: r.token_in ?? \"file\", readable: !!r.token });\n report.keys = keys;\n for (const k of keys)\n if (!k.readable)\n warnings.push(\n `${k.what}: its key is in ${storeLabel(k.where as StoreName)}, which this session can't read (locked, or an ssh shell). Events wait; the control daemon sends them from your own session.`,\n );\n // Each Claude Code account: a message's headless run needs its login.\n const claudeBin = claudeControl.findClaude();\n if (claudeBin) {\n const dirs = claudeDirs();\n const logins = await Promise.all(dirs.map((d) => claudeControl.claudeLogin(claudeBin, d)));\n report.claude_accounts = dirs.map((d, i) => ({ dir: tilde(d), signed_in: logins[i]?.loggedIn ?? null }));\n dirs.forEach((d, i) => {\n if (logins[i]?.loggedIn === false && control?.receivers.length)\n warnings.push(`Claude Code ${tilde(d)} isn't signed in from here: ${claudeControl.loginCommand(d)}`);\n });\n }\n // A systemd user service stops at logout unless the user lingers.\n if (process.platform === \"linux\" && control?.receivers.length) {\n let linger: boolean | null = null;\n try {\n linger = /^Linger=yes/m.test(\n execFileSync(\"loginctl\", [\"show-user\", os.userInfo().username, \"--property=Linger\"], {\n encoding: \"utf8\",\n timeout: 5000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }),\n );\n } catch {}\n report.linger = linger;\n if (linger === false)\n warnings.push(\n `the control daemon stops when you log out: \\`loginctl enable-linger ${os.userInfo().username}\\` (with sudo if refused) keeps it running`,\n );\n }\n if (/\\/Cellar\\/node(?:@\\d+)?\\/[^/]+\\//.test(distDir))\n warnings.push(\n \"sessionpipe is installed inside Homebrew's versioned node folder; `brew upgrade node` will delete it. Install with `npm install -g --prefix ~/.local sessionpipe`.\",\n );\n for (const a of ADAPTERS) {\n if (!a.detect()) continue;\n const st = a.installed(hc, process.env, { lean: isLean(cfg) });\n (report.harnesses as Record<string, unknown>)[a.name] = st.map((r) => ({\n file: tilde(r.file),\n state: r.state,\n ...(r.note ? { note: r.note } : {}),\n }));\n for (const r of st)\n if (r.state === \"inactive\")\n warnings.push(`${a.name}: hooks are written but the harness will not run them \u2014 ${r.note ?? \"\"}`);\n for (const r of st)\n if (r.state === \"stale\")\n warnings.push(\n `${a.name}: the hook in ${tilde(r.file)} points at an old node or script path; run \\`sessionpipe install\\` again.`,\n );\n for (const r of st)\n if (r.state === \"misplaced\")\n warnings.push(\n `${a.name}: the notify line in ${tilde(r.file)} sits inside a [table], where Codex never reads it; run \\`sessionpipe install\\` again.`,\n );\n }\n for (const s of cfg.sinks)\n (report.sinks as unknown[]).push({\n name: s.name,\n url: s.url,\n tier: s.tier,\n max_tier: s.max_tier ?? null,\n pii: !!s.pii,\n control: !!s.control,\n paused: s.paused ?? null,\n token: s.token_in ? `in ${s.token_in}` : s.token ? `${s.token.slice(0, 4)}\u2026` : null,\n });\n const w = report.hook_wall_ms as { p50: number; p95: number; n: number } | null;\n if (w && w.p50 > 150)\n warnings.push(\n `the harness waits ${w.p50} ms per hook (p50, target < 150): that is Node's own startup on this machine. A lean install (no sink above tier 0) hooks fewer events.`,\n );\n if (has(\"--json\")) {\n out(JSON.stringify(report, null, 2));\n return;\n }\n out(` sessionpipe ${VERSION} \u00B7 node ${process.version} at ${report.node_path}`);\n out(` config ${tilde(configFile())} \u00B7 state ${tilde(state)}`);\n for (const [h, st] of Object.entries(report.harnesses as Record<string, { file: string; state: string }[]>))\n for (const r of st) out(` ${h.padEnd(12)} ${r.file.padEnd(44)} ${r.state}`);\n for (const s of report.sinks as { name: string; tier: number; max_tier: number | null; paused: string | null }[])\n out(\n ` sink ${s.name.padEnd(16)} tier ${s.tier}${s.max_tier !== null ? ` (receiver max ${s.max_tier})` : \"\"}${s.paused ? ` PAUSED ${s.paused}` : \"\"}`,\n );\n controlLines(health);\n const lr = report.launcher as { file: string; node: string | null; node_ok: boolean } | undefined;\n if (lr)\n out(` hooks run ${lr.file} \u2192 node ${lr.node ? tilde(lr.node) : \"?\"}${lr.node_ok ? \"\" : \" (gone: PATH's node)\"}`);\n for (const k of keys)\n out(` key ${k.what.padEnd(28)} ${storeLabel(k.where as StoreName)}${k.readable ? \"\" : \" (unreadable here)\"}`);\n for (const a of (report.claude_accounts as { dir: string; signed_in: boolean | null }[] | undefined) ?? [])\n out(\n ` claude ${a.dir.padEnd(26)} ${a.signed_in === true ? \"signed in\" : a.signed_in === false ? \"NOT signed in from here\" : \"can't tell\"}`,\n );\n out(` update ${updateLine(upd, Date.now())}`);\n const t = report.timing as { p50: number; p95: number; n: number } | null;\n out(\n w\n ? ` hook wall clock (what the harness waits): p50 ${w.p50} ms \u00B7 p95 ${w.p95} ms over ${w.n} spawns`\n : \" hook wall clock: could not spawn dist/hook.js\",\n );\n out(\n t\n ? ` hook in-process: p50 ${t.p50} ms \u00B7 p95 ${t.p95} ms over the last ${t.n} runs`\n : \" hook in-process: no runs yet\",\n );\n for (const w of warnings) out(` ! ${w}`);\n if (!warnings.length) out(\" no warnings\");\n}\n\n/** Follow the local outbox: one event per line, filtered to a tier. The zero-server demo. */\nasync function tail(): Promise<void> {\n const tier = Math.max(0, Math.min(3, Number(flag(\"--tier\") ?? 1))) as Tier;\n const onlySession = flag(\"--session\");\n const onlyHarness = flag(\"--harness\");\n const outbox = new Outbox(state);\n const offsets = new Map<string, number>();\n const fmt = (e: Event): string => {\n const t = e.time.slice(11, 19);\n const d = e.data as Record<string, unknown>;\n let detail = \"\";\n switch (e.type) {\n case \"session.started\":\n detail = `source=${d.source} ${e.session.cwd ?? \"\"} ${e.session.branch ?? \"\"}`;\n break;\n case \"turn.started\":\n detail = [\n d.submitted_by !== undefined ? `submitted_by=${d.submitted_by}` : \"\",\n d.injected ? \"injected\" : \"\",\n d.prompt_chars !== undefined ? `prompt_chars=${d.prompt_chars}` : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n break;\n case \"tool.started\":\n detail = String(d.tool ?? \"\");\n break;\n case \"tool.ended\":\n detail = `${d.tool} ${d.ok ? \"ok\" : \"error\"}${d.ms !== undefined ? ` ${d.ms}ms` : \"\"}`;\n break;\n case \"attention.needed\":\n detail = `${d.kind}${d.tool ? ` ${d.tool}` : \"\"}${d.message ? ` \"${String(d.message).slice(0, 60)}\"` : \"\"}`;\n break;\n case \"turn.ended\":\n detail = String(d.reason ?? \"\");\n break;\n case \"session.ended\":\n detail = `reason=${d.reason}`;\n break;\n case \"turn.transcript\":\n detail = `#${d.turn} \"${String(d.user).slice(0, 50).replace(/\\s+/g, \" \")}\"`;\n break;\n case \"turn.progress\":\n detail = `#${d.turn} ${String(d.assistant ?? \"\").length} chars so far`;\n break;\n case \"session.backfill\":\n detail = `${e.session.title ?? \"\"}`;\n break;\n default:\n detail = JSON.stringify(d).slice(0, 80);\n }\n return `${t} ${e.harness.name.padEnd(11)} ${e.session.id.slice(0, 4)}\u2026 ${e.type.padEnd(17)} ${detail}`;\n };\n out(`sessionpipe tail \u00B7 tier ${tier} \u00B7 ${tilde(state)}/outbox (Ctrl-C to stop)`);\n // Start at the end of each file unless --all.\n for (const ref of outbox.sessions()) {\n try {\n offsets.set(`${ref.harness}/${ref.session}`, has(\"--all\") ? 0 : statSync(outbox.file(ref)).size);\n } catch {}\n }\n for (;;) {\n for (const ref of outbox.sessions()) {\n if (onlyHarness && ref.harness !== onlyHarness) continue;\n if (onlySession && !ref.session.startsWith(onlySession)) continue;\n const k = `${ref.harness}/${ref.session}`;\n const from = offsets.get(k) ?? 0;\n const { events, offset } = outbox.read(ref, from, 200);\n offsets.set(k, offset);\n for (const e of events) {\n const f = filterEvent(e, tier, false);\n if (f) out(has(\"--json\") ? JSON.stringify(f) : fmt(f));\n }\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n}\n\nasync function workerFromArgv(): Promise<void> {\n const f = args[1];\n if (!f) return;\n const job = JSON.parse(readFileSync(f, \"utf8\"));\n try {\n unlinkSync(f);\n } catch {}\n await runJob(job);\n}\n\n/** Whether the daemon updates this copy by itself, and what it last found. */\nfunction updateState(cfg: Config) {\n return updateSummary({\n // The shell's own SESSIONPIPE_NO_UPDATE_CHECK says nothing about the daemon's\n // environment; the daemon records that one itself.\n off: autoUpdateOff({ env: {}, config: cfg, distDir }),\n paired: pairedCount() > 0,\n rec: readUpdate(updateFile()),\n });\n}\n\n/** `sessionpipe update [off|on]`: install the latest release into this copy's prefix\n * now, then have the daemon restart onto it once idle; or switch the daemon's daily\n * update off or on (config.json `update_check`; the daemon reads it every ten minutes). */\nasync function update(): Promise<void> {\n const sub = args[1];\n if (sub === \"off\" || sub === \"on\") {\n const cfg = readConfig();\n cfg.update_check = sub === \"on\";\n writeConfig(cfg);\n return out(\n sub === \"off\"\n ? \" \u2713 The control daemon no longer checks npm or updates itself. `sessionpipe update` still updates by hand; `sessionpipe update on` undoes this.\"\n : \" \u2713 The control daemon checks npm once a day and installs a new release when it's idle.\",\n );\n }\n if (process.env.SESSIONPIPE_NO_UPDATE_CHECK) return out(\" update check is off (SESSIONPIPE_NO_UPDATE_CHECK)\");\n let latest: string;\n try {\n latest = await latestVersion();\n } catch (e) {\n return out(` couldn't check npm: ${(e as Error).message}`);\n }\n if (!isNewer(latest, VERSION)) return out(` sessionpipe ${VERSION} is current (npm latest: ${latest})`);\n const prefix = globalPrefix(distDir);\n if (!prefix)\n return out(\n ` ${latest} is available (you run ${VERSION}), but this copy isn't a global npm install (npx, a checkout or a dev build): \\`npm install -g sessionpipe@${latest}\\` installs one.`,\n );\n out(` ${latest} is available (you run ${VERSION}); installing into ${tilde(prefix)}\u2026`);\n const r = await installVersion(latest, {\n node: process.execPath,\n distDir,\n harnesses: enabledHarnesses(readConfig().harnesses),\n });\n if (!r.ok) {\n process.exitCode = 1;\n return out(` \u2717 ${r.error}`);\n }\n out(` \u2713 sessionpipe ${latest} installed in ${(r.ms / 1000).toFixed(1)} s; ${r.hooks}`);\n // The daemon still runs the old code: it restarts onto this copy when nothing is in hand.\n const sock = socketPath(state);\n const st = await ask(sock, { op: \"status\" }, 2000);\n if (st?.op !== \"status\") return;\n const running = (st.status as { version?: string }).version ?? \"?\";\n if (running === latest) return;\n const r2 = await ask(sock, { op: \"restart\" }, 2000);\n if (r2?.op === \"ok\") out(` The control daemon (${running}) restarts onto ${latest} as soon as nothing is in hand.`);\n else\n out(\n ` The control daemon still runs ${running} and can't restart itself: ${\n process.platform === \"darwin\"\n ? `\\`launchctl kickstart -k gui/${process.getuid?.() ?? \"$(id -u)\"}/org.sessionpipe.control\\``\n : process.platform === \"linux\"\n ? \"`systemctl --user restart sessionpipe-control.service`\"\n : \"stop `sessionpipe control run` and start it again\"\n } moves it (a run in progress stops).`,\n );\n}\n\n// The process entrypoint (`node dist/cli.js`, or npm's bin link to it) runs the command;\n// an import of this module runs nothing.\nif (isEntrypoint(process.argv[1], import.meta.url)) {\n process.stdout.on(\"error\", (e: NodeJS.ErrnoException) => {\n if (e.code === \"EPIPE\") process.exit(0);\n });\n void main(process.argv.slice(2));\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Any agent that speaks the Agent Client Protocol (agentclientprotocol.com) \u2014 control\n// delivery (spec/CONTROL.md \u00A76, ADAPTERS.md \"Agents driven through ACP\"). One client\n// for all of them: the daemon runs the agent's own CLI as a child, speaks JSON-RPC 2.0\n// over its stdin and stdout (`initialize`, `session/new` or `session/load`,\n// `session/prompt`, `session/cancel`), reads the reply from its `agent_message_chunk`\n// updates, and answers its `session/request_permission` from the machine's mode. The\n// agent names its own session, so the daemon keeps the start's id as its name\n// (CONTROL.md \u00A76 `start`), and keeps the process for the next message (`api` mode).\n// Which agents, and how each is launched, is the ACP registry's word\n// (github.com/agentclientprotocol/registry, 2026-10-22); only one already installed\n// here is ever run. Shapes measured against codex-acp 2.2.2 on 2026-10-22.\nimport { type ChildProcess, spawn } from \"node:child_process\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { deniedNote, findBinary, JOB_TIMEOUT_MS, jobEnv, type Mode } from \"./headless.js\";\n\nexport interface AcpAgent {\n /** sessionpipe's harness name (ADAPTERS.md): the registry's id unless a hook adapter already named it. */\n harness: string;\n /** The registry's id. */\n registry: string;\n label: string;\n /** The CLI's name on PATH. */\n bin: string;\n args: string[];\n}\n\n/** The agents the daemon can drive, with the launch line the registry publishes. */\nexport const ACP_AGENTS: readonly AcpAgent[] = [\n { harness: \"gemini-cli\", registry: \"gemini\", label: \"Gemini CLI\", bin: \"gemini\", args: [\"--acp\"] },\n { harness: \"devin\", registry: \"devin\", label: \"Devin\", bin: \"devin\", args: [\"acp\"] },\n { harness: \"opencode\", registry: \"opencode\", label: \"OpenCode\", bin: \"opencode\", args: [\"acp\"] },\n { harness: \"cursor\", registry: \"cursor\", label: \"Cursor\", bin: \"cursor-agent\", args: [\"acp\"] },\n { harness: \"copilot-cli\", registry: \"github-copilot-cli\", label: \"Copilot CLI\", bin: \"copilot\", args: [\"--acp\"] },\n {\n harness: \"droid\",\n registry: \"factory-droid\",\n label: \"Droid\",\n bin: \"droid\",\n args: [\"exec\", \"--output-format\", \"acp-daemon\"],\n },\n { harness: \"goose\", registry: \"goose\", label: \"goose\", bin: \"goose\", args: [\"acp\"] },\n { harness: \"kilo\", registry: \"kilo\", label: \"Kilo\", bin: \"kilo\", args: [\"acp\"] },\n {\n harness: \"qwen-code\",\n registry: \"qwen-code\",\n label: \"Qwen Code\",\n bin: \"qwen\",\n args: [\"--acp\", \"--experimental-skills\"],\n },\n { harness: \"cline\", registry: \"cline\", label: \"Cline\", bin: \"cline\", args: [\"--acp\"] },\n { harness: \"auggie\", registry: \"auggie\", label: \"Auggie\", bin: \"auggie\", args: [\"--acp\"] },\n { harness: \"kimi\", registry: \"kimi\", label: \"Kimi CLI\", bin: \"kimi\", args: [\"acp\"] },\n { harness: \"amp\", registry: \"amp-acp\", label: \"Amp\", bin: \"amp-acp\", args: [] },\n { harness: \"mistral-vibe\", registry: \"mistral-vibe\", label: \"Mistral Vibe\", bin: \"vibe-acp\", args: [] },\n { harness: \"bob\", registry: \"bob\", label: \"Bob\", bin: \"bob\", args: [\"acp\"] },\n { harness: \"grok-build\", registry: \"grok-build\", label: \"Grok Build\", bin: \"grok\", args: [\"agent\", \"stdio\"] },\n { harness: \"qoder\", registry: \"qoder\", label: \"Qoder CLI\", bin: \"qodercli\", args: [\"--acp\"] },\n { harness: \"minimax-code\", registry: \"minimax-code\", label: \"MiniMax Code\", bin: \"mcode\", args: [\"acp\"] },\n { harness: \"codebuddy-code\", registry: \"codebuddy-code\", label: \"Codebuddy Code\", bin: \"codebuddy\", args: [\"--acp\"] },\n { harness: \"nova\", registry: \"nova\", label: \"Nova\", bin: \"nova\", args: [\"acp\"] },\n { harness: \"dimcode\", registry: \"dimcode\", label: \"DimCode\", bin: \"dim\", args: [\"acp\"] },\n { harness: \"dirac\", registry: \"dirac\", label: \"Dirac\", bin: \"dirac\", args: [\"--acp\"] },\n { harness: \"harn\", registry: \"harn\", label: \"Harn\", bin: \"harn\", args: [\"serve\", \"acp\"] },\n { harness: \"vtcode\", registry: \"vtcode\", label: \"VT Code\", bin: \"vtcode\", args: [\"acp\"] },\n { harness: \"stakpak\", registry: \"stakpak\", label: \"Stakpak\", bin: \"stakpak\", args: [\"acp\"] },\n { harness: \"crow-cli\", registry: \"crow-cli\", label: \"crow-cli\", bin: \"crow-cli\", args: [\"acp\"] },\n { harness: \"corust-agent\", registry: \"corust-agent\", label: \"Corust Agent\", bin: \"corust-agent-acp\", args: [] },\n { harness: \"cortex-code\", registry: \"cortex-code\", label: \"Cortex Code\", bin: \"cortex\", args: [\"acp\", \"serve\"] },\n { harness: \"kimchi\", registry: \"kimchi\", label: \"Kimchi\", bin: \"kimchi\", args: [\"--mode\", \"acp\"] },\n];\n\nexport const ACP_HARNESSES: readonly string[] = ACP_AGENTS.map((a) => a.harness);\n\nexport const acpAgent = (harness: string): AcpAgent | undefined => ACP_AGENTS.find((a) => a.harness === harness);\n\n/** The env var that names an agent's CLI by hand: `SESSIONPIPE_ACP_GEMINI_CLI`. */\nexport const acpOverride = (harness: string): string => `SESSIONPIPE_ACP_${harness.toUpperCase().replace(/-/g, \"_\")}`;\n\n/** An agent's CLI on this machine: the override, else on PATH, else beside the node\n * running this (an `npm install -g` there) or where the installers put it. */\nexport function findAcpAgent(\n harness: string,\n env: NodeJS.ProcessEnv = process.env,\n home = os.homedir(),\n nodeDir = path.dirname(process.execPath),\n): { bin: string; args: string[] } | null {\n const a = acpAgent(harness);\n if (!a) return null;\n const bin = findBinary({\n override: env[acpOverride(harness)],\n names: process.platform === \"win32\" ? [`${a.bin}.exe`, `${a.bin}.cmd`] : [a.bin],\n env,\n dirs: [\n nodeDir,\n path.join(home, \".local\", \"bin\"),\n path.join(home, \".cargo\", \"bin\"),\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\",\n ],\n });\n return bin ? { bin, args: a.args } : null;\n}\n\n/** The ACP agents installed here, by harness name, for the daemon's hello. */\nexport function acpHarnesses(env: NodeJS.ProcessEnv = process.env): string[] {\n return ACP_HARNESSES.filter((h) => findAcpAgent(h, env));\n}\n\ntype Json = Record<string, unknown>;\nconst obj = (v: unknown): Json | null => (v && typeof v === \"object\" && !Array.isArray(v) ? (v as Json) : null);\nconst str = (v: unknown): string => (typeof v === \"string\" ? v : \"\");\n\ninterface Option {\n optionId: string;\n kind: string;\n}\n\n/** Which permission option the machine's mode picks, or null for `cancelled`: safe\n * refuses (once, else always), auto allows (once, else always). Inherit refuses as safe\n * does: the agent asked because its own settings want a person, and none is there.\n * Never the other way. */\nexport function permissionChoice(options: unknown, mode: Mode): Option | null {\n const list = (Array.isArray(options) ? options : [])\n .map(obj)\n .filter((o): o is Json => !!o && !!str(o.optionId))\n .map((o) => ({ optionId: str(o.optionId), kind: str(o.kind) }));\n const want = mode === \"auto\" ? [\"allow_once\", \"allow_always\"] : [\"reject_once\", \"reject_always\"];\n for (const k of want) {\n const hit = list.find((o) => o.kind === k);\n if (hit) return hit;\n }\n return null;\n}\n\n/** A JSON-RPC error in words: its message, and its `data` where that says more (goose\n * 1.55 answers session/new with \"Internal error\" and the reason in `data`). */\nexport function errorWords(err: Json): string {\n const message = str(err.message);\n const data = str(err.data) || str(obj(err.data)?.message);\n return data && data !== message ? (message ? `${message}: ${data}` : data) : message;\n}\n\n/** What a request to run something was called, for the reply's list of refusals. */\nfunction toolName(call: Json | null, titles: Map<string, string>): string | null {\n if (!call) return null;\n const t = str(call.title) || titles.get(str(call.toolCallId)) || str(call.name) || str(call.toolCallId);\n return t ? t.slice(0, 80) : null;\n}\n\n/** A session the daemon holds (the shape of daemon.ts's SdkSession, plus the agent's own id). */\nexport interface AcpHeld {\n /** Deliver one message; resolves with the agent's reply when the turn ends. */\n send(text: string): Promise<{ reply: string; error?: string }>;\n interrupt(): Promise<void>;\n close(): void;\n readonly busy: boolean;\n readonly lastUsed: number;\n readonly mode: \"api\";\n /** The id the agent gave the session. */\n readonly session: string;\n /** The process is gone or was closed: nothing more can be sent. */\n readonly closed: boolean;\n}\n\nexport interface AcpOptions {\n bin: string;\n args: string[];\n cwd: string;\n mode: Mode;\n label: string;\n env?: NodeJS.ProcessEnv;\n /** Reopen this session of the agent's (`session/load`) instead of starting a new one. */\n load?: string;\n /** The reply so far, each time it grows. */\n onText?: (text: string) => void;\n log?: (line: string) => void;\n now?: () => number;\n /** A turn still running after this is cancelled, then stopped. */\n timeoutMs?: number;\n /** How long the agent may take to answer `initialize` and open the session. */\n openTimeoutMs?: number;\n /** On close, how long the agent gets to leave by itself before SIGTERM (then SIGKILL). */\n closeGraceMs?: number;\n}\n\nexport type AcpStart = { held: AcpHeld } | { failed: string } | { unsupported: string };\n\nconst CLIENT_INFO = { name: \"sessionpipe\", title: \"sessionpipe control\", version: \"1\" };\n\n/** Run an ACP agent and open a session in it. Resolves once the agent has answered\n * `session/new` (or `session/load`); every later turn goes through `held.send`. */\nexport function startAcp(o: AcpOptions): Promise<AcpStart> {\n const now = o.now ?? Date.now;\n const log = o.log ?? (() => {});\n const label = o.label;\n let child: ChildProcess;\n try {\n child = spawn(o.bin, o.args, {\n cwd: o.cwd,\n env: jobEnv(o.env),\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n detached: process.platform !== \"win32\",\n windowsHide: true,\n });\n } catch (e) {\n return Promise.resolve({ failed: `couldn't start ${label}: ${(e as Error).message}` });\n }\n const kill = (sig: NodeJS.Signals) => {\n try {\n if (process.platform !== \"win32\" && child.pid) process.kill(-child.pid, sig);\n else child.kill(sig);\n } catch {}\n };\n\n let gone: string | null = null; // why the process is no longer there\n let errTail = \"\";\n let nextId = 1;\n const pending = new Map<number, { resolve: (r: unknown) => void; reject: (e: Error) => void }>();\n const write = (m: Json) => {\n if (gone) return;\n try {\n child.stdin?.write(`${JSON.stringify(m)}\\n`);\n } catch {}\n };\n const request = (method: string, params: Json, timeoutMs: number): Promise<unknown> =>\n new Promise((resolve, reject) => {\n if (gone) return reject(new Error(gone));\n const id = nextId++;\n const t = setTimeout(() => {\n pending.delete(id);\n reject(new Error(`${label} didn't answer ${method} in ${Math.round(timeoutMs / 1000)} s`));\n }, timeoutMs);\n t.unref();\n pending.set(id, {\n resolve: (r) => {\n clearTimeout(t);\n resolve(r);\n },\n reject: (e) => {\n clearTimeout(t);\n reject(e);\n },\n });\n write({ jsonrpc: \"2.0\", id, method, params });\n });\n const notify = (method: string, params: Json) => write({ jsonrpc: \"2.0\", method, params });\n\n // The turn in flight: its reply as it grows, and what it was refused.\n // `message`: the id of the chunk before, null for one that had none, undefined before any.\n let turn: { text: string; message?: string | null; denied: string[]; count: number } | null = null;\n const titles = new Map<string, string>();\n const onUpdate = (u: Json | null) => {\n if (!u) return;\n const kind = str(u.sessionUpdate);\n if (kind === \"tool_call\" && str(u.toolCallId) && str(u.title)) {\n if (titles.size >= 200) titles.clear();\n titles.set(str(u.toolCallId), str(u.title));\n return;\n }\n if (kind !== \"agent_message_chunk\" || !turn) return;\n const c = obj(u.content);\n if (c?.type !== \"text\" || !str(c.text)) return;\n // A new message after a tool step starts a new paragraph.\n const mid = str(u.messageId) || null;\n if (turn.message !== undefined && mid !== turn.message && turn.text.trim())\n turn.text = `${turn.text.trimEnd()}\\n\\n`;\n turn.message = mid;\n turn.text += str(c.text);\n o.onText?.(turn.text);\n };\n const onRequest = (id: unknown, method: string, params: Json | null) => {\n if (method !== \"session/request_permission\") {\n write({ jsonrpc: \"2.0\", id: id as string, error: { code: -32601, message: `Method not found: ${method}` } });\n return;\n }\n const pick = permissionChoice(params?.options, o.mode);\n if (!pick?.kind.startsWith(\"allow\")) {\n const name = toolName(obj(params?.toolCall), titles);\n if (turn) {\n turn.count++;\n if (name && !turn.denied.includes(name) && turn.denied.length < 20) turn.denied.push(name);\n }\n }\n write({\n jsonrpc: \"2.0\",\n id: id as string,\n result: { outcome: pick ? { outcome: \"selected\", optionId: pick.optionId } : { outcome: \"cancelled\" } },\n });\n };\n const onLine = (line: string) => {\n let m: Json | null;\n try {\n m = obj(JSON.parse(line));\n } catch {\n return;\n }\n if (!m) return;\n const method = str(m.method);\n if (method) {\n if (m.id !== undefined) onRequest(m.id, method, obj(m.params));\n else if (method === \"session/update\") onUpdate(obj(obj(m.params)?.update));\n return;\n }\n const p = typeof m.id === \"number\" ? pending.get(m.id) : undefined;\n if (!p) return;\n pending.delete(m.id as number);\n const err = obj(m.error);\n if (err) p.reject(new Error(errorWords(err) || `${label} returned error ${String(err.code ?? \"?\")}`));\n else p.resolve(m.result);\n };\n let partial = \"\";\n child.stdout?.on(\"data\", (b: Buffer) => {\n const lines = (partial + b.toString(\"utf8\")).split(\"\\n\");\n partial = lines.pop() as string;\n for (const l of lines) if (l.trim()) onLine(l);\n if (partial.length > 4 * 1024 * 1024) partial = \"\";\n });\n child.stderr?.on(\"data\", (b: Buffer) => {\n errTail = (errTail + b.toString(\"utf8\")).slice(-4000);\n });\n const left = (why: string) => {\n if (gone) return;\n gone = why;\n for (const p of pending.values()) p.reject(new Error(why));\n pending.clear();\n };\n child.on(\"error\", (e) => left(`couldn't start ${label}: ${e.message}`));\n const exited = (code: number | null, signal: NodeJS.Signals | null) => {\n const tail = errTail.trim().split(\"\\n\").slice(-3).join(\" \").trim();\n left(`${label} exited (${signal || `code ${code}`})${tail ? `: ${tail}` : \"\"}`);\n };\n child.on(\"exit\", exited);\n // A tool the agent left running can hold its stdout open after it exited; `close`\n // is also the end for a process that never started.\n child.on(\"close\", exited);\n\n let closed = false;\n const close = () => {\n if (closed) return;\n closed = true;\n try {\n child.stdin?.end();\n } catch {}\n const grace = o.closeGraceMs ?? 2000;\n const t = setTimeout(() => kill(\"SIGTERM\"), grace);\n t.unref();\n const k = setTimeout(() => kill(\"SIGKILL\"), grace * 6);\n k.unref();\n child.once(\"exit\", () => {\n clearTimeout(t);\n clearTimeout(k);\n });\n };\n\n const open = o.openTimeoutMs ?? 60_000;\n\n function held(session: string): AcpHeld {\n let busy = false;\n let lastUsed = now();\n return {\n session,\n mode: \"api\",\n get busy() {\n return busy;\n },\n get lastUsed() {\n return lastUsed;\n },\n get closed() {\n return closed || !!gone;\n },\n async send(text) {\n if (closed) return { reply: \"\", error: `${label} was closed` };\n busy = true;\n lastUsed = now();\n const t = { text: \"\", denied: [], count: 0 };\n turn = t;\n const limit = o.timeoutMs ?? JOB_TIMEOUT_MS;\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n notify(\"session/cancel\", { sessionId: session });\n setTimeout(close, 5000).unref();\n }, limit);\n timer.unref();\n try {\n const res = obj(\n await request(\"session/prompt\", { sessionId: session, prompt: [{ type: \"text\", text }] }, limit + 10_000),\n );\n const stop = str(res?.stopReason);\n const words = t.text.trim() || `(${label} finished without a written reply.)`;\n const refused = deniedNote(t.denied, t.count);\n if (stop === \"end_turn\" || stop === \"max_tokens\") return { reply: words + refused };\n if (stop === \"refusal\") return { reply: `${words}\\n\\n(${label} refused the request.)${refused}` };\n if (stop === \"cancelled\")\n return timedOut\n ? {\n reply: \"\",\n error: `${label} was still working after ${Math.round(limit / 60_000)} minutes, so it was stopped`,\n }\n : { reply: `${words}\\n\\n(The turn was cancelled.)${refused}` };\n return { reply: \"\", error: `${label} ended the turn with ${stop || \"no stop reason\"}` };\n } catch (e) {\n return { reply: \"\", error: (e as Error).message };\n } finally {\n clearTimeout(timer);\n turn = null;\n busy = false;\n lastUsed = now();\n }\n },\n async interrupt() {\n notify(\"session/cancel\", { sessionId: session });\n },\n close,\n };\n }\n\n return (async (): Promise<AcpStart> => {\n let signIn = \"\";\n try {\n const init = obj(\n await request(\n \"initialize\",\n {\n protocolVersion: 1,\n clientCapabilities: { fs: { readTextFile: false, writeTextFile: false }, terminal: false },\n clientInfo: CLIENT_INFO,\n },\n open,\n ),\n );\n const caps = obj(init?.agentCapabilities);\n const info = obj(init?.agentInfo);\n log(\n `${label}: ${str(info?.name) || \"agent\"} ${str(info?.version)} (ACP ${String(init?.protocolVersion ?? \"?\")})`,\n );\n // An agent that lists ways to sign in may refuse a session until someone did, at\n // the machine's terminal: the daemon never signs in for anyone. The agent's own\n // words for the first way, when it gives any (goose: \"Run `goose configure` \u2026\").\n const methods = Array.isArray(init?.authMethods) ? init.authMethods.map(obj) : [];\n if (methods.length) {\n const how = str(methods[0]?.description) || str(methods[0]?.name);\n signIn = ` (if ${label} wants a sign-in, do it at the machine's terminal${how ? `: ${how}` : \"\"})`;\n }\n if (o.load) {\n if (!caps?.loadSession) {\n close();\n return { unsupported: `${label} can't reopen a session once it has been closed (no session/load)` };\n }\n await request(\"session/load\", { sessionId: o.load, cwd: o.cwd, mcpServers: [] }, open);\n return { held: held(o.load) };\n }\n const res = obj(await request(\"session/new\", { cwd: o.cwd, mcpServers: [] }, open));\n const session = str(res?.sessionId);\n if (!session) throw new Error(`${label} opened a session without naming it`);\n return { held: held(session) };\n } catch (e) {\n close();\n return { failed: `${(e as Error).message}${signIn}` };\n }\n })();\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// One headless agent turn as a child process (spec/CONTROL.md \u00A76): the spawner the\n// control daemon runs every harness through, and the shape each harness's reading of\n// its own output takes. Which binary, which flags and how the answer is read are the\n// harness's own (`<harness>-control.ts`); what is the same for all of them is here.\nimport { spawn } from \"node:child_process\";\nimport { accessSync, constants, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** A headless turn still running after this is stopped. */\nexport const JOB_TIMEOUT_MS = 30 * 60_000;\nconst OUT_CAP = 1024 * 1024;\n\n/** How a turn the daemon runs may act (spec/CONTROL.md \u00A72), chosen at the machine's own\n * terminal: safe, the harness's auto mode, or inherit (no permission flag, so the\n * harness starts in its own default on this machine). */\nexport type Mode = \"safe\" | \"auto\" | \"inherit\";\n\nexport function isExe(p: string): boolean {\n try {\n if (!statSync(p).isFile()) return false;\n accessSync(p, constants.X_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/** A harness's CLI: the override the person set (`SESSIONPIPE_<NAME>`), else the first\n * of `names` on PATH, else the first of `dirs` that holds one. A launchd or systemd\n * service starts with a short PATH, so the installers' own folders are looked in too. */\nexport function findBinary(o: {\n override?: string | undefined;\n names: string[];\n dirs: string[];\n env?: NodeJS.ProcessEnv;\n}): string | null {\n if (o.override && isExe(o.override)) return o.override;\n for (const d of String(o.env?.PATH || \"\").split(path.delimiter)) {\n if (!d || !path.isAbsolute(d)) continue;\n for (const n of o.names) if (isExe(path.join(d, n))) return path.join(d, n);\n }\n for (const d of o.dirs) for (const n of o.names) if (isExe(path.join(d, n))) return path.join(d, n);\n return null;\n}\n\n/** The env every headless turn runs with: SESSIONPIPE_CONTROL_JOB tells the turn's own\n * hooks that the daemon runs it, so its Stop hook never takes a message meant for a\n * person's session (cli/src/hook.ts). */\nexport function jobEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n return { ...env, SESSIONPIPE_CONTROL_JOB: \"1\" };\n}\n\n/** Whether a harness is signed in, in its own words. `loggedIn: null` means it can't\n * say (too old, or it didn't answer): never a reason to refuse. */\nexport interface Login {\n loggedIn: boolean | null;\n /** claude.ai, an API key, a long-lived token\u2026 as the harness names it. */\n method?: string;\n subscription?: string;\n}\n\nexport interface RunResult {\n error?: string;\n code?: number | null;\n signal?: NodeJS.Signals | null;\n stdout?: string | null;\n tooBig?: boolean;\n stderr?: string;\n timedOut?: boolean;\n}\n\nexport interface RunOptions {\n cwd: string;\n env: NodeJS.ProcessEnv;\n timeoutMs?: number;\n /** Streaming: each stdout line as it arrives. Only the lines `keep` names are kept\n * for the RunResult (none by default), so a long stream never hits the cap. */\n onLine?: (line: string) => void;\n keep?: (line: string) => boolean;\n}\n\n/** Run one headless turn in its own process group, stdin closed (Codex waits on an open\n * one), holding at most 1 MB of stdout. */\nexport function runHeadless(bin: string, args: string[], o: RunOptions): Promise<RunResult> {\n return new Promise((resolve) => {\n let out: Buffer[] = [];\n let outLen = 0;\n let tooBig = false;\n let errTail = \"\";\n let timedOut = false;\n let settled = false;\n let child: import(\"node:child_process\").ChildProcess;\n try {\n child = spawn(bin, args, {\n cwd: o.cwd,\n env: o.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: process.platform !== \"win32\",\n windowsHide: true,\n });\n } catch (e) {\n resolve({ error: (e as Error).message });\n return;\n }\n const kill = (sig: NodeJS.Signals) => {\n try {\n if (process.platform !== \"win32\" && child.pid) process.kill(-child.pid, sig);\n else child.kill(sig);\n } catch {\n try {\n child.kill(sig);\n } catch {}\n }\n };\n const keep = (line: string) => {\n if (!o.keep?.(line)) return;\n out = [Buffer.from(line)];\n outLen = line.length;\n };\n let partial = \"\";\n child.stdout?.on(\"data\", (b: Buffer) => {\n if (o.onLine) {\n const chunk = partial + b.toString(\"utf8\");\n const lines = chunk.split(\"\\n\");\n partial = lines.pop() as string;\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n o.onLine(line);\n } catch {}\n keep(line);\n }\n if (partial.length > OUT_CAP) partial = \"\";\n return;\n }\n if (tooBig) return;\n if (outLen + b.length > OUT_CAP) {\n tooBig = true;\n out = [];\n return;\n }\n out.push(b);\n outLen += b.length;\n });\n child.stderr?.on(\"data\", (b: Buffer) => {\n errTail = (errTail + b.toString(\"utf8\")).slice(-4000);\n });\n const timer = setTimeout(() => {\n timedOut = true;\n kill(\"SIGTERM\");\n setTimeout(() => kill(\"SIGKILL\"), 10_000).unref();\n }, o.timeoutMs ?? JOB_TIMEOUT_MS);\n const result = (code: number | null, signal: NodeJS.Signals | null): RunResult => ({\n code,\n signal,\n stdout: tooBig ? null : Buffer.concat(out).toString(\"utf8\"),\n tooBig,\n stderr: errTail,\n timedOut,\n });\n const finish = (r: RunResult) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(r);\n };\n child.on(\"error\", (e) => finish({ error: e.message }));\n // A tool the agent left running can hold stdout open after the harness exits.\n child.on(\"exit\", (code, signal) => setTimeout(() => finish(result(code, signal)), 2000).unref());\n child.on(\"close\", (code, signal) => {\n // The last line may end without a newline: it is often the result itself.\n if (o.onLine && partial.trim()) {\n try {\n o.onLine(partial);\n } catch {}\n keep(partial);\n partial = \"\";\n }\n finish(result(code, signal));\n });\n });\n}\n\n/** A harness's output read as it streams: the session it names, the answer so far, and\n * the outcome once the process is gone. One per run. */\nexport interface Reading {\n /** One stdout line. True when the answer so far changed. */\n feed(line: string): boolean;\n /** The session id the harness revealed (it picks its own), or null so far. */\n readonly session: string | null;\n /** The answer so far, whole. */\n readonly text: string;\n /** How many lines were fed. */\n readonly lines: number;\n outcome(res: RunResult): { failed: string } | { reply: string };\n}\n\n/** The last few lines a harness wrote to stderr, on one line. */\nexport function stderrTail(stderr: string | undefined, n = 3): string {\n return String(stderr || \"\")\n .trim()\n .split(\"\\n\")\n .slice(-n)\n .join(\" \")\n .trim();\n}\n\n/** What a run that wasn't there to ask says about the actions it was refused. */\nexport function deniedNote(names: string[], count: number): string {\n if (!count) return \"\";\n return `\\n\\n(Not allowed on this machine, since nobody was there to approve: ${names.join(\", \") || `${count} action(s)`}.)`;\n}\n\n/** A process that failed before or without its answer, in words. */\nexport function runFailure(label: string, res: RunResult): string | null {\n if (res.error) return `couldn't start ${label}: ${res.error}`;\n if (res.timedOut) return `${label} was still working after 30 minutes, so it was stopped`;\n return null;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Antigravity (Google) \u2014 docs: https://antigravity.google/docs/hooks\n// Config: ~/.gemini/config/hooks.json \u2014 top-level keys are hook NAMES, ours is\n// \"sessionpipe\". stdin is camelCase with NO event name (it rides in argv). A hook's\n// stdout is its answer; non-JSON is a deny. Timeouts in seconds. No session end\n// exists. Ported from spacesheep-cli lib/sessions.js (facts, remote url, projects).\n//\n// No PreToolUse. Its answer must carry a `decision` (allow / deny / ask / force_ask),\n// none of which means \"carry on\": `{}` is read as a deny with no reason, which blocked\n// every tool call on every machine 0.1\u20130.6.0 was installed on (2026-10-04, Antigravity\n// 2.19.1), and `allow` would wave calls past the person's own review settings. So the\n// tool events come from PostToolUse alone, which carries no tool name (only `stepIdx`\n// and `error`): it is a \"still working\" beat.\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n realpathSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines } from \"../readers/files.js\";\nimport { readAntigravity } from \"../readers/transcripts.js\";\nimport { formatJson, readJsonFile } from \"./claude-shaped.js\";\nimport type {\n Adapter,\n BackfillRow,\n HookCommand,\n HookInput,\n HookResult,\n InstallOptions,\n InstallReport,\n SessionFacts,\n} from \"./types.js\";\n\nconst NAME = \"antigravity\";\nconst HOOK_NAME = \"sessionpipe\";\nexport const AG_EVENTS = [\"PreInvocation\", \"PostInvocation\", \"PostToolUse\", \"Stop\"] as const;\n/** What a PreToolUse entry an older install left behind gets, until a restarted\n * conversation reads the rewritten hooks.json: the person's own prompt, with why. The\n * hook (cli/src/hook.ts) and the launcher (cli/src/launcher.ts) print the same line. */\nexport const AG_STALE_PRETOOL =\n '{\"decision\":\"ask\",\"reason\":\"sessionpipe: an outdated PreToolUse hook is still loaded. Restart this conversation (or run sessionpipe install) to drop it.\"}\\n';\n/** Antigravity's answer for one event: `{}` is \"carry on\" for every event we register. */\nexport const antigravityAnswer = (event: string): string => (event === \"PreToolUse\" ? AG_STALE_PRETOOL : \"{}\\n\");\nconst gemini = (env: NodeJS.ProcessEnv) => env.GEMINI_CLI_HOME || path.join(homeDir(), \".gemini\");\nconst hooksFile = (env: NodeJS.ProcessEnv) => path.join(gemini(env), \"config\", \"hooks.json\");\nconst projectsDir = (env: NodeJS.ProcessEnv) => path.join(gemini(env), \"config\", \"projects\");\nconst dataDirs = (env: NodeJS.ProcessEnv) =>\n [\"antigravity\", \"antigravity-cli\", \"antigravity-ide\"].map((d) => path.join(gemini(env), d));\nconst ID_RE = /^[A-Za-z0-9_-]{1,128}$/;\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\n\n// One tool event already, so a lean install is the same entry.\nfunction entry(cmd: HookCommand) {\n const handler = (e: string) => ({ type: \"command\", command: cmd([NAME, e]).command, timeout: 5 });\n const out: Record<string, unknown> = { enabled: true };\n for (const e of AG_EVENTS) out[e] = /Tool/.test(e) ? [{ matcher: \"*\", hooks: [handler(e)] }] : [handler(e)];\n return out;\n}\n\nexport const antigravity: Adapter = {\n name: NAME,\n events: AG_EVENTS,\n detect: (env = process.env) =>\n existsSync(path.join(gemini(env), \"config\")) || dataDirs(env).some((d) => existsSync(d)),\n configFiles: (env = process.env) => [hooksFile(env)],\n install(cmd, env = process.env): InstallReport[] {\n const file = hooksFile(env);\n const f = readJsonFile(file);\n if (!f.ok) return [{ file, changed: false, skipped: true, note: `${f.reason}; not touched` }];\n const hooks = f.value;\n const e = entry(cmd);\n if (JSON.stringify(hooks[HOOK_NAME]) === JSON.stringify(e)) return [{ file, changed: false }];\n hooks[HOOK_NAME] = e;\n mkdirSync(path.dirname(file), { recursive: true });\n writeFileSync(file, formatJson(hooks, f));\n return [\n {\n file,\n changed: true,\n created: !f.existed,\n note: \"hooks.json is read when a conversation starts; open ones report after a restart\",\n },\n ];\n },\n uninstall(env = process.env, opts: InstallOptions = {}): InstallReport[] {\n const file = hooksFile(env);\n if (!existsSync(file)) return [{ file, changed: false }];\n const f = readJsonFile(file);\n if (!f.ok) return [{ file, changed: false, skipped: true, note: `${f.reason}; not touched` }];\n const hooks = f.value;\n if (!(HOOK_NAME in hooks)) return [{ file, changed: false }];\n delete hooks[HOOK_NAME];\n if (opts.created?.includes(file) && !Object.keys(hooks).length) {\n unlinkSync(file);\n return [{ file, changed: true, note: \"removed (sessionpipe created it)\" }];\n }\n writeFileSync(file, formatJson(hooks, f));\n return [{ file, changed: true }];\n },\n installed(cmd, env = process.env) {\n const file = hooksFile(env);\n const f = readJsonFile(file);\n const have = f.ok ? f.value[HOOK_NAME] : undefined;\n return [\n {\n file,\n state: !have ? \"missing\" : JSON.stringify(have) === JSON.stringify(entry(cmd)) ? \"current\" : \"stale\",\n },\n ];\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = (s.conversationId ?? s.session_id ?? s.sessionId) as string | undefined;\n const stdout = antigravityAnswer(event);\n if (!id) return { session: { id: \"\" }, events: [], stdout };\n const workspaces = agWorkspaces(s.workspacePaths);\n const session: HookResult[\"session\"] = { id: String(id), cwd: workspaces[0] ?? input.cwd };\n if (typeof s.modelName === \"string\" && s.modelName !== \"auto\") session.model = s.modelName;\n const toolCall = s.toolCall as { name?: unknown; args?: unknown } | undefined;\n const tool = validTool(toolCall?.name) ? toolCall?.name : validTool(s.toolName) ? s.toolName : undefined;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"PreInvocation\":\n // Fires before every model call of an execution; only the first is the person's ask.\n if (Number(s.invocationNum) === 0 || s.invocationNum === undefined) {\n events.push(ev(\"session.started\", { source: \"unknown\" }));\n events.push(ev(\"turn.started\", {}));\n } else events.push(ev(\"session.heartbeat\", {}));\n break;\n case \"PostInvocation\":\n break;\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, input: toolCall?.args }));\n break;\n case \"PostToolUse\":\n // Antigravity names no tool here; a beat keeps a long run of tools \"working\".\n if (!tool) events.push(ev(\"session.heartbeat\", {}));\n else\n events.push(\n ev(\"tool.ended\", {\n tool,\n ok: !s.error,\n error: typeof s.error === \"string\" ? s.error.slice(0, 2000) : undefined,\n input: toolCall?.args,\n }),\n );\n break;\n case \"Stop\":\n events.push(ev(\"turn.ended\", { reason: s.error ? \"error\" : \"stop\" }));\n break;\n default:\n return { session, events: [], stdout };\n }\n const r: HookResult = { session, events, stdout, hints: { workspaces } };\n if (typeof s.transcriptPath === \"string\") r.transcript = s.transcriptPath;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readAntigravity(text.split(\"\\n\"), fromLine);\n },\n\n facts(session, transcript, hints): SessionFacts {\n if (!transcript) return {};\n return antigravityFacts(transcript, {\n conversation: session.id,\n workspaces: (hints.workspaces as string[] | undefined) ?? (session.cwd ? [session.cwd] : []),\n env: process.env,\n });\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows: BackfillRow[] = [];\n for (const data of dataDirs(env)) {\n let ids: string[] = [];\n try {\n ids = readdirSync(path.join(data, \"brain\")).filter((n) => /^[0-9a-f-]{36}$/i.test(n));\n } catch {}\n for (const id of ids) {\n const f = path.join(data, \"brain\", id, \".system_generated\", \"logs\", \"transcript.jsonl\");\n try {\n if (statSync(f).mtimeMs < sinceMs) continue;\n } catch {\n continue;\n }\n const facts = antigravityFacts(f, { conversation: id, workspaces: [], env });\n if (!facts.started_at || !facts.last_at) continue;\n const { started_at, last_at, first_ask: _fa, harness_version: _hv, ...rest } = facts;\n rows.push({ session: { id, ...rest }, started_at, last_at });\n }\n }\n return rows;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n\n/** A folder as Antigravity writes it (a file:// URI or a path) \u2192 an absolute path, or null. */\nexport function agPath(p: unknown): string | null {\n if (typeof p !== \"string\" || !p) return null;\n let s = p;\n if (/^file:/i.test(s)) {\n try {\n s = decodeURIComponent(new URL(s).pathname);\n } catch {\n return null;\n }\n if (process.platform === \"win32\" && /^\\/[A-Za-z]:/.test(s)) s = s.slice(1);\n } else if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(s)) return null;\n if (!path.isAbsolute(s)) return null;\n return path.resolve(s);\n}\nexport const agWorkspaces = (paths: unknown): string[] =>\n (Array.isArray(paths) ? paths : [])\n .map(agPath)\n .filter((p): p is string => !!p)\n .filter((p, i, a) => a.indexOf(p) === i);\n\nfunction agVariants(p: string): string[] {\n const out = [p];\n try {\n const r = realpathSync.native(p);\n if (r !== p) out.push(r);\n } catch {}\n return out;\n}\nfunction agProjects(dir: string): { id: string; folders: string[] }[] {\n const out: { id: string; folders: string[] }[] = [];\n let names: string[] = [];\n try {\n names = readdirSync(dir).filter((n) => n.endsWith(\".json\"));\n } catch {\n return out;\n }\n for (const n of names) {\n const id = n.slice(0, -5);\n if (!ID_RE.test(id)) continue;\n let j: { projectResources?: { resources?: { folderUri?: unknown; gitFolder?: { folderUri?: unknown } }[] } };\n try {\n j = JSON.parse(readFileSync(path.join(dir, n), \"utf8\"));\n } catch {\n continue;\n }\n const folders: string[] = [];\n // A resource is one of the kinds in Antigravity's project.proto: a plain folder is\n // `{ folderUri }`, a git checkout `{ gitFolder: { folderUri, defaultBranch, allowWrite } }`\n // (what 2.23.1 writes for a folder under git); google3 and remote resources name no folder.\n for (const r of j?.projectResources?.resources ?? []) {\n const f = agPath(r?.folderUri ?? r?.gitFolder?.folderUri);\n if (f) folders.push(...agVariants(f));\n }\n if (folders.length) out.push({ id, folders });\n }\n return out;\n}\n/** The project whose folder is the workspace or contains it; the deepest wins. */\nexport function agMatchProject(projects: { id: string; folders: string[] }[], workspaces: string[]): string | null {\n const ws: string[] = [];\n for (const w of workspaces) {\n const p = agPath(w);\n if (p) ws.push(...agVariants(p));\n }\n let best: string | null = null;\n let bestLen = -1;\n for (const pr of projects)\n for (const f of pr.folders) {\n const within = ws.some((w) => w === f || w.startsWith(f.endsWith(path.sep) ? f : f + path.sep));\n if (within && f.length > bestLen) {\n best = pr.id;\n bestLen = f.length;\n }\n }\n return best;\n}\n\n/** Antigravity's web remote: https://antigravity.google.com/r/<installation uuid>-v2, with\n * ?p=c/<conversation>?section=<project> when the project is known. */\nexport function antigravityRemoteUrl(\n transcript: string,\n opts: { conversation?: string; workspaces?: string[]; env: NodeJS.ProcessEnv; projectsDir?: string },\n): string | null {\n const i = transcript.indexOf(`${path.sep}brain${path.sep}`);\n const dirs = (i > 0 ? [transcript.slice(0, i)] : []).concat(dataDirs(opts.env));\n for (const d of dirs) {\n try {\n const m = /installation_uuid:\\s*\"([0-9a-f-]{36})\"/i.exec(\n readFileSync(path.join(d, \"antigravity_state.pbtxt\"), \"utf8\"),\n );\n if (!m) continue;\n const base = `https://antigravity.google.com/r/${m[1]}-v2`;\n const conv = opts.conversation ?? \"\";\n if (!ID_RE.test(conv) || !opts.workspaces?.length) return base;\n const project = agMatchProject(agProjects(opts.projectsDir ?? projectsDir(opts.env)), opts.workspaces);\n return project ? `${base}?p=${encodeURIComponent(`c/${conv}?section=${project}`)}` : base;\n } catch {}\n }\n return null;\n}\n\nexport function antigravityFacts(\n file: string,\n opts: { conversation: string; workspaces: string[]; env: NodeJS.ProcessEnv },\n): SessionFacts {\n const { head, tail } = ends(file, 128 * 1024, 64 * 1024);\n const H = parseLines(head);\n const T = parseLines(tail);\n const out: SessionFacts = {};\n const url = antigravityRemoteUrl(file, opts);\n if (url) out.url = url;\n for (const j of H) {\n if (j.type !== \"USER_INPUT\" || typeof j.content !== \"string\") continue;\n const m = /<USER_REQUEST>([\\s\\S]*?)(?:<\\/USER_REQUEST>|$)/.exec(j.content);\n const text = (m ? (m[1] as string) : j.content).trim();\n const line = (text.split(\"\\n\").find((l) => l.trim()) ?? \"\").trim();\n if (!line || /^<[a-z_-]+>/i.test(line)) continue;\n out.title = line.length > 80 ? `${line.slice(0, 80).replace(/\\s+\\S*$/, \"\")}\u2026` : line;\n out.title_source = \"first-ask\";\n break;\n }\n const times = H.concat(T)\n .map((j) => Date.parse(String(j.created_at ?? j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Where sessionpipe keeps its files (spec: the client's Files section).\n// config ~/.config/sessionpipe/config.json SESSIONPIPE_CONFIG\n// state ~/.local/state/sessionpipe/ SESSIONPIPE_STATE\n// Windows %APPDATA%\\sessionpipe\\ and %LOCALAPPDATA%\\sessionpipe\\\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n/** The home directory, read when asked: a test that sets HOME after importing core\n * (or a process whose HOME changes) gets the new one, never one cached at load. */\nexport const homeDir = (): string => os.homedir();\n\nexport function configFile(env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_CONFIG) return path.resolve(env.SESSIONPIPE_CONFIG);\n if (process.platform === \"win32\")\n return path.join(env.APPDATA || path.join(homeDir(), \"AppData\", \"Roaming\"), \"sessionpipe\", \"config.json\");\n return path.join(env.XDG_CONFIG_HOME || path.join(homeDir(), \".config\"), \"sessionpipe\", \"config.json\");\n}\n\nexport function stateDir(env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_STATE) return path.resolve(env.SESSIONPIPE_STATE);\n if (process.platform === \"win32\")\n return path.join(env.LOCALAPPDATA || path.join(homeDir(), \"AppData\", \"Local\"), \"sessionpipe\");\n return path.join(env.XDG_STATE_HOME || path.join(homeDir(), \".local\", \"state\"), \"sessionpipe\");\n}\n\n/** `~` for the home directory, as the session block writes paths. */\nexport function tilde(p: string, home: string = homeDir()): string {\n if (!p) return p;\n if (p === home) return \"~\";\n return p.startsWith(home + path.sep) || p.startsWith(`${home}/`) ? `~${p.slice(home.length)}` : p;\n}\n\n/** The other way: `~`, `~/\u2026` (or `~\\\u2026`) under the home directory, as a control `start`'s\n * `cwd` may name a folder an event reported (CONTROL.md \u00A73.1). Anything else, `~user`\n * included, is returned as it is. */\nexport function untilde(p: string, home: string = homeDir()): string {\n if (p === \"~\") return home;\n return /^~[\\\\/]/.test(p) ? path.join(home, p.slice(2)) : p;\n}\n\n/** A file-name-safe id. */\nexport const safeId = (s: string): string =>\n String(s)\n .replace(/[^A-Za-z0-9_.-]/g, \"_\")\n .slice(0, 160);\n", "// SPDX-License-Identifier: Apache-2.0\n// Reading the ends of large files, JSON lines, and recent files under a root.\nimport { closeSync, fstatSync, openSync, readdirSync, readSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** The first and last bytes of a file, as lines \u2014 a transcript can be tens of MB. */\nexport function ends(file: string, headBytes: number, tailBytes: number): { head: string[]; tail: string[] } {\n let fd: number | undefined;\n try {\n fd = openSync(file, \"r\");\n const size = fstatSync(fd).size;\n const read = (pos: number, len: number) => {\n const b = Buffer.alloc(len);\n const n = readSync(fd as number, b, 0, len, pos);\n return b.subarray(0, n).toString(\"utf8\");\n };\n const head = read(0, Math.min(size, headBytes));\n const tail = size > headBytes ? read(Math.max(0, size - tailBytes), Math.min(size, tailBytes)) : head;\n return { head: head.split(\"\\n\").slice(0, -1), tail: tail.split(\"\\n\").slice(size > headBytes ? 1 : 0) };\n } catch {\n return { head: [], tail: [] };\n } finally {\n if (fd !== undefined)\n try {\n closeSync(fd);\n } catch {}\n }\n}\n\nexport const parseLines = (lines: string[]): Record<string, unknown>[] =>\n lines\n .map((l) => {\n try {\n return JSON.parse(l) as Record<string, unknown>;\n } catch {\n return null;\n }\n })\n .filter((x): x is Record<string, unknown> => !!x);\n\n/** Read line by line up to `cap` bytes, stopping when `visit` returns a value. */\nexport function scanLines<T>(file: string, visit: (line: string) => T | null, cap = 16 * 1024 * 1024): T | null {\n let fd: number | undefined;\n try {\n fd = openSync(file, \"r\");\n const buf = Buffer.alloc(1024 * 1024);\n let pos = 0;\n let rest: Buffer = Buffer.alloc(0);\n while (pos < cap) {\n const n = readSync(fd, buf, 0, buf.length, pos);\n if (!n) break;\n pos += n;\n let chunk = Buffer.concat([rest, buf.subarray(0, n)]);\n let nl = chunk.indexOf(10);\n while (nl >= 0) {\n const r = visit(chunk.subarray(0, nl).toString(\"utf8\"));\n if (r !== null) return r;\n chunk = chunk.subarray(nl + 1);\n nl = chunk.indexOf(10);\n }\n rest = chunk;\n }\n } catch {\n } finally {\n if (fd !== undefined)\n try {\n closeSync(fd);\n } catch {}\n }\n return null;\n}\n\nexport function recentFiles(root: string, depth: number, sinceMs: number, match: (name: string) => boolean): string[] {\n const out: string[] = [];\n const walk = (dir: string, d: number) => {\n let names: import(\"node:fs\").Dirent[] = [];\n try {\n names = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const e of names) {\n const p = path.join(dir, e.name);\n if (e.isDirectory()) {\n if (d < depth) walk(p, d + 1);\n continue;\n }\n if (!match(e.name)) continue;\n try {\n if (statSync(p).mtimeMs >= sinceMs) out.push(p);\n } catch {}\n }\n };\n walk(root, 0);\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n\n/** A thread another thread started \u2014 a subagent, a review \u2014 names a `source.subagent`\n * in its own metadata (the rollout's first record). A fork the person made carries\n * only `forked_from_id`, and is a session of its own. */\nexport function codexSubagent(meta: Record<string, unknown> | null | undefined): boolean {\n if (meta?.type !== \"session_meta\") return false;\n const p = meta.payload as { source?: { subagent?: unknown } } | undefined;\n return !!p?.source?.subagent;\n}\n\n/** A fork starts with its own metadata, then replays the parent's history. Only\n * an event naming the new thread establishes where its own records begin. */\nexport function codexReplayBoundary(meta: Record<string, unknown> | null | undefined) {\n if (meta?.type !== \"session_meta\") return undefined;\n const p = meta.payload as { id?: unknown; forked_from_id?: unknown; source?: { subagent?: unknown } } | undefined;\n if (!p || (!p.forked_from_id && !p.source?.subagent)) return undefined;\n return (record: Record<string, unknown> | null) =>\n typeof p.id === \"string\" &&\n !!p.id &&\n record?.type === \"event_msg\" &&\n (record.payload as { thread_id?: unknown } | undefined)?.thread_id === p.id;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Transcript readers: complete turns (a person's message + everything the assistant\n// said before the next one), each with the line it ends on, and the line the\n// cursor may advance to once every turn is delivered. Ported from spacesheep-cli\n// lib/memory.js. One reader per harness file format; nothing else is vendor code.\nimport { codexReplayBoundary } from \"../adapters/codex-rollout.js\";\nimport type { TranscriptRead } from \"../adapters/types.js\";\n\ninterface Msg {\n role: \"user\" | \"assistant\";\n text: string;\n at: number;\n line: number;\n}\n\nexport function pairTurns(msgs: Msg[], endLine: number): TranscriptRead {\n const turns: { user: string; assistant: string; at: number; startLine: number; endLine: number }[] = [];\n let cur: (typeof turns)[number] | null = null;\n for (const m of msgs) {\n if (m.role === \"user\") {\n // Never overwrite a prompt that has no reply yet: in an agentic turn the reply\n // comes after tool calls, and a second user record is not a new question.\n if (cur && !cur.assistant) {\n cur.user += `\\n\\n${m.text}`;\n continue;\n }\n if (cur) turns.push(cur);\n cur = { user: m.text, assistant: \"\", at: m.at, startLine: m.line, endLine: m.line };\n } else {\n if (!cur) cur = { user: \"\", assistant: \"\", at: m.at, startLine: m.line, endLine: m.line };\n cur.assistant += (cur.assistant ? \"\\n\\n\" : \"\") + m.text;\n cur.endLine = m.line;\n }\n }\n if (cur?.assistant) turns.push(cur);\n // A user message with no reply yet stays unsent: the cursor stops before it.\n const line = cur && !cur.assistant ? cur.startLine : endLine;\n const out: TranscriptRead = {\n turns: turns.map((t) => ({ user: t.user, assistant: t.assistant, at: t.at, endLine: t.endLine })),\n line,\n };\n if (cur && !cur.assistant && cur.user) out.open = { user: cur.user, at: cur.at };\n return out;\n}\n\n/** Injected context the person never typed: <tag>\u2026</tag> wrappers (the tag may carry\n * attributes, as Claude Code's `<cross-session-message from=\"\u2026\">` does), HTML comments,\n * slash-command expansions. */\nexport const isInjected = (text: string): boolean =>\n (/^<[a-z_-]+(?:\\s[^>]*)?>/i.test(text) && /<\\/[a-z_-]+>\\s*$/i.test(text)) ||\n /^<!--\\s/.test(text) ||\n /^<command-/.test(text);\n\nconst parse = (raw: string): Record<string, unknown> | null => {\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n};\n/** The line after the last whole one. A trailing line that does not parse has no\n * newline yet (a write in progress): the cursor stops before it, or the prompt in\n * it would never be read. */\nconst endOf = (lines: string[]) => {\n const last = lines[lines.length - 1];\n if (last === undefined) return 0;\n return last === \"\" || parse(last) === null ? lines.length - 1 : lines.length;\n};\nconst textParts = (c: unknown, kinds: string[]): string => {\n if (typeof c === \"string\") return c;\n if (!Array.isArray(c)) return \"\";\n return c\n .filter(\n (b) =>\n b &&\n typeof b === \"object\" &&\n kinds.includes((b as { type?: string }).type ?? \"\") &&\n typeof (b as { text?: unknown }).text === \"string\",\n )\n .map((b) => (b as { text: string }).text)\n .join(\"\\n\");\n};\n\n/** A message the person sent while a turn was running, absorbed by that turn. Claude Code\n * writes it as an attachment, never as a `user` record: {type:\"attachment\",\n * attachment:{type:\"queued_command\", prompt, commandMode:\"prompt\", origin:{kind:\"human\"}}}.\n * Task notifications and other sessions' messages share the record with another\n * `commandMode` or `origin.kind`; older versions wrote no origin. */\nconst queuedPrompt = (a: unknown): string => {\n if (!a || typeof a !== \"object\") return \"\";\n const q = a as { type?: unknown; commandMode?: unknown; origin?: { kind?: string }; prompt?: unknown };\n if (q.type !== \"queued_command\" || (q.commandMode ?? \"prompt\") !== \"prompt\") return \"\";\n if (q.origin?.kind && q.origin.kind !== \"human\") return \"\";\n return textParts(q.prompt, [\"text\"]).trim();\n};\n\n/** Claude Code / Droid: {type:\"user\"|\"assistant\", message:{content}, timestamp, isMeta, isSidechain, origin},\n * plus the person's mid-turn messages (queuedPrompt). */\nexport function readClaude(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n for (let i = from; i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j || j.isSidechain) continue;\n const origin = j.origin as { kind?: string } | undefined;\n if (\n j.type === \"user\" &&\n (j.isMeta || j.isCompactSummary || j.repeatsCompactSummary || (origin?.kind && origin.kind !== \"human\"))\n )\n continue;\n const at = Date.parse(String(j.timestamp ?? \"\")) || Date.now();\n const c = (j.message as { content?: unknown } | undefined)?.content;\n if (j.type === \"user\") {\n const text = textParts(c, [\"text\"]).trim();\n if (!text || isInjected(text)) continue;\n msgs.push({ role: \"user\", text, at, line: i });\n } else if (j.type === \"assistant\" && Array.isArray(c)) {\n const text = textParts(c, [\"text\"]).trim();\n if (text) msgs.push({ role: \"assistant\", text, at, line: i });\n } else if (j.type === \"attachment\") {\n const text = queuedPrompt(j.attachment);\n if (text && !isInjected(text)) msgs.push({ role: \"user\", text, at, line: i });\n }\n }\n return pairTurns(msgs, endOf(lines));\n}\n\n/** What Codex writes into a session as a \"user\" message that the person never typed:\n * `<environment_context>` and the like, and the AGENTS.md it read (`# AGENTS.md\n * instructions for <folder>` followed by `<INSTRUCTIONS>`). */\nexport function codexInjected(text: string): boolean {\n return /^<[a-z_-]+>/i.test(text) || /^# AGENTS\\.md instructions\\b/i.test(text);\n}\n\n/** Codex rollout: {type:\"response_item\", payload:{type:\"message\", role, content:[{type:\"input_text\"|\"output_text\", text}]}}. */\nexport function readCodex(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n const boundary = codexReplayBoundary(parse(lines.find((line) => line.trim()) ?? \"\"));\n // Find the boundary from the header even when resuming inside the replay.\n // Keep absolute line numbers: the delivery cursor refers to the original file.\n const start = boundary ? lines.findIndex((line) => boundary(parse(line))) : 0;\n if (start < 0) return pairTurns(msgs, endOf(lines));\n for (let i = Math.max(from, start); i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j || j.type !== \"response_item\") continue;\n const p = j.payload as { type?: string; role?: string; content?: unknown } | undefined;\n if (!p || p.type !== \"message\") continue;\n const at = Date.parse(String(j.timestamp ?? \"\")) || Date.now();\n const text = textParts(p.content, [\"input_text\", \"output_text\"]).trim();\n if (!text) continue;\n if (p.role === \"user\") {\n if (codexInjected(text)) continue; // Codex's own injections, not the person's words\n msgs.push({ role: \"user\", text, at, line: i });\n } else if (p.role === \"assistant\") msgs.push({ role: \"assistant\", text, at, line: i });\n }\n return pairTurns(msgs, endOf(lines));\n}\n\n/** Gemini CLI chat log: {type:\"user\"|\"gemini\", content|message|text, timestamp}. */\nexport function readGemini(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n for (let i = from; i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j) continue;\n const role = j.type === \"user\" ? \"user\" : j.type === \"gemini\" || j.type === \"model\" ? \"assistant\" : null;\n if (!role) continue;\n const raw = j.content ?? j.message ?? j.text;\n const text = (typeof raw === \"string\" ? raw : textParts(raw, [\"text\"])).trim();\n if (!text) continue;\n const at = Date.parse(String(j.timestamp ?? \"\")) || Date.now();\n msgs.push({ role, text, at, line: i });\n }\n return pairTurns(msgs, endOf(lines));\n}\n\n/** Antigravity: one step per line, type USER_INPUT | PLANNER_RESPONSE, content with <USER_REQUEST> wrapping. */\nexport function readAntigravity(lines: string[], from: number): TranscriptRead {\n const msgs: Msg[] = [];\n for (let i = from; i < lines.length; i++) {\n const j = lines[i] ? parse(lines[i] as string) : null;\n if (!j || typeof j.content !== \"string\") continue;\n const at = Date.parse(String(j.created_at ?? j.timestamp ?? \"\")) || Date.now();\n if (j.type === \"USER_INPUT\") {\n const m = /<USER_REQUEST>([\\s\\S]*?)(?:<\\/USER_REQUEST>|$)/.exec(j.content);\n const text = (m ? (m[1] as string) : j.content).trim();\n if (text) msgs.push({ role: \"user\", text, at, line: i });\n } else if (j.type === \"PLANNER_RESPONSE\") {\n const text = j.content.trim();\n if (text) msgs.push({ role: \"assistant\", text, at, line: i });\n }\n }\n return pairTurns(msgs, endOf(lines));\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The hooks file shape Claude Code introduced and Codex, Droid and (with\n// `version: 1`) Cursor and Copilot reuse: {\"hooks\":{\"<Event>\":[{\"matcher\"?,\n// \"hooks\":[{\"type\":\"command\",\"command\",\"timeout\"}]}]}}. Ours is one entry per\n// event; a re-install replaces a stale entry of ours (an old node path) and never\n// touches anyone else's.\n//\n// Two rules from issue #8: a file that is not plain JSON (a comment, a trailing\n// comma, a write in progress) is never written back \u2014 the harness is skipped and\n// the report says why; and a file is written back in its own shape (indent, final\n// newline) so uninstall leaves it byte-identical. A file that did not exist before\n// install is reported `created`, and uninstall deletes it once it is empty again.\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { HookCommand, InstallReport } from \"./types.js\";\n\nexport interface ClaudeShapedOptions {\n /** Which events take a `matcher` (tool and permission events). */\n matcherFor: (event: string) => string | undefined;\n /** Seconds (milliseconds for Gemini CLI). */\n timeout: number;\n /** A longer timeout for one event (Claude Code's PermissionRequest, which may wait\n * for a verified control answer: spec/CONTROL.md \u00A76). */\n timeoutFor?: (event: string) => number | undefined;\n /** Extra top-level keys the file must carry (Cursor/Copilot: version: 1). */\n top?: Record<string, unknown>;\n}\n\n/** A command of ours: a path that contains \"sessionpipe\" and ends in hook.js (or in\n * sessionpipe-hook, the launcher that outlives a node upgrade), then a harness and an event. */\nexport const OURS = /(?:sessionpipe[^\"\\n]*[\\\\/]hook\\.js|[\\\\/]sessionpipe-hook)\"?\\s+[a-z][a-z-]*\\s+[A-Za-z]+\\s*$/;\nexport const isOurs = (h: { hooks?: { command?: string }[] }): boolean =>\n Array.isArray(h?.hooks) && h.hooks.some((x) => typeof x.command === \"string\" && OURS.test(x.command));\n\nexport type JsonFile =\n | {\n ok: true;\n existed: true;\n value: Record<string, unknown>;\n raw: string;\n indent: string;\n eol: string;\n finalNewline: boolean;\n }\n | { ok: true; existed: false; value: Record<string, unknown>; raw: \"\"; indent: \" \"; eol: \"\\n\"; finalNewline: true }\n | { ok: false; existed: true; reason: string };\n\n/** Read a JSON config file with its shape. Never guesses: a parse failure is a\n * refusal to touch the file, not an empty object. */\nexport function readJsonFile(file: string): JsonFile {\n let raw: string;\n try {\n raw = readFileSync(file, \"utf8\");\n } catch {\n return { ok: true, existed: false, value: {}, raw: \"\", indent: \" \", eol: \"\\n\", finalNewline: true };\n }\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n const hint = /^\\s*\\/\\/|\\/\\*/m.test(raw) ? \"not plain JSON (it has comments)\" : \"not plain JSON\";\n return { ok: false, existed: true, reason: hint };\n }\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n return { ok: false, existed: true, reason: \"not a JSON object\" };\n const eol = raw.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const m = /^( +|\\t+)\\S/m.exec(raw);\n const indent = m?.[1] ?? \" \";\n return {\n ok: true,\n existed: true,\n value: value as Record<string, unknown>,\n raw,\n indent,\n eol,\n finalNewline: /\\r?\\n$/.test(raw),\n };\n}\n\n/** Serialise in the file's own shape. */\nexport function formatJson(value: unknown, f: { indent: string; eol: string; finalNewline: boolean }): string {\n const text = JSON.stringify(value, null, f.indent).replace(/\\n/g, f.eol);\n return f.finalNewline ? text + f.eol : text;\n}\n\n/** Back-compat helper for callers that only read. */\nexport function readJson(file: string): Record<string, unknown> {\n const f = readJsonFile(file);\n return f.ok ? f.value : {};\n}\n\nfunction entryFor(event: string, harness: string, cmd: HookCommand, o: ClaudeShapedOptions) {\n const matcher = o.matcherFor(event);\n return {\n ...(matcher !== undefined ? { matcher } : {}),\n hooks: [{ type: \"command\", command: cmd([harness, event]).command, timeout: o.timeoutFor?.(event) ?? o.timeout }],\n };\n}\n\nexport function installClaudeShaped(\n file: string,\n harness: string,\n events: readonly string[],\n cmd: HookCommand,\n o: ClaudeShapedOptions,\n): InstallReport {\n const f = readJsonFile(file);\n if (!f.ok) return { file, changed: false, skipped: true, note: `${f.reason}; not touched` };\n const settings = f.value;\n const hooks = (settings.hooks && typeof settings.hooks === \"object\" ? settings.hooks : {}) as Record<\n string,\n unknown[]\n >;\n let changed = false;\n const want = new Set(events);\n // Events we no longer hook (a lean install) lose their entry of ours.\n for (const ev of Object.keys(hooks)) {\n if (want.has(ev)) continue;\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const kept = list.filter((h) => !isOurs(h as never));\n if (kept.length !== list.length) {\n changed = true;\n if (kept.length) hooks[ev] = kept;\n else delete hooks[ev];\n }\n }\n for (const ev of events) {\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const entry = entryFor(ev, harness, cmd, o);\n const mine = list.filter((h) => isOurs(h as never));\n if (mine.length === 1 && JSON.stringify(mine[0]) === JSON.stringify(entry)) continue;\n hooks[ev] = list.filter((h) => !isOurs(h as never)).concat([entry]);\n changed = true;\n }\n if (o.top)\n for (const [k, v] of Object.entries(o.top))\n if (settings[k] !== v) {\n settings[k] = v;\n changed = true;\n }\n if (changed) {\n settings.hooks = hooks;\n mkdirSync(path.dirname(file), { recursive: true });\n writeFileSync(file, formatJson(settings, f));\n }\n return { file, changed, created: !f.existed && changed };\n}\n\nexport function uninstallClaudeShaped(\n file: string,\n events: readonly string[],\n opts: { created?: boolean | undefined } = {},\n): InstallReport {\n if (!existsSync(file)) return { file, changed: false };\n const f = readJsonFile(file);\n if (!f.ok) return { file, changed: false, skipped: true, note: `${f.reason}; not touched` };\n const settings = f.value;\n const hooks = settings.hooks as Record<string, unknown[]> | undefined;\n if (!hooks || typeof hooks !== \"object\") return { file, changed: false };\n let changed = false;\n for (const ev of [...events, ...Object.keys(hooks)]) {\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const kept = list.filter((h) => !isOurs(h as never));\n if (kept.length !== list.length) {\n changed = true;\n if (kept.length) hooks[ev] = kept;\n else delete hooks[ev];\n }\n }\n if (!changed) return { file, changed: false };\n if (!Object.keys(hooks).length) delete settings.hooks;\n if (opts.created && !Object.keys(settings).length) {\n unlinkSync(file);\n return { file, changed: true, note: \"removed (sessionpipe created it)\" };\n }\n writeFileSync(file, formatJson(settings, f));\n return { file, changed: true };\n}\n\nexport function installedClaudeShaped(\n file: string,\n harness: string,\n events: readonly string[],\n cmd: HookCommand,\n o: ClaudeShapedOptions,\n): \"current\" | \"stale\" | \"missing\" {\n const f = readJsonFile(file);\n const hooks = (f.ok ? (f.value.hooks ?? {}) : {}) as Record<string, unknown[]>;\n let present = 0;\n let current = 0;\n for (const ev of events) {\n const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];\n const mine = list.filter((h) => isOurs(h as never));\n if (mine.length) present++;\n if (mine.length === 1 && JSON.stringify(mine[0]) === JSON.stringify(entryFor(ev, harness, cmd, o))) current++;\n }\n // An entry of ours on an event outside the wanted set (a lean install after a full one) is stale.\n for (const ev of Object.keys(hooks))\n if (!events.includes(ev) && (Array.isArray(hooks[ev]) ? hooks[ev] : []).some((h) => isOurs(h as never)))\n return \"stale\";\n if (!present) return \"missing\";\n return current === events.length ? \"current\" : \"stale\";\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Antigravity (Google) \u2014 control delivery (spec/CONTROL.md \u00A76). Its CLI, `agy`, as the\n// control daemon needs it: which `agy` to run, one headless turn (`agy -p \u2026 --output-\n// format stream-json`, and `--conversation <id>` for the next message), and its stream\n// read as it arrives. agy picks a new conversation's id itself (the `init` line) and\n// starts a fresh one for an id it doesn't know, so the daemon names it after the\n// command that started it (CONTROL.md \u00A76 `start`). No transcript records the folder, so\n// the daemon keeps that too. Shapes measured on agy 1.2.16, 2026-10-04.\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { RunLevel, StartPermission } from \"../control/verify.js\";\nimport { deniedNote, findBinary, jobEnv, type Mode, type Reading, type RunResult, runFailure } from \"./headless.js\";\n\nconst LABEL = \"Antigravity\";\n\n/** The `agy` to run: SESSIONPIPE_AGY, else on PATH, else where its installer puts it. */\nexport function findAgy(env: NodeJS.ProcessEnv = process.env, home = os.homedir()): string | null {\n return findBinary({\n override: env.SESSIONPIPE_AGY,\n names: process.platform === \"win32\" ? [\"agy.exe\", \"agy.cmd\"] : [\"agy\"],\n env,\n dirs: [path.join(home, \".local\", \"bin\"), \"/opt/homebrew/bin\", \"/usr/local/bin\"],\n });\n}\n\n/** Permission flags for a level. Safe: none \u2014 agy denies every tool call nobody is\n * there to approve, and says which. Edits: `--mode accept-edits`, its widest, which is\n * also what an auto machine's mode means for it. Inherit: none either, so agy runs as\n * it would by itself. agy has no read-only mode known, so `read` is never offered and\n * throws rather than run at safe. Never `--dangerously-skip-permissions`: no path here\n * writes it. */\nexport function agyModeFlags(level: RunLevel): string[] {\n if (level === \"read\") throw new Error(\"Antigravity has no read-only mode\");\n return level === \"safe\" || level === \"inherit\" ? [] : [\"--mode\", \"accept-edits\"];\n}\n\n/** The levels a start may ask agy for on a machine in `mode`: safe, and edits on an\n * auto machine. */\nexport const offeredLevels = (mode: Mode): StartPermission[] => (mode === \"auto\" ? [\"safe\", \"edits\"] : [\"safe\"]);\n\n/** What a start that names no level gets, said as what it is: edits on an auto machine,\n * no flag on an inherit one. */\nexport const defaultLevel = (mode: Mode): RunLevel => (mode === \"auto\" ? \"edits\" : mode);\n\n/** One headless turn in the folder it is spawned in. A message that starts with a dash\n * would read as a flag after `-p`; a leading space keeps it the prompt. */\nexport function agyArgs(o: { permission: RunLevel; prompt: string; resume?: string }): string[] {\n const prompt = o.prompt.startsWith(\"-\") ? ` ${o.prompt}` : o.prompt;\n return [\n ...(o.resume ? [\"--conversation\", o.resume] : []),\n \"-p\",\n prompt,\n \"--output-format\",\n \"stream-json\",\n ...agyModeFlags(o.permission),\n ];\n}\n\n/** The env a headless turn runs with. */\nexport const agyEnv = (env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv => jobEnv(env);\n\nexport interface AgyResult {\n status: string;\n response: string;\n error: string;\n denied: unknown[];\n}\n\n/** One stream-json line, as much of it as the daemon uses. */\nexport interface AgyPiece {\n /** The conversation's id, which agy chose (`init`, then every step and the result). */\n session?: string;\n /** Text an `agent_response` step wrote, and which step it belongs to. */\n delta?: { step: number; text: string };\n /** The final `result`. */\n result?: AgyResult;\n /** An `error_message` step's words: the reason only if the run then fails. */\n note?: string;\n}\n\nexport function agyLine(line: string): AgyPiece | null {\n let j: Record<string, unknown>;\n try {\n j = JSON.parse(line);\n } catch {\n return null;\n }\n if (!j || typeof j !== \"object\") return null;\n const str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n const out: AgyPiece = {};\n if (j.event === \"init\") {\n if (str(j.conversation_id)) out.session = str(j.conversation_id);\n } else if (j.event === \"step_update\") {\n const s = (j.step_update ?? {}) as Record<string, unknown>;\n if (str(s.conversation_id)) out.session = str(s.conversation_id);\n if (s.step_type === \"agent_response\" && str(s.text_delta))\n out.delta = { step: Number(s.step_index ?? 0), text: str(s.text_delta) };\n if (s.step_type === \"error_message\") {\n const why = str(s.text_delta) || str(s.error) || str(s.message);\n if (why) out.note = why;\n }\n } else if (j.event === \"result\") {\n const r = (j.result ?? {}) as Record<string, unknown>;\n if (str(r.conversation_id)) out.session = str(r.conversation_id);\n out.result = {\n status: str(r.status),\n response: str(r.response),\n error: str(r.error),\n denied: Array.isArray(r.denied_actions) ? r.denied_actions : [],\n };\n } else return null;\n return Object.keys(out).length ? out : null;\n}\n\n/** What agy names a denied action by, whatever shape the entry has. */\nfunction deniedName(d: unknown): string | null {\n if (typeof d === \"string\") return d.slice(0, 80);\n if (!d || typeof d !== \"object\") return null;\n const o = d as Record<string, unknown>;\n for (const k of [\"tool_name\", \"toolName\", \"name\", \"tool\", \"action\", \"type\"])\n if (typeof o[k] === \"string\" && o[k]) return (o[k] as string).slice(0, 80);\n return null;\n}\n\n/** An `AGY_ERROR: {\u2026}` agy may end stderr with, in words. */\nexport function agyError(stderr: string | undefined): string {\n const s = String(stderr || \"\");\n const i = s.lastIndexOf(\"AGY_ERROR:\");\n if (i < 0) return \"\";\n const raw = s.slice(i + \"AGY_ERROR:\".length).trim();\n try {\n const j = JSON.parse(raw) as Record<string, unknown>;\n for (const k of [\"message\", \"error\", \"detail\"]) if (typeof j[k] === \"string\" && j[k]) return j[k] as string;\n } catch {}\n return (raw.split(\"\\n\")[0] as string).slice(0, 300);\n}\n\n/** An agy run read as it streams: the answer is the agent_response steps' text, and the\n * result's `response` once it comes. */\nexport class AgyReading implements Reading {\n session: string | null = null;\n lines = 0;\n private buf = \"\";\n private step: number | null = null;\n private result: AgyResult | null = null;\n private note: string | null = null;\n\n get text(): string {\n return this.buf;\n }\n\n feed(line: string): boolean {\n this.lines++;\n const p = agyLine(line);\n if (!p) return false;\n if (p.session && !this.session) this.session = p.session;\n if (p.note) this.note = p.note;\n if (p.result) this.result = p.result;\n if (!p.delta) return false;\n // A new response step after a tool step starts a new paragraph.\n if (this.step !== null && p.delta.step !== this.step && this.buf && !this.buf.endsWith(\"\\n\\n\")) this.buf += \"\\n\\n\";\n this.step = p.delta.step;\n this.buf += p.delta.text;\n return true;\n }\n\n outcome(res: RunResult): { failed: string } | { reply: string } {\n const broke = runFailure(LABEL, res);\n if (broke) return { failed: broke };\n const r = this.result;\n if (!r) {\n const why = agyError(res.stderr) || this.note || \"\";\n return {\n failed: `Antigravity exited (${res.signal || `code ${res.code}`}) without an answer${why ? `: ${why}` : \"\"}`,\n };\n }\n if (r.status !== \"SUCCESS\")\n return { failed: r.error || agyError(res.stderr) || this.note || \"Antigravity reported an error\" };\n const names = [...new Set(r.denied.map(deniedName).filter((n): n is string => !!n))];\n const text = r.response.trim()\n ? r.response.trim()\n : this.buf.trim() || \"(Antigravity finished without a written reply.)\";\n return { reply: text + deniedNote(names, r.denied.length) };\n }\n}\n\nexport const reading = (): AgyReading => new AgyReading();\n", "// SPDX-License-Identifier: Apache-2.0\n// Claude Code (Anthropic) \u2014 docs: https://code.claude.com/docs/en/hooks\n// Config: settings.json in EVERY config dir (~/.claude, $CLAUDE_CONFIG_DIR, ~/.claude-*):\n// one per account; hooks written to one never fire for the others. Reads only the\n// hook's stdin, the transcript it names, the per-pid session registry and the config\n// dir's .claude.json account (its id; its email only for control's pair and hello) \u2014\n// or, with no login there, the API its settings.json names (that one key, no token).\n// Ported from spacesheep-cli lib/sessions.js.\n\nimport { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines, recentFiles, scanLines } from \"../readers/files.js\";\nimport { gitFacts } from \"../readers/git.js\";\nimport { isInjected, readClaude } from \"../readers/transcripts.js\";\nimport type { HarnessAccount } from \"../types.js\";\nimport { installClaudeShaped, installedClaudeShaped, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport type {\n Adapter,\n BackfillRow,\n FactsState,\n HookCommand,\n HookInput,\n HookResult,\n InstallOptions,\n SessionFacts,\n} from \"./types.js\";\n\nconst NAME = \"claude-code\";\nexport const CLAUDE_EVENTS = [\n \"SessionStart\",\n \"UserPromptSubmit\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PostToolUseFailure\",\n \"PermissionRequest\",\n \"Notification\",\n \"Stop\",\n \"SubagentStart\",\n \"SubagentStop\",\n \"PreCompact\",\n \"PostCompact\",\n \"SessionEnd\",\n \"StopFailure\",\n] as const;\n/** With no sink above tier 0 only the heartbeat needs a tool event: one, not three (issue #12). */\nconst LEAN_SKIP = new Set([\"PreToolUse\", \"PostToolUseFailure\"]);\nconst eventsFor = (lean?: boolean) => (lean ? CLAUDE_EVENTS.filter((e) => !LEAN_SKIP.has(e)) : [...CLAUDE_EVENTS]);\nconst OPTS = {\n matcherFor: (e: string) => (/Tool|Permission/.test(e) ? \"\" : undefined),\n timeout: 5,\n // The hook waits up to 125 s for a verified control answer, and only when control\n // is paired on this machine; everywhere else it exits in milliseconds as before.\n timeoutFor: (e: string) => (e === \"PermissionRequest\" ? 130 : undefined),\n};\nconst DESKTOP_ID = /^local_[A-Za-z0-9-]{1,64}$/;\n\n/** Every Claude Code config dir on this machine. `home` follows the env's HOME, so a\n * caller with its own env (a test) never reaches the real ~/.claude: the install test\n * once rewrote a real settings.json with its fake hook paths on every run. */\nexport function claudeDirs(env: NodeJS.ProcessEnv = process.env, home = env.HOME || homeDir()): string[] {\n const out: string[] = [];\n const add = (d?: string) => {\n if (!d) return;\n const r = path.resolve(d);\n if (!out.includes(r)) out.push(r);\n };\n add(path.join(home, \".claude\"));\n add(env.CLAUDE_CONFIG_DIR);\n try {\n for (const e of readdirSync(home, { withFileTypes: true })) {\n if (!e.isDirectory() || !/^\\.claude[-_.]/.test(e.name)) continue;\n const d = path.join(home, e.name);\n if (existsSync(path.join(d, \"projects\")) || existsSync(path.join(d, \"settings.json\"))) add(d);\n }\n } catch {}\n return out.filter((d, i) => i === 0 || existsSync(d));\n}\nconst settingsIn = (dir: string) => path.join(dir, \"settings.json\");\nconst configDirOf = (transcript: string) => path.dirname(path.dirname(path.dirname(transcript)));\n\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst endReason = (r: unknown): \"clear\" | \"logout\" | \"exit\" | \"other\" =>\n r === \"clear\" || r === \"logout\" || r === \"exit\" ? r : r === \"prompt_input_exit\" ? \"exit\" : \"other\";\nconst notifKind = (t: unknown): \"permission\" | \"question\" | \"elicitation\" | \"idle\" | \"error\" =>\n t === \"permission_prompt\"\n ? \"permission\"\n : t === \"idle_prompt\"\n ? \"idle\"\n : t === \"elicitation_dialog\"\n ? \"elicitation\"\n : \"question\";\n\nexport const claudeCode: Adapter = {\n name: NAME,\n events: CLAUDE_EVENTS,\n detect: (env = process.env) => claudeDirs(env).some((d) => existsSync(d)),\n configFiles: (env = process.env) => claudeDirs(env).map(settingsIn),\n install: (cmd, env = process.env, opts: InstallOptions = {}) =>\n claudeDirs(env).map((d) => installClaudeShaped(settingsIn(d), NAME, eventsFor(opts.lean), cmd, OPTS)),\n uninstall: (env = process.env, opts: InstallOptions = {}) =>\n claudeDirs(env).map((d) =>\n uninstallClaudeShaped(settingsIn(d), CLAUDE_EVENTS, { created: opts.created?.includes(settingsIn(d)) }),\n ),\n installed: (cmd, env = process.env, opts: InstallOptions = {}) =>\n claudeDirs(env).map((d) => ({\n file: settingsIn(d),\n state: installedClaudeShaped(settingsIn(d), NAME, eventsFor(opts.lean), cmd, OPTS),\n })),\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = (s.session_id ?? s.sessionId) as string | undefined;\n if (!id) return null;\n if (notClaudeCode(String(id), s)) return null;\n const session: HookResult[\"session\"] = { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd };\n if (typeof s.model === \"string\") session.model = s.model;\n if (typeof s.agent_id === \"string\" && event.startsWith(\"Subagent\") === false && s.agent_id)\n session.parent_id = null;\n const turn_id = typeof s.prompt_id === \"string\" ? s.prompt_id : undefined;\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const call_id = typeof s.tool_use_id === \"string\" ? s.tool_use_id : undefined;\n const ms = typeof s.duration_ms === \"number\" ? Math.round(s.duration_ms) : undefined;\n const agent_id = typeof s.agent_id === \"string\" ? s.agent_id : undefined;\n // PermissionRequest carries no tool_use_id (recorded 2026-09-28): the id is a hash\n // of the prompt, the tool and its input, so the same prompt yields the same id and\n // a later control answer can name it.\n const permissionId = () =>\n `perm-${createHash(\"sha256\")\n .update(`${turn_id ?? \"\"}|${tool ?? \"\"}|${JSON.stringify(s.tool_input ?? null)}`)\n .digest(\"hex\")\n .slice(0, 16)}`;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(ev(\"session.started\", { source: pickSource(s.source ?? s.trigger) }));\n break;\n case \"UserPromptSubmit\": {\n // Only a string prompt is read; anything else is left unread rather than guessed at.\n const prompt = typeof s.prompt === \"string\" ? s.prompt : undefined;\n events.push(\n ev(\"turn.started\", {\n turn_id,\n prompt_chars: prompt === undefined ? undefined : [...prompt].length,\n // Claude Code's hook schema documents `source`\n // (user | sdk | system | loop_wakeup | schedule_wakeup | poll_event) and says a\n // payload may omit it while the field rolls out; 2.1.304's payload has no such\n // key at all. Forwarded verbatim, shape-guarded only: the list is the harness's\n // to extend.\n submitted_by: harnessWord(s.source),\n // One of Claude Code's own prompt wrappers: the prompt is a block the harness\n // wrote, so it is not the person's words. Absent is unknown, never \"the person\" \u2014\n // and `true` is never \"no person caused this turn\", because a Talk or\n // `sessionpipe wait` delivery hands the person's own message over inside a\n // <task-notification> (PROTOCOL.md \u00A74).\n injected: prompt !== undefined && injectedBlock(prompt) ? true : undefined,\n }),\n );\n break;\n }\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, call_id, turn_id, agent_id, input: s.tool_input }));\n break;\n case \"PostToolUse\":\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n call_id,\n turn_id,\n agent_id,\n ms,\n ok: true,\n input: s.tool_input,\n output: s.tool_response,\n }),\n );\n break;\n case \"PostToolUseFailure\":\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n call_id,\n turn_id,\n agent_id,\n ms,\n ok: false,\n error: errText(s.error ?? s.tool_response),\n input: s.tool_input,\n output: s.tool_response,\n }),\n );\n break;\n case \"PermissionRequest\":\n events.push(\n ev(\"attention.needed\", {\n attention_id: call_id ?? permissionId(),\n kind: \"permission\",\n tool,\n message: tool ? `${tool}${describe(s.tool_input)}` : undefined,\n }),\n );\n break;\n case \"Notification\":\n events.push(\n ev(\"attention.needed\", {\n attention_id: `notif-${Date.now()}`,\n kind: notifKind(s.notification_type),\n message: typeof s.message === \"string\" ? s.message.slice(0, 200) : undefined,\n }),\n );\n break;\n case \"Stop\":\n // In-flight background work (shell commands, monitors, subagents, workflows)\n // that will wake the session when it finishes: a paused session, not a done one\n // (Claude Code's `background_tasks`, in every Stop recorded since 2.1.258). A count, never what they run.\n events.push(\n ev(\"turn.ended\", {\n turn_id,\n reason: \"stop\",\n background: Array.isArray(s.background_tasks) ? s.background_tasks.length : undefined,\n }),\n );\n break;\n case \"StopFailure\":\n // The turn ended on an API error (rate_limit, overloaded, authentication_failed,\n // server_error \u2026); the payload key is `error` (issue #10, recorded 2026-09-28).\n events.push(\n ev(\"turn.ended\", {\n turn_id,\n reason: \"error\",\n error: typeof s.error === \"string\" ? s.error.slice(0, 200) : undefined,\n }),\n );\n break;\n case \"SubagentStart\":\n events.push(\n ev(\"subagent.started\", {\n agent_id: String(s.agent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"SubagentStop\":\n events.push(\n ev(\"subagent.ended\", {\n agent_id: String(s.agent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"PreCompact\":\n events.push(ev(\"context.compacted\", { trigger: s.trigger === \"manual\" ? \"manual\" : \"auto\" }));\n break;\n case \"PostCompact\":\n break; // PreCompact already said it; a second event would double-count\n case \"SessionEnd\":\n events.push(ev(\"session.ended\", { reason: endReason(s.reason) }));\n break;\n default:\n return null;\n }\n const hints: Record<string, unknown> = {};\n // The prompt, for the turn's first turn.progress: the transcript may not hold it\n // yet when the worker runs. Never an event field of its own (tier 2 carries it).\n if (event === \"UserPromptSubmit\" && typeof s.prompt === \"string\") hints.prompt = s.prompt;\n const host = input.env.CLAUDE_CODE_HOST_SESSION_ID;\n if (host && DESKTOP_ID.test(host)) hints.desktop_id = host;\n // Whether a person attends the session, in Claude Code's own word (\"1\" or \"0\" in a hook's\n // environment); a turn the control daemon runs on the person's signed message is theirs.\n // facts() turns it into session.attended once it knows whether the session has a link.\n const attended = input.env.CLAUDE_CODE_SESSION_ATTENDED;\n if (attended === \"1\" || attended === \"0\") hints.attended = attended === \"1\" || !!input.env.SESSIONPIPE_CONTROL_JOB;\n // The registry file is found while the process tree stands (the detached\n // worker's parent is gone by the time it runs). Heartbeat-class events skip it.\n if (event !== \"PreToolUse\" && event !== \"PostToolUse\") hints.claude_pid = claudePid(input.env);\n const r: HookResult = { session, events, hints };\n if (typeof s.transcript_path === \"string\") r.transcript = s.transcript_path;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readClaude(text.split(\"\\n\"), fromLine);\n },\n\n facts(session, transcript, hints, state): SessionFacts {\n const out: SessionFacts = {};\n if (transcript) Object.assign(out, claudeFacts(transcript, session.id, hints, state));\n const cwd = out.cwd ?? session.cwd;\n Object.assign(out, gitFacts(cwd), out.branch ? { branch: out.branch } : {});\n if (!out.url && typeof hints.desktop_id === \"string\") out.url = `claude://code/continue/${hints.desktop_id}`;\n // A Remote Control session says \"0\" though a person drives it from claude.ai: it runs as a\n // headless child of `claude remote-control`. Its link is what tells it from a `claude -p`;\n // CLAUDE_CODE_ENVIRONMENT_KIND cannot, since a `claude -p` started inside a Remote Control\n // session inherits \"bridge\", while the registry entry it writes has no bridge id of its own.\n if (typeof hints.attended === \"boolean\") out.attended = hints.attended || !!out.url;\n return out;\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows: BackfillRow[] = [];\n const files: string[] = [];\n for (const d of claudeDirs(env))\n files.push(...recentFiles(path.join(d, \"projects\"), 1, sinceMs, (n) => /^[0-9a-f-]{36}\\.jsonl$/.test(n)));\n const noState: FactsState = { get: () => ({}), save: () => {} };\n for (const f of files) {\n const id = path.basename(f, \".jsonl\");\n const facts = claudeFacts(f, id, {}, noState);\n if (!facts.started_at || !facts.last_at) continue;\n const { started_at, last_at, first_ask: _fa, harness_version: _hv, ...rest } = facts;\n const cwd = rest.cwd;\n rows.push({\n session: { id, ...rest, ...gitFacts(cwd), ...(rest.branch ? { branch: rest.branch } : {}) },\n started_at,\n last_at,\n });\n }\n return rows;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/** Another harness reading this settings file, not Claude Code. Several harnesses\n * import `~/.claude/settings.json` hooks, so our entries there can be run by a tool\n * that has its own adapter: it would arrive under the wrong name, with ids that mean\n * nothing to a Claude Code reader. Every Claude Code payload names a transcript and a\n * UUID session (all 21 recorded fixtures do); a payload with neither is somebody else's. */\nexport function notClaudeCode(id: string, s: Record<string, unknown>): boolean {\n return typeof s.transcript_path !== \"string\" && !UUID.test(id);\n}\nfunction pickSource(v: unknown): string {\n return typeof v === \"string\" && [\"startup\", \"resume\", \"clear\", \"compact\", \"fork\"].includes(v) ? v : \"unknown\";\n}\n/** One of the harness's own words for who submitted a prompt, forwarded as is (PROTOCOL.md\n * \u00A74, `turn.started.submitted_by`). Not an enum of ours: a value we have never seen is\n * still carried, so the guard is the shape the spec allows \u2014 a bare word of at most 40\n * characters, which is all a receiver may show or group by. Tier 0 is not redacted\n * (PRIVACY.md \u00A72), so that shape is the only guard there is. */\nconst harnessWord = (v: unknown): string | undefined =>\n typeof v === \"string\" && /^[A-Za-z0-9][A-Za-z0-9_.-]{0,39}$/.test(v) ? v : undefined;\n/** Claude Code's own prompt wrappers, as a CLOSED list: a task notification, a peer message,\n * a system reminder, a local command's output, a slash command's expansion \u2014 with or\n * without a closing tag, after trimming. Narrower than the reader's `isInjected` on\n * purpose, because the two directions do not cost the same. A wrapper we have not recorded\n * yet reads as unknown and a receiver keeps the turn, which is what it does today; a shape\n * test wide enough to catch every wrapper also fires on a person who pasted nothing but an\n * SVG, an HTML page or a JSX element, and a recency board acting on that would drop one of\n * the person's own turns. Dropping one record from a transcript costs little, which is why\n * the reader's test stays wide; ADAPTERS.md (Claude Code \u00B7 Quirks) says why they differ. */\nconst WRAPPER =\n /^<(?:task-notification|cross-session-message|system-reminder|local-command-stdout|command-[a-z-]+)[\\s/>]/i;\nconst injectedBlock = (prompt: string): boolean => WRAPPER.test(prompt.trim());\nfunction errText(v: unknown): string | undefined {\n if (typeof v === \"string\") return v.slice(0, 2000);\n if (v && typeof v === \"object\") {\n const e = v as { error?: unknown; message?: unknown };\n if (typeof e.error === \"string\") return e.error.slice(0, 2000);\n if (typeof e.message === \"string\") return e.message.slice(0, 2000);\n }\n return undefined;\n}\nfunction describe(input: unknown): string {\n if (!input || typeof input !== \"object\") return \"\";\n const i = input as Record<string, unknown>;\n const v = i.command ?? i.file_path ?? i.path ?? i.url ?? i.pattern;\n return typeof v === \"string\" ? ` ${v.slice(0, 120)}` : \"\";\n}\n\n// --- facts: title, url, model, account, from Claude Code's own files ------------------\n\nconst NAME_RANK: Record<string, \"custom\" | \"harness\"> = {\n user: \"custom\",\n auto: \"harness\",\n hook: \"harness\",\n peer: \"harness\",\n};\ninterface Registry {\n sessionId: string | null;\n name: string | null;\n name_source: \"custom\" | \"harness\" | null;\n bridge: string | null;\n}\nfunction registryEntry(j: unknown): Registry | null {\n if (!j || typeof j !== \"object\") return null;\n const r = j as { sessionId?: unknown; name?: unknown; nameSource?: string; bridgeSessionId?: unknown };\n const source = r.nameSource ? NAME_RANK[r.nameSource] : undefined;\n return {\n sessionId: r.sessionId ? String(r.sessionId) : null,\n name: source && typeof r.name === \"string\" && r.name.trim() ? r.name.trim() : null,\n name_source: source ?? null,\n bridge: typeof r.bridgeSessionId === \"string\" ? r.bridgeSessionId : null,\n };\n}\nconst liveCache = new Map<string, Map<string, Registry>>();\nfunction claudeLive(dir: string): Map<string, Registry> {\n const hit = liveCache.get(dir);\n if (hit) return hit;\n const map = new Map<string, Registry>();\n let names: string[] = [];\n try {\n names = readdirSync(path.join(dir, \"sessions\")).filter((n) => n.endsWith(\".json\"));\n } catch {}\n for (const n of names) {\n try {\n const e = registryEntry(JSON.parse(readFileSync(path.join(dir, \"sessions\", n), \"utf8\")));\n if (e?.sessionId) map.set(e.sessionId, e);\n } catch {}\n }\n liveCache.set(dir, map);\n return map;\n}\nfunction claudeLiveByPid(dir: string, pid: unknown): Registry | null {\n if (!pid) return null;\n try {\n return registryEntry(JSON.parse(readFileSync(path.join(dir, \"sessions\", `${pid}.json`), \"utf8\")));\n } catch {\n return null;\n }\n}\n/** The Claude Code process that ran this hook: the nearest ancestor with a registry\n * file (hooks run under a shell, so usually the parent's parent). */\nexport function claudePid(env: NodeJS.ProcessEnv = process.env): number | null {\n try {\n const dirs = claudeDirs(env);\n const has = (pid: number) => dirs.some((d) => existsSync(path.join(d, \"sessions\", `${pid}.json`)));\n let pid = process.ppid;\n if (has(pid)) return pid;\n const parent = parentOf();\n for (let hop = 0; hop < 6 && pid > 1; hop++) {\n pid = parent(pid);\n if (pid > 1 && has(pid)) return pid;\n }\n } catch {}\n return null;\n}\nfunction parentOf(): (pid: number) => number {\n if (process.platform === \"linux\") {\n return (pid) => {\n try {\n const st = readFileSync(`/proc/${pid}/stat`, \"utf8\");\n return Number(st.slice(st.lastIndexOf(\")\") + 2).split(\" \")[1]) || 0;\n } catch {\n return 0;\n }\n };\n }\n const table = new Map<number, number>();\n try {\n const out = execFileSync(\"ps\", [\"-axo\", \"pid=,ppid=\"], {\n encoding: \"utf8\",\n timeout: 2000,\n maxBuffer: 8 * 1024 * 1024,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n for (const l of out.split(\"\\n\")) {\n const m = /^\\s*(\\d+)\\s+(\\d+)/.exec(l);\n if (m) table.set(Number(m[1]), Number(m[2]));\n }\n } catch {}\n return (pid) => table.get(pid) || 0;\n}\nconst EMAIL_RE = /^[^@\\s]{1,64}@[^@\\s]{1,189}$/;\n/** Who a config dir is signed in as, from its .claude.json (the default dir keeps it\n * at ~/.claude.json): the account id, and the email it signs in with. A dir with no\n * claude.ai login that runs on another API is that API's account (apiAccount). */\nfunction claudeLogin(dir: string, home = homeDir()): { id: string; email?: string; name?: string } | null {\n const files = [path.join(dir, \".claude.json\")];\n if (path.resolve(dir) === path.join(home, \".claude\")) files.unshift(path.join(home, \".claude.json\"));\n for (const f of files) {\n try {\n const a = (\n JSON.parse(readFileSync(f, \"utf8\")) as { oauthAccount?: { accountUuid?: unknown; emailAddress?: unknown } }\n ).oauthAccount;\n if (typeof a?.accountUuid === \"string\" && a.accountUuid) {\n const email = typeof a.emailAddress === \"string\" && EMAIL_RE.test(a.emailAddress) ? a.emailAddress : undefined;\n return { id: a.accountUuid.slice(0, 128), ...(email ? { email } : {}) };\n }\n } catch {}\n }\n return apiAccount(dir);\n}\n/** Anthropic's own API: a key for it is an Anthropic account no local file names. */\nconst ANTHROPIC_HOST = /(^|\\.)anthropic\\.com$/i;\n/** A config dir whose settings send Claude Code to another API (`env.ANTHROPIC_BASE_URL`:\n * Kimi on a Modal endpoint, GLM on Z.ai) has no claude.ai login, so its account is the\n * endpoint: `api-` and 16 hex of the SHA-256 of its origin for events (the same on every\n * machine that uses it), and its host as the name control's pair and hello give it.\n * Only that one key is read; the tokens and headers beside it never are. */\nfunction apiAccount(dir: string): { id: string; name: string } | null {\n let base: unknown;\n try {\n base = (JSON.parse(readFileSync(settingsIn(dir), \"utf8\")) as { env?: { ANTHROPIC_BASE_URL?: unknown } }).env\n ?.ANTHROPIC_BASE_URL;\n } catch {\n return null;\n }\n if (typeof base !== \"string\") return null;\n let u: URL;\n try {\n u = new URL(base.trim());\n } catch {\n return null;\n }\n if ((u.protocol !== \"https:\" && u.protocol !== \"http:\") || !u.hostname || ANTHROPIC_HOST.test(u.hostname))\n return null;\n // The origin alone: a path or a user:password@ can carry a key.\n const origin = `${u.protocol}//${u.host}`;\n return { id: `api-${createHash(\"sha256\").update(origin).digest(\"hex\").slice(0, 16)}`, name: u.host };\n}\nconst accountCache = new Map<string, string | null>();\n/** The account id for `session.account_id`: never the email. Events go to every sink,\n * a team board included; the email (or an API's host) reaches only a receiver the\n * person paired with, in control's pair and hello (claudeAccounts). */\nfunction claudeAccount(dir: string): string | null {\n const hit = accountCache.get(dir);\n if (hit !== undefined) return hit;\n const acct = claudeLogin(dir)?.id ?? null;\n accountCache.set(dir, acct);\n return acct;\n}\n/** Every account signed in across these config dirs, read fresh (a person signs in to\n * another account without restarting anything), for control's pair and hello. */\nexport function claudeAccounts(dirs: string[], home = homeDir()): HarnessAccount[] {\n const out: HarnessAccount[] = [];\n for (const d of dirs) {\n const l = claudeLogin(d, home);\n if (!l) continue;\n const seen = out.find((a) => a.id === l.id);\n if (!seen) out.push({ harness: NAME, ...l });\n else if (!seen.email && l.email) seen.email = l.email;\n }\n return out;\n}\nconst LINK_RE = /^https:\\/\\/claude\\.ai\\/code\\/session_[A-Za-z0-9]+$/;\nfunction transcriptLink(records: Record<string, unknown>[]): string | null {\n for (let i = records.length - 1; i >= 0; i--) {\n const j = records[i] as { type?: string; subtype?: string; url?: unknown; bridgeSessionId?: unknown };\n if (j.type === \"system\" && j.subtype === \"bridge_status\" && typeof j.url === \"string\" && LINK_RE.test(j.url))\n return j.url;\n if (j.type === \"bridge-session\" && typeof j.bridgeSessionId === \"string\") {\n const m = /^(?:cse|session)_([A-Za-z0-9]+)$/.exec(j.bridgeSessionId);\n if (m) return `https://claude.ai/code/session_${m[1]}`;\n }\n }\n return null;\n}\n/** A first ask as the Claude Code app titles an untitled session: whitespace\n * collapsed, whole up to 50 characters, else its first 50 and \"...\". */\nexport function appTitle(text: string): string {\n const t = String(text).replace(/\\s+/g, \" \").trim();\n return t.length > 50 ? `${t.slice(0, 50)}...` : t;\n}\nfunction askText(j: Record<string, unknown> | null): string | null {\n if (!j || j.type !== \"user\" || j.isMeta || j.isSidechain) return null;\n const origin = j.origin as { kind?: string } | undefined;\n if (origin?.kind && origin.kind !== \"human\") return null;\n const c = (j.message as { content?: unknown } | undefined)?.content;\n const text = (\n typeof c === \"string\"\n ? c\n : Array.isArray(c)\n ? c\n .filter((b) => b && b.type === \"text\" && typeof b.text === \"string\")\n .map((b) => b.text as string)\n .join(\"\\n\")\n : \"\"\n ).trim();\n if (!text || isInjected(text)) return null;\n return text;\n}\nfunction firstAsk(records: Record<string, unknown>[]): string | null {\n for (const j of records) {\n const t = askText(j);\n if (t) return appTitle(t);\n }\n return null;\n}\nfunction scanTitles(file: string, from: number, found: { custom?: string | null; ai?: string | null }) {\n const out = { custom: found.custom ?? null, ai: found.ai ?? null, upto: from };\n let size = 0;\n try {\n size = statSync(file).size;\n } catch {\n return out;\n }\n if (size < from) {\n out.upto = 0;\n out.custom = out.ai = null;\n from = 0;\n }\n // Only lines carrying a title record are parsed; the rest of the new bytes are skipped.\n let pos = 0;\n scanLines<null>(\n file,\n (l) => {\n pos += Buffer.byteLength(l, \"utf8\") + 1;\n if (pos <= from || l.indexOf('-title\"') < 0) return null;\n try {\n const j = JSON.parse(l) as { type?: string; customTitle?: string; aiTitle?: string };\n if (j.type === \"custom-title\" && j.customTitle) out.custom = j.customTitle;\n if (j.type === \"ai-title\" && j.aiTitle) out.ai = j.aiTitle;\n } catch {}\n return null;\n },\n 512 * 1024 * 1024,\n );\n out.upto = size;\n return out;\n}\n\n/** A session's title and where it came from, best first: /rename (registry \"user\"\n * name or custom-title) \u2192 Claude Code's own title (registry \"auto\" name or\n * ai-title) \u2192 the first ask, marked first-ask so a real title later replaces it. */\nexport function claudeFacts(\n file: string,\n sessionId: string,\n hints: Record<string, unknown>,\n state: FactsState,\n): SessionFacts {\n const { head, tail } = ends(file, 64 * 1024, 256 * 1024);\n const H = parseLines(head);\n const T = parseLines(tail);\n const out: SessionFacts = {};\n const id = sessionId || path.basename(file, \".jsonl\");\n const mem = state.get(NAME, id);\n let custom: string | null = null;\n let ai: string | null = null;\n for (const j of H.concat(T)) {\n if (j.type === \"custom-title\" && typeof j.customTitle === \"string\") custom = j.customTitle;\n if (j.type === \"ai-title\" && typeof j.aiTitle === \"string\") ai = j.aiTitle;\n }\n let size = 0;\n try {\n size = statSync(file).size;\n } catch {}\n if (!custom && !ai && size > 64 * 1024 + 256 * 1024) {\n const s = scanTitles(file, Number(mem.scan_upto) || 0, {\n custom: mem.scan_custom as string | null,\n ai: mem.scan_ai as string | null,\n });\n custom = s.custom;\n ai = s.ai;\n state.save(NAME, id, { scan_upto: s.upto, scan_custom: s.custom, scan_ai: s.ai });\n }\n const dir = configDirOf(file);\n const live = claudeLive(dir).get(id) ?? claudeLiveByPid(dir, hints.claude_pid);\n if (live?.name) state.save(NAME, id, { name: live.name, name_source: live.name_source });\n const bridge =\n live?.bridge && /^session_[A-Za-z0-9]+$/.test(live.bridge) ? `https://claude.ai/code/${live.bridge}` : null;\n const url = bridge ?? transcriptLink(T) ?? transcriptLink(H) ?? (typeof mem.url === \"string\" ? mem.url : null);\n if (url) {\n out.url = url;\n state.save(NAME, id, { url });\n }\n const name = live?.name\n ? { title: live.name, source: live.name_source as \"custom\" | \"harness\" }\n : typeof mem.name === \"string\"\n ? { title: mem.name, source: mem.name_source as \"custom\" | \"harness\" }\n : null;\n const pick =\n (name && name.source === \"custom\" && name) ||\n (custom && { title: custom, source: \"custom\" as const }) ||\n name ||\n (ai && { title: ai, source: \"harness\" as const });\n let ask = typeof mem.first_ask === \"string\" ? mem.first_ask : firstAsk(H);\n if (!ask && size > 64 * 1024 && !mem.first_ask_none) {\n ask = scanLines<string>(file, (l) => {\n try {\n const t = askText(JSON.parse(l) as Record<string, unknown>);\n return t ? appTitle(t) : null;\n } catch {\n return null;\n }\n });\n if (!ask && size > 16 * 1024 * 1024) state.save(NAME, id, { first_ask_none: true });\n }\n if (ask) {\n out.first_ask = ask;\n if (!mem.first_ask) state.save(NAME, id, { first_ask: ask });\n }\n if (pick) {\n out.title = String(pick.title).slice(0, 120);\n out.title_source = pick.source;\n } else if (ask) {\n out.title = ask;\n out.title_source = \"first-ask\";\n }\n const acct = claudeAccount(dir);\n if (acct) out.account_id = acct;\n for (let i = T.length - 1; i >= 0; i--) {\n const m = (T[i] as { message?: { model?: string } }).message?.model;\n if (T[i]?.type === \"assistant\" && m && m !== \"<synthetic>\") {\n out.model = m;\n break;\n }\n }\n const meta = [...T].reverse().find((j) => j.version) ?? H.find((j) => j.version);\n if (meta?.version) out.harness_version = String(meta.version);\n const times = H.concat(T)\n .map((j) => Date.parse(String(j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n const withCwd = H.find((j) => typeof j.cwd === \"string\");\n if (withCwd) {\n out.cwd = withCwd.cwd as string;\n if (typeof withCwd.gitBranch === \"string\" && withCwd.gitBranch !== \"HEAD\") out.branch = withCwd.gitBranch;\n }\n return out;\n}\n\n/** For tests: each hook runs in a fresh process; a test that edits the registry mid-run clears the cache. */\nexport const _resetClaudeCaches = (): void => {\n liveCache.clear();\n accountCache.clear();\n};\n", "// SPDX-License-Identifier: Apache-2.0\n// The repo and branch of a folder, from git itself; credentials stripped from the\n// remote. Cached per folder for the life of the process (a worker run).\nimport { execFileSync } from \"node:child_process\";\n\nconst cache = new Map<string, { repo?: string; branch?: string }>();\n\nexport function gitFacts(cwd: string | undefined): { repo?: string; branch?: string } {\n if (!cwd) return {};\n const hit = cache.get(cwd);\n if (hit) return hit;\n const run = (args: string[]) => {\n try {\n return execFileSync(\"git\", [\"-C\", cwd, ...args], {\n encoding: \"utf8\",\n timeout: 1500,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return \"\";\n }\n };\n const out: { repo?: string; branch?: string } = {};\n const repo = run([\"remote\", \"get-url\", \"origin\"]);\n if (repo) out.repo = stripCredentials(repo);\n const branch = run([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n if (branch && branch !== \"HEAD\") out.branch = branch;\n cache.set(cwd, out);\n return out;\n}\n\n/** `https://user:token@host/x` \u2192 `https://host/x`; `git@github.com:a/b.git` \u2192 `github.com/a/b`. */\nexport function stripCredentials(url: string): string {\n // The ssh forms first: the `git@` they are known by is what the credential strip removes.\n const ssh = /^(?:ssh:\\/\\/)?git@([^:/]+)[:/](.+?)(?:\\.git)?$/.exec(url);\n if (ssh) return `${ssh[1]}/${ssh[2]}`;\n return url\n .replace(/\\/\\/[^/@]*@/, \"//\")\n .replace(/^https?:\\/\\//, \"\")\n .replace(/\\.git$/, \"\");\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Claude Code (Anthropic) \u2014 control delivery (spec/CONTROL.md \u00A76). Claude Code on\n// this machine, as the control daemon needs it: which `claude` to\n// run and with which permission flags, where a session's transcript is and which\n// folder it runs in, whether a live process holds it, and running one headless\n// turn (`claude -p --resume`, `--fork-session`, `--session-id`). Ported from the\n// spacesheep CLI's machine listener (lib/machine.js, 1.22), which ran it in\n// production first.\nimport { execFile, execFileSync } from \"node:child_process\";\nimport { closeSync, openSync, readdirSync, readFileSync, readSync, statSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { levelRank, type RunLevel, START_PERMISSIONS, type StartPermission } from \"../control/verify.js\";\nimport {\n isExe,\n JOB_TIMEOUT_MS,\n type Login,\n type Mode,\n type RunOptions,\n type RunResult,\n runHeadless,\n} from \"./headless.js\";\n\nexport { JOB_TIMEOUT_MS, type Login, type Mode, type RunResult };\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/** A transcript someone else wrote this recently is in use. */\nconst LIVE_WRITE_MS = 90_000;\n\n/** Dotted versions by number, a missing part as 0: 1.9.0 < 1.10 = 1.10.0. */\nexport const cmpVersion = (a: string, b: string) => {\n const pa = a.split(\".\").map(Number);\n const pb = b.split(\".\").map(Number);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++)\n if ((pa[i] ?? 0) !== (pb[i] ?? 0)) return (pa[i] ?? 0) - (pb[i] ?? 0);\n return 0;\n};\n\n/** The `claude` to run: on PATH, else where the installers put it, else the newest\n * copy the desktop app ships. Null when this machine has none. */\nexport function findClaude(env: NodeJS.ProcessEnv = process.env, home = os.homedir()): string | null {\n if (env.SESSIONPIPE_CLAUDE && isExe(env.SESSIONPIPE_CLAUDE)) return env.SESSIONPIPE_CLAUDE;\n const names = process.platform === \"win32\" ? [\"claude.exe\", \"claude.cmd\"] : [\"claude\"];\n for (const d of String(env.PATH || \"\").split(path.delimiter)) {\n if (!d || !path.isAbsolute(d)) continue;\n for (const n of names) if (isExe(path.join(d, n))) return path.join(d, n);\n }\n for (const p of [\n path.join(home, \".claude\", \"local\", \"claude\"),\n path.join(home, \".local\", \"bin\", \"claude\"),\n \"/opt/homebrew/bin/claude\",\n \"/usr/local/bin/claude\",\n ])\n if (isExe(p)) return p;\n const app = path.join(home, \"Library\", \"Application Support\", \"Claude\", \"claude-code\");\n let versions: string[] = [];\n try {\n versions = readdirSync(app)\n .filter((n) => /^\\d+(\\.\\d+)*$/.test(n))\n .sort(cmpVersion)\n .reverse();\n } catch {}\n for (const v of versions) {\n const p = path.join(app, v, \"claude.app\", \"Contents\", \"MacOS\", \"claude\");\n if (isExe(p)) return p;\n }\n return null;\n}\n\n/** One option's text in `claude --help`: its line and the deeper-indented lines under it. */\nfunction optionBlock(help: string, flag: string): string | null {\n const lines = help.split(\"\\n\");\n const re = new RegExp(`^\\\\s{0,4}(?:-\\\\w, )?${flag.replace(/-/g, \"\\\\-\")}(?![\\\\w-])`);\n const start = lines.findIndex((l) => re.test(l));\n if (start < 0) return null;\n const out = [lines[start] as string];\n for (let i = start + 1; i < lines.length && lines[i]?.trim() && !/^\\s{0,4}-/.test(lines[i] as string); i++)\n out.push(lines[i] as string);\n return out.join(\" \");\n}\n\nexport interface Caps {\n hasMode: boolean;\n modes: string[];\n promptsNone: boolean;\n fork: boolean;\n /** `--output-format stream-json` with `--include-partial-messages`: the answer can be\n * forwarded as it is written. Optional so older callers' literals still type. */\n stream?: boolean;\n}\n\nexport function parseCaps(help: string): Caps {\n const pm = optionBlock(help, \"--permission-mode\");\n const pp = optionBlock(help, \"--permission-prompts\");\n return {\n hasMode: !!pm,\n modes: pm ? [...pm.matchAll(/\"([A-Za-z]+)\"/g)].map((m) => m[1] as string) : [],\n promptsNone: !!pp && /\"none\"/.test(pp),\n fork: !!optionBlock(help, \"--fork-session\"),\n stream: !!optionBlock(help, \"--include-partial-messages\"),\n };\n}\n\n/** The `--permission-mode` each level (CONTROL.md \u00A73.1) is, where it is one mode. */\nconst LEVEL_MODE: Record<Exclude<StartPermission, \"safe\">, string> = {\n read: \"plan\",\n edits: \"acceptEdits\",\n auto: \"auto\",\n};\n\n/** Permission flags for a level (a machine's mode is one: safe, auto, inherit). Read:\n * plan mode. Safe: `dontAsk` (nothing that needs approval runs). Edits: acceptEdits.\n * Auto: Claude Code's own auto mode. Inherit: none, so the turn starts in the mode\n * Claude Code picks by itself here, its settings' `permissions.defaultMode` (a resume\n * too: Claude Code never restores a session's earlier mode). A level this Claude Code\n * has no mode for is a refusal, never another level. Never bypassPermissions \u2014 no path\n * here writes it. */\nexport function modeFlags(level: RunLevel, caps: Caps): { args: string[] } | { error: string } {\n if (level === \"inherit\") return { args: [] };\n if (level === \"auto\" && !caps.modes.includes(\"auto\"))\n return { error: \"this machine is in auto mode, but its Claude Code has no auto permission mode\" };\n if (level !== \"safe\") {\n const m = LEVEL_MODE[level];\n if (!caps.modes.includes(m)) return { error: `this machine's Claude Code has no ${m} permission mode` };\n return { args: [\"--permission-mode\", m] };\n }\n if (caps.modes.includes(\"dontAsk\")) return { args: [\"--permission-mode\", \"dontAsk\"] };\n const args: string[] = [];\n if (caps.hasMode)\n args.push(\n \"--permission-mode\",\n caps.modes.includes(\"manual\") && !caps.modes.includes(\"default\") ? \"manual\" : \"default\",\n );\n if (caps.promptsNone) args.push(\"--permission-prompts\", \"none\");\n return { args };\n}\n\n/** The widest level a start may name on a machine in `mode`: the mode itself, and safe\n * on an inherit machine, whose own default sessionpipe can't rank, so a message there may\n * only narrow to a level that never runs anything needing approval. */\nexport const ceilingLevel = (mode: Mode): StartPermission => (mode === \"inherit\" ? \"safe\" : mode);\n\n/** The levels a start may ask Claude Code for on a machine in `mode`: never above its\n * ceiling, and each only where `claude --help` lists the mode it maps to (safe always). */\nexport function offeredLevels(mode: Mode, caps: Caps): StartPermission[] {\n return START_PERMISSIONS.filter(\n (l) => levelRank(l) <= levelRank(ceilingLevel(mode)) && (l === \"safe\" || caps.modes.includes(LEVEL_MODE[l])),\n );\n}\n\n/** What a start that names no level gets: what the machine's mode means for Claude Code. */\nexport const defaultLevel = (mode: Mode): RunLevel => mode;\n\n/** How a headless run prints: streamed where this Claude Code can, else one JSON at the end. */\nexport function outputArgs(caps: { stream?: boolean }): string[] {\n return caps.stream\n ? [\"--output-format\", \"stream-json\", \"--verbose\", \"--include-partial-messages\"]\n : [\"--output-format\", \"json\"];\n}\n\n/** One headless `claude -p` run: a new session (`session`), or the next message of one\n * (`resume`, optionally as a fork). The model is its own argument after `--model`, and\n * a prompt that starts with a dash gets a leading space, so it is never read as a flag. */\nexport function claudeArgs(o: {\n caps: Caps;\n level: RunLevel;\n prompt: string;\n session?: string;\n resume?: string;\n fork?: boolean;\n model?: string;\n allowedTools?: string[];\n}): { args: string[] } | { error: string } {\n const mf = modeFlags(o.level, o.caps);\n if (\"error\" in mf) return mf;\n const where = o.resume\n ? [\"--resume\", o.resume, ...(o.fork ? [\"--fork-session\"] : [])]\n : [\"--session-id\", o.session as string];\n return {\n args: [\n \"-p\",\n ...outputArgs(o.caps),\n ...mf.args,\n ...(o.model ? [\"--model\", o.model] : []),\n ...(o.allowedTools?.length ? [`--allowedTools=${o.allowedTools.join(\",\")}`] : []),\n ...where,\n o.prompt.startsWith(\"-\") ? ` ${o.prompt}` : o.prompt,\n ],\n };\n}\n\n/** The env a headless turn runs with: ours, minus the markers that make Claude Code\n * think it runs inside another session, with CLAUDE_CONFIG_DIR naming the account. */\nexport function claudeEnv(configDir?: string, env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n const e = { ...env };\n for (const k of [\n \"CLAUDECODE\",\n \"CLAUDE_CODE_SESSION_ID\",\n \"CLAUDE_CODE_HOST_SESSION_ID\",\n \"CLAUDE_CODE_ENTRYPOINT\",\n \"CLAUDE_CODE_SESSION_ATTENDED\",\n \"CLAUDE_CODE_SSE_PORT\",\n ])\n delete e[k];\n e.SESSIONPIPE_CONTROL_JOB = \"1\";\n if (configDir !== undefined) {\n if (path.resolve(configDir) === path.resolve(os.homedir(), \".claude\")) delete e.CLAUDE_CONFIG_DIR;\n else e.CLAUDE_CONFIG_DIR = configDir;\n }\n return e;\n}\n\n/** Whether Claude Code is signed in for one account, in Claude Code's own words\n * (`claude auth status --json`). `loggedIn: null` means this Claude Code can't say\n * (too old for `auth status`, or it didn't answer): never a reason to refuse. */\nexport function parseAuthStatus(stdout: string | null | undefined): Login {\n const text = String(stdout || \"\").trim();\n const start = text.indexOf(\"{\");\n if (start < 0) return { loggedIn: null };\n try {\n const j = JSON.parse(text.slice(start)) as Record<string, unknown>;\n if (typeof j.loggedIn !== \"boolean\") return { loggedIn: null };\n return {\n loggedIn: j.loggedIn,\n ...(typeof j.authMethod === \"string\" ? { method: j.authMethod } : {}),\n ...(typeof j.subscriptionType === \"string\" ? { subscription: j.subscriptionType } : {}),\n };\n } catch {\n return { loggedIn: null };\n }\n}\n\n/** Ask Claude Code whether the account in `configDir` (the default one when omitted)\n * is signed in, from this process \u2014 which is the point: a login kept in the macOS\n * keychain is readable from the screen's own session and not from a background\n * service on a Mac nobody is logged in to, or from an ssh shell, so a headless turn\n * started there dies with \"please run /login\". */\nexport function claudeLogin(bin: string, configDir?: string, env: NodeJS.ProcessEnv = process.env): Promise<Login> {\n return new Promise((resolve) => {\n execFile(\n bin,\n [\"auth\", \"status\", \"--json\"],\n { encoding: \"utf8\", timeout: 20_000, env: claudeEnv(configDir, env), maxBuffer: 256 * 1024 },\n // `auth status` may exit non-zero when signed out; its JSON still says so.\n (_err, stdout) => resolve(parseAuthStatus(stdout)),\n );\n });\n}\n\n/** The command that signs one account in, quoted for a sentence. */\nexport function loginCommand(configDir: string | undefined): string {\n const home = os.homedir();\n const isDefault = !configDir || path.resolve(configDir) === path.resolve(home, \".claude\");\n return isDefault ? \"`claude auth login`\" : `\\`CLAUDE_CONFIG_DIR=${configDir.replace(home, \"~\")} claude auth login\\``;\n}\n\n/** What to tell the person when an account isn't signed in for the daemon. */\nexport function loginHint(configDir: string | undefined, platform: NodeJS.Platform = process.platform): string {\n const shown = configDir ? configDir.replace(os.homedir(), \"~\") : \"~/.claude\";\n const login = loginCommand(configDir);\n if (platform === \"darwin\")\n return `Claude Code (${shown}) isn't signed in as this machine's background service sees it. On a Mac its login lives in the login keychain, which a background service can read only while someone is logged in at the screen: log in at the Mac, or run ${login} there.`;\n return `Claude Code (${shown}) isn't signed in on this machine: run ${login} there.`;\n}\n\nexport function detectCaps(bin: string): Caps {\n let help = \"\";\n try {\n help = execFileSync(bin, [\"--help\"], {\n encoding: \"utf8\",\n timeout: 30_000,\n env: claudeEnv(),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n maxBuffer: 4 * 1024 * 1024,\n });\n } catch (e) {\n help = String((e as { stdout?: string })?.stdout || \"\");\n }\n return parseCaps(help);\n}\n\nexport interface Transcript {\n file: string;\n configDir: string;\n project: string;\n}\n\n/** <config dir>/projects/<folder>/<session>.jsonl in any Claude Code config dir. */\nexport function findTranscript(session: string, dirs: string[]): Transcript | null {\n if (!UUID_RE.test(session)) return null;\n for (const dir of dirs) {\n let projects: import(\"node:fs\").Dirent[] = [];\n try {\n projects = readdirSync(path.join(dir, \"projects\"), { withFileTypes: true });\n } catch {\n continue;\n }\n for (const p of projects) {\n if (!p.isDirectory()) continue;\n const file = path.join(dir, \"projects\", p.name, `${session}.jsonl`);\n try {\n if (statSync(file).isFile()) return { file, configDir: dir, project: p.name };\n } catch {}\n }\n }\n return null;\n}\n\nconst projectName = (cwd: string) => cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n\n/** The folder a session runs in, from its transcript's own records (never from a\n * command): the `cwd` whose project name is the folder the transcript is filed\n * under, else the first `cwd`. Streams; a line over 2 MB is skipped. */\nexport function sessionFolder(t: Transcript, cap = 8 * 1024 * 1024): string | null {\n let first: string | null = null;\n let count = 0;\n let fd: number | undefined;\n const look = (line: Buffer): string | null => {\n if (line.indexOf('\"cwd\"') < 0) return null;\n let j: { cwd?: unknown };\n try {\n j = JSON.parse(line.toString(\"utf8\"));\n } catch {\n return null;\n }\n if (!j || typeof j.cwd !== \"string\" || !path.isAbsolute(j.cwd)) return null;\n if (projectName(j.cwd) === t.project) return j.cwd;\n first ??= j.cwd;\n count++;\n return null;\n };\n try {\n fd = openSync(t.file, \"r\");\n const buf = Buffer.alloc(256 * 1024);\n let pos = 0;\n let rest = Buffer.alloc(0);\n let skipping = false;\n while (pos < cap && count < 50) {\n const n = readSync(fd, buf, 0, buf.length, pos);\n if (!n) {\n if (!skipping && rest.length) {\n const hit = look(rest);\n if (hit) return hit;\n }\n break;\n }\n pos += n;\n let chunk = rest.length ? Buffer.concat([rest, buf.subarray(0, n)]) : buf.subarray(0, n);\n let nl = chunk.indexOf(10);\n while (nl >= 0) {\n const line = chunk.subarray(0, nl);\n chunk = chunk.subarray(nl + 1);\n if (skipping) skipping = false;\n else {\n const hit = look(line);\n if (hit) return hit;\n }\n nl = chunk.indexOf(10);\n }\n if (chunk.length > 2 * 1024 * 1024) {\n skipping = true;\n rest = Buffer.alloc(0);\n } else rest = skipping ? Buffer.alloc(0) : Buffer.from(chunk);\n }\n } catch {\n } finally {\n if (fd !== undefined)\n try {\n closeSync(fd);\n } catch {}\n }\n return first;\n}\n\nfunction pidAlive(pid: number): boolean {\n if (!Number.isSafeInteger(pid) || pid <= 1) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n return (e as { code?: string }).code === \"EPERM\";\n }\n}\n\n/** A Claude Code process holds this session right now: its registry file,\n * <config>/sessions/<pid>.json, names it and the pid is alive (interactive and\n * Agent SDK sessions both file one). */\nexport function liveProcess(session: string, configDir: string): boolean {\n let names: string[] = [];\n try {\n names = readdirSync(path.join(configDir, \"sessions\")).filter((n) => /^\\d+\\.json$/.test(n));\n } catch {\n return false;\n }\n for (const n of names) {\n try {\n const j = JSON.parse(readFileSync(path.join(configDir, \"sessions\", n), \"utf8\")) as {\n sessionId?: unknown;\n pid?: unknown;\n };\n if (String(j.sessionId) !== session) continue;\n if (pidAlive(Number(j.pid ?? n.slice(0, -5)))) return true;\n } catch {}\n }\n return false;\n}\n\n/** Written in the last 90 s, and not by a job of ours. */\nexport function recentlyWritten(file: string, ourLastEnd?: number, now = Date.now()): boolean {\n let m: number;\n try {\n m = statSync(file).mtimeMs;\n } catch {\n return false;\n }\n if (now - m > LIVE_WRITE_MS) return false;\n return !(ourLastEnd && m <= ourLastEnd + 2000);\n}\n\n/** Run one headless turn (headless.ts). Streaming (`--output-format stream-json`), only\n * the `result` line is kept for the RunResult unless the caller says otherwise. */\nexport function runClaude(bin: string, args: string[], o: RunOptions): Promise<RunResult> {\n return runHeadless(bin, args, { ...o, keep: o.keep ?? ((line) => line.includes('\"type\":\"result\"')) });\n}\n\nexport interface ClaudeResult {\n type?: string;\n result?: unknown;\n is_error?: boolean;\n subtype?: string;\n session_id?: unknown;\n permission_denials?: { tool_name?: unknown }[];\n}\n\n/** `--output-format json`: one result object, or an array whose last `result` entry it is. */\nexport function parseResult(stdout: string | null | undefined): ClaudeResult | null {\n const s = String(stdout || \"\").trim();\n if (!s) return null;\n const pick = (j: unknown): ClaudeResult | null => {\n if (Array.isArray(j)) {\n for (let i = j.length - 1; i >= 0; i--) if (j[i]?.type === \"result\") return j[i];\n return null;\n }\n return j && typeof j === \"object\" ? (j as ClaudeResult) : null;\n };\n try {\n return pick(JSON.parse(s));\n } catch {}\n const lines = s.split(\"\\n\");\n for (let i = lines.length - 1; i >= 0; i--) {\n try {\n const j = pick(JSON.parse(lines[i] as string));\n if (j && (j.type === \"result\" || \"result\" in j)) return j;\n } catch {}\n }\n return null;\n}\n\nexport const isUuid = (s: unknown): s is string => typeof s === \"string\" && UUID_RE.test(s);\n", "// SPDX-License-Identifier: Apache-2.0\n// The one verifier for signed control commands (spec/CONTROL.md \u00A74\u2013\u00A75). A machine\n// runs a command only when this says yes; a receiver MAY run it too, as an early\n// word, so a bad command is refused where the person can see why.\n//\n// WebCrypto only (globalThis.crypto.subtle), no node: imports, no clock of its own\n// (`now` is passed in): the same file runs in a Cloudflare Worker, in a browser and\n// in Node \u2265 20, and conformance/control-vectors/ pins its answers.\n//\n// Every signature covers the EXACT bytes as transmitted (`cmd`, `grant.str`): the\n// strings are parsed to read their fields and never re-serialized to verify.\n\n/** One passkey tap vouches for a day key for at most this long. */\nexport const GRANT_MAX_MS = 24 * 3600_000;\n/** Clock slack between the signing device, the receiver and the machine. */\nexport const SKEW_MS = 5 * 60_000;\n/** The machine judges a command by when it was SIGNED: a message sent while the lid\n * was shut still runs when the machine wakes, up to a day later. */\nexport const MACHINE_MAX_AGE_MS = 24 * 3600_000;\n/** A receiver's early check is stricter: a command is carried within ten minutes of\n * being signed, or not at all. */\nexport const RECEIVER_MAX_AGE_MS = 10 * 60_000;\n/** How long a machine remembers a nonce: longer than MACHINE_MAX_AGE_MS + SKEW_MS. */\nexport const NONCE_TTL_MS = 25 * 3600_000;\n/** The whole command string, in UTF-16 code units (what JSON.parse sees). */\nexport const CMD_MAX = 48_000;\n/** A prompt's text, in characters. */\nexport const TEXT_MAX = 20_000;\n/** A permission answer's note. */\nexport const NOTE_MAX = 2_000;\n/** A grant string. */\nexport const GRANT_STR_MAX = 2_000;\n/** Attachments on a `start` or a `prompt` (CONTROL.md \u00A73.1): at most this many files, */\nexport const FILES_MAX = 10;\n/** each at most this many bytes, */\nexport const FILE_SIZE_MAX = 26_214_400;\n/** together at most this many, */\nexport const FILES_TOTAL_MAX = 52_428_800;\n/** with a name of at most this many characters (after NFC) */\nexport const FILE_NAME_MAX = 200;\n/** and a media type of at most this many. */\nexport const FILE_TYPE_MAX = 100;\n/** A start's `model` (CONTROL.md \u00A73.1): at most this many characters, */\nexport const MODEL_MAX = 100;\n/** in this alphabet, never starting with a dash, so it can never read as a flag. */\nexport const MODEL_RE = /^[A-Za-z0-9][A-Za-z0-9._:/@[\\]-]*$/;\n/** The levels a start may ask for (CONTROL.md \u00A73.1), narrowest first. Closed: no level\n * is wider than `auto`, and none turns a harness's approval off. */\nexport const START_PERMISSIONS = [\"read\", \"safe\", \"edits\", \"auto\"] as const;\nexport type StartPermission = (typeof START_PERMISSIONS)[number];\n/** What a run is started with: a level, or `inherit` (CONTROL.md \u00A72) \u2014 no permission\n * flag at all, so the harness starts in its own default on the machine. Only a machine\n * the person put in inherit mode runs that way; a command never names it. */\nexport type RunLevel = StartPermission | \"inherit\";\n\n/** Where a level sits, narrowest (0) to widest; -1 for anything that isn't one. */\nexport const levelRank = (l: unknown): number => START_PERMISSIONS.indexOf(l as StartPermission);\n/** The narrower of two levels: what a later run of a session gets, its recorded level\n * against what the machine's mode allows now. */\nexport const narrower = (a: StartPermission, b: StartPermission): StartPermission =>\n levelRank(a) <= levelRank(b) ? a : b;\n\nexport const COMMAND_TYPE = \"sessionpipe.control\";\nexport const GRANT_TYPE = \"sessionpipe.grant\";\nexport const CONTROL_KINDS = [\"prompt\", \"permission.answer\", \"cancel\", \"start\", \"key.add\"] as const;\n/** The session a `key.add` names: the machine's own key store, not a coding session. */\nexport const KEY_STORE_SESSION = \"sessionpipe:keys\";\nexport type ControlKind = (typeof CONTROL_KINDS)[number];\n\n/** COSE algorithm ids a trusted key may use. */\nexport const ES256 = -7;\nexport const RS256 = -257;\n\n/** The kinds of key a machine may trust (CONTROL.md \u00A72): a WebAuthn passkey, or a\n * device key an app holds in hardware where it has no passkey to offer. */\nexport const KEY_TYPES = [\"passkey\", \"device\"] as const;\nexport type KeyType = (typeof KEY_TYPES)[number];\n\n/** A key enrolled on the machine: a passkey's credential id, COSE alg and SPKI\n * (base64url); a device key also says so (`type`), and what its app declared about\n * it (`store`, `uv`). The machine verifies by its own record, never by a message. */\nexport interface TrustedKey {\n id: string;\n alg: number;\n spki: string;\n /** Present only on a device key (CONTROL.md \u00A72 \"Device keys\"). */\n type?: \"device\";\n store?: \"hardware\";\n uv?: \"each-use\";\n}\n/** A WebAuthn assertion: credential id, authenticatorData, clientDataJSON, signature (base64url). */\nexport interface Assertion {\n cred: string;\n ad: string;\n cd: string;\n sig: string;\n}\n/** A device key's signature (CONTROL.md \u00A73.2): its id and 64 bytes r\u2016s over deviceMessage(). */\nexport interface DeviceSignature {\n cred: string;\n sig: string;\n}\n/** The day's grant: a passkey's assertion over sha256(str), where str names the day key. */\nexport interface GrantBundle extends Assertion {\n str: string;\n}\n/** The day's grant from a device key: its signature over deviceMessage(\"grant\", rp, sha256(str)). */\nexport interface DeviceGrant extends DeviceSignature {\n str: string;\n}\n/** What a receiver carries for one command (control.json minus the receiver's envelope). */\nexport interface SignedCommand {\n cmd: string;\n csig?: string | null;\n grant?: GrantBundle | DeviceGrant | null;\n confirm?: Assertion | DeviceSignature | null;\n}\nexport interface Grant {\n v: 1;\n t: typeof GRANT_TYPE;\n pub: string;\n iat: number;\n exp: number;\n rp: string;\n}\n/** One file attached to a `start`: the bytes live on the receiver, named by their hash. */\nexport interface ControlFile {\n /** The file name the machine writes (NFC). */\n name: string;\n /** Media type, `type/subtype`. */\n type: string;\n /** Bytes. */\n size: number;\n /** SHA-256 of the bytes, base64url without padding (43 characters). */\n sha256: string;\n}\nexport interface ControlCommand {\n v: 1;\n t: typeof COMMAND_TYPE;\n machine: string;\n kind: ControlKind;\n /** `<harness>:<id>`, e.g. `claude-code:8c132906-\u2026`. */\n session: string;\n text?: string;\n for?: string;\n decision?: \"allow\" | \"deny\";\n note?: string;\n cwd?: string;\n /** key.add only: the key to trust from now on, as the receiver holds it (a passkey,\n * or a device key with its `type`, `store` and `uv`). */\n key?: TrustedKey;\n /** key.add only: what the person calls the device (\"iPhone\"), for `control keys`. */\n name?: string;\n /** start, prompt: files to download, verify and write into the session's folder. */\n files?: ControlFile[];\n /** start only: the level the new session runs at (never above the machine's mode). */\n permission?: StartPermission;\n /** start only: the model the harness runs, as the harness names it. */\n model?: string;\n nonce: string;\n iat: number;\n}\n\n/** Why a command was refused. Stable: conformance vectors and acks name these. */\nexport type RefusalCode =\n | \"malformed\"\n | \"not_a_command\"\n | \"wrong_machine\"\n | \"unknown_kind\"\n | \"bad_session\"\n | \"bad_fields\"\n | \"bad_nonce\"\n | \"too_old\"\n | \"future\"\n | \"unsigned\"\n | \"untrusted_key\"\n | \"bad_assertion\"\n | \"bad_grant\"\n | \"outside_grant\"\n | \"bad_csig\"\n | \"replay\"\n | \"nonce_store\";\n\nexport type Verdict =\n | { ok: true; cmd: ControlCommand; via: \"grant\" | \"confirm\"; key: string }\n | { ok: false; code: RefusalCode; why: string };\n\nexport interface VerifyOptions {\n /** This machine's id; a command for another machine is refused. */\n machine: string;\n /** The receiver's WebAuthn rp id the keys were enrolled for (well-known control.signing.rp_id). */\n rpId: string;\n /** The keys enrolled on this machine (or, for a receiver's early check, the account's). */\n trusted: TrustedKey[];\n /** Epoch ms. */\n now: number;\n /** MACHINE_MAX_AGE_MS on a machine (default), RECEIVER_MAX_AGE_MS on a receiver. */\n maxAgeMs?: number;\n /** Called once, last, only for a command whose signatures all verified: answer\n * true when the nonce was seen before, otherwise record it (durably) and answer\n * false. A throw refuses the command (`nonce_store`): never run what could not\n * be remembered. Omit it on a receiver's early check. */\n seenNonce?: (nonce: string) => boolean | Promise<boolean>;\n}\n\nconst NONCE_RE = /^[A-Za-z0-9_-]{22,64}$/;\nconst MACHINE_RE = /^m_[A-Za-z0-9_-]{16,40}$/;\nconst HARNESS_RE = /^[a-z][a-z0-9-]{0,39}$/;\nconst SESSION_ID_RE = /^[A-Za-z0-9._:-]{1,128}$/;\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst B64URL_RE = /^[A-Za-z0-9_-]*$/;\nconst SHA256_RE = /^[A-Za-z0-9_-]{43}$/;\nconst MEDIA_TYPE_RE = /^[a-z0-9][a-z0-9!#$&^_.+-]*\\/[a-z0-9][a-z0-9!#$&^_.+-]*$/i;\n// biome-ignore lint/suspicious/noControlCharactersInRegex: control characters are exactly what it rejects\nconst BAD_NAME_CHAR_RE = /[/\\\\\\x00-\\x1f\\x7f]/;\nconst UP = 0x01;\nconst UV = 0x04;\n\n/** The fields each kind carries besides the common ones (CONTROL.md \u00A73.1). The set is\n * closed: a field it doesn't list is `bad_fields`, so a field added later fails closed\n * on a machine that predates it instead of being ignored. */\nconst COMMON_FIELDS: readonly string[] = [\"v\", \"t\", \"machine\", \"kind\", \"session\", \"nonce\", \"iat\", \"note\"];\nconst FIELDS: Record<ControlKind, readonly string[]> = {\n prompt: [\"text\", \"files\"],\n \"permission.answer\": [\"for\", \"decision\"],\n cancel: [],\n start: [\"text\", \"cwd\", \"files\", \"permission\", \"model\"],\n \"key.add\": [\"key\", \"name\"],\n};\n\n// --- encodings ------------------------------------------------------------------\n\nconst enc = new TextEncoder();\nconst dec = new TextDecoder();\n\nexport function b64url(bytes: Uint8Array | ArrayBuffer): string {\n const u = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n let s = \"\";\n for (const b of u) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** base64url without padding, strictly; null for anything else. */\nexport function fromB64url(s: unknown): Uint8Array | null {\n if (typeof s !== \"string\" || !B64URL_RE.test(s) || s.length % 4 === 1) return null;\n try {\n const bin = atob(s.replace(/-/g, \"+\").replace(/_/g, \"/\") + \"===\".slice((s.length + 3) % 4));\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n } catch {\n return null;\n }\n}\n\nexport async function sha256(data: string | Uint8Array): Promise<Uint8Array> {\n const bytes = typeof data === \"string\" ? enc.encode(data) : data;\n return new Uint8Array(await crypto.subtle.digest(\"SHA-256\", bytes as Uint8Array<ArrayBuffer>));\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\n/** Equal, compared whole: a mismatch costs the same as a match. */\nexport function sameBytes(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let d = 0;\n for (let i = 0; i < a.length; i++) d |= (a[i] as number) ^ (b[i] as number);\n return d === 0;\n}\n\n/** A DER ECDSA signature (what WebAuthn returns) as the 64-byte r\u2016s WebCrypto verifies.\n * Strict: every length must match the bytes, so one signature has one encoding (a\n * P-256 signature is at most 72 bytes, so the short length form is the only one). */\nexport function derToRaw(der: Uint8Array): Uint8Array | null {\n if (der[0] !== 0x30 || der.length < 8 || der[1] !== der.length - 2) return null;\n let i = 2;\n const part = (): Uint8Array | null => {\n if (der[i] !== 0x02) return null;\n const len = der[i + 1] as number;\n if (len < 1 || len > 33) return null;\n let v = der.slice(i + 2, i + 2 + len);\n if (v.length !== len) return null;\n // Minimal integers only: no needless leading zero, and never negative.\n if ((v[0] as number) & 0x80) return null;\n if (len > 1 && v[0] === 0 && !((v[1] as number) & 0x80)) return null;\n i += 2 + len;\n while (v.length > 32 && v[0] === 0) v = v.slice(1);\n if (v.length > 32) return null;\n const out = new Uint8Array(32);\n out.set(v, 32 - v.length);\n return out;\n };\n const r = part();\n const s = part();\n return r && s && i === der.length ? concat(r, s) : null;\n}\n\nconst u8 = (b: Uint8Array) => b as Uint8Array<ArrayBuffer>;\n/** WebCrypto's key type, named without the DOM lib (Workers, Node and browsers all have it). */\ntype CryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>;\n\nasync function importKey(key: TrustedKey): Promise<CryptoKey | null> {\n const spki = fromB64url(key.spki);\n if (!spki?.length) return null;\n try {\n if (key.alg === ES256)\n return await crypto.subtle.importKey(\"spki\", u8(spki), { name: \"ECDSA\", namedCurve: \"P-256\" }, false, [\"verify\"]);\n if (key.alg === RS256) {\n const k = await crypto.subtle.importKey(\"spki\", u8(spki), { name: \"RSASSA-PKCS1-v1_5\", hash: \"SHA-256\" }, false, [\n \"verify\",\n ]);\n const bits = (k.algorithm as { modulusLength?: number }).modulusLength as number; // every RSA key has one\n return bits >= 2048 ? k : null;\n }\n } catch {}\n return null;\n}\n\nconst PASSKEY_FIELDS = new Set([\"id\", \"alg\", \"spki\"]);\nconst DEVICE_FIELDS = new Set([\"id\", \"alg\", \"spki\", \"type\", \"store\", \"uv\"]);\n/** The only fields a device signature has (`str` only in a grant). */\nexport const DEVICE_SIG_FIELDS = [\"cred\", \"sig\", \"str\"] as const;\n\n/** A device key's id: the SHA-256 of its SPKI bytes, base64url without padding. */\nexport async function deviceKeyId(spki: string): Promise<string> {\n return b64url(await sha256(fromB64url(spki) ?? new Uint8Array()));\n}\n\n/** A device key's declared rules, ignoring any bookkeeping fields a store keeps beside\n * them (a name, when it was added): ES256, hardware, verified each use, named by its\n * SPKI's hash, and a P-256 key WebCrypto can import. */\nasync function deviceRecordValid(key: TrustedKey): Promise<boolean> {\n if (key.type !== \"device\" || key.alg !== ES256 || key.store !== \"hardware\" || key.uv !== \"each-use\") return false;\n if (typeof key.id !== \"string\" || !SHA256_RE.test(key.id) || key.id !== (await deviceKeyId(key.spki))) return false;\n return !!(await importKey(key));\n}\n\n/** Can this key be enrolled at all? A machine refuses to trust a key it could never\n * verify with. The key's fields are closed: a passkey is `id`, `alg`, `spki` and\n * nothing else; a device key adds exactly `type`, `store` and `uv` (CONTROL.md \u00A72),\n * so a kind added later is refused by every machine that predates it. */\nexport async function keyUsable(key: TrustedKey): Promise<boolean> {\n if (!key || typeof key !== \"object\" || Array.isArray(key)) return false;\n const fields = Object.keys(key).filter((k) => (key as unknown as Record<string, unknown>)[k] !== undefined);\n if (\"type\" in key && key.type !== undefined) {\n if (!fields.every((f) => DEVICE_FIELDS.has(f))) return false;\n return deviceRecordValid(key);\n }\n if (!fields.every((f) => PASSKEY_FIELDS.has(f))) return false;\n return (\n typeof key.id === \"string\" &&\n /^[A-Za-z0-9_-]{16,1400}$/.test(key.id) &&\n (key.alg === ES256 || key.alg === RS256) &&\n !!(await importKey(key))\n );\n}\n\n// --- WebAuthn -------------------------------------------------------------------\n\n/** A WebAuthn origin a key may have been used from: https on the rp id or a subdomain;\n * for rp id `localhost`, plain http on any port too. A bare origin, as a browser writes it. */\nexport function originAllowed(origin: unknown, rpId: string): boolean {\n if (typeof origin !== \"string\" || !rpId) return false;\n let u: URL;\n try {\n u = new URL(origin);\n } catch {\n return false;\n }\n if (u.origin !== origin) return false;\n if (u.hostname !== rpId && !u.hostname.endsWith(`.${rpId}`)) return false;\n if (u.protocol === \"https:\") return true;\n return u.protocol === \"http:\" && rpId === \"localhost\";\n}\n\ntype Check = { ok: true } | { ok: false; why: string };\nconst no = (why: string): Check => ({ ok: false, why });\n\n// --- device keys (CONTROL.md \u00A73.2) ------------------------------------------------\n\n/** The first line of every message a device key signs. */\nexport const DEVICE_CONTEXT = \"sessionpipe.device.v1\";\n/** What a device signature is for: one use can never answer for another. */\nexport type DevicePurpose = \"grant\" | \"confirm\" | \"pair\";\n\n/** The exact bytes a device key signs: the context, the purpose, the rp id as the\n * machine recorded it, and the base64url (no padding) of the 32-byte challenge a\n * passkey would sign for that purpose, joined by single line feeds, none at the end. */\nexport function deviceMessage(purpose: DevicePurpose, rpId: string, challenge: Uint8Array): Uint8Array {\n return enc.encode(`${DEVICE_CONTEXT}\\n${purpose}\\n${rpId}\\n${b64url(challenge)}`);\n}\n\n/** One device signature over `challenge` for `purpose`, made with the device key `key`. */\nasync function verifyDeviceSignature(\n challenge: Uint8Array,\n a: object,\n key: TrustedKey,\n rpId: string,\n purpose: DevicePurpose,\n): Promise<Check> {\n const sig = a as Record<string, unknown>;\n for (const f of Object.keys(sig)) {\n if (f === \"str\" && purpose === \"grant\") continue;\n if (f !== \"cred\" && f !== \"sig\") return no(`a device key's signature carries no ${f}`);\n }\n if (sig.cred !== key.id) return no(\"signed with a key this machine doesn't trust\");\n if (!(await deviceRecordValid(key))) return no(\"a trusted key is unusable\");\n const raw = fromB64url(sig.sig);\n if (raw?.length !== 64) return no(\"a device key's signature is 64 bytes, r\u2016s\");\n const pub = await importKey(key);\n /* v8 ignore next -- deviceRecordValid imported it already */\n if (!pub) return no(\"a trusted key is unusable\");\n let good = false;\n try {\n good = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n pub,\n u8(raw),\n u8(deviceMessage(purpose, rpId, challenge)),\n );\n } catch {\n /* v8 ignore next -- WebCrypto answers false for a bad signature; a throw is a broken runtime */\n good = false;\n }\n return good ? { ok: true } : no(\"the device key's signature doesn't verify\");\n}\n\n/** One signature over `challenge` by `key`, chosen from the machine's own record of\n * the key, never from the signature: a device key's signature for `purpose`\n * (CONTROL.md \u00A73.2), or a passkey assertion made by a verified person. */\nexport async function verifyAssertion(\n challenge: Uint8Array,\n a: Assertion | DeviceSignature | null | undefined,\n key: TrustedKey,\n rpId: string,\n purpose: DevicePurpose,\n): Promise<Check> {\n if (!a || typeof a !== \"object\") return no(\"no passkey signature\");\n if (key.type !== undefined) {\n if (key.type !== \"device\") return no(\"a trusted key is unusable\");\n return verifyDeviceSignature(challenge, a, key, rpId, purpose);\n }\n return verifyPasskeyAssertion(challenge, a as Assertion, key, rpId);\n}\n\nasync function verifyPasskeyAssertion(\n challenge: Uint8Array,\n a: Assertion,\n key: TrustedKey,\n rpId: string,\n): Promise<Check> {\n if (a.cred !== key.id) return no(\"signed with a key this machine doesn't trust\");\n const cdBytes = fromB64url(a.cd);\n const ad = fromB64url(a.ad);\n const sig = fromB64url(a.sig);\n if (!cdBytes || !ad || !sig?.length) return no(\"the passkey signature is malformed\");\n let cd: { type?: unknown; challenge?: unknown; origin?: unknown; crossOrigin?: unknown };\n try {\n cd = JSON.parse(dec.decode(cdBytes));\n } catch {\n return no(\"the passkey signature is malformed\");\n }\n if (!cd || typeof cd !== \"object\") return no(\"the passkey signature is malformed\");\n if (cd.type !== \"webauthn.get\") return no(\"the passkey answered a different question\");\n if (cd.challenge !== b64url(challenge)) return no(\"the passkey signed something else\");\n if (!originAllowed(cd.origin, rpId)) return no(`the passkey was used on another site, not ${rpId}`);\n if (cd.crossOrigin === true) return no(\"the passkey was used inside another site's frame\");\n if (ad.length < 37) return no(\"the passkey signature is malformed\");\n if (!sameBytes(ad.slice(0, 32), await sha256(rpId))) return no(`the passkey belongs to another site, not ${rpId}`);\n const flags = ad[32] as number;\n if (!(flags & UP) || !(flags & UV)) return no(\"the passkey signed without verifying the person\");\n const pub = await importKey(key);\n if (!pub) return no(\"a trusted key is unusable\");\n const signed = concat(ad, await sha256(cdBytes));\n let good = false;\n try {\n if (key.alg === ES256) {\n const raw = derToRaw(sig);\n good = !!raw && (await crypto.subtle.verify({ name: \"ECDSA\", hash: \"SHA-256\" }, pub, u8(raw), u8(signed)));\n } else {\n good = await crypto.subtle.verify({ name: \"RSASSA-PKCS1-v1_5\" }, pub, u8(sig), u8(signed));\n }\n } catch {\n good = false;\n }\n return good ? { ok: true } : no(\"the passkey signature doesn't verify\");\n}\n\n/** What a passkey signs to enroll on a machine: bound to that machine and that pairing code. */\nexport function pairChallenge(machine: string, code: string): Promise<Uint8Array> {\n return sha256(`sessionpipe.pair:${machine}:${code}`);\n}\n\n/** The enrollment proof: the new key's assertion over pairChallenge(machine, code).\n * Only after this verifies does the key go into the machine's trust store. */\nexport async function verifyEnrollment(o: {\n machine: string;\n code: string;\n key: TrustedKey;\n proof: Assertion | DeviceSignature;\n rpId: string;\n}): Promise<Check> {\n if (!(await keyUsable(o.key))) return no(\"the key is in a shape this machine can't use\");\n return verifyAssertion(await pairChallenge(o.machine, o.code), o.proof, o.key, o.rpId, \"pair\");\n}\n\n// --- the command ------------------------------------------------------------------\n\ntype Parsed = { ok: true; cmd: ControlCommand } | { ok: false; code: RefusalCode; why: string };\nconst bad = (code: RefusalCode, why: string): { ok: false; code: RefusalCode; why: string } => ({\n ok: false,\n code,\n why,\n});\nconst isNum = (n: unknown): n is number => typeof n === \"number\" && Number.isFinite(n);\n\n/** The session id rule per harness (ADAPTERS.md): Claude Code ids are UUIDs. */\nexport function sessionIdOk(harness: string, id: string): boolean {\n if (!SESSION_ID_RE.test(id)) return false;\n if (harness === \"claude-code\") return UUID_RE.test(id);\n return true;\n}\n\n/** Split `<harness>:<id>`; null when either half breaks its rule. */\nexport function parseSessionRef(ref: unknown): { harness: string; id: string } | null {\n if (typeof ref !== \"string\") return null;\n const i = ref.indexOf(\":\");\n if (i <= 0) return null;\n const harness = ref.slice(0, i);\n const id = ref.slice(i + 1);\n return HARNESS_RE.test(harness) && sessionIdOk(harness, id) ? { harness, id } : null;\n}\n\n/** Read the command's fields from the exact string. Structure only; no clock, no keys. */\nexport function parseCommand(str: unknown): Parsed {\n if (typeof str !== \"string\" || !str || str.length > CMD_MAX)\n return bad(\"malformed\", \"the command is missing or too long\");\n let c: Record<string, unknown>;\n try {\n c = JSON.parse(str);\n } catch {\n return bad(\"malformed\", \"the command is not JSON\");\n }\n if (!c || typeof c !== \"object\" || Array.isArray(c)) return bad(\"malformed\", \"the command is not an object\");\n if (c.v !== 1 || c.t !== COMMAND_TYPE) return bad(\"not_a_command\", \"not a sessionpipe control command\");\n if (typeof c.machine !== \"string\" || !MACHINE_RE.test(c.machine)) return bad(\"malformed\", \"which machine?\");\n if (!CONTROL_KINDS.includes(c.kind as ControlKind))\n return bad(\"unknown_kind\", \"the command asks for something unknown\");\n const ref = parseSessionRef(c.session);\n if (!ref) return bad(\"bad_session\", \"which session?\");\n if (typeof c.nonce !== \"string\" || !NONCE_RE.test(c.nonce))\n return bad(\"bad_nonce\", \"the nonce is missing or malformed\");\n if (!isNum(c.iat) || !Number.isInteger(c.iat) || c.iat <= 0)\n return bad(\"malformed\", \"the command has no signing time\");\n const has = (k: string) => c[k] !== undefined;\n const text = () => typeof c.text === \"string\" && c.text.trim().length > 0 && c.text.length <= TEXT_MAX;\n switch (c.kind as ControlKind) {\n case \"prompt\":\n if (!text()) return bad(\"bad_fields\", `a prompt needs text, at most ${TEXT_MAX} characters`);\n if (has(\"for\") || has(\"decision\") || has(\"cwd\")) return bad(\"bad_fields\", \"a prompt carries text and files\");\n if (has(\"files\")) {\n const why = filesProblem(c.files);\n if (why) return bad(\"bad_fields\", why);\n }\n break;\n case \"start\":\n if (!text()) return bad(\"bad_fields\", `a new session needs text, at most ${TEXT_MAX} characters`);\n if (typeof c.cwd !== \"string\" || !(isAbsolute(c.cwd) || HOME_RELATIVE_RE.test(c.cwd)) || c.cwd.length > 1024)\n return bad(\"bad_fields\", \"a new session needs an absolute folder, or one under ~\");\n if (has(\"for\") || has(\"decision\"))\n return bad(\"bad_fields\", \"a start carries text, cwd, files, a permission and a model\");\n if (has(\"files\")) {\n const why = filesProblem(c.files);\n if (why) return bad(\"bad_fields\", why);\n }\n if (has(\"permission\") && levelRank(c.permission) < 0)\n return bad(\"bad_fields\", `a permission is one of ${START_PERMISSIONS.join(\", \")}`);\n if (has(\"model\") && (typeof c.model !== \"string\" || c.model.length > MODEL_MAX || !MODEL_RE.test(c.model)))\n return bad(\"bad_fields\", `a model is 1 to ${MODEL_MAX} letters, digits and ._:/@[]-, not starting with a dash`);\n break;\n case \"permission.answer\":\n if (typeof c.for !== \"string\" || !c.for || c.for.length > 128) return bad(\"bad_fields\", \"which attention?\");\n if (c.decision !== \"allow\" && c.decision !== \"deny\") return bad(\"bad_fields\", \"allow or deny?\");\n if (has(\"text\") || has(\"cwd\")) return bad(\"bad_fields\", \"a permission answer carries for, decision and note\");\n break;\n case \"cancel\":\n if (has(\"text\") || has(\"for\") || has(\"decision\") || has(\"cwd\"))\n return bad(\"bad_fields\", \"a cancel carries nothing\");\n break;\n case \"key.add\": {\n // A device the machine already trusts vouches for a new one (CONTROL.md \u00A72): the\n // new key's id, algorithm and public key (and, for a device key, its type, store\n // and uv) are inside the signed bytes.\n if (c.session !== KEY_STORE_SESSION) return bad(\"bad_session\", `a key.add names ${KEY_STORE_SESSION}`);\n const k = c.key as Record<string, unknown> | undefined;\n const b64 = (v: unknown, min: number, max: number) =>\n typeof v === \"string\" && v.length >= min && v.length <= max && /^[A-Za-z0-9_-]+$/.test(v);\n if (\n !k ||\n typeof k !== \"object\" ||\n Array.isArray(k) ||\n !b64(k.id, 16, 1400) ||\n (k.alg !== -7 && k.alg !== -257) ||\n !b64(k.spki, 40, 2000)\n )\n return bad(\"bad_fields\", \"a key.add carries the key: id, alg (-7 or -257) and spki\");\n if (k.type !== undefined) {\n if (k.type !== \"device\") return bad(\"bad_fields\", \"a key's type is device, or absent for a passkey\");\n if (k.alg !== ES256 || k.store !== \"hardware\" || k.uv !== \"each-use\" || !SHA256_RE.test(k.id as string))\n return bad(\"bad_fields\", \"a device key is ES256, store hardware, uv each-use, named by its SPKI's hash\");\n if (Object.keys(k).some((f) => !DEVICE_FIELDS.has(f)))\n return bad(\"bad_fields\", \"a device key carries id, alg, spki, type, store and uv\");\n } else if (Object.keys(k).some((f) => !PASSKEY_FIELDS.has(f)))\n return bad(\"bad_fields\", \"a passkey carries id, alg and spki: store and uv belong to a device key\");\n if (has(\"name\") && (typeof c.name !== \"string\" || !c.name.trim() || c.name.length > 80))\n return bad(\"bad_fields\", \"a device name is text, at most 80 characters\");\n if (has(\"text\") || has(\"for\") || has(\"decision\") || has(\"cwd\"))\n return bad(\"bad_fields\", \"a key.add carries the key and a name\");\n break;\n }\n }\n if (c.kind !== \"key.add\" && (has(\"key\") || has(\"name\"))) return bad(\"bad_fields\", \"only a key.add carries a key\");\n if (c.kind !== \"start\" && c.kind !== \"prompt\" && has(\"files\"))\n return bad(\"bad_fields\", \"only a start or a prompt carries files\");\n if (c.kind !== \"start\" && (has(\"permission\") || has(\"model\")))\n return bad(\"bad_fields\", \"only a start carries a model or a permission\");\n const allowed = FIELDS[c.kind as ControlKind];\n for (const k of Object.keys(c))\n if (!COMMON_FIELDS.includes(k) && !allowed.includes(k))\n return bad(\"bad_fields\", `the command carries a field its kind doesn't have: ${k.slice(0, 40)}`);\n if (has(\"note\") && (typeof c.note !== \"string\" || c.note.length > NOTE_MAX))\n return bad(\"bad_fields\", `a note is text, at most ${NOTE_MAX} characters`);\n return { ok: true, cmd: c as unknown as ControlCommand };\n}\n\n/** Why a start's or a prompt's `files` breaks the rules (CONTROL.md \u00A73.1), or null when it doesn't. */\nexport function filesProblem(files: unknown): string | null {\n if (!Array.isArray(files) || files.length < 1 || files.length > FILES_MAX)\n return `files is a list of 1 to ${FILES_MAX} files`;\n const seen = new Set<string>();\n let total = 0;\n for (const f of files as unknown[]) {\n if (!f || typeof f !== \"object\" || Array.isArray(f)) return \"each file is an object\";\n const { name, type, size, sha256: hash } = f as Record<string, unknown>;\n const why = fileNameProblem(name);\n if (why) return why;\n const key = (name as string).normalize(\"NFC\").toLowerCase();\n if (seen.has(key)) return \"two files have the same name\";\n seen.add(key);\n if (typeof type !== \"string\" || type.length > FILE_TYPE_MAX || !MEDIA_TYPE_RE.test(type))\n return \"a file's type isn't a media type\";\n if (!isNum(size) || !Number.isInteger(size) || size < 1 || size > FILE_SIZE_MAX)\n return `a file is 1 byte to ${FILE_SIZE_MAX / 1_048_576} MiB`;\n total += size;\n if (typeof hash !== \"string\" || !SHA256_RE.test(hash)) return \"a file's sha256 isn't 43 base64url characters\";\n }\n if (total > FILES_TOTAL_MAX) return `the files add up to more than ${FILES_TOTAL_MAX / 1_048_576} MiB`;\n return null;\n}\n\n/** A file name the machine can write inside the session's folder and nowhere else. */\nfunction fileNameProblem(name: unknown): string | null {\n if (typeof name !== \"string\") return \"a file has no name\";\n const n = name.normalize(\"NFC\");\n if (n.length < 1 || n.length > FILE_NAME_MAX) return `a file name is 1 to ${FILE_NAME_MAX} characters`;\n if (BAD_NAME_CHAR_RE.test(n)) return \"a file name has a slash, a backslash or a control character\";\n if (n.startsWith(\".\")) return \"a file name can't start with a dot\";\n return null;\n}\n\n/** A `start`'s `cwd` under the machine's home: `~` alone, or `~/\u2026` (`~\\\u2026`). Never `~user`. */\nexport const HOME_RELATIVE_RE = /^~(?:[\\\\/]|$)/;\n\nfunction isAbsolute(p: string): boolean {\n return p.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(p);\n}\n\n/** The grant's fields, read from its exact string. */\nexport function parseGrant(str: unknown, rpId: string): { ok: true; grant: Grant } | { ok: false; why: string } {\n if (typeof str !== \"string\" || !str || str.length > GRANT_STR_MAX)\n return { ok: false, why: \"the grant is missing or too long\" };\n let g: Record<string, unknown>;\n try {\n g = JSON.parse(str);\n } catch {\n return { ok: false, why: \"the grant is not JSON\" };\n }\n if (!g || typeof g !== \"object\" || Array.isArray(g)) return { ok: false, why: \"the grant is not an object\" };\n if (g.v !== 1 || g.t !== GRANT_TYPE) return { ok: false, why: \"not a sessionpipe grant\" };\n if (g.rp !== rpId) return { ok: false, why: `the grant is for another site, not ${rpId}` };\n if (typeof g.pub !== \"string\" || !fromB64url(g.pub)?.length || !isNum(g.iat) || !isNum(g.exp))\n return { ok: false, why: \"the grant is missing parts\" };\n if (g.exp <= g.iat) return { ok: false, why: \"the grant ends before it starts\" };\n if (g.exp - g.iat > GRANT_MAX_MS + SKEW_MS) return { ok: false, why: \"the grant lasts longer than a day\" };\n return { ok: true, grant: g as unknown as Grant };\n}\n\nasync function verifyCsig(cmd: string, csig: unknown, pub: string): Promise<boolean> {\n const sig = fromB64url(csig);\n const spki = fromB64url(pub);\n if (sig?.length !== 64 || !spki) return false;\n try {\n const key = await crypto.subtle.importKey(\"spki\", u8(spki), { name: \"ECDSA\", namedCurve: \"P-256\" }, false, [\n \"verify\",\n ]);\n return await crypto.subtle.verify({ name: \"ECDSA\", hash: \"SHA-256\" }, key, u8(sig), u8(enc.encode(cmd)));\n } catch {\n return false;\n }\n}\n\n/**\n * Is this a command this machine may run? The checks, in the spec's order\n * (CONTROL.md \u00A75): the exact bytes parse; the command is for this machine; it is\n * signed \u2014 a grant from a trusted key plus the day key's signature, or a confirm\n * over sha256(cmd); it was signed within the age window; its nonce is new.\n * The folder and open-attention checks that follow are the daemon's (they read\n * the machine, not the command).\n */\nexport async function verifyCommand(s: SignedCommand | null | undefined, o: VerifyOptions): Promise<Verdict> {\n if (!s || typeof s !== \"object\") return bad(\"malformed\", \"nothing to verify\");\n const p = parseCommand(s.cmd);\n if (!p.ok) return p;\n const c = p.cmd;\n if (c.machine !== o.machine) return bad(\"wrong_machine\", \"the command is for another machine\");\n\n let via: \"grant\" | \"confirm\" | null = null;\n let keyId = \"\";\n let refusal: { code: RefusalCode; why: string } | null = null;\n if (s.grant && s.csig) {\n const r = await checkGrantPath(s, c, o);\n if (r.ok) {\n via = \"grant\";\n keyId = r.key;\n } else refusal = r;\n }\n if (!via && s.confirm) {\n const key = o.trusted.find((k) => k && k.id === s.confirm?.cred);\n if (!key) refusal = { code: \"untrusted_key\", why: \"confirmed with a key this machine doesn't trust\" };\n else {\n const a = await verifyAssertion(await sha256(s.cmd), s.confirm, key, o.rpId, \"confirm\");\n if (a.ok) {\n via = \"confirm\";\n keyId = key.id;\n } else refusal = { code: \"bad_assertion\", why: a.why };\n }\n }\n if (!via) {\n if (refusal) return bad(refusal.code, refusal.why);\n return bad(\"unsigned\", \"the command isn't signed\");\n }\n // The key a key.add brings must be one this machine could ever verify with: an\n // SPKI it can import for that alg, and every rule of a device key (CONTROL.md \u00A72).\n if (c.kind === \"key.add\" && !(await keyUsable(c.key as TrustedKey)))\n return bad(\"bad_fields\", \"the key a key.add brings is in a shape this machine can't use\");\n if (c.iat > o.now + SKEW_MS) return bad(\"future\", \"the command is dated in the future (is this clock right?)\");\n if (o.now - c.iat > (o.maxAgeMs ?? MACHINE_MAX_AGE_MS)) return bad(\"too_old\", \"the command was signed too long ago\");\n if (o.seenNonce) {\n let seen: boolean;\n try {\n seen = await o.seenNonce(c.nonce);\n } catch {\n return bad(\"nonce_store\", \"the nonce couldn't be recorded, so the command didn't run\");\n }\n if (seen) return bad(\"replay\", \"this command was already used once\");\n }\n return { ok: true, cmd: c, via, key: keyId };\n}\n\nasync function checkGrantPath(\n s: SignedCommand,\n c: ControlCommand,\n o: VerifyOptions,\n): Promise<{ ok: true; key: string } | { ok: false; code: RefusalCode; why: string }> {\n const bundle = s.grant as GrantBundle | DeviceGrant;\n const g = parseGrant(bundle.str, o.rpId);\n if (!g.ok) return bad(\"bad_grant\", g.why);\n const key = o.trusted.find((k) => k && k.id === bundle.cred);\n if (!key) return bad(\"untrusted_key\", \"the grant was signed with a key this machine doesn't trust\");\n const a = await verifyAssertion(await sha256(bundle.str), bundle, key, o.rpId, \"grant\");\n if (!a.ok) return bad(\"bad_assertion\", a.why);\n if (!(await verifyCsig(s.cmd, s.csig, g.grant.pub)))\n return bad(\"bad_csig\", \"the command's signature doesn't verify \u2014 it was changed after it was signed\");\n if (c.iat < g.grant.iat - SKEW_MS || c.iat > g.grant.exp)\n return bad(\"outside_grant\", \"the command was signed outside its grant's window\");\n return { ok: true, key: key.id };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Codex CLI (OpenAI) \u2014 docs: https://learn.chatgpt.com/docs/hooks\n// Config: ~/.codex/hooks.json (Claude-shaped, 12 events, timeouts in seconds) AND\n// `notify` at the top level of config.toml as the fallback when hooks are off or\n// not yet trusted (non-managed hooks need a /hooks review in the CLI). An existing\n// notify (Codex Computer Use) is chained through --previous-notify, never replaced.\nimport { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines, recentFiles, scanLines } from \"../readers/files.js\";\nimport { codexInjected, readCodex } from \"../readers/transcripts.js\";\nimport { installClaudeShaped, installedClaudeShaped, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport * as toml from \"./codex-config.js\";\nimport { codexReplayBoundary, codexSubagent } from \"./codex-rollout.js\";\nimport type {\n Adapter,\n BackfillRow,\n HookCommand,\n HookInput,\n HookResult,\n InstalledReport,\n InstallOptions,\n SessionFacts,\n} from \"./types.js\";\n\nconst NAME = \"codex\";\nexport const CODEX_EVENTS = [\n \"SessionStart\",\n \"UserPromptSubmit\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PermissionRequest\",\n \"Stop\",\n \"Interrupt\",\n \"SubagentStart\",\n \"SubagentStop\",\n \"PreCompact\",\n \"PostCompact\",\n \"SessionEnd\",\n] as const;\nconst OPTS = { matcherFor: (e: string) => (/Tool|Permission/.test(e) ? \"\" : undefined), timeout: 5 };\nconst eventsFor = (lean?: boolean) => (lean ? CODEX_EVENTS.filter((e) => e !== \"PreToolUse\") : [...CODEX_EVENTS]);\n\nconst codexHome = (env: NodeJS.ProcessEnv) => env.CODEX_HOME || path.join(homeDir(), \".codex\");\nconst hooksFile = (env: NodeJS.ProcessEnv) => path.join(codexHome(env), \"hooks.json\");\nconst configFile = (env: NodeJS.ProcessEnv) => path.join(codexHome(env), \"config.toml\");\nconst sessionsDir = (env: NodeJS.ProcessEnv) => path.join(codexHome(env), \"sessions\");\n\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst endReason = (r: unknown): \"clear\" | \"logout\" | \"exit\" | \"other\" =>\n r === \"clear\" || r === \"logout\" || r === \"exit\" ? r : \"other\";\n\nfunction installNotify(cmd: HookCommand, env: NodeJS.ProcessEnv) {\n const file = configFile(env);\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {}\n const argv = cmd([NAME, \"notify\"]).argv;\n const line = `notify = ${JSON.stringify(argv)}`;\n const n = toml.readNotify(text);\n const write = (next: string) => {\n mkdirSync(path.dirname(file), { recursive: true });\n writeFileSync(file, next);\n };\n if (n && !n.other) {\n if (!n.misplaced && JSON.stringify(n.argv) === JSON.stringify(argv))\n return { file, changed: false, note: \"notify current\" };\n write(toml.withNotify(text, line));\n return {\n file,\n changed: true,\n note: n.misplaced\n ? \"notify moved to the top level (it sat inside a [table], where Codex never reads it)\"\n : \"notify updated\",\n };\n }\n if (n?.other) {\n const prev = toml.previousNotify(n.argv);\n if (toml.isComputerUse(n.argv)) {\n if (prev && toml.OURS.test(JSON.stringify(prev))) {\n if (JSON.stringify(prev) === JSON.stringify(argv))\n return { file, changed: false, note: \"notify current (after Codex Computer Use)\" };\n }\n if (!prev || toml.OURS.test(JSON.stringify(prev))) {\n write(toml.replaceNotify(text, n, `notify = ${toml.withPreviousRaw(n.raw, argv)}`));\n return { file, changed: true, note: \"chained after Codex Computer Use (--previous-notify)\" };\n }\n }\n return {\n file,\n changed: false,\n skipped: true,\n note: `notify belongs to ${(n.argv?.[0] ?? n.raw).replace(/^.*\\//, \"\").slice(0, 40)}; left alone. Codex will report nothing until you approve the hooks: start \\`codex\\` and accept the hook review`,\n };\n }\n write(toml.withNotify(text, line));\n return { file, changed: true, note: \"notify set at the top level\" };\n}\n\nfunction uninstallNotify(env: NodeJS.ProcessEnv) {\n const file = configFile(env);\n let text: string;\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { file, changed: false };\n }\n const n = toml.readNotify(text);\n if (!n) return { file, changed: false };\n if (!n.other) {\n writeFileSync(file, toml.withoutNotify(text));\n return { file, changed: true };\n }\n const prev = toml.previousNotify(n.argv);\n if (toml.isComputerUse(n.argv) && prev && toml.OURS.test(JSON.stringify(prev))) {\n writeFileSync(file, toml.replaceNotify(text, n, `notify = ${toml.stripPreviousRaw(n.raw)}`));\n return { file, changed: true };\n }\n return { file, changed: false };\n}\n\n/** The rollout file of one thread: `<CODEX_HOME>/sessions/YYYY/MM/DD/rollout-<time>-<thread\n * id>.jsonl`, newest day first. Null for an id that isn't a thread id's shape, so a\n * short or odd one never matches some other session's file. */\nexport function findRollout(threadId: string, env: NodeJS.ProcessEnv = process.env): string | null {\n if (!/^[A-Za-z0-9-]{8,128}$/.test(threadId)) return null;\n let best: string | null = null;\n const walk = (dir: string, depth: number) => {\n let names: string[] = [];\n try {\n names = readdirSync(dir);\n } catch {\n return;\n }\n for (const n of names.sort().reverse()) {\n const p = path.join(dir, n);\n if (n.endsWith(`-${threadId}.jsonl`)) {\n best = p;\n return;\n }\n if (depth < 3) {\n walk(p, depth + 1);\n if (best) return;\n }\n }\n };\n walk(sessionsDir(env), 0);\n return best;\n}\n\n/** A rollout's first record, its own session_meta. About 50 KB (it carries the base\n * instructions), so it is read on its own rather than from a sampled head. */\nfunction rolloutMeta(file: string): Record<string, unknown> | null {\n return scanLines(file, (line) => parseLines([line])[0] ?? {});\n}\n\n/** A rollout named for a thread other than `id` (`rollout-<time>-<thread id>.jsonl`).\n * A name of any other shape says nothing, so it is not taken for another thread's. */\nfunction ofAnotherThread(file: string, id: string): boolean {\n const m = /-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\.jsonl(?:\\.zst)?$/i.exec(file);\n return !!m?.[1] && m[1].toLowerCase() !== id.toLowerCase();\n}\n\nexport const codex: Adapter = {\n name: NAME,\n events: CODEX_EVENTS,\n detect: (env = process.env) => existsSync(codexHome(env)),\n configFiles: (env = process.env) => [hooksFile(env), configFile(env)],\n install: (cmd, env = process.env, opts: InstallOptions = {}) => [\n installClaudeShaped(hooksFile(env), NAME, eventsFor(opts.lean), cmd, OPTS),\n installNotify(cmd, env),\n ],\n uninstall: (env = process.env, opts: InstallOptions = {}) => [\n uninstallClaudeShaped(hooksFile(env), CODEX_EVENTS, { created: opts.created?.includes(hooksFile(env)) }),\n uninstallNotify(env),\n ],\n installed: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const out: InstalledReport[] = [\n {\n file: hooksFile(env),\n state: installedClaudeShaped(hooksFile(env), NAME, eventsFor(opts.lean), cmd, OPTS),\n note: \"Codex runs non-managed hooks only after the review in `codex` (/hooks); until then nothing is reported unless the notify fallback is ours\",\n },\n ];\n let text = \"\";\n try {\n text = readFileSync(configFile(env), \"utf8\");\n } catch {}\n const n = toml.readNotify(text);\n const argv = cmd([NAME, \"notify\"]).argv;\n const prev = n ? toml.previousNotify(n.argv) : null;\n const ours = n && (!n.other || (prev && JSON.stringify(prev) === JSON.stringify(argv)));\n out.push({\n file: configFile(env),\n state:\n !n || (n.other && !ours)\n ? \"missing\"\n : n.misplaced\n ? \"misplaced\"\n : JSON.stringify(n.argv) === JSON.stringify(argv) || (prev && JSON.stringify(prev) === JSON.stringify(argv))\n ? \"current\"\n : \"stale\",\n });\n return out;\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n if (event === \"notify\") {\n // Codex's notify passes one JSON argument: {\"type\":\"agent-turn-complete\",\"thread-id\":\u2026,\"turn-id\":\u2026,\"cwd\":\u2026}\n const raw = input.argv.find((a) => a.startsWith(\"{\")) ?? input.stdin;\n try {\n const j: unknown = raw ? JSON.parse(raw) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = (s[\"thread-id\"] ?? s.thread_id ?? s[\"session-id\"] ?? s.session_id) as string | undefined;\n if (!id) return null;\n // Notify names the thread whose turn ended. Without a rollout it is an ephemeral\n // thread, kept nowhere (the hooks' `transcript_path: null` below). A subagent's\n // thread belongs to its parent, whose hooks already report it: SubagentStart and\n // SubagentStop name it as `agent_id`. Neither is a session of its own.\n const file = findRollout(String(id), input.env as NodeJS.ProcessEnv);\n if (!file || codexSubagent(rolloutMeta(file))) return null;\n const r: HookResult = {\n session: { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd },\n events: [\n {\n type: \"turn.ended\",\n data: { reason: \"stop\", ...(typeof s[\"turn-id\"] === \"string\" ? { turn_id: s[\"turn-id\"] } : {}) },\n harnessEvent: \"notify\",\n },\n ],\n hints: {},\n transcript: file,\n };\n return r;\n }\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = (s.session_id ?? s.thread_id ?? s.conversation_id ?? s[\"thread-id\"] ?? s[\"session-id\"]) as\n | string\n | undefined;\n if (!id) return null;\n // `transcript_path: null` is an ephemeral thread (recorded on codex-cli 0.160.0):\n // Codex Desktop's own background threads (ambient suggestions and their safety\n // review) and `codex exec --ephemeral`. Codex keeps nothing of one, so there is no\n // session to name, read or resume.\n if (s.transcript_path === null) return null;\n const session: HookResult[\"session\"] = { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd };\n if (typeof s.model === \"string\") session.model = s.model;\n const turn_id = typeof s.turn_id === \"string\" ? s.turn_id : undefined;\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const call_id = typeof s.tool_use_id === \"string\" ? s.tool_use_id : undefined;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(\n ev(\"session.started\", {\n source:\n typeof s.source === \"string\" && [\"startup\", \"resume\", \"clear\", \"compact\", \"fork\"].includes(s.source)\n ? s.source\n : \"unknown\",\n }),\n );\n break;\n case \"UserPromptSubmit\":\n events.push(\n ev(\"turn.started\", {\n turn_id,\n prompt_chars: typeof s.prompt === \"string\" ? [...s.prompt].length : undefined,\n }),\n );\n break;\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, call_id, turn_id, input: s.tool_input }));\n break;\n case \"PostToolUse\":\n if (tool)\n events.push(\n ev(\"tool.ended\", { tool, call_id, turn_id, ok: true, input: s.tool_input, output: s.tool_response }),\n );\n break;\n case \"PermissionRequest\":\n events.push(\n ev(\"attention.needed\", { attention_id: call_id ?? `perm-${Date.now()}`, kind: \"permission\", tool }),\n );\n break;\n case \"Stop\":\n events.push(ev(\"turn.ended\", { turn_id, reason: \"stop\" }));\n break;\n case \"Interrupt\":\n events.push(ev(\"turn.ended\", { turn_id, reason: \"interrupt\" }));\n break;\n case \"SubagentStart\":\n events.push(\n ev(\"subagent.started\", {\n agent_id: String(s.agent_id ?? s.subagent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"SubagentStop\":\n events.push(\n ev(\"subagent.ended\", {\n agent_id: String(s.agent_id ?? s.subagent_id ?? \"\"),\n agent_type: typeof s.agent_type === \"string\" ? s.agent_type : undefined,\n }),\n );\n break;\n case \"PreCompact\":\n events.push(ev(\"context.compacted\", { trigger: s.trigger === \"manual\" ? \"manual\" : \"auto\" }));\n break;\n case \"PostCompact\":\n break;\n case \"SessionEnd\":\n events.push(ev(\"session.ended\", { reason: endReason(s.reason) }));\n break;\n default:\n return null;\n }\n const r: HookResult = { session, events, hints: {} };\n // Inside a subagent Codex sends the parent's session_id with the subagent's own\n // rollout (its SubagentStart, its tool calls): that file is not this session's.\n if (typeof s.transcript_path === \"string\" && !ofAnotherThread(s.transcript_path, String(id)))\n r.transcript = s.transcript_path;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readCodex(text.split(\"\\n\"), fromLine);\n },\n\n facts(session, transcript): SessionFacts {\n const out: SessionFacts = {};\n if (transcript) Object.assign(out, codexFacts(transcript));\n return out;\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows: BackfillRow[] = [];\n for (const f of recentFiles(sessionsDir(env), 3, sinceMs, (n) => /^rollout-.*\\.jsonl$/.test(n))) {\n const m = /([0-9a-f]{8}-[0-9a-f-]{27,})\\.jsonl$/i.exec(path.basename(f));\n if (!m?.[1]) continue;\n // A subagent's rollout is part of its parent's session, as in fromHook's notify.\n if (codexSubagent(rolloutMeta(f))) continue;\n const facts = codexFacts(f);\n if (!facts.started_at || !facts.last_at) continue;\n const { started_at, last_at, first_ask: _fa, harness_version: _hv, ...rest } = facts;\n rows.push({ session: { id: m[1], ...rest }, started_at, last_at });\n }\n return rows;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n\n/** Codex keeps no title; its first real ask stands in. A fork's replay is not its ask. */\nexport function codexFacts(file: string): SessionFacts {\n const { head, tail } = ends(file, 128 * 1024, 64 * 1024);\n let H = parseLines(head);\n let T = parseLines(tail);\n const out: SessionFacts = {};\n const meta = H.find((j) => j.type === \"session_meta\" && j.payload);\n const boundary = codexReplayBoundary(meta);\n if (meta?.payload) {\n const p = meta.payload as {\n cwd?: string;\n cli_version?: string;\n git?: { branch?: string; repository_url?: string };\n };\n if (p.cwd) out.cwd = p.cwd;\n if (p.cli_version) out.harness_version = String(p.cli_version);\n if (p.git?.branch) out.branch = p.git.branch;\n if (p.git?.repository_url) out.repo = String(p.git.repository_url).replace(/\\/\\/[^/@]*@/, \"//\");\n }\n if (boundary) {\n const h = H.findIndex(boundary);\n const t = T.findIndex(boundary);\n H = h < 0 ? [] : H.slice(h);\n // The samples can overlap, so trim each one at the boundary independently.\n // If both miss it, scan the gap before trusting the tail: it could still be\n // parent replay. Stop as soon as the boundary is found, without loading the file.\n const found =\n h >= 0 ||\n t >= 0 ||\n scanLines(file, (line) => (boundary(parseLines([line])[0] ?? null) ? true : null), Number.POSITIVE_INFINITY);\n T = t >= 0 ? T.slice(t) : found ? T : [];\n }\n const ctx = H.concat(T)\n .reverse()\n .find((j) => j.type === \"turn_context\" && (j.payload as { model?: string } | undefined)?.model) as\n | { payload?: { model?: string } }\n | undefined;\n if (ctx?.payload?.model) out.model = ctx.payload.model;\n for (const j of H) {\n const p = j.payload as { type?: string; role?: string; content?: { type?: string; text?: string }[] } | undefined;\n if (j.type !== \"response_item\" || !p || p.type !== \"message\" || p.role !== \"user\") continue;\n const text = (p.content ?? [])\n .filter((b) => b && b.type === \"input_text\" && typeof b.text === \"string\")\n .map((b) => b.text as string)\n .join(\"\\n\")\n .trim();\n if (!text || codexInjected(text)) continue;\n const line = text.split(\"\\n\")[0] as string; // trimmed, so its first line is its first non-blank one\n out.title = line.length > 80 ? `${line.slice(0, 80).replace(/\\s+\\S*$/, \"\")}\u2026` : line;\n out.title_source = \"first-ask\";\n break;\n }\n const times = (boundary && meta ? [meta, ...H, ...T] : H.concat(T))\n .map((j) => Date.parse(String(j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Codex's ~/.codex/config.toml, as far as the notify fallback needs it: its one\n// top-level `notify` command. Codex reads `notify` only at the top level \u2014 before\n// the first [table] \u2014 and Codex itself appends a [projects.\"<path>\"] table for every\n// folder it trusts, so a line appended at the end lands inside one and never runs.\n// Ported from spacesheep-cli lib/codex-config.js. Pure text in, text out.\n\nconst NOTIFY_LINE = /^[ \\t]*notify[ \\t]*=[ \\t]*(\\[.*\\])[ \\t]*(?:#.*)?$/m;\nconst NOTIFY_KEY = /^[ \\t]*notify[ \\t]*=/m;\n/** A notify that runs sessionpipe's hook directly (or through its launcher). */\nexport const OURS = /(?:hook\\.js|sessionpipe-hook)\",\\s*\"codex\",\\s*\"notify\"/;\n\nfunction scan(line: string, st: { depth: number; str: string | null }): void {\n let i = 0;\n while (i < line.length) {\n if (st.str) {\n const j = line.indexOf(st.str, i);\n if (j < 0) return;\n i = j + 3;\n st.str = null;\n continue;\n }\n const ch = line[i];\n if (ch === \"#\") return;\n if (line.startsWith('\"\"\"', i) || line.startsWith(\"'''\", i)) {\n st.str = line.slice(i, i + 3);\n i += 3;\n continue;\n }\n if (ch === '\"') {\n i++;\n while (i < line.length && line[i] !== '\"') i += line[i] === \"\\\\\" ? 2 : 1;\n i++;\n continue;\n }\n if (ch === \"'\") {\n const j = line.indexOf(\"'\", i + 1);\n i = j < 0 ? line.length : j + 1;\n continue;\n }\n if (ch === \"[\") st.depth++;\n else if (ch === \"]\") st.depth = Math.max(0, st.depth - 1);\n i++;\n }\n}\n\n/** Offset of the first table header, or -1. */\nexport function firstTableAt(text: string): number {\n const st = { depth: 0, str: null as string | null };\n let pos = 0;\n for (const line of text.split(\"\\n\")) {\n if (!st.str && st.depth === 0 && /^[ \\t]*\\[/.test(line)) return pos;\n scan(line, st);\n pos += line.length + 1;\n }\n return -1;\n}\n\nfunction split(text: string) {\n const at = firstTableAt(text);\n return at < 0 ? { head: text, tail: \"\", at: text.length } : { head: text.slice(0, at), tail: text.slice(at), at };\n}\n\nexport function parseArgv(raw: string): string[] | null {\n try {\n const a = JSON.parse(raw) as unknown;\n return Array.isArray(a) && a.every((x) => typeof x === \"string\") ? (a as string[]) : null;\n } catch {\n return null;\n }\n}\n\nexport interface Notify {\n raw: string;\n argv: string[] | null;\n index: number;\n length: number;\n misplaced: boolean;\n other: boolean;\n}\n\n/** notify as Codex sees it; `misplaced` for a line of ours inside a table. */\nexport function readNotify(text: string): Notify | null {\n const { head, tail, at } = split(text);\n const m = NOTIFY_LINE.exec(head);\n if (m) {\n const raw = m[1] as string;\n return { raw, argv: parseArgv(raw), index: m.index, length: m[0].length, misplaced: false, other: !OURS.test(raw) };\n }\n const k = NOTIFY_KEY.exec(head);\n if (k) {\n const rest = head.slice(k.index).split(\"\\n\")[0] as string;\n return {\n raw: rest.replace(NOTIFY_KEY, \"\").trim(),\n argv: null,\n index: k.index,\n length: 0,\n misplaced: false,\n other: true,\n };\n }\n const t = NOTIFY_LINE.exec(tail);\n if (t) {\n const raw = t[1] as string;\n if (OURS.test(raw))\n return { raw, argv: parseArgv(raw), index: at + t.index, length: t[0].length, misplaced: true, other: false };\n }\n return null;\n}\n\nfunction dropLine(text: string, index: number, length: number): string {\n return text.slice(0, index) + text.slice(index + length).replace(/^\\r?\\n/, \"\");\n}\n\n/** Put `line` at the top level: before the first table, or at the end of a file that has none. */\nexport function insertTopLevel(text: string, line: string): string {\n const { head, tail } = split(text);\n if (!tail) return (head.trim() ? head.replace(/\\s*$/, \"\\n\") : \"\") + line + \"\\n\";\n return `${(head.trim() ? head.replace(/\\s*$/, \"\\n\") : \"\") + line}\\n\\n${tail}`;\n}\n\n/** The config with `line` as its notify, for a config whose notify is ours or absent. */\nexport function withNotify(text: string, line: string): string {\n const n = readNotify(text);\n if (n && !n.misplaced && !n.other) return text.slice(0, n.index) + line + text.slice(n.index + n.length);\n if (n?.misplaced) return insertTopLevel(dropLine(text, n.index, n.length), line);\n return insertTopLevel(text, line);\n}\n\n/** The config with its notify line `n` (as readNotify found it in `text`) replaced by `line`. */\nexport function replaceNotify(text: string, n: Notify, line: string): string {\n return text.slice(0, n.index) + line + text.slice(n.index + n.length);\n}\n\n/** The config with our top-level or misplaced notify removed. */\nexport function withoutNotify(text: string): string {\n const n = readNotify(text);\n if (!n || n.other || !n.length) return text;\n return dropLine(text, n.index, n.length);\n}\n\n// Codex Computer Use takes the notify slot itself and keeps the command it found in\n// its own argv: [client, \"turn-ended\", \"--previous-notify\", \"<that command as JSON>\"].\nconst PREVIOUS = \"--previous-notify\";\nexport function previousNotify(argv: string[] | null): string[] | null {\n if (!Array.isArray(argv)) return null;\n const i = argv.indexOf(PREVIOUS);\n return i >= 0 && typeof argv[i + 1] === \"string\" ? parseArgv(argv[i + 1] as string) : null;\n}\nexport function withPrevious(argv: string[], prev: string[] | null): string[] {\n const out = argv.slice();\n const i = out.indexOf(PREVIOUS);\n if (i >= 0) out.splice(i, 2);\n if (prev) out.push(PREVIOUS, JSON.stringify(prev));\n return out;\n}\n/** The raw notify value with its --previous-notify pair removed, formatting kept. */\nexport function stripPreviousRaw(raw: string): string {\n return raw.replace(/,\\s*\"--previous-notify\",\\s*\"(?:[^\"\\\\]|\\\\.)*\"\\s*(?=\\])/, \"\");\n}\n/** The raw notify value with `prev` as its --previous-notify, formatting of the rest kept. */\nexport function withPreviousRaw(raw: string, prev: string[]): string {\n const base = stripPreviousRaw(raw).replace(/\\s*\\]\\s*$/, \"\");\n return `${base}, \"--previous-notify\", ${JSON.stringify(JSON.stringify(prev))}]`;\n}\nexport const isComputerUse = (argv: string[] | null): boolean =>\n Array.isArray(argv) && typeof argv[0] === \"string\" && /(^|\\/)SkyComputerUseClient$/.test(argv[0]);\n", "// SPDX-License-Identifier: Apache-2.0\n// Codex CLI (OpenAI) \u2014 control delivery (spec/CONTROL.md \u00A76). Codex on this machine,\n// as the control daemon needs it: which `codex` to run, with which sandbox flags, one\n// headless turn (`codex exec --json` for a new session, `codex exec resume --json <id>`\n// for the next message), and its JSONL output read as it streams. Codex picks a new\n// session's id itself (the first line, `thread.started`), so the daemon names it after\n// the command that started it (CONTROL.md \u00A76 `start`). Shapes measured on codex-cli\n// 0.160.0, 2026-10-04.\nimport { execFile } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { MODEL_RE, type RunLevel, type StartPermission } from \"../control/verify.js\";\nimport {\n findBinary,\n jobEnv,\n type Login,\n type Mode,\n type Reading,\n type RunResult,\n runFailure,\n stderrTail,\n} from \"./headless.js\";\n\nexport { codexFacts, findRollout } from \"./codex.js\";\n\nconst LABEL = \"Codex\";\n\n/** The `codex` to run: SESSIONPIPE_CODEX, else on PATH, else beside the node running\n * this (an `npm install -g` there) or where the installers put it. */\nexport function findCodex(\n env: NodeJS.ProcessEnv = process.env,\n home = os.homedir(),\n nodeDir = path.dirname(process.execPath),\n): string | null {\n return findBinary({\n override: env.SESSIONPIPE_CODEX,\n names: process.platform === \"win32\" ? [\"codex.exe\", \"codex.cmd\"] : [\"codex\"],\n env,\n dirs: [nodeDir, path.join(home, \".local\", \"bin\"), \"/opt/homebrew/bin\", \"/usr/local/bin\"],\n });\n}\n\n/** Sandbox flags for a level (a machine's mode is one: safe, auto, inherit). Read: the\n * read-only sandbox. Safe: workspace-write, and nothing escalates unattended (exec never\n * asks); that sandbox already edits inside the folder, so `edits` is never offered and\n * means the same. Auto: approval requests go through Codex's own automatic review.\n * Inherit: none, so `sandbox_mode` and `approval_policy` come from the person's own\n * config.toml, a new session's and a resume's alike. Never\n * `--dangerously-bypass-approvals-and-sandbox`, `--dangerously-bypass-hook-trust` or\n * `danger-full-access`: no path here writes them. */\nexport function codexModeFlags(level: RunLevel, resume = false): string[] {\n if (level === \"inherit\") return [];\n const sandbox = level === \"read\" ? \"read-only\" : \"workspace-write\";\n // `codex exec resume` takes neither `-s` nor `--approve-for-me` (0.160: \"unexpected\n // argument\"), so a resume says the same thing as config overrides, which it does take.\n if (resume)\n return level === \"auto\"\n ? [\n \"-c\",\n 'sandbox_mode=\"workspace-write\"',\n \"-c\",\n 'approval_policy=\"on-request\"',\n \"-c\",\n 'approvals_reviewer=\"auto_review\"',\n ]\n : [\"-c\", `sandbox_mode=\"${sandbox}\"`];\n return level === \"auto\" ? [\"--approve-for-me\"] : [\"-s\", sandbox];\n}\n\n/** The levels a start may ask Codex for on a machine in `mode`: read and safe, and auto\n * on an auto machine. */\nexport const offeredLevels = (mode: Mode): StartPermission[] =>\n mode === \"auto\" ? [\"read\", \"safe\", \"auto\"] : [\"read\", \"safe\"];\n\n/** What a start that names no level gets: what the machine's mode means for Codex. */\nexport const defaultLevel = (mode: Mode): RunLevel => mode;\n\n/** One headless turn. A new session runs in `cwd` (`-C`); a resume names the thread.\n * The model is its own argument after `-m`. The prompt goes after `--`, so a message\n * that starts with a dash is never a flag. */\nexport function codexArgs(o: {\n permission: RunLevel;\n prompt: string;\n cwd?: string;\n resume?: string;\n model?: string;\n}): string[] {\n const common = [\"--json\", \"--skip-git-repo-check\"];\n const model = o.model ? [\"-m\", o.model] : [];\n if (o.resume)\n return [\"exec\", \"resume\", ...common, ...codexModeFlags(o.permission, true), ...model, \"--\", o.resume, o.prompt];\n return [\n \"exec\",\n ...common,\n ...(o.cwd ? [\"-C\", o.cwd] : []),\n ...codexModeFlags(o.permission),\n ...model,\n \"--\",\n o.prompt,\n ];\n}\n\n/** The models a hello offers for Codex (CONTROL.md \u00A72 `start`): the slugs Codex's own\n * picker lists, from `$CODEX_HOME/models_cache.json` (visibility `list`; hidden ones,\n * such as its review model, left out), at most 50. Empty when there is no cache. */\nexport function codexModels(env: NodeJS.ProcessEnv = process.env, home = os.homedir()): string[] {\n try {\n const file = path.join(env.CODEX_HOME || path.join(home, \".codex\"), \"models_cache.json\");\n const j = JSON.parse(readFileSync(file, \"utf8\")) as { models?: unknown };\n if (!Array.isArray(j.models)) return [];\n const out: string[] = [];\n for (const m of j.models as { slug?: unknown; visibility?: unknown }[])\n if (m && m.visibility === \"list\" && typeof m.slug === \"string\" && MODEL_RE.test(m.slug) && m.slug.length <= 100)\n if (!out.includes(m.slug)) out.push(m.slug);\n return out.slice(0, 50);\n } catch {\n return [];\n }\n}\n\n/** The env a headless turn runs with. */\nexport const codexEnv = (env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv => jobEnv(env);\n\nexport const LOGIN_HINT = \"Codex isn't signed in on this machine: run `codex login --device-auth` there.\";\n\n/** Whether Codex can run as this process: CODEX_API_KEY in the env is enough; else\n * `codex login status` (exit 0 signed in, exit 1 \"Not logged in\"). Anything else \u2014\n * it didn't run, it timed out \u2014 is null, never a reason to refuse. */\nexport function codexLogin(bin: string, env: NodeJS.ProcessEnv = process.env): Promise<Login> {\n if (env.CODEX_API_KEY) return Promise.resolve({ loggedIn: true, method: \"api key\" });\n return new Promise((resolve) => {\n execFile(\n bin,\n [\"login\", \"status\"],\n { encoding: \"utf8\", timeout: 20_000, env: codexEnv(env), maxBuffer: 256 * 1024 },\n (err) => {\n if (!err) return resolve({ loggedIn: true });\n const code = (err as { code?: unknown }).code;\n resolve(code === 1 ? { loggedIn: false } : { loggedIn: null });\n },\n );\n });\n}\n\n/** One `--json` line, as much of it as the daemon uses. */\nexport interface CodexPiece {\n /** `thread.started`: the session's id, which Codex chose. */\n session?: string;\n /** A finished `agent_message`: one part of the answer. */\n message?: string;\n /** `turn.completed` (or `turn.failed`). */\n done?: boolean;\n /** `turn.failed`: why. */\n failed?: string;\n /** A top-level `error` (\"Reconnecting... 2/5\"): transient, the reason only if the run then fails. */\n note?: string;\n /** An `error` item: a warning Codex printed and carried on after (hook trust, a clamped timeout). */\n warning?: string;\n}\n\nexport function codexLine(line: string): CodexPiece | null {\n let j: {\n type?: unknown;\n thread_id?: unknown;\n message?: unknown;\n item?: { type?: unknown; text?: unknown; message?: unknown };\n error?: { message?: unknown };\n };\n try {\n j = JSON.parse(line);\n } catch {\n return null;\n }\n if (!j || typeof j !== \"object\") return null;\n const str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n switch (j.type) {\n case \"thread.started\":\n return str(j.thread_id) ? { session: str(j.thread_id) } : null;\n case \"item.completed\": {\n const it = j.item;\n if (it?.type === \"agent_message\" && str(it.text)) return { message: str(it.text) };\n if (it?.type === \"error\" && str(it.message)) return { warning: str(it.message) };\n return null;\n }\n case \"turn.completed\":\n return { done: true };\n case \"turn.failed\":\n return { done: true, failed: str(j.error?.message) || \"Codex reported an error\" };\n case \"error\":\n return str(j.message) ? { note: str(j.message) } : null;\n default:\n return null;\n }\n}\n\n/** A Codex run read as it streams: the answer is its finished agent messages. */\nexport class CodexReading implements Reading {\n session: string | null = null;\n lines = 0;\n readonly warnings: string[] = [];\n private readonly messages: string[] = [];\n private done = false;\n private failed: string | null = null;\n private note: string | null = null;\n\n get text(): string {\n return this.messages.join(\"\\n\\n\");\n }\n\n feed(line: string): boolean {\n this.lines++;\n const p = codexLine(line);\n if (!p) return false;\n if (p.session && !this.session) this.session = p.session;\n if (p.note) this.note = p.note;\n if (p.warning && this.warnings.length < 20) this.warnings.push(p.warning);\n if (p.failed) this.failed = p.failed;\n if (p.done) this.done = true;\n if (p.message?.trim()) {\n this.messages.push(p.message.trim());\n return true;\n }\n return false;\n }\n\n /** A failure is `turn.failed`, or a run that exits non-zero having said nothing; an\n * `error` item before a turn that then succeeds is only a warning. */\n outcome(res: RunResult): { failed: string } | { reply: string } {\n const broke = runFailure(LABEL, res);\n if (broke) return { failed: broke };\n if (this.failed) return { failed: this.failed };\n if (this.done || res.code === 0 || this.messages.length)\n return { reply: this.text || \"(Codex finished without a written reply.)\" };\n const why = this.note || codexStderr(res.stderr) || this.warnings.at(-1) || \"\";\n return { failed: `Codex exited (${res.signal || `code ${res.code}`}) without an answer${why ? `: ${why}` : \"\"}` };\n }\n}\n\n/** stderr's tail without the line Codex prints even with stdin closed. */\nfunction codexStderr(stderr: string | undefined): string {\n return stderrTail(\n String(stderr || \"\")\n .split(\"\\n\")\n .filter((l) => !/^Reading additional input from stdin/.test(l.trim()))\n .join(\"\\n\"),\n );\n}\n\nexport const reading = (): CodexReading => new CodexReading();\n", "// SPDX-License-Identifier: Apache-2.0\n// Devin CLI (Cognition) \u2014 docs: https://docs.devin.ai/cli/extensibility/hooks/overview\n// Config: the `hooks` key of the user config file \u2014 `~/.config/devin/config.json`\n// (`$XDG_CONFIG_HOME/devin/config.json` when that is set), `%APPDATA%\\devin\\config.json`\n// on Windows. Claude-shaped, matcher a REGEX on the tool name, timeouts in SECONDS.\n// That file is the only user-level location Devin reads hooks from; `hooks.v1.json` is\n// project-level only.\n//\n// Devin accepts exactly eight event names and rejects the WHOLE file on one it does not\n// know (\"unknown variant `Notification`, expected one of \u2026\"), which silently disables\n// every hook in it. DEVIN_EVENTS is that set, and nothing else may be added to it.\n//\n// The payload carries no `cwd`, no `transcript_path` and no `model`: the folder comes\n// from DEVIN_PROJECT_DIR in the hook's environment, and the transcript, the model, the\n// title and the times come from Devin's own session store \u2014 one SQLite file under the\n// data directory, read only, through readers/sqlite.ts. A session's transcript is\n// addressed as \"<database>#<session id>\", because readTranscript is given a file.\n//\n// stdout stays empty for every event: Devin reads a decision from stdout, and silence\n// plus exit 0 is \"carry on\" (printing nothing, printing `{}`, exiting 1 and blowing the\n// timeout were all measured as non-blocking; only exit 2 or an explicit\n// {\"decision\":\"block\"} blocks a tool).\nimport { createHash } from \"node:crypto\";\nimport { existsSync, readlinkSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { querySqlite } from \"../readers/sqlite.js\";\nimport { pairTurns } from \"../readers/transcripts.js\";\nimport { installClaudeShaped, installedClaudeShaped, readJson, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport type {\n Adapter,\n BackfillRow,\n HookInput,\n HookResult,\n InstallOptions,\n SessionFacts,\n TranscriptRead,\n} from \"./types.js\";\n\nconst NAME = \"devin\";\n/** The eight event names Devin accepts. One it does not know makes it drop the whole\n * hooks file, so this list is exact, not a superset \u2014 see devin.test.ts. */\nexport const DEVIN_EVENTS = [\n \"SessionStart\",\n \"UserPromptSubmit\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PermissionRequest\",\n \"Stop\",\n \"PostCompaction\",\n \"SessionEnd\",\n] as const;\nconst OPTS = { matcherFor: (e: string) => (/Tool|Permission/.test(e) ? \"\" : undefined), timeout: 5 };\nconst eventsFor = (lean?: boolean) => (lean ? DEVIN_EVENTS.filter((e) => e !== \"PreToolUse\") : [...DEVIN_EVENTS]);\nconst INSTALL_NOTE =\n \"Devin drops a whole hooks file on one event name it doesn't know; `/hooks` in `devin` lists what loaded\";\nconst CLAUDE_NOTE =\n \"Devin also reads ~/.claude/settings.json hooks (read_config_from.claude); a Claude-only event name there makes it ignore that file whole\";\n\nconst deadFileNote = (bad: string) =>\n `Devin loads NO hooks from this file: \"${bad}\" is not one of its event names and it rejects the file whole \u2014 remove that key (\\`/hooks\\` in \\`devin\\` lists what loaded)`;\n\n/** The first `hooks` key in the file that Devin does not accept, if there is one.\n * One such key disables every hook in the file, ours and any other tool's. */\nexport function foreignEvent(file: string): string | undefined {\n const hooks = readJson(file).hooks;\n if (!hooks || typeof hooks !== \"object\" || Array.isArray(hooks)) return undefined;\n const ok = DEVIN_EVENTS as readonly string[];\n return Object.keys(hooks).find((k) => !ok.includes(k));\n}\n\nconst homeOf = (env: NodeJS.ProcessEnv) => env.HOME || homeDir();\nconst appData = (env: NodeJS.ProcessEnv) => env.APPDATA || path.join(homeOf(env), \"AppData\", \"Roaming\");\n/** `~/.config/devin`, `$XDG_CONFIG_HOME/devin`, or `%APPDATA%\\devin`. */\nexport const devinConfigDir = (env: NodeJS.ProcessEnv = process.env): string =>\n process.platform === \"win32\"\n ? path.join(appData(env), \"devin\")\n : path.join(env.XDG_CONFIG_HOME || path.join(homeOf(env), \".config\"), \"devin\");\nconst configFile = (env: NodeJS.ProcessEnv) => path.join(devinConfigDir(env), \"config.json\");\n/** `~/.local/share/devin/cli`, `$XDG_DATA_HOME/devin/cli`, or `%APPDATA%\\devin\\cli`. */\nexport const devinDataDir = (env: NodeJS.ProcessEnv = process.env): string =>\n process.platform === \"win32\"\n ? path.join(appData(env), \"devin\", \"cli\")\n : path.join(env.XDG_DATA_HOME || path.join(homeOf(env), \".local\", \"share\"), \"devin\", \"cli\");\nconst sessionsDb = (env: NodeJS.ProcessEnv) => path.join(devinDataDir(env), \"sessions.db\");\n\nconst SESSION_ID = /^[A-Za-z0-9._:-]{1,128}$/;\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst endReason = (r: unknown): \"clear\" | \"logout\" | \"exit\" | \"other\" =>\n r === \"clear\" || r === \"logout\" || r === \"exit\" ? r : \"other\";\nconst pickSource = (v: unknown): string =>\n typeof v === \"string\" && [\"startup\", \"resume\", \"clear\", \"compact\", \"fork\"].includes(v) ? v : \"unknown\";\nfunction errText(v: unknown): string | undefined {\n if (typeof v === \"string\" && v) return v.slice(0, 2000);\n if (v && typeof v === \"object\") {\n const e = v as { message?: unknown; error?: unknown };\n if (typeof e.message === \"string\" && e.message) return e.message.slice(0, 2000);\n if (typeof e.error === \"string\" && e.error) return e.error.slice(0, 2000);\n }\n return undefined;\n}\nconst cut = (s: string, n: number): string => (s.length > n ? `${s.slice(0, n).replace(/\\s+\\S*$/, \"\")}\u2026` : s);\n\nexport const devin: Adapter = {\n name: NAME,\n events: DEVIN_EVENTS,\n detect: (env = process.env) => existsSync(devinConfigDir(env)) || existsSync(devinDataDir(env)),\n configFiles: (env = process.env) => [configFile(env)],\n install: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const file = configFile(env);\n const r = installClaudeShaped(file, NAME, eventsFor(opts.lean), cmd, OPTS);\n if (r.skipped) return [r];\n const bad = foreignEvent(file);\n return [{ ...r, note: bad ? deadFileNote(bad) : INSTALL_NOTE }];\n },\n uninstall: (env = process.env, opts: InstallOptions = {}) => [\n uninstallClaudeShaped(configFile(env), DEVIN_EVENTS, { created: opts.created?.includes(configFile(env)) }),\n ],\n installed: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const file = configFile(env);\n const state = installedClaudeShaped(file, NAME, eventsFor(opts.lean), cmd, OPTS);\n // Our entries can be present and current and still report nothing: one event name\n // Devin does not know makes it drop the whole file, ours with it. `status` has to\n // say so, or it tells the person reporting is on while it is dead.\n const bad = state === \"missing\" ? undefined : foreignEvent(file);\n return [{ file, state: bad ? \"inactive\" : state, note: bad ? deadFileNote(bad) : CLAUDE_NOTE }];\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = typeof s.session_id === \"string\" ? s.session_id : \"\";\n if (!id) return null;\n // Nothing in the payload names the folder; DEVIN_PROJECT_DIR is the only thing that does.\n const session: HookResult[\"session\"] = { id, cwd: input.env.DEVIN_PROJECT_DIR ?? input.cwd };\n const turn_id = typeof s.prompt_id === \"string\" ? s.prompt_id : undefined;\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const call_id = typeof s.tool_use_id === \"string\" ? s.tool_use_id : undefined;\n // Every recorded payload has an object here, but the field is free-form: a Devin\n // version or an MCP-style tool could send a bare string, and then there is no\n // `success` and no `output` to read \u2014 the whole value IS the output.\n const response =\n s.tool_response && typeof s.tool_response === \"object\" && !Array.isArray(s.tool_response)\n ? (s.tool_response as { success?: unknown; output?: unknown; error?: unknown })\n : undefined;\n // The same prompt must always name the same attention (CONTROL.md \u00A76). Devin's\n // PermissionRequest does carry tool_use_id; the hash is the fallback for one that\n // doesn't, and is the bytes ADAPTERS.md's common conventions prescribe.\n const permissionId = () =>\n `perm-${createHash(\"sha256\")\n .update(`${turn_id ?? \"\"}|${tool ?? \"\"}|${JSON.stringify(s.tool_input ?? null)}`)\n .digest(\"hex\")\n .slice(0, 16)}`;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(ev(\"session.started\", { source: pickSource(s.source) }));\n break;\n case \"UserPromptSubmit\":\n events.push(\n ev(\"turn.started\", {\n turn_id,\n prompt_chars: typeof s.prompt === \"string\" ? [...s.prompt].length : undefined,\n }),\n );\n break;\n case \"PreToolUse\":\n if (tool) events.push(ev(\"tool.started\", { tool, call_id, turn_id, input: s.tool_input }));\n break;\n case \"PostToolUse\":\n // Devin is the one harness that says so outright: tool_response.success.\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n call_id,\n turn_id,\n // `ok` is required on tool.ended (PROTOCOL.md \u00A7events), so a response\n // that carries no success flag at all reads as \"nothing said it failed\".\n ok: response?.success !== false,\n error: errText(response?.error),\n input: s.tool_input,\n output: response ? response.output : s.tool_response,\n }),\n );\n break;\n case \"PermissionRequest\":\n events.push(ev(\"attention.needed\", { attention_id: call_id ?? permissionId(), kind: \"permission\", tool }));\n break;\n case \"Stop\":\n events.push(ev(\"turn.ended\", { turn_id, reason: \"stop\" }));\n break;\n case \"PostCompaction\":\n // Devin has no pre-compaction event; the payload carries only the summary.\n events.push(ev(\"context.compacted\", { trigger: \"auto\" }));\n break;\n case \"SessionEnd\":\n events.push(ev(\"session.ended\", { reason: endReason(s.reason) }));\n break;\n default:\n return null;\n }\n return {\n session,\n events,\n hints: {},\n transcript: transcriptRef(sessionsDb(input.env as NodeJS.ProcessEnv), id),\n };\n },\n\n readTranscript(file, fromLine) {\n const ref = splitRef(file);\n if (!ref) return { turns: [], line: fromLine };\n return readDevinChain(ref.db, ref.session, fromLine);\n },\n\n facts(session, transcript, _hints, _state, env = process.env): SessionFacts {\n const out: SessionFacts = {};\n const version = devinVersion(env);\n if (version) out.harness_version = version;\n const account = devinAccount(env);\n if (account) out.account_id = account;\n const ref = splitRef(transcript) ?? { db: sessionsDb(env), session: session.id };\n if (!SESSION_ID.test(ref.session)) return out;\n const rows = querySqlite(ref.db, SESSION_SQL, [ref.session]);\n const row = rows?.[0];\n if (!row) return out;\n Object.assign(out, sessionFacts(row));\n return out;\n },\n\n backfill(sinceMs, env = process.env): BackfillRow[] {\n const rows = querySqlite(sessionsDb(env), BACKFILL_SQL, [\"text\", Math.floor(sinceMs / 1000)]);\n if (!rows) return [];\n const out: BackfillRow[] = [];\n for (const row of rows) {\n const id = String(row.id); // text, the query says\n if (!SESSION_ID.test(id)) continue;\n const { started_at, last_at, ...rest } = sessionFacts(row);\n if (!started_at || !last_at) continue;\n out.push({ session: { id, ...rest }, started_at, last_at });\n }\n return out;\n },\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n\n// --- the session store ---------------------------------------------------------------\n\n/** `<database>#<session id>`: readTranscript is given a file, and Devin keeps every\n * session in one database, so the session has to ride in the string. */\nexport const transcriptRef = (db: string, session: string): string => `${db}#${session}`;\nexport function splitRef(ref: string | undefined): { db: string; session: string } | null {\n if (!ref) return null;\n const at = ref.lastIndexOf(\"#\");\n if (at <= 0) return null;\n const db = ref.slice(0, at);\n const session = ref.slice(at + 1);\n return db && SESSION_ID.test(session) ? { db, session } : null;\n}\n\n/** `message_nodes` is a forest: it keeps abandoned branches too (27 nodes for a\n * two-turn session). The transcript is the one chain that ends at\n * `sessions.main_chain_id`, walked up through `parent_node_id` \u2014 never every node. */\n/** The walk stops at the cursor (`m.node_id >= ?`): everything below it has been read\n * already, and without that bound every Stop pulled `chat_message` for every ancestor\n * \u2014 the root of a real chain carries a 17 kB system prompt and four more system\n * blocks, re-read on every event, and past 32 MB the child and CLI engines give up\n * and return nothing. The cap keeps the NEWEST rows (`DESC`), re-sorted below: an\n * ascending cap would have kept the oldest and delivered no new turn ever again. */\nconst CHAIN_LIMIT = 4000;\nexport const CHAIN_SQL = `WITH RECURSIVE chain(node_id, parent_node_id, chat_message, created_at) AS (\n SELECT node_id, parent_node_id, chat_message, created_at FROM message_nodes\n WHERE session_id = ? AND node_id = (SELECT main_chain_id FROM sessions WHERE id = ?)\n UNION ALL\n SELECT m.node_id, m.parent_node_id, m.chat_message, m.created_at FROM message_nodes m\n JOIN chain c ON m.node_id = c.parent_node_id AND m.session_id = ? AND m.node_id >= ?\n)\nSELECT node_id, chat_message, created_at FROM chain ORDER BY node_id DESC LIMIT ${CHAIN_LIMIT}`;\n\n/** Times are unix SECONDS in this store. The first ask comes from `prompt_history`,\n * because `sessions.title` holds whatever the titler last produced \u2014 a backticked\n * command, or a raw `functions.Shell:0{\u2026}` mid-turn. */\nconst SESSION_FIELDS = `s.model, s.working_directory, s.created_at, s.last_activity_at,\n (SELECT p.content FROM prompt_history p WHERE p.session_id = s.id AND p.is_shell = 0\n ORDER BY p.timestamp ASC, p.id ASC LIMIT 1) AS first_ask`;\nconst SESSION_SQL = `SELECT ${SESSION_FIELDS} FROM sessions s WHERE s.id = ? LIMIT 1`;\n// typeof(id) = 'text' (the literal rides as a parameter: the CLI engine takes no quote\n// in the SQL): an id a session ref could carry. A blob id comes back from the sqlite3\n// CLI as a string shaped by its version, so the database says what it is.\nconst BACKFILL_SQL = `SELECT s.id, ${SESSION_FIELDS} FROM sessions s\n WHERE s.hidden = 0 AND typeof(s.id) = ? AND s.last_activity_at >= ?\n ORDER BY s.last_activity_at DESC LIMIT 500`;\n\nfunction sessionFacts(row: Record<string, unknown>): SessionFacts {\n const out: SessionFacts = {};\n if (typeof row.model === \"string\" && row.model) out.model = row.model;\n if (typeof row.working_directory === \"string\" && path.isAbsolute(row.working_directory))\n out.cwd = row.working_directory;\n const started = Number(row.created_at);\n const last = Number(row.last_activity_at);\n if (Number.isFinite(started) && started > 0) out.started_at = Math.round(started * 1000);\n if (Number.isFinite(last) && last > 0) out.last_at = Math.round(last * 1000);\n if (typeof row.first_ask === \"string\") {\n const line = row.first_ask.split(\"\\n\").find((l) => l.trim()) ?? \"\";\n if (line.trim()) {\n out.title = cut(line.trim(), 80);\n out.title_source = \"first-ask\";\n }\n }\n return out;\n}\n\ninterface ChatMessage {\n role?: unknown;\n content?: unknown;\n metadata?: { is_user_input?: unknown; created_at?: unknown } | null;\n}\n\n/** The canonical chain as turns. `node_id` is the cursor: it rises along the chain and\n * is stable across a resume, so a later read starts where the last one stopped.\n * `role: \"system\"` is Cognition's own prompt (and the skills manifest, and the\n * generated system_info block), never the person's words \u2014 it is skipped at every\n * tier, as is `role: \"tool\"`. */\nexport function readDevinChain(db: string, session: string, fromLine: number): TranscriptRead {\n if (!SESSION_ID.test(session)) return { turns: [], line: fromLine };\n const floor = Number.isFinite(fromLine) && fromLine > 0 ? Math.floor(fromLine) : 0;\n const rows = querySqlite(db, CHAIN_SQL, [session, session, session, floor]);\n if (!rows?.length) return { turns: [], line: fromLine };\n const msgs: { role: \"user\" | \"assistant\"; text: string; at: number; line: number }[] = [];\n let end = fromLine;\n for (const row of rows) {\n const node = Number(row.node_id);\n if (!Number.isFinite(node)) continue;\n if (node + 1 > end) end = node + 1;\n if (node < fromLine) continue;\n let j: ChatMessage;\n try {\n j = JSON.parse(String(row.chat_message ?? \"\")) as ChatMessage;\n } catch {\n continue;\n }\n const text = typeof j.content === \"string\" ? j.content.trim() : \"\";\n if (!text) continue;\n // The message's own time, not the row's. `message_nodes.created_at` is when the row\n // batch was last WRITTEN: Devin rewrites it on every save of the chain, so every\n // node of a chain usually carries one identical value, and it is not even monotonic\n // along the chain. Measured on a live store 2026-10-08: a two-turn session had all\n // four of its chain nodes at 23:33:10 while their own `metadata.created_at` read\n // 23:32:29, :34, 23:33:08 and :10 (turn 1 reported 41 s late, both turns at the same\n // instant); one node's row time was rewritten 12 s later between two reads; and a\n // descendant's row time was 27 s EARLIER than its ancestor's. The column is only the\n // fallback for a row whose message has no time of its own.\n const secs = Number(row.created_at);\n const at =\n Date.parse(String(j.metadata?.created_at ?? \"\")) ||\n (Number.isFinite(secs) && secs > 0 ? Math.round(secs * 1000) : 0) ||\n Date.now();\n if (j.role === \"user\" && j.metadata?.is_user_input === true) msgs.push({ role: \"user\", text, at, line: node });\n else if (j.role === \"assistant\") msgs.push({ role: \"assistant\", text, at, line: node });\n }\n // The rows come newest first (the cap keeps the newest); a transcript runs the other way.\n msgs.sort((a, b) => a.line - b.line);\n return pairTurns(msgs, end);\n}\n\n/** `<data dir>/_versions/current` is a symlink to the running version's folder. */\nexport function devinVersion(env: NodeJS.ProcessEnv = process.env): string | undefined {\n try {\n const target = readlinkSync(path.join(devinDataDir(env), \"_versions\", \"current\"));\n const name = path.basename(target);\n return /^[0-9][0-9A-Za-z.+-]{0,63}$/.test(name) ? name : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The organisation the CLI is signed in to, from the user config \u2014 the only account id\n * Devin keeps in a plain local file. Never the email, and never credentials.toml. */\nexport function devinAccount(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const d = readJson(configFile(env)).devin as { org_id?: unknown } | undefined;\n const id = d && typeof d === \"object\" ? d.org_id : undefined;\n return typeof id === \"string\" && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Read-only SQLite, for a harness that keeps its sessions in a database instead of a\n// JSONL file. Three ways in, tried in order, because `node:sqlite` does not exist on\n// Node 20 (the floor this package builds for) and is behind --experimental-sqlite on\n// 22.5\u201322.12:\n// \"node\" in this process, through createRequire \u2014 no static import, so the bundle\n// still loads on a Node without the module;\n// \"child\" one `node --experimental-sqlite -e \u2026` run through execFileSync: no shell,\n// arguments passed as argv, a short timeout;\n// \"cli\" the `sqlite3` binary, when it is on PATH and every parameter is a plain\n// scalar that can be written as a literal.\n// Every path opens the file read-only, is bounded in time, and returns null instead of\n// throwing: a database that is busy, missing, locked or unreadable costs the caller\n// nothing but an empty read.\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\n\nexport type SqliteParam = string | number;\nexport type SqliteRow = Record<string, unknown>;\nexport type SqliteEngine = \"auto\" | \"node\" | \"child\" | \"cli\";\n\nexport interface SqliteOptions {\n /** Busy timeout and the child's wall clock, in ms (default 2000). */\n timeoutMs?: number;\n /** Force one way in; \"auto\" tries node, then child, then cli (default). */\n engine?: SqliteEngine;\n /** Largest reply a child or the CLI may print (default 32 MB). */\n maxBuffer?: number;\n}\n\ninterface Statement {\n all(...params: SqliteParam[]): unknown[];\n}\ninterface Db {\n prepare(sql: string): Statement;\n exec(sql: string): void;\n close(): void;\n}\ntype DbCtor = new (path: string, options?: Record<string, unknown>) => Db;\n\n/** `node:sqlite` is still experimental, and Node says so on stderr the first time it is\n * used. A reader has no business writing to a harness's terminal, so that one warning\n * is swallowed while the module is loaded and used \u2014 nothing else is, and the original\n * emitter is back before this returns. (The child path passes --no-warnings instead.)\n * Exported for its test: Node emits that warning once per process. */\nexport function quiet<T>(fn: () => T): T {\n const original = process.emitWarning;\n try {\n process.emitWarning = ((warning: unknown, ...rest: unknown[]) => {\n const kind = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string } | undefined)?.type;\n if (kind === \"ExperimentalWarning\" && /sqlite/i.test(String(warning))) return;\n (original as (...a: unknown[]) => void).call(process, warning, ...rest);\n }) as typeof process.emitWarning;\n return fn();\n } finally {\n process.emitWarning = original;\n }\n}\n\nlet ctorCache: DbCtor | null | undefined;\n/** `node:sqlite` if this Node has it; null if it does not (Node 20, or 22.x unflagged). */\nfunction dbCtor(): DbCtor | null {\n if (ctorCache !== undefined) return ctorCache;\n ctorCache = null;\n try {\n const req = createRequire(import.meta.url);\n const m = quiet(() => req(\"node:sqlite\")) as { DatabaseSync?: unknown };\n if (typeof m?.DatabaseSync === \"function\") ctorCache = m.DatabaseSync as DbCtor;\n } catch {}\n return ctorCache;\n}\n\n/** SQLite gives back strings, numbers, null, BigInt and Uint8Array; the protocol takes JSON. */\nfunction plain(row: unknown): SqliteRow | null {\n if (!row || typeof row !== \"object\") return null;\n const out: SqliteRow = {};\n for (const [k, v] of Object.entries(row as SqliteRow)) {\n if (typeof v === \"bigint\") out[k] = Number(v);\n else if (v instanceof Uint8Array) out[k] = null;\n else out[k] = v;\n }\n return out;\n}\nconst rows = (v: unknown): SqliteRow[] | null => {\n if (!Array.isArray(v)) return null;\n const out: SqliteRow[] = [];\n for (const r of v) {\n const p = plain(r);\n if (p) out.push(p);\n }\n return out;\n};\n\nfunction viaNode(file: string, sql: string, params: SqliteParam[], o: Required<SqliteOptions>): SqliteRow[] | null {\n const C = dbCtor();\n if (!C) return null;\n let db: Db;\n try {\n db = quiet(() => new C(file, { readOnly: true, timeout: o.timeoutMs }));\n } catch {\n return null;\n }\n try {\n try {\n db.exec(`PRAGMA busy_timeout = ${Math.round(o.timeoutMs)}`);\n } catch {}\n return quiet(() => rows(db.prepare(sql).all(...params)));\n } catch {\n return null;\n } finally {\n try {\n db.close();\n } catch {}\n }\n}\n\n/** Runs in a child Node, with the file, the SQL, the parameters and the timeout as argv. */\nconst CHILD = `const { DatabaseSync } = require(\"node:sqlite\");\nconst [, file, sql, params, ms] = process.argv;\nconst db = new DatabaseSync(file, { readOnly: true, timeout: Number(ms) });\ntry { db.exec(\"PRAGMA busy_timeout = \" + Number(ms)); } catch {}\nconst out = db.prepare(sql).all(...JSON.parse(params));\ndb.close();\nprocess.stdout.write(JSON.stringify(out));`;\n\nfunction viaChild(file: string, sql: string, params: SqliteParam[], o: Required<SqliteOptions>): SqliteRow[] | null {\n try {\n const out = execFileSync(\n process.execPath,\n [\"--experimental-sqlite\", \"--no-warnings\", \"-e\", CHILD, file, sql, JSON.stringify(params), String(o.timeoutMs)],\n {\n encoding: \"utf8\",\n timeout: o.timeoutMs + 3000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n maxBuffer: o.maxBuffer,\n windowsHide: true,\n },\n );\n return rows(JSON.parse(out || \"null\"));\n } catch {\n return null;\n }\n}\n\n/** A parameter safe to write into SQL as a literal: no quote, no backslash, no newline. */\nconst SAFE = /^[A-Za-z0-9 ._:@/+-]{0,256}$/;\nexport function inlineParams(sql: string, params: SqliteParam[]): string | null {\n if (sql.includes(\"'\")) return null; // a literal in the SQL would make the `?` count a guess\n const holes = sql.split(\"?\").length - 1;\n if (holes !== params.length) return null;\n let i = 0;\n let bad = false;\n const out = sql.replace(/\\?/g, () => {\n const p = params[i++];\n if (typeof p === \"number\") {\n if (!Number.isFinite(p)) {\n bad = true;\n return \"NULL\";\n }\n return String(p);\n }\n if (typeof p !== \"string\" || !SAFE.test(p)) {\n bad = true;\n return \"NULL\";\n }\n return `'${p}'`;\n });\n return bad ? null : out;\n}\n\nfunction viaCli(file: string, sql: string, params: SqliteParam[], o: Required<SqliteOptions>): SqliteRow[] | null {\n const text = inlineParams(sql, params);\n if (!text) return null;\n try {\n const out = execFileSync(\"sqlite3\", [\"-readonly\", \"-json\", file, text], {\n encoding: \"utf8\",\n timeout: o.timeoutMs + 3000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n maxBuffer: o.maxBuffer,\n windowsHide: true,\n }).trim();\n if (!out) return [];\n return rows(JSON.parse(out));\n } catch {\n return null;\n }\n}\n\n/** One read-only query. Null means \"could not read it\", never an exception. */\nexport function querySqlite(\n file: string,\n sql: string,\n params: SqliteParam[] = [],\n opts: SqliteOptions = {},\n): SqliteRow[] | null {\n const o: Required<SqliteOptions> = {\n timeoutMs: opts.timeoutMs ?? 2000,\n engine: opts.engine ?? \"auto\",\n maxBuffer: opts.maxBuffer ?? 32 * 1024 * 1024,\n };\n if (!file) return null;\n try {\n if (!existsSync(file)) return null;\n } catch {\n return null;\n }\n const ways =\n o.engine === \"auto\"\n ? ([viaNode, viaChild, viaCli] as const)\n : o.engine === \"node\"\n ? ([viaNode] as const)\n : o.engine === \"child\"\n ? ([viaChild] as const)\n : ([viaCli] as const);\n for (const way of ways) {\n const r = way(file, sql, params, o);\n if (r) return r;\n }\n return null;\n}\n\n/** Is `node:sqlite` in this process? (Tests skip what they cannot set up.) */\nexport const sqliteInProcess = (): boolean => dbCtor() !== null;\n", "// SPDX-License-Identifier: Apache-2.0\n// Gemini CLI (Google) \u2014 docs: https://geminicli.com/docs/hooks/reference\n// Config: ~/.gemini/settings.json `hooks` key, same array-of-groups shape as Claude\n// Code but timeouts in MILLISECONDS and a `name` per handler. stdout must be JSON or\n// empty. Its own telemetry defaults logPrompts on; the installer says so once.\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { homeDir } from \"../paths.js\";\nimport { ends, parseLines } from \"../readers/files.js\";\nimport { readGemini } from \"../readers/transcripts.js\";\nimport { installClaudeShaped, installedClaudeShaped, uninstallClaudeShaped } from \"./claude-shaped.js\";\nimport type { Adapter, HookInput, HookResult, InstallOptions, SessionFacts } from \"./types.js\";\n\nconst NAME = \"gemini-cli\";\nexport const GEMINI_EVENTS = [\n \"SessionStart\",\n \"BeforeAgent\",\n \"BeforeTool\",\n \"AfterTool\",\n \"Notification\",\n \"AfterAgent\",\n \"PreCompress\",\n \"SessionEnd\",\n] as const;\nconst OPTS = { matcherFor: (e: string) => (/Tool/.test(e) ? \".*\" : undefined), timeout: 5000 };\nconst geminiDir = (env: NodeJS.ProcessEnv) => env.GEMINI_CLI_HOME || path.join(homeDir(), \".gemini\");\nconst settings = (env: NodeJS.ProcessEnv) => path.join(geminiDir(env), \"settings.json\");\nconst validTool = (n: unknown): n is string => typeof n === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);\nconst eventsFor = (lean?: boolean) => (lean ? GEMINI_EVENTS.filter((e) => e !== \"BeforeTool\") : [...GEMINI_EVENTS]);\n\n/** Before 0.46 the hooks system is off unless tools.enableHooks is true (issue #11). */\nexport function geminiHooksActive(settingsFile: string): { active: boolean; note?: string } {\n let tools: { enableHooks?: unknown } | undefined;\n try {\n tools = (JSON.parse(readFileSync(settingsFile, \"utf8\")) as { tools?: { enableHooks?: unknown } }).tools;\n } catch {}\n if (tools?.enableHooks === true) return { active: true };\n if (tools?.enableHooks === false)\n return { active: false, note: \"inactive: tools.enableHooks is false in settings.json\" };\n let version = \"\";\n try {\n version = execFileSync(\"gemini\", [\"--version\"], {\n encoding: \"utf8\",\n timeout: 4000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return {\n active: true,\n note: \"could not run `gemini --version`; hooks need tools.enableHooks on versions before 0.46\",\n };\n }\n const m = /(\\d+)\\.(\\d+)/.exec(version);\n if (m && (Number(m[1]) > 0 || Number(m[2]) >= 46)) return { active: true };\n return {\n active: false,\n note: `inactive: Gemini CLI ${version || \"?\"} runs hooks only with \"tools\": {\"enableHooks\": true} in settings.json`,\n };\n}\n\nexport const geminiCli: Adapter = {\n name: NAME,\n events: GEMINI_EVENTS,\n // ~/.gemini also belongs to Antigravity; Gemini CLI is here when its settings or its chat logs exist.\n detect: (env = process.env) => existsSync(settings(env)) || existsSync(path.join(geminiDir(env), \"tmp\")),\n configFiles: (env = process.env) => [settings(env)],\n install: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const r = installClaudeShaped(settings(env), NAME, eventsFor(opts.lean), cmd, OPTS);\n const a = geminiHooksActive(settings(env));\n return [a.note && !r.skipped ? { ...r, note: [r.note, a.note].filter(Boolean).join(\"; \") } : r];\n },\n uninstall: (env = process.env, opts: InstallOptions = {}) => [\n uninstallClaudeShaped(settings(env), GEMINI_EVENTS, { created: opts.created?.includes(settings(env)) }),\n ],\n installed: (cmd, env = process.env, opts: InstallOptions = {}) => {\n const state = installedClaudeShaped(settings(env), NAME, eventsFor(opts.lean), cmd, OPTS);\n const a = geminiHooksActive(settings(env));\n return [\n {\n file: settings(env),\n state: state === \"current\" && !a.active ? \"inactive\" : state,\n ...(a.note ? { note: a.note } : {}),\n },\n ];\n },\n\n fromHook(input: HookInput): HookResult | null {\n const event = input.argv[1] ?? \"\";\n let s: Record<string, unknown> = {};\n try {\n // A stdin that is JSON but not an object (`null`, a number) is no payload.\n const j: unknown = input.stdin ? JSON.parse(input.stdin) : {};\n if (j && typeof j === \"object\" && !Array.isArray(j)) s = j as Record<string, unknown>;\n } catch {}\n const id = s.session_id as string | undefined;\n if (!id) return null;\n const session: HookResult[\"session\"] = { id: String(id), cwd: typeof s.cwd === \"string\" ? s.cwd : input.cwd };\n const tool = validTool(s.tool_name) ? s.tool_name : undefined;\n const ev = (type: string, data: Record<string, unknown>) => ({ type, data: prune(data), harnessEvent: event });\n const events: HookResult[\"events\"] = [];\n switch (event) {\n case \"SessionStart\":\n events.push(\n ev(\"session.started\", {\n source:\n typeof s.source === \"string\" && [\"startup\", \"resume\", \"clear\"].includes(s.source) ? s.source : \"unknown\",\n }),\n );\n break;\n case \"BeforeAgent\":\n events.push(\n ev(\"turn.started\", { prompt_chars: typeof s.prompt === \"string\" ? [...s.prompt].length : undefined }),\n );\n break;\n case \"BeforeTool\":\n if (tool) events.push(ev(\"tool.started\", { tool, input: s.tool_input }));\n break;\n case \"AfterTool\": {\n const resp = s.tool_response as { error?: unknown; llmContent?: unknown } | undefined;\n const err =\n resp && typeof resp === \"object\" && resp.error\n ? String(typeof resp.error === \"string\" ? resp.error : JSON.stringify(resp.error)).slice(0, 2000)\n : undefined;\n if (tool)\n events.push(\n ev(\"tool.ended\", {\n tool,\n ok: !err,\n error: err,\n input: s.tool_input,\n output: resp?.llmContent ?? s.tool_response,\n }),\n );\n break;\n }\n case \"Notification\":\n events.push(\n ev(\"attention.needed\", {\n attention_id: `notif-${Date.now()}`,\n kind: s.notification_type === \"ToolPermission\" ? \"permission\" : \"question\",\n message: typeof s.message === \"string\" ? s.message.slice(0, 200) : undefined,\n }),\n );\n break;\n case \"AfterAgent\":\n events.push(ev(\"turn.ended\", { reason: \"stop\" }));\n break;\n case \"PreCompress\":\n events.push(ev(\"context.compacted\", { trigger: s.trigger === \"manual\" ? \"manual\" : \"auto\" }));\n break;\n case \"SessionEnd\":\n events.push(\n ev(\"session.ended\", {\n reason:\n s.reason === \"clear\" || s.reason === \"logout\" || s.reason === \"exit\"\n ? s.reason\n : s.reason === \"prompt_input_exit\"\n ? \"exit\"\n : \"other\",\n }),\n );\n break;\n default:\n return null;\n }\n const r: HookResult = { session, events, hints: {} };\n if (typeof s.transcript_path === \"string\") r.transcript = s.transcript_path;\n return r;\n },\n\n readTranscript(file, fromLine) {\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return { turns: [], line: fromLine };\n }\n return readGemini(text.split(\"\\n\"), fromLine);\n },\n\n facts(_session, transcript): SessionFacts {\n const out: SessionFacts = {};\n if (!transcript) return out;\n const { head, tail } = ends(transcript, 64 * 1024, 64 * 1024);\n const H = parseLines(head);\n const T = parseLines(tail);\n const first = H.find((j) => j.type === \"user\");\n const raw = first ? (first.content ?? first.message ?? first.text) : undefined;\n const text = typeof raw === \"string\" ? raw.trim() : \"\";\n if (text) {\n const line = text.split(\"\\n\")[0] as string; // trimmed, so its first line is its first non-blank one\n out.title = line.length > 80 ? `${line.slice(0, 80).replace(/\\s+\\S*$/, \"\")}\u2026` : line;\n out.title_source = \"first-ask\";\n }\n const times = H.concat(T)\n .map((j) => Date.parse(String(j.timestamp ?? \"\")))\n .filter((n) => n > 0);\n if (times.length) {\n out.started_at = Math.min(...times);\n out.last_at = Math.max(...times);\n }\n return out;\n },\n\n backfill: () => [], // chat logs are keyed by a project hash, not a session id we can name; the first hook of a resumed session reports it\n};\n\nfunction prune<T extends Record<string, unknown>>(o: T): T {\n for (const k of Object.keys(o)) if (o[k] === undefined) delete o[k];\n return o;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The registry: the only place that lists vendors. A new harness is one file here\n// plus its fixtures and its row in spec/ADAPTERS.md.\nimport { acpHarnesses } from \"./acp-control.js\";\nimport { antigravity } from \"./antigravity.js\";\nimport { findAgy } from \"./antigravity-control.js\";\nimport { claudeCode } from \"./claude-code.js\";\nimport { findClaude } from \"./claude-code-control.js\";\nimport { codex } from \"./codex.js\";\nimport { findCodex } from \"./codex-control.js\";\nimport { devin } from \"./devin.js\";\nimport { geminiCli } from \"./gemini-cli.js\";\nimport type { Adapter } from \"./types.js\";\n\nexport const ADAPTERS: readonly Adapter[] = [claudeCode, codex, geminiCli, antigravity, devin];\nexport const adapterByName = (name: string): Adapter | undefined => ADAPTERS.find((a) => a.name === name);\nexport * as acpControl from \"./acp-control.js\";\nexport { AG_STALE_PRETOOL, antigravityAnswer } from \"./antigravity.js\";\nexport * as antigravityControl from \"./antigravity-control.js\";\nexport { claudeAccounts, claudeDirs, notClaudeCode } from \"./claude-code.js\";\nexport * as claudeControl from \"./claude-code-control.js\";\nexport * as codexControl from \"./codex-control.js\";\nexport { DEVIN_EVENTS, devinConfigDir, devinDataDir, readDevinChain } from \"./devin.js\";\nexport {\n deniedNote,\n JOB_TIMEOUT_MS,\n jobEnv,\n type Login,\n type Reading,\n type RunOptions,\n type RunResult,\n runHeadless,\n} from \"./headless.js\";\n\n/** How many harnesses a pairing request or a hello lists at most (control-pair.json,\n * control-hello.json). */\nexport const HELLO_HARNESSES_MAX = 20;\n\n/** The harnesses a control daemon here can drive headlessly (CONTROL.md \u00A76): each whose\n * CLI is installed on this machine, and every ACP agent that is. What `control pair`\n * and every hello advertise: the three with their own drivers first, then the ACP\n * agents in the registry's order, at most HELLO_HARNESSES_MAX of them. */\nexport function drivableHarnesses(env: NodeJS.ProcessEnv = process.env): string[] {\n return [\n ...(findClaude(env) ? [\"claude-code\"] : []),\n ...(findCodex(env) ? [\"codex\"] : []),\n ...(findAgy(env) ? [\"antigravity\"] : []),\n ...acpHarnesses(env),\n ].slice(0, HELLO_HARNESSES_MAX);\n}\nexport type {\n Adapter,\n AdapterEvent,\n BackfillRow,\n FactsState,\n HookCommand,\n HookInput,\n HookResult,\n InstallReport,\n SessionFacts,\n TranscriptRead,\n Turn,\n} from \"./types.js\";\nexport { antigravity, claudeCode, codex, devin, geminiCli };\n", "// SPDX-License-Identifier: Apache-2.0\n// ~/.config/sessionpipe/config.json, mode 0600: the machine's name, the sinks with\n// their tier and token, per-harness switches, the update check.\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { configFile } from \"./paths.js\";\nimport type { Tier } from \"./types.js\";\n\nexport interface SinkConfig {\n name: string;\n /** https://\u2026, file:PATH, stdout, otlp:URL */\n url: string;\n tier: Tier;\n pii?: boolean;\n /** @deprecated Never set: control is per machine (spec/CONTROL.md \u00A72). Kept so an\n * older config still reads. */\n control?: boolean;\n token?: string;\n /** whsec_\u2026 for Standard Webhooks signatures. */\n secret?: string;\n /** The token (and secret) live in this store instead of in this file; the client\n * reads them from it when it sends. */\n token_in?: \"keychain\" | \"secret-service\";\n /** Learned from the receiver's well-known file; re-read daily. */\n max_tier?: Tier;\n well_known_at?: string;\n paused?: string;\n}\n\nexport interface Config {\n machine?: string;\n sinks: SinkConfig[];\n harnesses: Record<string, { enabled?: boolean; created?: string[] }>;\n update_check?: boolean;\n keep_days?: number;\n}\n\nexport const DEFAULT_CONFIG: Config = { sinks: [], harnesses: {}, update_check: true, keep_days: 30 };\n\nexport function readConfig(file: string = configFile()): Config {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as Partial<Config>;\n return {\n ...DEFAULT_CONFIG,\n ...j,\n sinks: Array.isArray(j.sinks) ? j.sinks : [],\n harnesses: j.harnesses && typeof j.harnesses === \"object\" ? j.harnesses : {},\n };\n } catch {\n return { ...DEFAULT_CONFIG, sinks: [], harnesses: {} };\n }\n}\n\nexport function writeConfig(c: Config, file: string = configFile()): void {\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n writeFileSync(file, `${JSON.stringify(c, null, 2)}\\n`, { mode: 0o600 });\n if (process.platform !== \"win32\" && existsSync(file)) {\n try {\n chmodSync(file, 0o600);\n } catch {}\n }\n}\n\n/** The machine's name: what the person configured, else the hostname without a\n * local suffix. Never guessed from anything else (a hand-typed name once linked 64\n * versions to nothing). */\nexport function machineName(c: Config, hostname: string): string {\n if (c.machine) return String(c.machine).slice(0, 80);\n return hostname.replace(/\\.(local|lan|home)$/i, \"\");\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// ULID: 48-bit ms timestamp + 80 random bits, Crockford base32. Monotonic within a\n// process so two events in the same millisecond still sort in emit order.\nimport { randomBytes } from \"node:crypto\";\n\nconst ALPHABET = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\nlet lastTime = 0;\nlet lastRand: number[] = [];\n\nfunction encodeTime(t: number): string {\n let out = \"\";\n let n = t;\n for (let i = 0; i < 10; i++) {\n out = ALPHABET[n % 32] + out;\n n = Math.floor(n / 32);\n }\n return out;\n}\n\nexport function ulid(now: number = Date.now()): string {\n if (now === lastTime) {\n // increment the random part\n for (let i = lastRand.length - 1; i >= 0; i--) {\n const v = (lastRand[i] as number) + 1;\n if (v < 32) {\n lastRand[i] = v;\n break;\n }\n lastRand[i] = 0;\n }\n } else {\n lastTime = now;\n lastRand = Array.from(randomBytes(16), (b) => b % 32);\n }\n return encodeTime(now) + lastRand.map((v) => ALPHABET[v]).join(\"\");\n}\n\nexport const isUlid = (s: string): boolean => /^[0-9A-HJKMNP-TV-Z]{26}$/.test(s);\n", "// SPDX-License-Identifier: Apache-2.0\n// From an adapter's output to a protocol event: id, time, the full session block\n// as known now, and the raw (tier 3) data. Filtering per sink happens later.\nimport type { AdapterEvent } from \"./adapters/types.js\";\nimport type { Event, Session } from \"./types.js\";\nimport { ulid } from \"./ulid.js\";\n\nexport interface EventContext {\n harness: { name: string; version?: string };\n session: Session;\n now?: number;\n}\n\nexport function makeEvent(a: AdapterEvent, ctx: EventContext): Event {\n const now = ctx.now ?? Date.now();\n const harness: Event[\"harness\"] = { name: ctx.harness.name, event: a.harnessEvent };\n if (ctx.harness.version) harness.version = ctx.harness.version;\n return {\n protocol: 1,\n id: ulid(now),\n type: a.type,\n time: new Date(now).toISOString(),\n tier: 3,\n harness,\n session: ctx.session,\n privacy: { rulesets: [], pii: false },\n data: a.data,\n };\n}\n", "// SPDX-License-Identifier: Apache-2.0\nimport type { Adapter, HookInput, HookResult } from \"./adapters/types.js\";\n\n/** PROTOCOL.md \u00A73 `launched_by`: a launcher that starts a session for another one (a\n * script running `claude -p`) names itself here as `<harness>:<id>`, and the hook\n * carries it along. */\nexport const LAUNCHED_BY_ENV = \"SESSIONPIPE_LAUNCHED_BY\";\nconst LAUNCHED_BY = /^[a-z][a-z0-9-]{0,39}:[A-Za-z0-9._:-]{1,128}$/;\n\n/** The launcher the environment names, or nothing when it is absent or malformed. */\nexport function launchedBy(env: Record<string, string | undefined>): string | undefined {\n const v = env[LAUNCHED_BY_ENV]?.trim();\n return v && LAUNCHED_BY.test(v) ? v : undefined;\n}\n\n/** An adapter's reading of a hook, plus what every harness shares: the launcher, unless\n * the harness gave the session a parent of its own (a subagent's launcher is its parent)\n * or the value names the session itself (a launcher that forgot to reset it). */\nexport function readHook(adapter: Adapter, input: HookInput): HookResult | null {\n const r = adapter.fromHook(input);\n if (r && !r.session.parent_id) {\n const launcher = launchedBy(input.env);\n if (launcher && launcher !== `${adapter.name}:${r.session.id}`) r.session.launched_by = launcher;\n }\n return r;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The outbox: append-only JSONL per (harness, session) under\n// <state>/outbox/<harness>/<session>.jsonl, a per-session seq counter, a per-sink\n// cursor that moves only when the sink acknowledged, and a per-session lock so two\n// workers never interleave. Never lose, never duplicate.\nimport {\n appendFileSync,\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readdirSync,\n readFileSync,\n readSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport { safeId } from \"./paths.js\";\nimport type { Event } from \"./types.js\";\n\nexport interface OutboxRef {\n harness: string;\n session: string;\n}\n\nconst READ_CHUNK = 1024 * 1024;\nconst READ_MAX = 8 * 1024 * 1024;\n\nexport class Outbox {\n constructor(readonly root: string) {}\n\n dir(harness: string): string {\n return path.join(this.root, \"outbox\", safeId(harness));\n }\n file(ref: OutboxRef): string {\n return path.join(this.dir(ref.harness), `${safeId(ref.session)}.jsonl`);\n }\n private seqFile(ref: OutboxRef): string {\n return path.join(this.dir(ref.harness), `${safeId(ref.session)}.seq`);\n }\n\n /** The next seq for a session, persisted (survives a hibernating machine and a\n * restart; an in-memory counter would restart at 0 and collide). */\n nextSeq(ref: OutboxRef): number {\n const f = this.seqFile(ref);\n let n = -1;\n try {\n const t = readFileSync(f, \"utf8\").trim();\n if (/^\\d+$/.test(t)) n = Number(t);\n } catch {}\n // A missing or unreadable counter (a crash between truncate and write leaves it\n // empty) with an existing outbox: recover from the file's last line.\n if (n < 0) n = this.lastSeqInFile(ref) + 1;\n mkdirSync(path.dirname(f), { recursive: true, mode: 0o700 });\n writeFileSync(f, String(n + 1), { mode: 0o600 });\n return n;\n }\n\n private lastSeqInFile(ref: OutboxRef): number {\n const f = this.file(ref);\n if (!existsSync(f)) return -1;\n const lines = readFileSync(f, \"utf8\").trim().split(\"\\n\");\n for (let i = lines.length - 1; i >= 0; i--) {\n try {\n const j = JSON.parse(lines[i] as string) as Event;\n if (typeof j.session?.seq === \"number\") return j.session.seq;\n } catch {}\n }\n return -1;\n }\n\n append(ref: OutboxRef, events: Event[]): void {\n if (!events.length) return;\n mkdirSync(this.dir(ref.harness), { recursive: true, mode: 0o700 });\n appendFileSync(this.file(ref), `${events.map((e) => JSON.stringify(e)).join(\"\\n\")}\\n`, { mode: 0o600 });\n }\n\n /** Every session file, newest first. */\n sessions(): OutboxRef[] {\n const out: { ref: OutboxRef; mtime: number }[] = [];\n const base = path.join(this.root, \"outbox\");\n if (!existsSync(base)) return [];\n for (const h of readdirSync(base)) {\n const d = path.join(base, h);\n let names: string[] = [];\n try {\n names = readdirSync(d).filter((n) => n.endsWith(\".jsonl\"));\n } catch {\n continue;\n }\n for (const n of names) {\n try {\n out.push({ ref: { harness: h, session: n.slice(0, -6) }, mtime: statSync(path.join(d, n)).mtimeMs });\n } catch {}\n }\n }\n return out.sort((a, b) => b.mtime - a.mtime).map((x) => x.ref);\n }\n\n /** Read events after byte offset `from`; returns them and the new offset. Lines\n * are read whole; a partial trailing line (a write in progress) is left. A read\n * takes READ_CHUNK bytes at a time, not the rest of the file: a session file grows\n * to tens of MB and a drain takes it in batches of 50. It reads on until the batch\n * is full or the file ends, so lines that parse to nothing never stop a drain; one\n * line longer than the chunk gets a larger one, up to READ_MAX. */\n read(ref: OutboxRef, from: number, maxEvents = 500): { events: Event[]; offset: number } {\n const f = this.file(ref);\n if (!existsSync(f)) return { events: [], offset: from };\n const size = statSync(f).size;\n if (from >= size) return { events: [], offset: from };\n const fd = openSync(f, \"r\");\n try {\n const events: Event[] = [];\n let offset = from;\n let chunk = READ_CHUNK;\n while (events.length < maxEvents && offset < size) {\n const buf = Buffer.alloc(Math.min(size - offset, chunk));\n const n = readSync(fd, buf, 0, buf.length, offset);\n const text = buf.subarray(0, n).toString(\"utf8\");\n let pos = 0;\n let used = 0;\n while (events.length < maxEvents) {\n const nl = text.indexOf(\"\\n\", pos);\n if (nl < 0) break;\n const line = text.slice(pos, nl);\n pos = nl + 1;\n used += Buffer.byteLength(line, \"utf8\") + 1;\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as Event);\n } catch {}\n }\n offset += used;\n if (used) continue;\n // No whole line in this chunk: a line longer than it, or a write in progress.\n if (offset + n >= size || chunk >= READ_MAX) break;\n chunk *= 2;\n }\n return { events, offset };\n } finally {\n closeSync(fd);\n }\n }\n\n /** Files older than `days` are pruned; the cursor files with them. */\n prune(days: number, now = Date.now()): number {\n let n = 0;\n const cutoff = now - days * 86_400_000;\n for (const ref of this.sessions()) {\n const f = this.file(ref);\n try {\n if (statSync(f).mtimeMs < cutoff) {\n unlinkSync(f);\n try {\n unlinkSync(this.seqFile(ref));\n } catch {}\n n++;\n }\n } catch {}\n }\n return n;\n }\n\n delete(ref: OutboxRef): void {\n for (const f of [this.file(ref), this.seqFile(ref)]) {\n try {\n unlinkSync(f);\n } catch {}\n }\n }\n}\n\n/** Per-sink cursor: byte offset per session file, moved only on a 2xx. */\nexport class Cursors {\n constructor(\n readonly root: string,\n readonly sink: string,\n ) {}\n private file(): string {\n return path.join(this.root, \"cursors\", `${safeId(this.sink)}.json`);\n }\n read(): Record<string, number> {\n try {\n return JSON.parse(readFileSync(this.file(), \"utf8\")) as Record<string, number>;\n } catch {\n return {};\n }\n }\n write(c: Record<string, number>): void {\n const f = this.file();\n mkdirSync(path.dirname(f), { recursive: true, mode: 0o700 });\n const tmp = `${f}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(c), { mode: 0o600 });\n renameSync(tmp, f);\n }\n key(ref: OutboxRef): string {\n return `${ref.harness}/${ref.session}`;\n }\n}\n\n/** A lock per session so two workers never interleave. Stale once the worker that\n * took it is gone (its 15 s deadline ends it without a release), or after 5 min. */\nexport function takeLock(root: string, ref: OutboxRef, staleMs = 5 * 60_000): (() => void) | null {\n return takeNamedLock(root, `${safeId(ref.harness)}-${safeId(ref.session)}`, staleMs);\n}\n\n/** A named lock under <root>/locks, held by one process at a time: the file names\n * its pid. Stale once that process is gone, or after `staleMs`. */\nexport function takeNamedLock(root: string, name: string, staleMs = 5 * 60_000): (() => void) | null {\n const dir = path.join(root, \"locks\");\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n const f = path.join(dir, `${name}.lock`);\n try {\n if (Date.now() - statSync(f).mtimeMs > staleMs || !processAlive(Number(readFileSync(f, \"utf8\")))) unlinkSync(f);\n else return null;\n } catch {}\n try {\n writeFileSync(f, String(process.pid), { flag: \"wx\" });\n } catch {\n return null;\n }\n return () => {\n try {\n unlinkSync(f);\n } catch {}\n };\n}\n\n/** Whether the process a lock or a claimed job names is still running. A pid that\n * can't be read counts as running: the age rule decides then. */\nexport function processAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return true;\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n return (e as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// pii@1 \u2014 an opt-in second pass that reduces identifiers (spec/PRIVACY.md \u00A72). It\n// does not promise anonymity; it removes the obvious.\nimport { createHash } from \"node:crypto\";\n\nexport const RULESET_PII = \"pii@1\";\n\nconst EMAIL = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g;\n/** E.164 and common national forms: an optional +, 7\u201315 digits with separators,\n * optional area-code parentheses. A version number (22.23.1) or an IP never matches:\n * the run must not sit between dots, and needs \u2265 7 digits. */\nconst PHONE = /(?<![\\w.])(?:\\+\\d{1,3}[ .-]?)?(?:\\(\\d{2,4}\\)[ .-]?)?\\d{2,4}(?:[ .-]?\\d{2,4}){1,3}(?!\\w)/g;\n\nfunction looksPhone(s: string): boolean {\n const digits = s.replace(/\\D/g, \"\");\n if (digits.length < 7 || digits.length > 15) return false;\n // \"port 8891, pr 12345\": a bare run with no separator or + is a number, not a phone.\n if (!/[+() .-]/.test(s)) return false;\n // \"22.23.1\", \"185.199.108.153\": dots alone are a version or an address.\n if (!/[+() -]/.test(s)) return false;\n return true;\n}\n\n/** Replace emails and phone numbers, and write `home` as `~`. */\nexport function reducePii(text: string, home?: string): string {\n if (!text) return text;\n let out = text.replace(EMAIL, \"[email]\");\n out = out.replace(PHONE, (m) => (looksPhone(m) ? \"[phone]\" : m));\n if (home) {\n const h = home.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n out = out.replace(new RegExp(`(?<![A-Za-z0-9_])${h}(?=/|$|\\\\s|[\"'\\`])`, \"g\"), \"~\");\n }\n return out;\n}\n\n/** The machine's name under pii@1: the first 8 hex of its SHA-256. */\nexport function hashMachine(name: string): string {\n return createHash(\"sha256\").update(name).digest(\"hex\").slice(0, 8);\n}\n\n/** Apply pii@1 to every string in a value; `home` becomes `~`. */\nexport function reducePiiDeep<T>(v: T, home?: string): T {\n if (typeof v === \"string\") return reducePii(v, home) as T;\n if (Array.isArray(v)) return v.map((x) => reducePiiDeep(x, home)) as T;\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v as Record<string, unknown>)) out[k] = reducePiiDeep(x, home);\n return out as T;\n }\n return v;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// secrets@1 \u2014 credentials out of every string, on the person's machine, before an\n// event reaches the outbox. Ported from spacesheep-cli lib/redact.js (Michael\n// Makarov, MIT \u2192 Apache-2.0, see NOTICE). The ruleset is defined in\n// spec/PRIVACY.md \u00A72 and pinned by conformance/redaction/secrets.json.\n//\n// Every pattern is linear: bounded repetition, no nested quantifiers. The\n// adversarial vectors (password_ \u00D7 5000, a 50 000-space run) pin that.\n\nexport const RULESET_SECRETS = \"secrets@1\";\nexport const REDACTED = \"[redacted]\";\n\n/** Token formats that are a credential by their shape alone. Each is anchored on a\n * vendor prefix, so a commit sha or a UUID never matches. */\nconst TOKEN_PATTERNS: RegExp[] = [\n /-----BEGIN [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----[\\s\\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----|$)/g,\n /\\b(?:AKIA|ASIA|ABIA|ACCA)[0-9A-Z]{16}\\b/g, // AWS access key id\n /\\bgh[pousr]_[A-Za-z0-9]{30,}\\b/g, // GitHub\n /\\bgithub_pat_[A-Za-z0-9_]{30,}\\b/g,\n /\\bglpat-[A-Za-z0-9_-]{20,}\\b/g, // GitLab\n /\\bxox[abposre]-[A-Za-z0-9-]{10,}\\b/g, // Slack\n /\\bhttps:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Za-z0-9/_-]+/g,\n /\\bhttps:\\/\\/(?:ptb\\.|canary\\.)?discord(?:app)?\\.com\\/api\\/webhooks\\/[0-9]+\\/[A-Za-z0-9_-]+/g,\n /\\bsk-(?:ant-|proj-|svcacct-|admin-|or-v1-)?[A-Za-z0-9_-]{20,}\\b/g, // Anthropic, OpenAI, DeepSeek, OpenRouter\n /\\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\\b/g, // Stripe secret / restricted\n /\\bwhsec_[A-Za-z0-9+/=]{20,}/g, // Stripe / Svix / Standard Webhooks secret\n /\\bAIza[0-9A-Za-z_-]{35}\\b/g, // Google API key\n /\\bya29\\.[0-9A-Za-z_-]{20,}/g, // Google OAuth access token\n /\\b1\\/\\/0[0-9A-Za-z_-]{30,}/g, // Google OAuth refresh token\n /\\bGOCSPX-[0-9A-Za-z_-]{20,}/g, // Google OAuth client secret\n /\\bxai-[A-Za-z0-9]{30,}\\b/g,\n /\\bgsk_[A-Za-z0-9]{30,}\\b/g, // Groq\n /\\bpplx-[A-Za-z0-9]{30,}\\b/g, // Perplexity\n /\\bhf_[A-Za-z0-9]{30,}\\b/g, // Hugging Face\n /\\bpcsk_[A-Za-z0-9_]{30,}\\b/g, // Pinecone\n /\\bnpm_[A-Za-z0-9]{30,}\\b/g,\n /\\bpypi-[A-Za-z0-9_-]{50,}/g,\n /\\bSG\\.[A-Za-z0-9_-]{16,}\\.[A-Za-z0-9_-]{16,}/g, // SendGrid\n /\\bshp(?:at|ss|ca|pa)_[a-fA-F0-9]{32}\\b/g, // Shopify\n /\\bdop_v1_[a-f0-9]{64}\\b/g, // DigitalOcean\n /\\b(?:lin_api|lin_oauth)_[A-Za-z0-9]{30,}\\b/g, // Linear\n /\\b(?:ntn|secret)_[A-Za-z0-9]{40,}\\b/g, // Notion\n /\\bsbp_[a-f0-9]{40}\\b/g, // Supabase\n /\\bfigd_[A-Za-z0-9_-]{30,}/g, // Figma\n /\\bdp\\.(?:pt|st|sa|ct)\\.[A-Za-z0-9]{30,}/g, // Doppler\n /\\bgrn_[A-Za-z0-9_-]{20,}/g, // Granola\n /\\bss_[a-f0-9]{32,}\\b/g, // spacesheep API keys\n /\\b[0-9]{8,10}:AA[A-Za-z0-9_-]{33}\\b/g, // Telegram bot token\n /\\beyJ[A-Za-z0-9_-]{10,}\\.eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}/g, // JWT\n];\n/** `scheme://user:password@host` \u2014 the password goes, the user and host stay. */\nconst URL_CREDENTIALS = /\\b([a-z][a-z0-9+.-]{1,20}:\\/\\/[^\\s:/@'\"`<>]{1,100}:)([^\\s@/'\"`<>]{1,200})(@)/gi;\n/** `Authorization: Bearer \u2026` / `Basic \u2026`, and a bare `Bearer <token>` in a curl line. */\nconst AUTH_HEADER = /\\b((?:Bearer|Basic|Token)\\s+)([A-Za-z0-9._~+/=-]{16,})/g;\n// The words that name a secret, in prose. `key` alone is too common (\"the key\n// point\"), so it only counts with a qualifier.\nconst SECRET_WORD =\n \"(?:pass(?:word|wd|phrase|code)?s?|pwd|secret(?:[ _-]?key)?s?|client[ _-]?secret|api[ _-]?keys?|apikeys?|access[ _-]?keys?|access[ _-]?tokens?|auth[ _-]?tokens?|refresh[ _-]?tokens?|private[ _-]?keys?|tokens?|credentials?|creds)\";\n/** Strict form: a NAME, an explicit separator (`=`, `:`, `=>`), a value. The name is\n * one flat run of identifier characters judged in code (isSecretName), never by a\n * nested pattern. Only a secret name goes on to consume its value \u2014 otherwise\n * `https:` would swallow the `?token=\u2026` behind it. */\nconst NAME_SEP = /(?<![A-Za-z0-9_])([A-Za-z][A-Za-z0-9_-]{1,79})([\"']?\\s{0,3}(?::=|=>|=|:)\\s{0,3})/g;\nconst VALUE = /\"([^\"\\n]{1,300})\"|'([^'\\n]{1,300})'|`([^`\\n]{1,300})`|([^\\s\"'`,;&)}\\]]{1,300})/y;\n\nfunction redactAssignments(text: string): string {\n let out = \"\";\n let last = 0;\n NAME_SEP.lastIndex = 0;\n for (let m = NAME_SEP.exec(text); m; m = NAME_SEP.exec(text)) {\n const name = m[1] as string;\n if (!isSecretName(name)) continue;\n VALUE.lastIndex = NAME_SEP.lastIndex;\n const v = VALUE.exec(text);\n if (!v) continue;\n const value = (v[1] ?? v[2] ?? v[3] ?? v[4]) as string;\n NAME_SEP.lastIndex = VALUE.lastIndex;\n if (isPlaceholder(value) || value.includes(REDACTED)) continue;\n // `max_tokens: 4096`, `input_tokens=12k` \u2014 a token COUNT, not a token.\n if (/tokens?$/i.test(name) && /^\\d+(?:[.,]\\d+)*[km]?$/i.test(value)) continue;\n const q = v[1] != null ? '\"' : v[2] != null ? \"'\" : v[3] != null ? \"`\" : \"\";\n out += text.slice(last, v.index) + q + REDACTED + q;\n last = VALUE.lastIndex;\n }\n return last ? out + text.slice(last) : text;\n}\n\n/** Is this identifier the name of a secret? `DB_PASSWORD`, `apiKey`, `client-secret`,\n * `AWS_SECRET_ACCESS_KEY`, `GITHUB_TOKEN`; an env-style `STRIPE_KEY` too. Not\n * `password_hash`, `tokenizer`, `sort_key`. */\nexport function isSecretName(name: string): boolean {\n if (/^[A-Z0-9_]+_KEY$/.test(name)) return true;\n const flat = name.toLowerCase().replace(/[_-]/g, \"\");\n return /(?:pass(?:word|wd|phrase|code)|pwd|secret|secretkey|secretaccesskey|clientsecret|apikey|accesskey|accesstoken|authtoken|refreshtoken|privatekey|token|credential|creds)s?$/.test(\n flat,\n );\n}\n\n/** Loose form: prose. \"password is Hunter2!\", \"the token was ghx\u2026\". Only a value\n * that looks generated counts, so \"the password is wrong\" passes untouched.\n * Whitespace runs are bounded so a long run can't make the match quadratic. */\nconst PROSE = new RegExp(\n `(\\\\b${SECRET_WORD}(?:[ \\\\t]{1,3}(?:is|was|=|:|to|as|of|for[ \\\\t]{1,3}\\\\S{1,40}[ \\\\t]{1,3}is))?[ \\\\t]{1,3})([\"'\\`]?)([^\\\\s\"'\\`]{6,200})\\\\2`,\n \"gi\",\n);\n\n/** A value that is plainly not the secret itself: a type, a variable, a template, an\n * already-redacted marker, an env lookup. */\nfunction isPlaceholder(v: string): boolean {\n const s = v.replace(/[.,;:!?]+$/, \"\");\n if (!s) return true;\n if (\n /^(?:string|number|boolean|bool|str|int|any|unknown|null|undefined|none|nil|true|false|optional|required|text|varchar|password|secret|token|env|string\\[\\]|object|bytes)$/i.test(\n s,\n )\n )\n return true;\n if (/^\\[?redacted\\]?$/i.test(s) || /^\\*+$/.test(s) || /^x{3,}$/i.test(s) || /^\\.{3}$|^\u2026$/.test(s)) return true;\n if (/^[<{$%]/.test(s)) return true; // <your-key>, ${VAR}, {{var}}, $VAR, %VAR%\n if (\n /^(?:process\\.env|env|os\\.environ|c\\.env|this\\.env|import\\.meta\\.env|getenv|config|settings|secrets|args|opts|options|req|request|body|params|input|data|user|self|this)\\b/i.test(\n s,\n )\n )\n return true;\n if (/^[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)+$/.test(s)) return true; // a member path: form.password\n if (/[(]/.test(s)) return true; // a call: hash(pw), getSecret()\n if (/^(?:your|my|the|a|an|some|new|old)[-_ ]/i.test(s)) return true; // your-api-key\n return false;\n}\n\n/** Does a prose value look like something generated, rather than an English word? */\nfunction looksSecret(v: string): boolean {\n const s = v.replace(/[.,;:!?)]+$/, \"\");\n if (s.length < 6) return false;\n if (isPlaceholder(s)) return false;\n if (/^https?:\\/\\//i.test(s)) return false; // a link, handled by URL_CREDENTIALS if it carries one\n if (/^[a-z]+(?:[-'][a-z]+)*$/.test(s)) return false; // a lowercase word\n if (/^[A-Z][a-z]+$/.test(s)) return false; // a capitalised word\n if (/^\\d+(?:[.,]\\d+)*[a-z%]*$/i.test(s)) return false; // a count: 4096, 128k, 3.5, 50%\n if (/^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/.test(s)) return false; // an env var's NAME\n const kinds = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^A-Za-z0-9]/].filter((r) => r.test(s)).length;\n return kinds >= 3 || (/[0-9]/.test(s) && /[A-Za-z]/.test(s));\n}\n\n/** Redact every credential in `text`. Returns the same string when there is none. */\nexport function redactSecrets(text: string): string {\n if (!text) return text;\n let out = text;\n for (const re of TOKEN_PATTERNS) out = out.replace(re, REDACTED);\n out = out.replace(URL_CREDENTIALS, (_m, head: string, _pw: string, at: string) => `${head}${REDACTED}${at}`);\n out = out.replace(AUTH_HEADER, (_m, head: string) => `${head}${REDACTED}`);\n out = redactAssignments(out);\n out = out.replace(PROSE, (m, head: string, q: string, v: string) =>\n !looksSecret(v) || v.includes(REDACTED) ? m : `${head}${q}${REDACTED}${q}`,\n );\n return out;\n}\n\n/** Did redaction change anything? */\nexport function hasSecret(text: string): boolean {\n return !!text && redactSecrets(text) !== text;\n}\n\n/** Redact every string in a JSON-able value (keys are left alone). */\nexport function redactDeep<T>(v: T): T {\n if (typeof v === \"string\") return redactSecrets(v) as T;\n if (Array.isArray(v)) return v.map(redactDeep) as T;\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v as Record<string, unknown>)) out[k] = redactDeep(x);\n return out as T;\n }\n return v;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// filter(event, tier, pii): the pure function every sink runs an event through.\n// Removes by ALLOWLIST per type and tier (spec/PRIVACY.md \u00A71), redacts every string\n// above tier 0 with secrets@1, and runs pii@1 when asked. Returns null when the\n// type is not carried at the tier. The conformance runner runs the same function.\nimport type { Event, Tier } from \"../types.js\";\nimport { hashMachine, RULESET_PII, reducePiiDeep } from \"./pii.js\";\nimport { RULESET_SECRETS, redactDeep } from \"./secrets.js\";\n\n/** The lowest tier that carries each known type (kept in step with schema/v1.ts). */\nexport const TYPE_TIER: Record<string, Tier> = {\n \"session.started\": 0,\n \"session.heartbeat\": 0,\n \"session.ended\": 0,\n \"session.backfill\": 0,\n \"session.forgotten\": 0,\n \"turn.started\": 0,\n \"turn.ended\": 0,\n \"turn.transcript\": 2,\n \"turn.progress\": 2,\n \"tool.started\": 1,\n \"tool.ended\": 1,\n \"files.changed\": 1,\n \"attention.needed\": 0,\n \"attention.cleared\": 0,\n \"subagent.started\": 1,\n \"subagent.ended\": 1,\n \"context.compacted\": 1,\n native: 3,\n};\n\n/** data keys allowed per type at tier N (cumulative: tier 1 includes tier 0's). */\nconst DATA_ALLOW: Record<string, Partial<Record<Tier, string[]>>> = {\n \"session.started\": { 0: [\"source\"] },\n \"session.heartbeat\": { 0: [] },\n \"session.ended\": { 0: [\"reason\"] },\n \"session.backfill\": { 0: [\"started_at\", \"last_at\", \"turns\"] },\n \"session.forgotten\": { 0: [] },\n \"turn.started\": { 0: [\"turn_id\", \"submitted_by\", \"injected\"], 1: [\"prompt_chars\"] },\n \"turn.ended\": { 0: [\"turn_id\", \"reason\", \"ms\", \"background\"], 1: [\"error\"] },\n \"turn.transcript\": { 2: [\"turn\", \"user\", \"assistant\", \"at\"] },\n \"turn.progress\": { 2: [\"turn\", \"user\", \"assistant\", \"at\"] },\n \"tool.started\": { 1: [\"tool\", \"call_id\", \"turn_id\", \"agent_id\"], 3: [\"input\"] },\n \"tool.ended\": { 1: [\"tool\", \"call_id\", \"turn_id\", \"agent_id\", \"ms\", \"ok\", \"error\"], 3: [\"input\", \"output\"] },\n \"files.changed\": { 1: [\"paths\"] },\n \"attention.needed\": { 0: [\"attention_id\", \"kind\"], 1: [\"tool\", \"message\"] },\n \"attention.cleared\": { 0: [\"attention_id\", \"how\"] },\n \"subagent.started\": { 1: [\"agent_id\", \"agent_type\"] },\n \"subagent.ended\": { 1: [\"agent_id\", \"agent_type\"] },\n \"context.compacted\": { 1: [\"trigger\"] },\n};\n\nconst SESSION_ALLOW = [\n \"id\",\n \"seq\",\n \"machine\",\n \"cwd\",\n \"repo\",\n \"branch\",\n \"model\",\n \"title\",\n \"title_source\",\n \"url\",\n \"account_id\",\n \"attended\",\n \"parent_id\",\n \"launched_by\",\n];\nconst MAX_SIDE = 20_000;\nconst MAX_IO = 64 * 1024;\n\nfunction allowedKeys(type: string, tier: Tier): string[] | null {\n const table = DATA_ALLOW[type];\n if (!table) return null; // unknown type: kept whole (receivers keep extra keys), redacted\n const out: string[] = [];\n for (let t = 0; t <= tier; t++) for (const k of table[t as Tier] ?? []) out.push(k);\n return out;\n}\n\nfunction cap(v: unknown, max: number): unknown {\n if (typeof v === \"string\") return v.length > max ? `${v.slice(0, max)}\u2026` : v;\n if (v && typeof v === \"object\") {\n const s = JSON.stringify(v);\n return s.length > max ? `${s.slice(0, max)}\u2026` : v;\n }\n return v;\n}\n\n/** At most `max` characters, keeping the end: an ellipsis, then the last max \u2212 1. */\nexport function capTail(v: string, max: number): string {\n return v.length > max ? `\u2026${v.slice(v.length - max + 1)}` : v;\n}\n\nexport interface FilterOptions {\n /** The person's home directory, for pii@1's `~` rewrite. */\n home?: string;\n}\n\n/** The event as a sink at `tier` may see it, or null when the type is above the tier. */\nexport function filterEvent(event: Event, tier: Tier, pii: boolean, opts: FilterOptions = {}): Event | null {\n const minTier = TYPE_TIER[event.type];\n if (minTier !== undefined && minTier > tier) return null;\n\n const session: Record<string, unknown> = {};\n for (const k of SESSION_ALLOW)\n if (event.session[k as keyof typeof event.session] !== undefined)\n session[k] = event.session[k as keyof typeof event.session];\n\n let data: Record<string, unknown> = {};\n const keys = allowedKeys(event.type, tier);\n if (keys === null) data = { ...event.data };\n else for (const k of keys) if (event.data[k] !== undefined) data[k] = event.data[k];\n if (typeof data.user === \"string\") data.user = cap(data.user, MAX_SIDE);\n // A turn still running is read for where it is now: its reply keeps the end.\n if (typeof data.assistant === \"string\")\n data.assistant = event.type === \"turn.progress\" ? capTail(data.assistant, MAX_SIDE) : cap(data.assistant, MAX_SIDE);\n if (data.input !== undefined) data.input = cap(data.input, MAX_IO);\n if (data.output !== undefined) data.output = cap(data.output, MAX_IO);\n if (typeof data.message === \"string\") data.message = cap(data.message, 200);\n\n const rulesets: string[] = [];\n let out: Event = { ...event, tier, session: session as Event[\"session\"], data, privacy: { rulesets, pii } };\n if (tier > 0) {\n // Redact, then the caps above already applied: a cut before redaction could leave half a key.\n out = { ...out, session: redactDeep(out.session), data: redactDeep(out.data) };\n rulesets.push(RULESET_SECRETS);\n }\n if (pii) {\n const s = reducePiiDeep(out.session, opts.home) as Record<string, unknown>;\n if (typeof s.machine === \"string\") s.machine = hashMachine(s.machine);\n delete s.account_id;\n out = { ...out, session: s as Event[\"session\"], data: reducePiiDeep(out.data, opts.home) };\n rulesets.push(RULESET_PII);\n }\n out.privacy = { rulesets, pii };\n return out;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// A session's short id (spec/PROTOCOL.md \u00A73): the first 8 hex digits of\n// sha256(\"sessionpipe.session:\" + harness + \":\" + id). What a person reads in a log\n// line, a notification, a search box; derived, never sent. Not a prefix of the id\n// itself: Codex ids are time-ordered (UUIDv7), and two sessions started in the same\n// minute share their first eight characters.\nimport { createHash } from \"node:crypto\";\n\nexport function shortId(harness: string, id: string): string {\n return createHash(\"sha256\").update(`sessionpipe.session:${harness}:${id}`).digest(\"hex\").slice(0, 8);\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// file:PATH \u2014 append filtered events as JSONL. The zero-server sink.\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Event, Tier } from \"../types.js\";\nimport type { DeliveryResult, Sink } from \"./types.js\";\n\nexport class FileSink implements Sink {\n constructor(\n readonly name: string,\n readonly file: string,\n readonly tier: Tier,\n readonly pii: boolean,\n ) {}\n async send(events: Event[]): Promise<DeliveryResult> {\n try {\n mkdirSync(path.dirname(this.file), { recursive: true });\n appendFileSync(this.file, `${events.map((e) => JSON.stringify(e)).join(\"\\n\")}\\n`);\n return { ok: true, acknowledged: events.length, accepted: events.length, duplicates: 0, rejected: [] };\n } catch (e) {\n return { ok: false, acknowledged: 0, error: String((e as Error).message), action: \"retry\" };\n }\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// stdout \u2014 one JSON line per event to a writable (the worker's stdout is ignored\n// when spawned by a hook, so this sink is for `sessionpipe tail` and tests).\nimport type { Event, Tier } from \"../types.js\";\nimport type { DeliveryResult, Sink } from \"./types.js\";\n\nexport class StdoutSink implements Sink {\n constructor(\n readonly name: string,\n readonly tier: Tier,\n readonly pii: boolean,\n private readonly write: (line: string) => void = (l) => process.stdout.write(`${l}\\n`),\n ) {}\n async send(events: Event[]): Promise<DeliveryResult> {\n try {\n for (const e of events) this.write(JSON.stringify(e));\n return { ok: true, acknowledged: events.length, accepted: events.length, duplicates: 0, rejected: [] };\n } catch (e) {\n // A closed pipe (`sessionpipe tail | head`): a result, like every other sink.\n return { ok: false, acknowledged: 0, error: String((e as Error).message ?? e), action: \"retry\" };\n }\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The pure half of `sessionpipe connect`: which folders a machine allows sessions you\n// message to run in, when nobody said. Never the home folder or anything above it:\n// \"allow everything I own\" is not a default anyone should find out about later.\nimport path from \"node:path\";\n\n/** The home folder, or a folder that contains it (/, /Users), or the filesystem root. */\nexport function isBroad(dir: string, home: string): boolean {\n const d = path.resolve(dir);\n const h = path.resolve(home);\n if (d === path.parse(d).root) return true;\n // A resolved path ends with the separator only when it is the root, answered above.\n return d === h || h.startsWith(/* v8 ignore next */ d.endsWith(path.sep) ? d : d + path.sep);\n}\n\n// `parent` is a resolved, non-root folder (isBroad keeps the root out): it never ends with the separator.\nconst inside = (child: string, parent: string): boolean =>\n child !== parent && child.startsWith(/* v8 ignore next */ parent.endsWith(path.sep) ? parent : parent + path.sep);\n\nexport interface FolderChoice {\n folders: string[];\n /** Where they came from: the flags, the machine's own list, the folder this ran in,\n * the folders recent sessions ran in, or nowhere. */\n from: \"flags\" | \"existing\" | \"here\" | \"recent\" | \"none\";\n}\n\n/** `recent`: the folders this machine's sessions ran in, newest first. */\nexport function connectFolders(o: {\n cwd: string;\n home: string;\n flags: string[];\n existing: string[];\n recent: string[];\n exists?: (dir: string) => boolean;\n max?: number;\n}): FolderChoice {\n if (o.flags.length) return { folders: o.flags.map((d) => path.resolve(d)), from: \"flags\" };\n if (o.existing.length) return { folders: [], from: \"existing\" };\n if (!isBroad(o.cwd, o.home)) return { folders: [path.resolve(o.cwd)], from: \"here\" };\n const exists = o.exists ?? (() => true);\n const picked: string[] = [];\n for (const raw of o.recent) {\n if (!raw || !path.isAbsolute(raw)) continue;\n const d = path.resolve(raw);\n if (isBroad(d, o.home) || picked.includes(d) || !exists(d)) continue;\n if (picked.some((p) => inside(d, p))) continue;\n // A wider folder replaces the narrower ones already picked under it.\n for (let i = picked.length - 1; i >= 0; i--) if (inside(picked[i] as string, d)) picked.splice(i, 1);\n picked.push(d);\n if (picked.length >= (o.max ?? 8)) break;\n }\n return picked.length ? { folders: picked, from: \"recent\" } : { folders: [], from: \"none\" };\n}\n\n/** The tier `connect` reports at: --tier when given; otherwise 2 (what a session board\n * needs: the asks and the answers, secrets removed), never lowering a sink set higher. */\nexport function connectTier(flag: string | undefined, current: number | undefined): 0 | 1 | 2 | 3 {\n if (flag !== undefined && flag !== \"\")\n return Math.max(0, Math.min(3, Math.trunc(Number(flag)) || 0)) as 0 | 1 | 2 | 3;\n return Math.max(2, Math.min(3, current ?? 0)) as 2 | 3;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The control daemon keeps its own copy current. About a minute after it starts, and\n// then once a day by the wall clock (state/control/update.json remembers the last\n// check, so a restart or a machine that slept doesn't ask twice in a day), it reads\n// npm's `latest`. When that is newer it waits until the daemon has nothing in hand \u2014\n// no message being delivered, no headless run or start, no held SDK session mid-turn,\n// no permission prompt open, no session on the machine mid-turn, no acks being sent \u2014\n// stops taking new messages, installs the release into the prefix it runs from\n// (update.ts), and restarts onto it:\n//\n// launchd / systemd exit UPDATE_EXIT; the service restarts it on the new code\n// (every plist and unit sessionpipe ever wrote restarts on a\n// non-zero exit).\n// anything else this process stops being the daemon and becomes its parent:\n// it runs the new `control run` as its child with the same env\n// and output, restarts it on UPDATE_EXIT, and exits with it\n// otherwise. Whatever waits on this process (a terminal, a\n// container's init, a setsid'd shell) keeps waiting.\n//\n// Off with SESSIONPIPE_NO_UPDATE_CHECK, `update_check: false` in config.json\n// (`sessionpipe update off`), or when the running copy isn't a global npm install.\nimport { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Config } from \"@sessionpipe/core\";\nimport { compareVersions, globalPrefix, isNewer, unwritable } from \"../update.js\";\nimport { controlState, writePrivate } from \"./store.js\";\n\n// The exit code a restart asks for, and the parent that answers it where no service\n// manager will, live in core (sessionpipe-core/version).\nexport { supervise, UPDATE_EXIT } from \"@sessionpipe/core/version\";\nexport const DAY_MS = 24 * 3600_000;\nconst LABEL = \"org.sessionpipe.control\";\nconst UNIT = \"sessionpipe-control.service\";\n\n/** What the daemon remembers about updating, in state/control/update.json. */\nexport interface UpdateRecord {\n /** The last time it asked npm, whatever the answer. */\n checked_at?: string;\n /** What npm said was `latest` then; null when the check failed. */\n latest?: string | null;\n error?: string | null;\n /** The version that checked. */\n running?: string;\n /** Why the daemon's auto-update is off, as the daemon sees it (its own env), or null. */\n off?: string | null;\n /** A newer release waiting for the daemon to be idle. */\n pending?: string | null;\n updated?: { from: string; to: string; at: string; ms: number } | null;\n failed?: { version: string; at: string; error: string } | null;\n}\n\nexport const updateFile = (env: NodeJS.ProcessEnv = process.env): string => path.join(controlState(env), \"update.json\");\n\nexport function readUpdate(file: string): UpdateRecord {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as UpdateRecord;\n return j && typeof j === \"object\" ? j : {};\n } catch {\n return {};\n }\n}\n\n/** Due when it never checked, last checked a day or more ago, or the clock went back. */\nexport function isDue(rec: UpdateRecord, now: number): boolean {\n const t = Date.parse(rec.checked_at ?? \"\");\n if (!Number.isFinite(t)) return true;\n if (t > now + 5 * 60_000) return true;\n return now - t >= DAY_MS;\n}\n\n/** Why auto-update is off for this copy, or null when it is on. */\nexport function autoUpdateOff(o: {\n env: NodeJS.ProcessEnv;\n config: Pick<Config, \"update_check\">;\n distDir: string;\n platform?: NodeJS.Platform;\n}): string | null {\n if (o.env.SESSIONPIPE_NO_UPDATE_CHECK) return \"SESSIONPIPE_NO_UPDATE_CHECK is set\";\n if (o.config.update_check === false) return \"update_check is false in config.json (`sessionpipe update on`)\";\n const prefix = globalPrefix(o.distDir, o.platform);\n if (!prefix) return \"this copy isn't a global npm install (npx, a checkout or a dev build)\";\n return unwritable(prefix, o.platform);\n}\n\n/** What `status` and `doctor` say about updating. */\nexport interface UpdateSummary {\n auto: boolean;\n /** Why updates are by hand only, or null. */\n off: string | null;\n last_check: string | null;\n latest: string | null;\n last_error: string | null;\n pending: string | null;\n updated: UpdateRecord[\"updated\"] | null;\n failed: UpdateRecord[\"failed\"] | null;\n}\n\nexport function updateSummary(o: {\n /** autoUpdateOff() for this copy, from this shell (its env aside: the daemon's counts). */\n off: string | null;\n paired: boolean;\n rec: UpdateRecord;\n}): UpdateSummary {\n const daemonEnv = o.rec.off?.startsWith(\"SESSIONPIPE_NO_UPDATE_CHECK\")\n ? \"SESSIONPIPE_NO_UPDATE_CHECK is set in the daemon's environment\"\n : null;\n const off =\n o.off ?? (o.paired ? daemonEnv : \"it runs in the control daemon, which isn't set up here (`sessionpipe connect`)\");\n return {\n auto: !off,\n off,\n last_check: o.rec.checked_at ?? null,\n latest: o.rec.latest ?? null,\n last_error: o.rec.error ?? null,\n pending: o.rec.pending ?? null,\n updated: o.rec.updated ?? null,\n failed: o.rec.failed ?? null,\n };\n}\n\nexport function ago(iso: string, now: number): string {\n const ms = now - Date.parse(iso);\n if (!Number.isFinite(ms)) return \"at an unreadable time\";\n if (ms < 90_000) return \"just now\";\n if (ms < 90 * 60_000) return `${Math.round(ms / 60_000)} min ago`;\n if (ms < 36 * 3600_000) return `${Math.round(ms / 3600_000)} h ago`;\n return `${Math.round(ms / DAY_MS)} days ago`;\n}\n\n/** One line: whether it's automatic, when it last looked, what it found. */\nexport function updateLine(s: UpdateSummary, now: number): string {\n const parts = [\n s.auto\n ? \"automatic (the control daemon checks npm once a day and installs when idle; `sessionpipe update off` stops it)\"\n : `not automatic: ${s.off}`,\n ];\n if (s.last_check)\n parts.push(\n s.last_error\n ? `last check ${ago(s.last_check, now)} failed: ${s.last_error}`\n : `last check ${ago(s.last_check, now)}: latest ${s.latest ?? \"?\"}`,\n );\n else if (s.auto) parts.push(\"not checked yet (a minute after the daemon starts)\");\n if (s.pending) parts.push(`${s.pending} waits for the daemon to be idle`);\n if (s.failed) parts.push(`installing ${s.failed.version} failed ${ago(s.failed.at, now)}: ${s.failed.error}`);\n else if (s.updated) parts.push(`updated ${s.updated.from} \u2192 ${s.updated.to} ${ago(s.updated.at, now)}`);\n return parts.join(\" \u00B7 \");\n}\n\nexport type RestartVia = \"launchd\" | \"systemd\" | \"supervisor\";\n\n/** Who restarts this process when it exits UPDATE_EXIT, or null when nobody will (it\n * then supervises the new daemon itself). A wrong \"nobody\" costs one extra process; a\n * wrong \"somebody\" would leave the machine without a daemon, so each answer is checked\n * against the process's own parentage \u2014 a variable inherited by a child of the daemon\n * (a session it started) never counts. */\nexport function restartVia(o: {\n env: NodeJS.ProcessEnv;\n platform: NodeJS.Platform;\n pid: number;\n ppid: number;\n /** /proc/self/cgroup (Linux). */\n cgroup?: () => string;\n}): RestartVia | null {\n const s = o.env.SESSIONPIPE_SERVICE ?? \"\";\n if (s.startsWith(\"supervisor:\") && s === `supervisor:${o.ppid}`) return \"supervisor\";\n if (o.platform === \"darwin\" && o.ppid === 1 && (s === \"launchd\" || o.env.XPC_SERVICE_NAME === LABEL))\n return \"launchd\";\n if (o.platform === \"linux\") {\n let cg = \"\";\n try {\n cg = (o.cgroup ?? (() => readFileSync(\"/proc/self/cgroup\", \"utf8\")))();\n } catch {}\n const inUnit = cg.split(\"\\n\").some((l) => l.endsWith(`/${UNIT}`) || l.includes(`/${UNIT}/`));\n const mainPid = !o.env.SYSTEMD_EXEC_PID || o.env.SYSTEMD_EXEC_PID === String(o.pid);\n if (inUnit && mainPid) return \"systemd\";\n }\n return null;\n}\n\n/** What the daemon offers the updater. */\nexport interface Quiescent {\n /** Null when nothing is in hand; otherwise what is. */\n busy(): string | null;\n /** Stop taking new messages (in-flight long-polls end); the receiver keeps them. */\n pauseIntake(): void;\n resumeIntake(): void;\n}\n\nexport interface UpdaterDeps {\n now: () => number;\n log: (line: string) => void;\n /** The running version. */\n version: string;\n file: string;\n /** Why it is off right now (re-read every tick: config.json may have changed). */\n off: () => string | null;\n latest: () => Promise<string>;\n /** The version of the copy on disk. */\n installed: () => Promise<string | null>;\n install: (version: string) => Promise<{ ok: true; ms: number; hooks?: string } | { ok: false; error: string }>;\n daemon: Quiescent;\n /** Stop the daemon and come back on the code on disk. Doesn't return in production. */\n restart: (from: string, to: string) => Promise<void>;\n firstCheckMs?: number;\n /** How often it looks at the clock; a check runs only when one is due. */\n tickMs?: number;\n idlePollMs?: number;\n}\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms).unref?.());\n\nexport class AutoUpdater {\n private first: NodeJS.Timeout | null = null;\n private every: NodeJS.Timeout | null = null;\n private stopped = false;\n private busyWith: Promise<void> | null = null;\n private lastOff: string | null | undefined = undefined;\n\n constructor(private readonly d: UpdaterDeps) {}\n\n start(): void {\n // A wait that a restart cut short is picked up again from `latest` by tick().\n if (this.record().pending) this.save({ pending: null });\n this.first = setTimeout(() => void this.tick(), this.d.firstCheckMs ?? 60_000);\n this.first.unref?.();\n // A look at the clock every ten minutes (one small file read): a machine that\n // sleeps catches up soon after it wakes, not up to an hour of awake time later.\n this.every = setInterval(() => void this.tick(), this.d.tickMs ?? 10 * 60_000);\n this.every.unref?.();\n }\n\n stop(): void {\n this.stopped = true;\n if (this.first) clearTimeout(this.first);\n if (this.every) clearInterval(this.every);\n }\n\n record(): UpdateRecord {\n return readUpdate(this.d.file);\n }\n\n private save(patch: Partial<UpdateRecord>): void {\n try {\n writePrivate(this.d.file, { ...readUpdate(this.d.file), ...patch });\n } catch {}\n }\n\n /** One look at the clock: check when a check is due and nothing is under way. */\n async tick(): Promise<void> {\n if (this.stopped || this.busyWith) return;\n const off = this.d.off();\n if (off !== this.lastOff) {\n if (off) this.d.log(`auto-update off: ${off}`);\n else if (this.lastOff) this.d.log(\"auto-update on\");\n this.lastOff = off;\n this.save({ off });\n }\n if (off) return;\n const rec = this.record();\n if (isDue(rec, this.d.now())) return this.check();\n // Not due, but the last check found a release this daemon never got to (it was\n // restarted while it waited to be idle): carry on. One that failed waits a day.\n const known = rec.latest;\n if (known && isNewer(known, this.d.version) && rec.failed?.version !== known)\n return this.guard(() => this.apply(known));\n }\n\n /** One update job at a time; whatever it throws is logged, never left unhandled. */\n private guard(job: () => Promise<void>): Promise<void> {\n if (this.busyWith) return this.busyWith;\n this.busyWith = job()\n .catch((e) => {\n if (!this.stopped) this.d.log(`update: ${String((e as Error)?.message || e)}`);\n })\n .finally(() => {\n this.busyWith = null;\n });\n return this.busyWith;\n }\n\n /** Ask npm now; when it has a newer release, install it once idle and restart. */\n check(): Promise<void> {\n return this.guard(async () => {\n const t0 = this.d.now();\n let latest: string;\n try {\n latest = await this.d.latest();\n } catch (e) {\n const error = String((e as Error)?.message || e).slice(0, 200);\n this.save({ checked_at: new Date(t0).toISOString(), latest: null, error, running: this.d.version });\n this.d.log(`update check: failed after ${this.d.now() - t0} ms: ${error}`);\n return;\n }\n const ms = this.d.now() - t0;\n this.save({ checked_at: new Date(t0).toISOString(), latest, error: null, running: this.d.version });\n if (!isNewer(latest, this.d.version)) {\n this.save({ pending: null });\n this.d.log(`update check: ${this.d.version} is current (npm latest ${latest}, ${ms} ms)`);\n return;\n }\n this.d.log(`update check: ${latest} is out (running ${this.d.version}, ${ms} ms); updating once idle`);\n await this.apply(latest);\n });\n }\n\n /** Restart onto the copy on disk once idle (`sessionpipe update` installed it). */\n restartWhenIdle(): boolean {\n if (this.stopped) return false;\n // An update under way ends the same way: on the newest copy on disk.\n if (this.busyWith) return true;\n void this.guard(async () => {\n const onDisk = await this.d.installed();\n if (!onDisk || onDisk === this.d.version) {\n this.d.log(`restart asked: the copy on disk is ${onDisk ?? \"unreadable\"}, the one running; staying`);\n return;\n }\n await this.quiesce(onDisk, false);\n await this.resumeOnError(async () => {\n this.d.log(`restart: ${this.d.version} \u2192 ${onDisk} (installed by hand)`);\n this.save({ updated: { from: this.d.version, to: onDisk, at: new Date(this.d.now()).toISOString(), ms: 0 } });\n await this.d.restart(this.d.version, onDisk);\n });\n });\n return true;\n }\n\n /** Wait until the daemon has nothing in hand, then stop its intake. A message that\n * slipped in between is let through and waited for. An automatic update turned off\n * meanwhile (`sessionpipe update off`) stops waiting. */\n private async quiesce(target: string, auto = true): Promise<void> {\n let said = false;\n for (;;) {\n let why = this.d.daemon.busy();\n while (why) {\n if (this.stopped) throw new Error(\"stopped\");\n const off = auto ? this.d.off() : null;\n if (off) {\n this.save({ pending: null });\n throw new Error(`${target} not installed: auto-update was turned off (${off})`);\n }\n if (!said) {\n this.d.log(`update: ${target} waits until the daemon is idle (${why})`);\n said = true;\n }\n await sleep(this.d.idlePollMs ?? 15_000);\n why = this.d.daemon.busy();\n }\n this.d.daemon.pauseIntake();\n if (!this.d.daemon.busy()) return;\n this.d.daemon.resumeIntake();\n }\n }\n\n /** Intake is paused from quiesce() on: whatever goes wrong after it lets it go. */\n private async resumeOnError(fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (e) {\n this.d.daemon.resumeIntake();\n throw e;\n }\n }\n\n private async apply(target: string): Promise<void> {\n this.save({ pending: target });\n await this.quiesce(target);\n await this.resumeOnError(() => this.installAndRestart(target));\n }\n\n private async installAndRestart(target: string): Promise<void> {\n const from = this.d.version;\n const t0 = this.d.now();\n const onDisk = await this.d.installed();\n let note = \"\";\n // Someone already installed it (or something newer) by hand: never install over a\n // newer copy, just restart onto what is there.\n const c = onDisk ? compareVersions(onDisk, target) : null;\n if (onDisk && c !== null && c >= 0) {\n target = onDisk;\n note = \" (already on disk)\";\n } else {\n const r = await this.d.install(target);\n if (!r.ok) {\n this.d.daemon.resumeIntake();\n const ms = this.d.now() - t0;\n this.save({\n pending: null,\n failed: { version: target, at: new Date(this.d.now()).toISOString(), error: r.error },\n });\n this.d.log(`update: ${from} \u2192 ${target} failed after ${ms} ms: ${r.error}; still running ${from}`);\n return;\n }\n if (r.hooks) note = `; ${r.hooks}`;\n }\n const ms = this.d.now() - t0;\n // Anything that came in over the socket while npm ran (a permission prompt) ends\n // first. The new copy is on disk by now, so it is restarted onto whatever happens.\n if (this.d.daemon.busy()) {\n this.d.daemon.resumeIntake();\n await this.quiesce(target, false);\n }\n this.save({\n pending: null,\n failed: null,\n updated: { from, to: target, at: new Date(this.d.now()).toISOString(), ms },\n });\n this.d.log(`update: ${from} \u2192 ${target} in ${ms} ms${note}; restarting`);\n await this.d.restart(from, target);\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Updating this copy of sessionpipe from npm: what the latest release is, whether this\n// copy is one npm can update in place, and the install itself. `sessionpipe update`\n// runs it by hand; the control daemon runs it once a day (control/autoupdate.ts).\n//\n// Only a global npm install updates itself. A copy in the npx cache, a git checkout or\n// a dev build is somebody's deliberate choice of code, and npm installing over it\n// would be wrong or impossible: for those `globalPrefix` is null and nothing happens.\nimport { spawn } from \"node:child_process\";\nimport { accessSync, constants, existsSync, realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { viaNpx } from \"./runtime.js\";\n\nexport const REGISTRY_LATEST = \"https://registry.npmjs.org/sessionpipe/latest\";\n\n// How versions order lives in core, beside the restart they lead to.\nimport { parseVersion } from \"@sessionpipe/core/version\";\n\nexport { compareVersions, isNewer } from \"@sessionpipe/core/version\";\n\n/** The registry's `latest` for sessionpipe: one GET, nothing sent but the request. */\nexport async function latestVersion(f: typeof fetch = fetch, timeoutMs = 8000): Promise<string> {\n const r = await f(REGISTRY_LATEST, {\n signal: AbortSignal.timeout(timeoutMs),\n headers: { accept: \"application/json\" },\n });\n if (!r.ok) throw new Error(`the npm registry answered HTTP ${r.status}`);\n const j = (await r.json()) as { version?: unknown };\n if (typeof j.version !== \"string\" || !parseVersion(j.version)) throw new Error(\"the npm registry named no version\");\n return j.version;\n}\n\n/** The prefix a global npm install of sessionpipe lives under, from the running copy's\n * dist folder (`<prefix>/lib/node_modules/sessionpipe/dist`, on Windows\n * `<prefix>\\node_modules\\sessionpipe\\dist`). */\nexport function prefixOf(distDir: string, platform: NodeJS.Platform = process.platform): string | null {\n const re =\n platform === \"win32\" ? /^(.*?)[\\\\/]node_modules[\\\\/]sessionpipe[\\\\/]/ : /^(.*)\\/lib\\/node_modules\\/sessionpipe\\//;\n return re.exec(`${distDir}/`)?.[1] ?? null;\n}\n\n/** The npm prefix this copy was installed into with `npm install -g`, or null when it\n * isn't a global npm install (the npx cache, a git checkout, a project's\n * node_modules, a dev build). A global install always has its bin link in the prefix. */\nexport function globalPrefix(distDir: string, platform: NodeJS.Platform = process.platform): string | null {\n if (viaNpx(distDir)) return null;\n const prefix = prefixOf(distDir, platform);\n if (!prefix) return null;\n const bin = platform === \"win32\" ? path.join(prefix, \"sessionpipe.cmd\") : path.join(prefix, \"bin\", \"sessionpipe\");\n return existsSync(bin) ? prefix : null;\n}\n\n/** Why npm can't write this prefix (installed with sudo, a read-only image), or null. */\nexport function unwritable(prefix: string, platform: NodeJS.Platform = process.platform): string | null {\n const dir = platform === \"win32\" ? path.join(prefix, \"node_modules\") : path.join(prefix, \"lib\", \"node_modules\");\n try {\n accessSync(dir, constants.W_OK);\n return null;\n } catch {\n return `${dir} isn't writable by this user (installed with sudo?)`;\n }\n}\n\n/** npm, run by this very node: under launchd PATH is /usr/bin:/bin, so neither `npm`\n * nor the `node` its shebang asks for is on it. Its npm-cli.js sits beside the node\n * binary (nvm, Homebrew, the official builds, the node Docker images). */\nexport function npmArgv(node: string, platform: NodeJS.Platform = process.platform): string[] {\n const dir = path.dirname(node);\n const candidates =\n platform === \"win32\"\n ? [path.join(dir, \"node_modules\", \"npm\", \"bin\", \"npm-cli.js\")]\n : [path.join(dir, \"npm\"), path.join(dir, \"..\", \"lib\", \"node_modules\", \"npm\", \"bin\", \"npm-cli.js\")];\n for (const c of candidates) {\n try {\n const real = realpathSync(c);\n if (real.endsWith(\".js\")) return [node, real];\n } catch {}\n }\n return [platform === \"win32\" ? \"npm.cmd\" : \"npm\"];\n}\n\nexport interface ExecResult {\n code: number | null;\n stdout: string;\n stderr: string;\n error?: string;\n}\nexport type Exec = (argv: string[], o: { env: NodeJS.ProcessEnv; timeoutMs: number }) => Promise<ExecResult>;\n\n/** Run a command to the end, keeping the tail of its output. */\nexport const execCapture: Exec = (argv, o) =>\n new Promise((resolve) => {\n const [cmd, ...rest] = argv as [string, ...string[]];\n let stdout = \"\";\n let stderr = \"\";\n const keep = (s: string, b: Buffer) => (s + b.toString(\"utf8\")).slice(-16_000);\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn(cmd, rest, {\n env: o.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n shell: process.platform === \"win32\" && cmd.endsWith(\".cmd\"),\n });\n } catch (e) {\n resolve({ code: null, stdout, stderr, error: (e as Error).message });\n return;\n }\n const t = setTimeout(() => child.kill(\"SIGTERM\"), o.timeoutMs);\n child.stdout?.on(\"data\", (b: Buffer) => {\n stdout = keep(stdout, b);\n });\n child.stderr?.on(\"data\", (b: Buffer) => {\n stderr = keep(stderr, b);\n });\n child.on(\"error\", (e) => {\n clearTimeout(t);\n resolve({ code: null, stdout, stderr, error: e.message });\n });\n child.on(\"close\", (code) => {\n clearTimeout(t);\n resolve({ code, stdout, stderr });\n });\n });\n\nexport interface InstallOptions {\n /** The node running this copy (process.execPath). */\n node: string;\n /** The running copy's dist folder: where the new one lands, under the same prefix. */\n distDir: string;\n /** Harnesses whose hooks to re-arm afterwards (config.harnesses that are enabled). */\n harnesses: string[];\n env?: NodeJS.ProcessEnv;\n exec?: Exec;\n platform?: NodeJS.Platform;\n}\n\nexport type InstallResult =\n | { ok: true; ms: number; hooks: string }\n | { ok: false; ms: number; error: string; stage: \"prefix\" | \"npm\" | \"verify\" };\n\nconst lastLine = (r: ExecResult): string =>\n (r.error || r.stderr.trim().split(\"\\n\").filter(Boolean).slice(-2).join(\" \") || `exit ${r.code}`).slice(0, 300);\n\n/** The version of the copy on disk (which may not be the one running). */\nexport async function installedVersion(o: {\n node: string;\n distDir: string;\n env?: NodeJS.ProcessEnv;\n exec?: Exec;\n}): Promise<string | null> {\n const r = await (o.exec ?? execCapture)([o.node, path.join(o.distDir, \"cli.js\"), \"--version\"], {\n env: o.env ?? process.env,\n timeoutMs: 30_000,\n });\n const v = r.stdout.trim();\n return r.code === 0 && parseVersion(v) ? v : null;\n}\n\n/** `npm install -g sessionpipe@<version>` into the prefix the running copy came from,\n * check the copy on disk says that version, then re-copy the hook launcher's files\n * (the hooks run copies in ~/.local/share/sessionpipe, which npm never touches) for\n * the harnesses already set up here. Lifecycle scripts are off: sessionpipe has none,\n * and an unattended install runs nothing it fetched. */\nexport async function installVersion(version: string, o: InstallOptions): Promise<InstallResult> {\n const t0 = Date.now();\n const platform = o.platform ?? process.platform;\n const exec = o.exec ?? execCapture;\n const base = o.env ?? process.env;\n // npm and anything it starts find this node first.\n const env = { ...base, PATH: [path.dirname(o.node), base.PATH].filter(Boolean).join(path.delimiter) };\n const prefix = globalPrefix(o.distDir, platform);\n if (!prefix)\n return { ok: false, ms: Date.now() - t0, stage: \"prefix\", error: \"this copy isn't a global npm install\" };\n const npm = npmArgv(o.node, platform);\n const r = await exec(\n [\n ...npm,\n \"install\",\n \"--global\",\n \"--prefix\",\n prefix,\n \"--ignore-scripts\",\n \"--no-audit\",\n \"--no-fund\",\n `sessionpipe@${version}`,\n ],\n { env, timeoutMs: 5 * 60_000 },\n );\n if (r.code !== 0) return { ok: false, ms: Date.now() - t0, stage: \"npm\", error: `npm install: ${lastLine(r)}` };\n const now = await installedVersion({ node: o.node, distDir: o.distDir, env, exec });\n if (now !== version)\n return {\n ok: false,\n ms: Date.now() - t0,\n stage: \"verify\",\n error: `npm finished, but the copy in ${prefix} says ${now ?? \"nothing\"}, not ${version}`,\n };\n let hooks = \"no harness set up here; nothing to re-arm\";\n if (o.harnesses.length) {\n const h = await exec(\n [o.node, path.join(o.distDir, \"cli.js\"), \"install\", \"--backfill\", \"0\", ...o.harnesses.map((n) => `--${n}`)],\n { env, timeoutMs: 2 * 60_000 },\n );\n hooks =\n h.code === 0\n ? `hooks re-armed for ${o.harnesses.join(\", \")}`\n : `re-arming the hooks failed (${lastLine(h)}); \\`sessionpipe install\\` does it`;\n }\n return { ok: true, ms: Date.now() - t0, hooks };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Persistent paths shared by hook installation and control pairing.\nimport { execFileSync } from \"node:child_process\";\nimport { readFileSync, realpathSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { launcherState } from \"./launcher.js\";\nimport { VERSION } from \"./run.js\";\nimport { isNewer } from \"./update.js\";\n\n/** Homebrew's versioned Cellar path dies on `brew upgrade node`; its stable links survive. */\nexport function stableNode(exe: string): string {\n const m = /^(.*)\\/Cellar\\/(node(?:@\\d+)?)\\/[^/]+\\/bin\\/node$/.exec(exe);\n if (!m) return exe;\n let real: string;\n try {\n real = realpathSync(exe);\n } catch {\n return exe;\n }\n for (const c of [`${m[1]}/opt/${m[2]}/bin/node`, `${m[1]}/bin/node`]) {\n try {\n if (realpathSync(c) === real) return c;\n } catch {}\n }\n return exe;\n}\n\nexport function viaNpx(distDir: string): boolean {\n return /[\\\\/]_npx[\\\\/]/.test(distDir) || /[\\\\/]\\.npm[\\\\/]/.test(distDir);\n}\n\n/** Homebrew's default prefix disappears on a node upgrade; use the persistent one. */\nfunction installLocation(): { prefix: string; target: string } {\n let prefix = \"\";\n try {\n prefix = execFileSync(\"npm\", [\"prefix\", \"-g\"], {\n encoding: \"utf8\",\n timeout: 15000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {}\n return {\n prefix,\n target: /\\/Cellar\\/node(?:@\\d+)?\\/[^/]+/.test(prefix) ? path.join(os.homedir(), \".local\") : prefix,\n };\n}\n\n/** Refuse before npm, config or hook writes, including hooks left by another prefix. */\nexport function assertSetupVersion(allowDowngrade: boolean, target?: string): void {\n if (allowDowngrade) return;\n const check = (installed: string | null, where: string): void => {\n if (installed && isNewer(installed, VERSION, true))\n throw new Error(\n `refusing to downgrade sessionpipe: ${installed} is installed at ${where}; this command would install ${VERSION}. Use the installed newer CLI, or pass --allow-downgrade to force ${VERSION}.`,\n );\n };\n const hooks = launcherState(VERSION);\n check(hooks.version, hooks.file);\n const prefix = target ?? installLocation().target;\n if (!prefix) return;\n const pkg = path.join(\n prefix,\n ...(process.platform === \"win32\" ? [] : [\"lib\"]),\n \"node_modules\",\n \"sessionpipe\",\n \"package.json\",\n );\n let installed: unknown;\n try {\n installed = (JSON.parse(readFileSync(pkg, \"utf8\")) as { version?: unknown }).version;\n } catch {}\n if (typeof installed === \"string\") check(installed, pkg);\n}\n\n/** Install the running version persistently and hand off the original command before side effects. */\nexport function rerunGlobally(argv: string[], out: (s: string) => void, setup?: { allowDowngrade: boolean }): void {\n const { prefix, target } = installLocation();\n if (setup) assertSetupVersion(setup.allowDowngrade, target);\n out(` Installing sessionpipe@${VERSION} globally, so hooks and services use a persistent copy\u2026`);\n let bin: string;\n try {\n execFileSync(\"npm\", [\"install\", \"-g\", `sessionpipe@${VERSION}`, ...(target ? [\"--prefix\", target] : [])], {\n stdio: [\"ignore\", \"ignore\", \"inherit\"],\n });\n bin =\n process.platform === \"win32\"\n ? path.join(target, \"sessionpipe.cmd\")\n : target\n ? path.join(target, \"bin\", \"sessionpipe\")\n : \"sessionpipe\";\n if (target && target !== prefix)\n out(` Installed into ${target}; make sure ${path.join(target, \"bin\")} is on your PATH.`);\n } catch {\n out(\n \" ! couldn't install globally (`npm install -g sessionpipe` failed). Run it yourself, then retry this command.\",\n );\n process.exit(1);\n }\n // The command's own failure (a pairing that expired) is its own to report, not an\n // install that failed: it has said why; pass its exit status on.\n try {\n execFileSync(bin, argv, { stdio: \"inherit\", shell: process.platform === \"win32\" });\n } catch (e) {\n process.exit(typeof (e as { status?: unknown }).status === \"number\" ? (e as { status: number }).status : 1);\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The hook's own home, outside every npm prefix: a copy of hook.js and worker.js and a\n// small sh launcher, which is what the harnesses run. A hook entry that named node and\n// hook.js by their install paths died with them \u2014 `nvm uninstall`, a Volta or asdf\n// switch, a moved npm prefix \u2014 and the harness said nothing; the machine just stopped\n// reporting. The launcher runs the node sessionpipe was installed with and, once that\n// one is gone, any node on PATH. Windows keeps the direct entry (it has no sh).\n// ~/.local/share/sessionpipe/ SESSIONPIPE_DATA, else $XDG_DATA_HOME/sessionpipe\nimport { accessSync, chmodSync, constants, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { AG_STALE_PRETOOL } from \"@sessionpipe/core\";\n\nexport const LAUNCHER = \"sessionpipe-hook\";\nconst COPIED = [\"worker.js\", \"hook.js\"] as const;\n\nexport function dataDir(env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_DATA) return path.resolve(env.SESSIONPIPE_DATA);\n return path.join(env.XDG_DATA_HOME || path.join(os.homedir(), \".local\", \"share\"), \"sessionpipe\");\n}\nexport const launcherPath = (env: NodeJS.ProcessEnv = process.env): string => path.join(dataDir(env), LAUNCHER);\nexport const usesLauncher = (platform: NodeJS.Platform = process.platform): boolean => platform !== \"win32\";\n\nconst sq = (s: string): string => `'${s.replace(/'/g, `'\\\\''`)}'`;\n\n/** The launcher, in sh. No node at all prints what Antigravity needs and exits 0: the\n * hook must stay invisible to the harness whatever is missing (and a PreToolUse entry\n * an older install left must not turn into a silent deny). */\nexport function launcherScript(node: string, hook: string, version: string): string {\n return `#!/bin/sh\n# sessionpipe ${version} hook launcher, written by \\`sessionpipe install\\`. Harnesses run\n# this; it runs hook.js beside it with the node sessionpipe was installed with, or with\n# any node on PATH once that one is gone (an nvm uninstall, a Homebrew upgrade).\nn=${sq(node)}\n[ -x \"$n\" ] || n=$(command -v node) || { [ \"$1\" = antigravity ] && if [ \"$2\" = PreToolUse ]; then echo ${sq(AG_STALE_PRETOOL.trim())}; else echo '{}'; fi; exit 0; }\nexec \"$n\" ${sq(hook)} \"$@\"\n`;\n}\n\nfunction writeIfChanged(file: string, body: Buffer | string, mode: number): boolean {\n try {\n const cur = readFileSync(file);\n if (cur.equals(Buffer.isBuffer(body) ? body : Buffer.from(body))) {\n chmodSync(file, mode);\n return false;\n }\n } catch {}\n // A hook may start while this runs: write beside it and rename, never half a file.\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, body, { mode });\n renameSync(tmp, file);\n chmodSync(file, mode);\n return true;\n}\n\n/** Copy the hook and worker out of the npm install and (re)write the launcher. The\n * worker goes first, so a hook that starts mid-copy never spawns a missing one. */\nexport function installLauncher(o: { distDir: string; node: string; version: string; env?: NodeJS.ProcessEnv }): {\n launcher: string;\n changed: boolean;\n} {\n const dir = dataDir(o.env);\n mkdirSync(dir, { recursive: true, mode: 0o755 });\n let changed = false;\n for (const f of COPIED)\n changed = writeIfChanged(path.join(dir, f), readFileSync(path.join(o.distDir, f)), 0o644) || changed;\n const launcher = path.join(dir, LAUNCHER);\n changed = writeIfChanged(launcher, launcherScript(o.node, path.join(dir, \"hook.js\"), o.version), 0o755) || changed;\n return { launcher, changed };\n}\n\nexport function removeLauncher(env: NodeJS.ProcessEnv = process.env): void {\n for (const f of [LAUNCHER, ...COPIED]) rmSync(path.join(dataDir(env), f), { force: true });\n}\n\nexport interface LauncherState {\n file: string;\n present: boolean;\n /** The node the launcher names, and whether it can still run. */\n node: string | null;\n nodeOk: boolean;\n version: string | null;\n problems: string[];\n}\n\n/** What `doctor` says about the launcher. */\nexport function launcherState(version: string, env: NodeJS.ProcessEnv = process.env): LauncherState {\n const file = launcherPath(env);\n let text = \"\";\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return {\n file,\n present: false,\n node: null,\n nodeOk: false,\n version: null,\n problems: [\"the hook launcher is missing; run `sessionpipe install` again\"],\n };\n }\n const node = /^n='((?:[^']|'\\\\'')*)'$/m.exec(text)?.[1]?.replace(/'\\\\''/g, \"'\") ?? null;\n const v = /^# sessionpipe (\\S+) hook launcher/m.exec(text)?.[1] ?? null;\n let nodeOk = false;\n try {\n if (node) {\n accessSync(node, constants.X_OK);\n nodeOk = true;\n }\n } catch {}\n const problems: string[] = [];\n if (!nodeOk)\n problems.push(\n `the node the hook launcher names (${node ?? \"?\"}) is gone; it falls back to the node on PATH. \\`sessionpipe install\\` points it at this one.`,\n );\n for (const f of COPIED)\n try {\n accessSync(path.join(path.dirname(file), f), constants.R_OK);\n } catch {\n problems.push(`${f} is missing beside the hook launcher; run \\`sessionpipe install\\` again`);\n }\n if (v && v !== version)\n problems.push(\n `the hooks run sessionpipe ${v}, this is ${version}; run \\`sessionpipe install\\` to bring them up to date`,\n );\n return { file, present: true, node, nodeOk, version: v, problems };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// What a worker run does, as a function so tests and `sessionpipe replay` share it.\nimport {\n appendFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n adapterByName,\n Cursors,\n capTail,\n type DeliveryResult,\n type Event,\n type FactsState,\n FileSink,\n filterEvent,\n gitFacts,\n isInjected,\n machineName,\n makeEvent,\n Outbox,\n processAlive,\n readConfig,\n readHook,\n redactDeep,\n type Session,\n type Sink,\n type SinkConfig,\n StdoutSink,\n safeId,\n shortId,\n stateDir,\n type TranscriptRead,\n takeLock,\n takeNamedLock,\n tilde,\n writeConfig,\n} from \"@sessionpipe/core\";\nimport { aliasFile, readAliases, receiverIdOf } from \"./control/aliases.js\";\nimport { ask, socketPath } from \"./control/local.js\";\nimport { HttpSink } from \"./http-sink.js\";\nimport { sinkWithSecrets } from \"./secrets.js\";\n\nasync function tellDaemon(\n state: string,\n job: Job,\n session: string,\n cwd: string | undefined,\n transcript?: string,\n): Promise<void> {\n const sock = socketPath(state);\n if (process.platform !== \"win32\" && !existsSync(sock)) return;\n await ask(\n sock,\n {\n op: \"event\",\n session: `${job.harness}:${session}`,\n event: job.event,\n ...(cwd ? { cwd } : {}),\n ...(transcript ? { transcript } : {}),\n },\n 300,\n );\n}\n\ndeclare const __SESSIONPIPE_VERSION__: string;\nconst VERSION = typeof __SESSIONPIPE_VERSION__ === \"string\" ? __SESSIONPIPE_VERSION__ : \"0.0.0\";\n\nexport interface Job {\n harness: string;\n event: string;\n argv: string[];\n stdin: string;\n cwd: string;\n env: Record<string, string>;\n ppid?: number;\n at: number;\n /** How many times the session's lock held this job out (a fresh worker starts for\n * it each time, up to MAX_TRIES; after that a sweep picks it up). */\n tries?: number;\n}\n\nexport const MAX_TRIES = 10;\n\n/** A job file the worker will pick up: random suffix, 0600, in a 0700 dir. */\nexport function enqueueJob(state: string, job: Job): string {\n const jobs = jobsDir(state);\n mkdirSync(jobs, { recursive: true, mode: 0o700 });\n const f = path.join(jobs, `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.json`);\n writeFileSync(f, JSON.stringify(job), { mode: 0o600 });\n return f;\n}\n\n/** A job is claimed by renaming its file `<file>.<pid>.running`: of two workers that\n * race for it, one rename wins. The claim stays until the job's events are in the\n * outbox (or it went back to the queue), so a worker its deadline ended mid-run\n * leaves it behind for a sweep to give back (ground rule 4: no event lost). */\nexport function claimJob(file: string): { job: Job; file: string } | null {\n const claimed = `${file}.${process.pid}.running`;\n try {\n renameSync(file, claimed);\n } catch {\n return null;\n }\n try {\n return { job: JSON.parse(readFileSync(claimed, \"utf8\")) as Job, file: claimed };\n } catch {\n releaseJob(claimed);\n return null;\n }\n}\nexport function releaseJob(claimed: string | undefined): void {\n if (!claimed) return;\n try {\n unlinkSync(claimed);\n } catch {}\n}\n\n/** Jobs another worker left behind: a claim whose worker is gone (or older than any\n * worker lives, `abandonedMs`) goes back to the queue, then every queued job older\n * than `olderThanMs` (younger ones belong to the worker their hook just spawned)\n * is claimed and run. Every worker sweeps before it exits. */\nexport async function sweepJobs(state: string, olderThanMs = 3000, limit = 20, abandonedMs = 60_000): Promise<number> {\n const jobs = jobsDir(state);\n let names: string[] = [];\n try {\n names = readdirSync(jobs);\n } catch {\n return 0;\n }\n const queued = names.filter((n) => n.endsWith(\".json\"));\n for (const n of names) {\n const m = /^(.*\\.json)\\.(\\d+)\\.running$/.exec(n);\n if (!m) continue;\n const f = path.join(jobs, n);\n try {\n if (processAlive(Number(m[2])) && Date.now() - statSync(f).mtimeMs < abandonedMs) continue;\n renameSync(f, path.join(jobs, m[1] as string));\n queued.push(m[1] as string);\n } catch {}\n }\n let ran = 0;\n for (const n of queued.sort().slice(0, limit)) {\n const f = path.join(jobs, n);\n try {\n if (Date.now() - statSync(f).mtimeMs < olderThanMs) continue;\n } catch {\n continue;\n }\n const c = claimJob(f);\n if (!c) continue;\n try {\n await runJob(c.job, { state, claimed: c.file });\n } catch {\n } finally {\n releaseJob(c.file);\n }\n ran++;\n }\n return ran;\n}\n\nexport function log(state: string, line: string): void {\n try {\n mkdirSync(state, { recursive: true, mode: 0o700 });\n const f = path.join(state, \"log\");\n try {\n if (statSync(f).size > 1024 * 1024) renameSync(f, `${f}.1`);\n } catch {}\n appendFileSync(f, `${new Date().toISOString()} ${line}\\n`);\n } catch {}\n}\n\n/** <state>/facts/<harness>/<session>.json \u2014 what the machine learned about a session. */\nexport function factsState(state: string): FactsState {\n const file = (h: string, s: string) => path.join(state, \"facts\", safeId(h), `${safeId(s)}.json`);\n return {\n get(h, s) {\n try {\n return JSON.parse(readFileSync(file(h, s), \"utf8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n },\n save(h, s, patch) {\n const cur = this.get(h, s);\n const next = { ...cur, ...patch };\n if (JSON.stringify(next) === JSON.stringify(cur)) return;\n mkdirSync(path.dirname(file(h, s)), { recursive: true, mode: 0o700 });\n writeFileSync(file(h, s), JSON.stringify(next), { mode: 0o600 });\n },\n };\n}\n\nexport function buildSinks(sinks: SinkConfig[], o: { locked?: (name: string) => void } = {}): Sink[] {\n const out: Sink[] = [];\n for (const raw of sinks) {\n if (raw.paused) continue;\n // A token kept in a keychain is read now; one this process can't read (a keychain\n // locked in an ssh session) leaves the sink's events waiting, never sent unsigned.\n const s = sinkWithSecrets(raw);\n if (!s) {\n o.locked?.(raw.name);\n continue;\n }\n const tier = Math.min(s.tier, s.max_tier ?? 3) as 0 | 1 | 2 | 3;\n if (s.url === \"stdout\") out.push(new StdoutSink(s.name, tier, !!s.pii));\n else if (s.url.startsWith(\"file:\"))\n out.push(new FileSink(s.name, s.url.slice(5).replace(/^~(?=\\/|$)/, os.homedir()), tier, !!s.pii));\n else if (/^https?:\\/\\//.test(s.url)) out.push(new HttpSink(s, tier));\n }\n return out;\n}\n\n/** How often a running turn's words go out again (turn.progress), at most. */\nexport const PROGRESS_MS = 20_000;\n\n/** The turn still running in a transcript read from the delivery cursor: the last\n * turn with a reply so far, or a prompt nothing has answered yet (the hook's own\n * copy when the transcript doesn't hold it yet). `base` is the number the cursor's\n * first turn will get, so a turn keeps the number its turn.transcript will carry.\n * The reply keeps its end when it is long: where the turn is now. */\nexport function openTurn(\n read: TranscriptRead,\n o: { base: number; prompt?: string | undefined; at: number },\n): { turn: number; user: string; assistant: string; at: number } | null {\n const last = read.turns[read.turns.length - 1];\n const fresh = (user: string, at: number) => ({\n turn: o.base + read.turns.length,\n user: user.slice(0, MAX_TURN_SIDE),\n assistant: \"\",\n at,\n });\n if (read.open) return fresh(read.open.user, read.open.at);\n // The prompt the hook just reported, unless the transcript already has its reply.\n // Text the person never typed (a task notification, another session's message) opens\n // no turn: the readers skip it, so that turn would never be delivered, and its\n // reading would stand in for the turn that is running until the next one lands.\n const prompt = o.prompt?.trim();\n if (prompt && !isInjected(prompt) && !(last && last.user.includes(prompt.slice(0, 200)))) return fresh(prompt, o.at);\n if (!last) return null;\n return {\n turn: o.base + read.turns.length - 1,\n user: last.user.slice(0, MAX_TURN_SIDE),\n assistant: capTail(last.assistant, MAX_TURN_SIDE),\n at: last.at,\n };\n}\nconst MAX_TURN_SIDE = 20_000;\n/** What session.attended is read from, the desktop app's link included, and session.launched_by\n * (hook.ts picks all four): the job's own, never the worker's. */\nconst JOB_OWN_ENV = [\n \"CLAUDE_CODE_SESSION_ATTENDED\",\n \"CLAUDE_CODE_HOST_SESSION_ID\",\n \"SESSIONPIPE_CONTROL_JOB\",\n \"SESSIONPIPE_LAUNCHED_BY\",\n];\n\n/** Run one hook job end to end: events \u2192 outbox \u2192 sinks. Returns what happened.\n * `claimed` is the job file this run holds: released once the events are in the\n * outbox or the job is back in the queue (`requeued` names its new file). */\nexport async function runJob(\n job: Job,\n opts: { state?: string; now?: number; claimed?: string; lockWaitMs?: number } = {},\n): Promise<{ events: Event[]; delivered: Record<string, number>; requeued?: string }> {\n const state = opts.state ?? stateDir();\n const cfg = readConfig();\n const adapter = adapterByName(job.harness);\n // A hooks file can outlive the build that wrote it (an update to a sessionpipe without\n // that adapter, a hand-written entry): without this line the events are dropped in\n // silence, with nothing on the machine to say so.\n if (!adapter) {\n log(state, `${job.harness} ${job.event}: no adapter for harness \"${job.harness}\"; event dropped`);\n return { events: [], delivered: {} };\n }\n // Who attends a session, and who launched it, is the job's own word, never the worker's: a\n // worker another session's hook spawned (sweepJobs) carries that session's. A key the job\n // lacks stays absent.\n const env: NodeJS.ProcessEnv = { ...process.env };\n for (const k of JOB_OWN_ENV) delete env[k];\n const r = readHook(adapter, { argv: job.argv, stdin: job.stdin, env: { ...env, ...job.env }, cwd: job.cwd });\n // The adapter did not claim the payload (another harness ran our entry out of a\n // shared hooks file, an event name it does not map, a payload with no session id).\n // Dropped either way, but never in silence: this is where a wrongly-named event\n // lands, and the log is the only thing on the machine that can say so.\n if (!r || !r.session.id) {\n let keys: string[] = [];\n try {\n // Some hooks pass JSON in argv instead of stdin. Only the top-level names\n // belong in this default log: values can contain prompts, paths or secrets.\n const payload: unknown = JSON.parse(job.argv.find((a) => a.startsWith(\"{\")) ?? job.stdin);\n if (payload && typeof payload === \"object\" && !Array.isArray(payload)) keys = Object.keys(payload);\n } catch {}\n log(\n state,\n `${job.harness} ${job.event}: the ${job.harness} adapter did not claim this payload; event dropped; keys: ${keys.join(\", \") || \"(none)\"}`,\n );\n return { events: [], delivered: {} };\n }\n // A session the control daemon started goes by the id its start command named, not\n // the one the harness picked (CONTROL.md \u00A76 `start`; control/aliases.ts): its events\n // say so, and so does everything below. The adapter's own reading of the session\n // (facts, a remote URL) keeps the harness's id.\n const id =\n receiverIdOf(readAliases(aliasFile(path.join(state, \"control\"))), job.harness, r.session.id) ?? r.session.id;\n const claudeEnd = job.harness === \"claude-code\" && r.events.some((e) => e.type === \"session.ended\");\n // The control daemon learns each session's turn state and folder from its events (a\n // message for a session mid-turn waits for its Stop; a pending permission prompt\n // closes when the tool runs). A local round trip, and nothing when no daemon runs.\n if (!claudeEnd) await tellDaemon(state, job, id, r.session.cwd, r.transcript);\n const outbox = new Outbox(state);\n const ref = { harness: job.harness, session: id };\n // Hooks of one session fire close together (parallel subagents, issue #9): poll\n // for the lock, often enough that its siblings can't keep taking it in between,\n // before giving the job back to the queue.\n let release = takeLock(state, ref);\n const lockWait = opts.lockWaitMs ?? LOCK_WAIT_MS;\n for (const until = Date.now() + lockWait; !release && Date.now() < until; ) {\n await new Promise((res) => setTimeout(res, 50));\n release = takeLock(state, ref);\n }\n if (!release) {\n log(state, `${job.harness} ${job.event}: session ${id} locked for ${lockWait / 1000} s, re-queued`);\n const requeued = enqueueJob(state, { ...job, tries: (job.tries ?? 0) + 1 });\n releaseJob(opts.claimed);\n return { events: [], delivered: {}, requeued };\n }\n const events: Event[] = [];\n try {\n const facts = factsState(state);\n const mem = facts.get(job.harness, id);\n // `claude mcp list` fires SessionEnd with a fresh id but no SessionStart or\n // transcript. Check under the session lock, before creating facts or a seq:\n // any existing outbox, facts or transcript is enough to preserve a real end.\n if (\n claudeEnd &&\n !existsSync(outbox.file(ref)) &&\n Object.keys(mem).length === 0 &&\n !(r.transcript && existsSync(r.transcript))\n ) {\n releaseJob(opts.claimed);\n return { events: [], delivered: {} };\n }\n if (claudeEnd) await tellDaemon(state, job, id, r.session.cwd, r.transcript);\n // Heartbeat-class events read no facts (they fire every tool call); the rest refresh them.\n const heavy = !/^(PreToolUse|PostToolUse|PostToolUseFailure|BeforeTool|AfterTool|PostInvocation)$/.test(job.event);\n let learned: Partial<Session> = {};\n if (heavy) {\n // The hook's environment, not the worker's: a swept job may be run by a worker\n // another harness's hook spawned, whose env names none of this harness's homes.\n const f = adapter.facts(r.session, r.transcript, r.hints ?? {}, facts, { ...process.env, ...job.env });\n const { started_at: _s, last_at: _l, first_ask: _fa, harness_version, ...rest } = f;\n learned = rest;\n if (harness_version) facts.save(job.harness, id, { harness_version });\n facts.save(job.harness, id, { session: { ...(mem.session as object), ...learned } });\n // Antigravity's transcript never says which folder a conversation runs in, and\n // Devin's payload names none either (only DEVIN_PROJECT_DIR in the hook's env);\n // the hooks do. Kept raw (this file is the machine's own, 0600), so the control\n // daemon still knows where to resume it after a restart.\n if (CWD_FROM_HOOKS.has(job.harness) && r.session.cwd && path.isAbsolute(r.session.cwd))\n facts.save(job.harness, id, { cwd: r.session.cwd });\n }\n const known = (mem.session as Partial<Session> | undefined) ?? {};\n const cwdRaw = learned.cwd ?? r.session.cwd ?? known.cwd;\n const git = heavy ? gitFacts(cwdRaw) : {};\n const session: Session = {\n ...known,\n ...learned,\n ...git,\n ...(learned.branch ? { branch: learned.branch } : {}),\n id,\n seq: 0,\n machine: machineName(cfg, os.hostname()),\n ...(cwdRaw ? { cwd: tilde(cwdRaw) } : {}),\n ...(r.session.model ? { model: r.session.model } : {}),\n ...(r.session.launched_by ? { launched_by: r.session.launched_by } : {}),\n };\n const version = (facts.get(job.harness, id).harness_version as string | undefined) ?? undefined;\n for (const a of r.events) {\n const e = makeEvent(a, {\n harness: { name: job.harness, ...(version ? { version } : {}) },\n session: { ...session, seq: outbox.nextSeq(ref) },\n now: opts.now ?? job.at,\n });\n events.push(e);\n }\n const wantsTranscript = cfg.sinks.some((s) => !s.paused && Math.min(s.tier, s.max_tier ?? 3) >= 2);\n // Tier 2, while a turn runs: what it has said so far, so a receiver can show a long\n // turn before it ends. On the prompt, then at most every PROGRESS_MS on a tool call,\n // and only when it changed. The cursor stays where it is: turn.transcript still\n // delivers the whole turn when it ends.\n const ending = r.events.some((e) => e.type === \"turn.ended\" || e.type === \"session.ended\");\n const starting = r.events.some((e) => e.type === \"turn.started\");\n // A message sent while a turn runs is absorbed by that turn, and Claude Code reports\n // it as a prompt with the running turn's own id. It is not a new turn: where it\n // belongs is the transcript's to say, so its text is no reading of its own.\n const startedId = r.events.find((e) => e.type === \"turn.started\")?.data.turn_id;\n const absorbed = starting && typeof startedId === \"string\" && facts.get(job.harness, id).open_turn === startedId;\n if (wantsTranscript && r.transcript && !ending && (starting || r.events.some((e) => e.type === \"tool.ended\"))) {\n const cur = facts.get(job.harness, id);\n const at = opts.now ?? job.at;\n if (starting || at - (Number(cur.progress_at) || 0) >= PROGRESS_MS) {\n const p = openTurn(adapter.readTranscript(r.transcript, Number(cur.transcript_line) || 0), {\n base: Number(cur.transcript_turns) || 0,\n prompt: !absorbed && typeof r.hints?.prompt === \"string\" ? r.hints.prompt : undefined,\n at,\n });\n const sig = p && `${p.turn}:${p.user.length}:${p.assistant.length}`;\n if (p && (starting || sig !== cur.progress_sig)) {\n events.push(\n makeEvent(\n { type: \"turn.progress\", harnessEvent: job.event, data: { ...p, at: new Date(p.at).toISOString() } },\n {\n harness: { name: job.harness, ...(version ? { version } : {}) },\n session: { ...session, seq: outbox.nextSeq(ref) },\n now: at,\n },\n ),\n );\n facts.save(job.harness, id, { progress_at: at, progress_sig: sig });\n }\n }\n }\n // The turn running now, by its prompt's id, until it ends (for `absorbed`).\n if (starting && typeof startedId === \"string\" && !absorbed) facts.save(job.harness, id, { open_turn: startedId });\n if (ending) facts.save(job.harness, id, { open_turn: null });\n // Tier 2: after a turn ends, the transcript's new turns become turn.transcript events.\n if (\n wantsTranscript &&\n r.transcript &&\n r.events.some((e) => e.type === \"turn.ended\" || e.type === \"session.ended\")\n ) {\n const cur = facts.get(job.harness, id);\n const fromLine = Number(cur.transcript_line) || 0;\n let turnNo = Number(cur.transcript_turns) || 0;\n const read = adapter.readTranscript(r.transcript, fromLine);\n for (const t of read.turns) {\n events.push(\n makeEvent(\n {\n type: \"turn.transcript\",\n harnessEvent: job.event,\n data: { turn: turnNo++, user: t.user, assistant: t.assistant, at: new Date(t.at).toISOString() },\n },\n {\n harness: { name: job.harness, ...(version ? { version } : {}) },\n session: { ...session, seq: outbox.nextSeq(ref) },\n now: opts.now ?? job.at,\n },\n ),\n );\n }\n if (read.turns.length) facts.save(job.harness, id, { transcript_line: read.line, transcript_turns: turnNo });\n }\n // At rest the outbox holds redacted strings (advisory GHSA-8f6f-c3c9-j5p6): the\n // tier-3 fields stay, with their secrets already gone; filterEvent runs the same\n // idempotent pass again per sink.\n outbox.append(\n ref,\n events.map((e) => ({ ...e, session: redactDeep(e.session), data: redactDeep(e.data) })),\n );\n releaseJob(opts.claimed);\n log(\n state,\n `${job.harness} ${job.event}: ${events.map((e) => e.type).join(\",\") || \"nothing\"} (${shortId(job.harness, id)})`,\n );\n } finally {\n release();\n }\n // The session's lock covered the append; the sinks drain without it (the outbox\n // reader leaves a line still being written), so a sibling hook isn't held out for\n // a round trip.\n const delivered = (await drain(state, cfg.sinks, outbox, ref)) ?? {};\n if (Math.random() < 0.02) outbox.prune(cfg.keep_days ?? 30);\n return { events, delivered };\n}\n\n/** One worker drains a machine's sinks at a time (the `flush` lock). Another whose\n * events are in the outbox meanwhile marks that there is more and leaves them to\n * it (null: nothing sent by this one). The one draining looks for the mark after\n * each pass, once it has let the lock go, so events appended during a pass go out\n * in its next pass or with the worker that appended them, never wait for a later\n * hook. Under a flood of hook events this is one uploader sending full batches,\n * not one per event, all refused together (mordast, 2026-10-14: 828 refusals in\n * two minutes, 5 192 jobs queued). */\nexport async function drain(\n state: string,\n sinkConfigs: SinkConfig[],\n outbox: Outbox,\n first?: { harness: string; session: string },\n): Promise<Record<string, number> | null> {\n const more = path.join(state, \"locks\", \"flush.more\");\n let release = takeNamedLock(state, \"flush\");\n if (!release) {\n try {\n writeFileSync(more, \"\", { mode: 0o600 });\n } catch {}\n release = takeNamedLock(state, \"flush\");\n if (!release) return null;\n }\n const delivered: Record<string, number> = {};\n for (;;) {\n try {\n unlinkSync(more);\n } catch {}\n try {\n for (const [k, v] of Object.entries(await flush(state, sinkConfigs, outbox, first)))\n delivered[k] = (delivered[k] ?? 0) + v;\n } finally {\n release();\n }\n if (!existsSync(more)) return delivered;\n release = takeNamedLock(state, \"flush\");\n if (!release) return delivered;\n }\n}\n\n/** HTTP.md \u00A72: a sink that answered 429 isn't tried again before its `retry-after`;\n * one that was unreachable (5xx, a timeout) waits 2 s \u00B7 10 s \u00B7 60 s \u00B7 5 min \u00B7 30 min,\n * then every 30 min. Kept in <state>/backoff/<sink>.json, so every worker on the\n * machine waits, not only the one that was refused. Cleared by the next batch the\n * sink takes. */\nexport interface Backoff {\n until: number;\n failures: number;\n why: string;\n}\nconst BACKOFF_MS = [2_000, 10_000, 60_000, 5 * 60_000, 30 * 60_000];\nconst backoffFile = (state: string, sink: string): string => path.join(state, \"backoff\", `${safeId(sink)}.json`);\nexport function readBackoff(state: string, sink: string): Backoff | null {\n try {\n const b = JSON.parse(readFileSync(backoffFile(state, sink), \"utf8\")) as Backoff;\n return typeof b.until === \"number\" ? b : null;\n } catch {\n return null;\n }\n}\nfunction noteFailure(state: string, sink: string, res: DeliveryResult, prev: Backoff | null): Backoff {\n const failures = (prev?.failures ?? 0) + 1;\n const ladder = BACKOFF_MS[Math.min(failures, BACKOFF_MS.length) - 1] as number;\n const wait = Number.isFinite(res.retryAfterMs) ? (res.retryAfterMs as number) : ladder;\n const b = { until: Date.now() + wait, failures, why: `${res.status ?? \"\"} ${res.error ?? \"\"}`.trim() };\n const f = backoffFile(state, sink);\n try {\n mkdirSync(path.dirname(f), { recursive: true, mode: 0o700 });\n writeFileSync(f, JSON.stringify(b), { mode: 0o600 });\n } catch {}\n return b;\n}\nfunction clearBackoff(state: string, sink: string): void {\n try {\n unlinkSync(backoffFile(state, sink));\n } catch {}\n}\n\n/** How long a job waits for its session's lock before it goes back to the queue. */\nconst LOCK_WAIT_MS = 6000;\n/** Harnesses whose own files do not name the session's folder: the hooks' cwd is kept. */\nconst CWD_FROM_HOOKS = new Set([\"antigravity\", \"devin\"]);\n\nconst BATCH = 50;\nconst MAX_PER_RUN = 500;\n\n/** Drain every sink from its cursor: this session first, then any backlog. Events\n * from many sessions are packed into one batch of up to BATCH, so a first\n * install's 400-session backfill is nine POSTs, not four hundred (the receiver's\n * write limit ended the first replay at 278 events, 2026-09-28). A cursor moves\n * only after its batch was acknowledged; a refused batch stops the sink for this\n * run and the next worker starts from the same cursors. The sinks drain at once:\n * the session's lock is held for the slowest round trip, not the sum of them (a\n * verdict's config write is synchronous, so two sinks' never interleave). */\nexport async function flush(\n state: string,\n sinkConfigs: SinkConfig[],\n outbox: Outbox,\n first?: { harness: string; session: string },\n o: { /** Try a sink in backoff anyway (`sessionpipe replay`). */ force?: boolean } = {},\n): Promise<Record<string, number>> {\n const delivered: Record<string, number> = {};\n const sinks = buildSinks(sinkConfigs, {\n locked: (name) => log(state, `sink ${name}: its token is in a keychain this process can't read; left for later`),\n });\n const refs = outbox.sessions();\n if (first) {\n const k = `${first.harness}/${safeId(first.session)}`;\n refs.sort((a, b) => (`${a.harness}/${a.session}` === k ? -1 : `${b.harness}/${b.session}` === k ? 1 : 0));\n }\n const drainSink = async (sink: Sink): Promise<void> => {\n let backoff = readBackoff(state, sink.name);\n if (backoff && !o.force && backoff.until > Date.now()) {\n delivered[sink.name] = 0;\n return;\n }\n const cursors = new Cursors(state, sink.name);\n const c = cursors.read();\n let sent = 0;\n let stalled = false;\n // Pull filtered events session by session into one batch; remember where each\n // session's offset would land if the batch goes through.\n let batch: Event[] = [];\n let pending: Record<string, number> = {};\n // HTTP.md \u00A72 413: halve the batch and try again; one event too large on its own\n // is dropped and logged. A half that is refused for another reason stops the\n // run like any refusal: the cursor stays, and the halves that went through are\n // sent again next time (the receiver counts them as duplicates).\n const deliver = async (events: Event[]): Promise<DeliveryResult> => {\n const res = await sink.send(events);\n if (res.ok || res.action !== \"split\") return res;\n if (events.length === 1) {\n const e = events[0] as Event;\n log(state, `sink ${sink.name}: 413 ${res.error ?? \"\"} \u2192 event ${e.id} (${e.type}) is too large alone, dropped`);\n return { ok: true, acknowledged: 0, accepted: 0, duplicates: 0, rejected: [{ id: e.id, reason: \"too_large\" }] };\n }\n const half = Math.ceil(events.length / 2);\n const a = await deliver(events.slice(0, half));\n if (!a.ok) return a;\n const b = await deliver(events.slice(half));\n if (!b.ok) return b;\n return {\n ok: true,\n acknowledged: a.acknowledged + b.acknowledged,\n accepted: (a.accepted ?? 0) + (b.accepted ?? 0),\n duplicates: (a.duplicates ?? 0) + (b.duplicates ?? 0),\n rejected: [...(a.rejected ?? []), ...(b.rejected ?? [])],\n };\n };\n const send = async (): Promise<boolean> => {\n if (!batch.length) {\n Object.assign(c, pending);\n pending = {};\n cursors.write(c);\n return true;\n }\n const res = await deliver(batch);\n if (!res.ok) {\n const action = res.action ?? \"retry\";\n let wait = \"\";\n if (action === \"retry\") {\n backoff = noteFailure(state, sink.name, res, backoff);\n wait = `, waits ${Math.round((backoff.until - Date.now()) / 1000)} s`;\n }\n log(state, `sink ${sink.name}: ${res.status ?? \"\"} ${res.error ?? \"\"} \u2192 ${action}${wait}`);\n if (res.action === \"pause\" || res.action === \"lower-tier\") applySinkVerdict(sink.name, res);\n if (res.action !== \"drop\") {\n batch = [];\n pending = {};\n return false;\n }\n } else if (backoff) {\n clearBackoff(state, sink.name);\n backoff = null;\n }\n sent += batch.length;\n Object.assign(c, pending);\n cursors.write(c);\n batch = [];\n pending = {};\n return true;\n };\n for (const ref of refs) {\n if (stalled || sent >= MAX_PER_RUN) break;\n let offset = pending[cursors.key(ref)] ?? c[cursors.key(ref)] ?? 0;\n for (;;) {\n const room = BATCH - batch.length;\n const { events, offset: next } = outbox.read(ref, offset, room);\n if (!events.length) break;\n for (const e of events) {\n const f = filterEvent(e, sink.tier, sink.pii, { home: os.homedir() });\n if (f) batch.push(f);\n }\n offset = next;\n pending[cursors.key(ref)] = offset;\n if (batch.length >= BATCH) {\n if (!(await send())) {\n stalled = true;\n break;\n }\n if (sent >= MAX_PER_RUN) break;\n }\n }\n }\n if (!stalled && (batch.length || Object.keys(pending).length)) if (!(await send())) stalled = true;\n delivered[sink.name] = sent;\n };\n await Promise.all(sinks.map(drainSink));\n return delivered;\n}\n\nfunction applySinkVerdict(name: string, res: { action?: string; max_tier?: number; error?: string }): void {\n try {\n const cfg = readConfig();\n const s = cfg.sinks.find((x) => x.name === name);\n if (!s) return;\n if (res.action === \"pause\") s.paused = `${new Date().toISOString()} ${res.error ?? \"unauthorized\"}`;\n if (res.action === \"lower-tier\" && typeof res.max_tier === \"number\") s.max_tier = res.max_tier as 0 | 1 | 2 | 3;\n writeConfig(cfg);\n } catch {}\n}\n\nexport { VERSION };\nexport const versionLine = (): string => `sessionpipe ${VERSION}`;\nexport const jobsDir = (state: string): string => path.join(state, \"jobs\");\nexport const hasJobs = (state: string): boolean => existsSync(jobsDir(state));\n", "// SPDX-License-Identifier: Apache-2.0\n// Sessions the daemon started under the command's name (spec/CONTROL.md \u00A76 `start`).\n// Codex and Antigravity pick a new session's id themselves, but a `start` names the\n// session (`codex:<id>`), and that name is what the person's receiver knows it by. So\n// the moment a run reveals the harness's own id, the daemon records it here:\n//\n// state/control/aliases.json {\"codex:<command's id>\": {\"id\": \"<harness's id>\",\n// \"cwd\": \"<folder>\", \"at\": \"<iso>\",\n// \"permission\": \"<level>\", \"model\": \"<id>\"}, \u2026} (0600)\n//\n// and everything the machine reports uses the command's id: the daemon's acks, a later\n// prompt (resumed under the harness's id), and the hook events, which the worker renames\n// before it builds them (run.ts). Small, so it is read whole wherever it is needed.\nimport { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { type StartOptions, startOptionsOf } from \"./store.js\";\n\nexport interface Alias {\n /** The harness's own session id. */\n id: string;\n /** The folder the session runs in (the start's). */\n cwd: string;\n at: string;\n /** What the start ran with (CONTROL.md \u00A76, Options); absent for an alias recorded\n * before 0.10.0, whose later runs keep the machine's mode. */\n permission?: StartOptions[\"permission\"];\n model?: string;\n}\nexport type Aliases = Record<string, Alias>;\n\nexport const aliasFile = (controlDir: string): string => path.join(controlDir, \"aliases.json\");\n\nexport function readAliases(file: string): Aliases {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as unknown;\n if (!j || typeof j !== \"object\" || Array.isArray(j)) return {};\n const out: Aliases = {};\n for (const [k, v] of Object.entries(j as Record<string, unknown>)) {\n const a = v as Partial<Alias> | null;\n if (a && typeof a.id === \"string\" && a.id && typeof a.cwd === \"string\")\n out[k] = { id: a.id, cwd: a.cwd, at: typeof a.at === \"string\" ? a.at : \"\", ...startOptionsOf(a) };\n }\n return out;\n } catch {\n return {};\n }\n}\n\n/** Written whole and renamed into place, 0600 in a 0700 folder. */\nexport function writeAliases(file: string, all: Aliases): void {\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(all, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, file);\n try {\n chmodSync(file, 0o600);\n } catch {}\n}\n\n/** The command's id a harness's own session goes by, or null when it was never renamed. */\nexport function receiverIdOf(all: Aliases, harness: string, id: string): string | null {\n const prefix = `${harness}:`;\n for (const [k, a] of Object.entries(all)) if (a.id === id && k.startsWith(prefix)) return k.slice(prefix.length);\n return null;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// What the control daemon keeps on disk:\n// config/control.json the receivers this machine is paired with: machine id,\n// the machine's own token, the enrolled keys, folders, mode (0600)\n// state/control/nonces.jsonl every verified nonce for 25 h, fsync'd before a\n// command runs (a failed write refuses it)\n// state/control/acks.jsonl acks not yet accepted by their receiver\n// state/control/state.json forks: which copy a message to a session goes to, and\n// the options each session the daemon started runs with\nimport {\n appendFileSync,\n chmodSync,\n closeSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n writeFileSync,\n} from \"node:fs\";\nimport path from \"node:path\";\nimport { configFile, stateDir } from \"@sessionpipe/core\";\nimport { levelRank, MODEL_RE, NONCE_TTL_MS, type RunLevel, type TrustedKey } from \"@sessionpipe/core/control\";\nimport {\n controlAccount,\n defaultRunner,\n type Runner,\n type SecretStore,\n type StoreName,\n secretDel,\n secretGet,\n secretSet,\n} from \"../secrets.js\";\n\nexport interface PairedReceiver {\n /** The receiver's origin, as the person typed it. */\n url: string;\n /** Absolute control endpoint (from the well-known file). */\n control: string;\n rpId: string;\n machine: string;\n /** The machine's own bearer (polls, acks, hello, off): opens nothing else. Empty\n * when it lives in a store this process can't read right now. */\n token: string;\n /** The token lives in this store, not in control.json (secrets.ts). */\n token_in?: SecretStore;\n keys: (TrustedKey & { name?: string; added_at: string })[];\n paired_at: string;\n}\n\n/** How sessions run when a message arrives (CONTROL.md \u00A72): the person's choice at\n * this machine, never a receiver's. */\nexport const MODES = [\"safe\", \"auto\", \"inherit\"] as const;\nexport type ControlMode = (typeof MODES)[number];\nexport const parseMode = (m: unknown): ControlMode | null =>\n (MODES as readonly unknown[]).includes(m) ? (m as ControlMode) : null;\n\nexport interface ControlConfig {\n name: string;\n /** Folders sessions may run in; compared on whole path segments, real paths. */\n folders: string[];\n mode: ControlMode;\n receivers: PairedReceiver[];\n /** Caps this machine keeps whatever a receiver sends (defaults in daemon.ts,\n * LIMITS): new sessions running at once and per hour, headless Claude Code runs\n * at once. */\n limits?: { start_concurrent?: number; start_per_hour?: number; headless?: number };\n}\n\nexport const controlFile = (env: NodeJS.ProcessEnv = process.env) =>\n path.join(path.dirname(configFile(env)), \"control.json\");\nexport const controlState = (env: NodeJS.ProcessEnv = process.env) => path.join(stateDir(env), \"control\");\n\nexport function writePrivate(file: string, value: unknown): void {\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, file);\n try {\n chmodSync(file, 0o600);\n } catch {}\n}\n\nexport function readControl(env: NodeJS.ProcessEnv = process.env, run: Runner = defaultRunner): ControlConfig | null {\n try {\n const j = JSON.parse(readFileSync(controlFile(env), \"utf8\")) as ControlConfig;\n if (!j || !Array.isArray(j.receivers)) return null;\n return {\n name: j.name || \"machine\",\n folders: j.folders ?? [],\n mode: parseMode(j.mode) ?? \"safe\",\n receivers: j.receivers.map((r) =>\n r.token_in ? { ...r, token: secretGet(r.token_in, controlAccount(r.machine), run) ?? \"\" } : r,\n ),\n ...(j.limits ? { limits: j.limits } : {}),\n };\n } catch {\n return null;\n }\n}\n\n/** How many receivers this machine is paired with, from control.json alone (no\n * keychain read: `status` shouldn't ask one). */\nexport function pairedCount(env: NodeJS.ProcessEnv = process.env): number {\n try {\n const j = JSON.parse(readFileSync(controlFile(env), \"utf8\")) as { receivers?: unknown };\n return Array.isArray(j.receivers) ? j.receivers.length : 0;\n } catch {\n return 0;\n }\n}\n\n/** A token kept in a store is never written back into the file. */\nexport const writeControl = (c: ControlConfig, env: NodeJS.ProcessEnv = process.env) =>\n writePrivate(controlFile(env), {\n ...c,\n receivers: c.receivers.map((r) => {\n if (!r.token_in) return r;\n const { token: _t, ...rest } = r;\n return rest;\n }),\n });\n\n/** Move every paired receiver's token into `to` (or back into control.json). A token\n * this process can't read is left where it is. */\nexport function moveControlSecrets(\n to: StoreName,\n o: { env?: NodeJS.ProcessEnv; run?: Runner } = {},\n): { moved: string[]; kept: string[] } {\n const run = o.run ?? defaultRunner;\n const cfg = readControl(o.env, run);\n const moved: string[] = [];\n const kept: string[] = [];\n if (!cfg) return { moved, kept };\n const drop: { store: SecretStore; machine: string }[] = [];\n for (const r of cfg.receivers) {\n if ((r.token_in ?? \"file\") === to) continue;\n if (!r.token) {\n kept.push(r.url);\n continue;\n }\n if (to !== \"file\" && !secretSet(to, controlAccount(r.machine), r.token, run)) {\n secretDel(to, controlAccount(r.machine), run);\n kept.push(r.url);\n continue;\n }\n if (r.token_in) drop.push({ store: r.token_in, machine: r.machine });\n if (to === \"file\") delete r.token_in;\n else r.token_in = to;\n moved.push(r.url);\n }\n writeControl(cfg, o.env);\n for (const d of drop) secretDel(d.store, controlAccount(d.machine), run);\n return { moved, kept };\n}\n\n/** Forget a receiver's token wherever it is (control off). */\nexport function dropControlSecret(r: PairedReceiver, run: Runner = defaultRunner): void {\n if (r.token_in) secretDel(r.token_in, controlAccount(r.machine), run);\n}\n\n/** Nonces the machine has run, for NONCE_TTL_MS. `seen()` records a new nonce\n * durably BEFORE it answers false; a write that fails throws, and the verifier\n * refuses the command (`nonce_store`). */\nexport class NonceStore {\n private readonly seenAt = new Map<string, number>();\n constructor(\n private readonly file: string,\n private readonly now: () => number = Date.now,\n ) {\n let raw = \"\";\n try {\n raw = readFileSync(file, \"utf8\");\n } catch {}\n const cut = this.now() - NONCE_TTL_MS;\n for (const line of raw.split(\"\\n\")) {\n if (!line) continue;\n try {\n const { n, t } = JSON.parse(line) as { n: string; t: number };\n if (typeof n === \"string\" && t > cut) this.seenAt.set(n, t);\n } catch {}\n }\n this.compact();\n }\n\n seen = (nonce: string): boolean => {\n const t = this.seenAt.get(nonce);\n if (t !== undefined && t > this.now() - NONCE_TTL_MS) return true;\n const at = this.now();\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n const fd = openSync(this.file, \"a\", 0o600);\n try {\n appendFileSync(fd, `${JSON.stringify({ n: nonce, t: at })}\\n`);\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n this.seenAt.set(nonce, at);\n return false;\n };\n\n /** Rewrite the file with only the live window (on start, and daily). */\n compact(): void {\n const cut = this.now() - NONCE_TTL_MS;\n for (const [n, t] of this.seenAt) if (t <= cut) this.seenAt.delete(n);\n if (!existsSync(this.file) && !this.seenAt.size) return;\n const body = [...this.seenAt].map(([n, t]) => JSON.stringify({ n, t })).join(\"\\n\");\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n writeFileSync(`${this.file}.tmp`, body ? `${body}\\n` : \"\", { mode: 0o600 });\n renameSync(`${this.file}.tmp`, this.file);\n }\n\n get size(): number {\n return this.seenAt.size;\n }\n}\n\nexport interface Ack {\n receiver: string;\n id: string;\n outcome: \"taken\" | \"delivered\" | \"expired\" | \"unsupported\" | \"failed\" | \"refused\";\n at: string;\n mode?: string;\n session?: string;\n code?: string;\n detail?: string;\n reply?: string;\n /** A start's taken and delivered: what it ran with (CONTROL.md \u00A76, Options). */\n applied?: StartOptions;\n}\n\n/** What a session the daemon started runs with: its level and, when one was asked for,\n * its model. Recorded at the start; every later run of the session reads it. */\nexport interface StartOptions {\n /** A level, or `inherit`: started on an inherit machine with none named. */\n permission: RunLevel;\n model?: string;\n}\n\n/** A recorded entry as read back from disk, or null when it isn't one. */\nexport function startOptionsOf(v: unknown): StartOptions | null {\n const o = v as { permission?: unknown; model?: unknown } | null;\n if (!o || typeof o !== \"object\" || (levelRank(o.permission) < 0 && o.permission !== \"inherit\")) return null;\n return {\n permission: o.permission as RunLevel,\n ...(typeof o.model === \"string\" && MODEL_RE.test(o.model) ? { model: o.model } : {}),\n };\n}\n\n/** Acks not yet accepted: appended before they are sent, rewritten when sent, so a\n * daemon restart re-sends rather than forgets (every message is acked exactly once\n * with a final outcome; a duplicate is tolerated by the receiver). */\nexport class AckOutbox {\n constructor(private readonly file: string) {}\n all(): Ack[] {\n try {\n return readFileSync(this.file, \"utf8\")\n .split(\"\\n\")\n .filter(Boolean)\n .map((l) => JSON.parse(l) as Ack);\n } catch {\n return [];\n }\n }\n add(a: Ack): void {\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n appendFileSync(this.file, `${JSON.stringify(a)}\\n`, { mode: 0o600 });\n }\n keep(left: Ack[]): void {\n mkdirSync(path.dirname(this.file), { recursive: true, mode: 0o700 });\n writeFileSync(`${this.file}.tmp`, left.map((a) => JSON.stringify(a)).join(\"\\n\") + (left.length ? \"\\n\" : \"\"), {\n mode: 0o600,\n });\n renameSync(`${this.file}.tmp`, this.file);\n }\n}\n\nexport interface DaemonState {\n /** Original session \u2192 the fork its messages go to. */\n copies: Record<string, string>;\n /** Claude Code sessions the daemon started \u2192 what they run with (Codex and\n * Antigravity keep theirs in the alias entry, aliases.ts). */\n started: Record<string, StartOptions>;\n}\n\nexport function readState(file: string): DaemonState {\n try {\n const j = JSON.parse(readFileSync(file, \"utf8\")) as { copies?: unknown; started?: unknown };\n const started: Record<string, StartOptions> = {};\n if (j.started && typeof j.started === \"object\")\n for (const [k, v] of Object.entries(j.started)) {\n const o = startOptionsOf(v);\n if (o) started[k] = o;\n }\n return { copies: j.copies && typeof j.copies === \"object\" ? (j.copies as Record<string, string>) : {}, started };\n } catch {\n return { copies: {}, started: {} };\n }\n}\nexport const writeState = (file: string, s: DaemonState) => writePrivate(file, s);\n", "// SPDX-License-Identifier: Apache-2.0\n// Where this machine's secrets live: each sink's token (and Webhooks secret) and each\n// paired receiver's machine token. In the operating system's keychain when this person\n// has one unlocked \u2014 the macOS Keychain, or the Secret Service (GNOME Keyring, KWallet)\n// in a Linux desktop session \u2014 and otherwise in config.json / control.json at mode\n// 0600, which is all a headless server has (the same as ~/.ssh). A secret in a store\n// leaves `token_in` in the file and no token.\n//\n// What a store protects against, plainly: a dotfiles repo, a backup, a synced\n// ~/.config, a `cat` over a shoulder. Not a program running as you: `security` hands an\n// item it wrote back without asking, which is also how the hook's worker reads it.\n\nimport { spawnSync } from \"node:child_process\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { configFile, readConfig, type SinkConfig, writeConfig } from \"@sessionpipe/core\";\n\nexport type SecretStore = \"keychain\" | \"secret-service\";\nexport type StoreName = SecretStore | \"file\";\n\nconst SERVICE = \"sessionpipe\";\n\nexport type Runner = (cmd: string, args: string[], input?: string) => { status: number | null; stdout: string };\nexport const defaultRunner: Runner = (cmd, args, input) => {\n const r = spawnSync(cmd, args, {\n input: input ?? \"\",\n encoding: \"utf8\",\n timeout: 8000,\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n return { status: r.error ? null : r.status, stdout: r.stdout ?? \"\" };\n};\n\n/** A sink's item. The machine has one config, so a sink's name is enough \u2014 except\n * where SESSIONPIPE_CONFIG points at another (a second profile, a test): then the\n * item names that config too, so two configs' sinks of one name never share a key. */\nexport const sinkAccount = (name: string, what: \"token\" | \"secret\" = \"token\"): string => {\n const scope = process.env.SESSIONPIPE_CONFIG\n ? `@${createHash(\"sha256\").update(configFile()).digest(\"hex\").slice(0, 8)}`\n : \"\";\n return `sink:${name}:${what}${scope}`;\n};\nexport const controlAccount = (machine: string): string => `control:${machine}`;\n\n/** `security -i` reads its commands from stdin, so the value never sits in argv (and in\n * `ps`). Its parser takes double-quoted words: a value with a quote, a backslash or a\n * space isn't stored there and stays in the file. */\nconst KC_SAFE = /^[\\x21\\x23-\\x5b\\x5d-\\x7e]{1,4096}$/;\nconst NAME_SAFE = /^[\\x20\\x21\\x23-\\x5b\\x5d-\\x7e]{1,200}$/;\n\nexport function secretGet(store: SecretStore, account: string, run: Runner = defaultRunner): string | null {\n const r =\n store === \"keychain\"\n ? run(\"security\", [\"find-generic-password\", \"-s\", SERVICE, \"-a\", account, \"-w\"])\n : run(\"secret-tool\", [\"lookup\", \"service\", SERVICE, \"account\", account]);\n if (r.status !== 0) return null;\n const v = r.stdout.replace(/\\r?\\n$/, \"\");\n return v || null;\n}\n\nexport function secretSet(store: SecretStore, account: string, value: string, run: Runner = defaultRunner): boolean {\n if (store === \"keychain\") {\n if (!KC_SAFE.test(value) || !NAME_SAFE.test(account)) return false;\n run(\n \"security\",\n [\"-i\"],\n `add-generic-password -U -s ${SERVICE} -a \"${account}\" -l \"${SERVICE} ${account}\" -w \"${value}\"\\n`,\n );\n } else {\n run(\"secret-tool\", [\"store\", \"--label\", `${SERVICE} ${account}`, \"service\", SERVICE, \"account\", account], value);\n }\n // Trust only a read-back: `security -i` exits 0 whatever its commands did.\n return secretGet(store, account, run) === value;\n}\n\nexport function secretDel(store: SecretStore, account: string, run: Runner = defaultRunner): void {\n if (store === \"keychain\") run(\"security\", [\"delete-generic-password\", \"-s\", SERVICE, \"-a\", account]);\n else run(\"secret-tool\", [\"clear\", \"service\", SERVICE, \"account\", account]);\n}\n\n/** Can this process write, read back and delete an item in the store right now? */\nexport function probe(store: SecretStore, run: Runner = defaultRunner): boolean {\n const account = `probe:${randomBytes(6).toString(\"hex\")}`;\n const ok = secretSet(store, account, randomBytes(12).toString(\"base64url\"), run);\n secretDel(store, account, run);\n return ok;\n}\n\n/** The best place for secrets on this machine, from this session. SESSIONPIPE_SECRETS\n * (file | keychain | secret-service) overrides. The Secret Service is used only in a\n * desktop session: on a server its keyring is locked whenever nobody is logged in,\n * which is exactly when the daemon needs its token. */\nexport function bestStore(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n run: Runner = defaultRunner,\n): StoreName {\n const want = env.SESSIONPIPE_SECRETS;\n if (want === \"file\") return \"file\";\n const candidates: SecretStore[] =\n want === \"keychain\" || want === \"secret-service\"\n ? [want]\n : platform === \"darwin\"\n ? [\"keychain\"]\n : platform === \"linux\" && env.DBUS_SESSION_BUS_ADDRESS && (env.DISPLAY || env.WAYLAND_DISPLAY)\n ? [\"secret-service\"]\n : [];\n for (const s of candidates) if (probe(s, run)) return s;\n return \"file\";\n}\n\nexport const storeLabel = (s: StoreName | undefined): string =>\n s === \"keychain\" ? \"the macOS Keychain\" : s === \"secret-service\" ? \"the Secret Service keyring\" : \"a 0600 file\";\n\n/** The sink with its token and secret filled in from its store. Null when they live in\n * a store this process can't read right now (a keychain locked in an ssh session):\n * the caller leaves the events in the outbox rather than sending them unsigned. */\nexport function sinkWithSecrets(s: SinkConfig, run: Runner = defaultRunner): SinkConfig | null {\n if (!s.token_in) return s;\n const token = secretGet(s.token_in, sinkAccount(s.name), run);\n if (!token) return null;\n const secret = secretGet(s.token_in, sinkAccount(s.name, \"secret\"), run);\n return { ...s, token, ...(secret ? { secret } : {}) };\n}\n\n/** Store a sink's secrets in `to` (or back in the file) and save the config. */\nexport function moveSinkSecrets(\n to: StoreName,\n o: { run?: Runner; file?: string } = {},\n): { moved: string[]; kept: string[] } {\n const run = o.run ?? defaultRunner;\n const cfg = o.file ? readConfig(o.file) : readConfig();\n const moved: string[] = [];\n const kept: string[] = [];\n for (const s of cfg.sinks) {\n const from = s.token_in;\n if ((from ?? \"file\") === to) continue;\n const full = sinkWithSecrets(s, run);\n if (!full) {\n kept.push(s.name);\n continue;\n }\n if (!full.token && !full.secret) continue;\n if (to === \"file\") {\n // From a store, so with a token (sinkWithSecrets is null without one); a sink\n // already in the file never gets here.\n /* v8 ignore else */\n if (full.token) s.token = full.token;\n if (full.secret) s.secret = full.secret;\n delete s.token_in;\n } else {\n const ok =\n (!full.token || secretSet(to, sinkAccount(s.name), full.token, run)) &&\n (!full.secret || secretSet(to, sinkAccount(s.name, \"secret\"), full.secret, run));\n if (!ok) {\n secretDel(to, sinkAccount(s.name), run);\n secretDel(to, sinkAccount(s.name, \"secret\"), run);\n kept.push(s.name);\n continue;\n }\n delete s.token;\n delete s.secret;\n s.token_in = to;\n }\n moved.push(s.name);\n if (from) {\n // Written first, then the file says where; only then is the old copy dropped.\n if (o.file) writeConfig(cfg, o.file);\n else writeConfig(cfg);\n secretDel(from, sinkAccount(s.name), run);\n secretDel(from, sinkAccount(s.name, \"secret\"), run);\n }\n }\n if (o.file) writeConfig(cfg, o.file);\n else writeConfig(cfg);\n return { moved, kept };\n}\n\n/** Forget a sink's secrets wherever they are (sink remove, uninstall). */\nexport function dropSinkSecrets(s: SinkConfig, run: Runner = defaultRunner): void {\n if (!s.token_in) return;\n secretDel(s.token_in, sinkAccount(s.name), run);\n secretDel(s.token_in, sinkAccount(s.name, \"secret\"), run);\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The daemon's local socket (spec/CONTROL.md \u00A78): how the waiter, the Stop and\n// PermissionRequest hooks and the worker talk to the one daemon on this machine.\n// Line-delimited JSON, one request per connection. A Unix socket in the state\n// directory (0600, in a 0700 dir); a per-user named pipe on Windows. Only node:\n// builtins \u2014 the hook bundle imports this.\nimport net from \"node:net\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nexport type LocalRequest =\n /** A waiter parks until a message for its session arrives. */\n | { op: \"wait\"; session: string; pid?: number }\n /** A Stop hook asks for a queued message (turn mode). */\n | { op: \"stop\"; session: string; active: boolean }\n /** A PermissionRequest hook parks until a verified answer, or until it's released. */\n | { op: \"permission\"; session: string; attention: string; tool?: string }\n /** The worker reports a hook event: turn state and attention closure. */\n | { op: \"event\"; session: string; event: string; transcript?: string; cwd?: string }\n /** `sessionpipe control status`. */\n | { op: \"status\" }\n /** `sessionpipe update` installed a new copy: restart onto it once nothing is in hand. */\n | { op: \"restart\" };\n\nexport type LocalReply =\n | { op: \"message\"; text: string; id: string }\n | { op: \"block\"; reason: string; id: string }\n | { op: \"decision\"; behavior: \"allow\" | \"deny\"; message?: string; id: string }\n | { op: \"none\" }\n /** A newer waiter for the same session took over; this one stops. */\n | { op: \"replaced\" }\n | { op: \"ok\" }\n | { op: \"status\"; status: unknown };\n\n/** Where the daemon listens. `SESSIONPIPE_SOCKET` overrides (tests). */\nexport function socketPath(state: string, env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_SOCKET) return env.SESSIONPIPE_SOCKET;\n if (process.platform === \"win32\") return `\\\\\\\\.\\\\pipe\\\\sessionpipe-control-${os.userInfo().username}`;\n return path.join(state, \"control.sock\");\n}\n\n/** One request, one reply. `timeoutMs` bounds the whole exchange; null on any\n * failure (no daemon, a timeout, a garbled reply) \u2014 callers treat that as \"none\". */\nexport function ask(sock: string, req: LocalRequest, timeoutMs: number): Promise<LocalReply | null> {\n return new Promise((resolve) => {\n let buf = \"\";\n let done = false;\n const s = net.connect(sock);\n const finish = (r: LocalReply | null) => {\n if (done) return;\n done = true;\n clearTimeout(t);\n s.destroy();\n resolve(r);\n };\n const t = setTimeout(() => finish(null), timeoutMs);\n s.on(\"connect\", () => s.write(`${JSON.stringify(req)}\\n`));\n s.on(\"data\", (d) => {\n buf += d.toString(\"utf8\");\n const i = buf.indexOf(\"\\n\");\n if (i < 0) return;\n try {\n finish(JSON.parse(buf.slice(0, i)) as LocalReply);\n } catch {\n finish(null);\n }\n });\n s.on(\"error\", () => finish(null));\n s.on(\"close\", () => finish(null));\n });\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The HTTP sink (spec/HTTP.md \u00A72): POST {events} with the protocol header, a bearer\n// token and optional Standard Webhooks signature; errors map to what the sender\n// does next. The cursor moves only on 202. Retry/backoff is the worker's cadence\n// (each hook run drains the backlog); this class reports, it does not sleep.\nimport { createHash, createHmac } from \"node:crypto\";\nimport type { DeliveryResult, Event, Sink, SinkConfig, Tier } from \"@sessionpipe/core\";\n\nconst TIMEOUT_MS = 15_000;\n\n/** The Standard Webhooks message id (HTTP.md \u00A72): the same batch sent again carries\n * the same id, so a receiver that dedupes on webhook-id sees a retry as one message.\n * Derived from the events' own ids, which the outbox keeps across retries. */\nexport function webhookId(events: Pick<Event, \"id\">[]): string {\n return `msg_${createHash(\"sha256\")\n .update(events.map((e) => e.id).join(\",\"))\n .digest(\"base64url\")\n .slice(0, 32)}`;\n}\n\n/** HTTP.md \u00A72 429: wait as `retry-after` says, seconds or an HTTP date (RFC 9110\n * \u00A710.2.3); a minute when the header is missing or unreadable. */\nexport function retryAfterMs(header: string | null, now = Date.now()): number {\n if (header === null || header.trim() === \"\") return 60_000;\n const secs = Number(header);\n if (Number.isFinite(secs)) return Math.max(0, secs) * 1000;\n const at = Date.parse(header);\n return Number.isFinite(at) ? Math.max(0, at - now) : 60_000;\n}\n\nexport class HttpSink implements Sink {\n readonly name: string;\n readonly pii: boolean;\n private readonly url: string;\n constructor(\n private readonly cfg: SinkConfig,\n readonly tier: Tier,\n ) {\n this.name = cfg.name;\n this.pii = !!cfg.pii;\n this.url = cfg.url.replace(/\\/$/, \"\");\n }\n\n private eventsUrl(): string {\n // The endpoint from the well-known file is stored beside the url at `sink add`;\n // until then the spec's default path.\n const ep = (this.cfg as { endpoints?: { events?: string } }).endpoints?.events ?? \"/api/sessionpipe/v1/events\";\n return /^https?:\\/\\//.test(ep) ? ep : this.url + ep;\n }\n\n async send(events: Event[]): Promise<DeliveryResult> {\n const body = JSON.stringify({ events });\n const headers: Record<string, string> = { \"content-type\": \"application/json\", \"sessionpipe-protocol\": \"1\" };\n if (this.cfg.token) headers.authorization = `Bearer ${this.cfg.token}`;\n if (this.cfg.secret?.startsWith(\"whsec_\")) {\n const id = webhookId(events);\n const ts = Math.floor(Date.now() / 1000);\n const key = Buffer.from(this.cfg.secret.slice(6), \"base64\");\n const sig = createHmac(\"sha256\", key).update(`${id}.${ts}.${body}`).digest(\"base64\");\n headers[\"webhook-id\"] = id;\n headers[\"webhook-timestamp\"] = String(ts);\n headers[\"webhook-signature\"] = `v1,${sig}`;\n }\n const ctl = new AbortController();\n const t = setTimeout(() => ctl.abort(), TIMEOUT_MS);\n try {\n const r = await fetch(this.eventsUrl(), { method: \"POST\", headers, body, signal: ctl.signal });\n const text = await r.text();\n let j: Record<string, unknown> = {};\n try {\n j = text ? (JSON.parse(text) as Record<string, unknown>) : {};\n } catch {}\n if (r.status === 202 || r.status === 200) {\n return {\n ok: true,\n acknowledged: events.length,\n accepted: Number(j.accepted ?? events.length),\n duplicates: Number(j.duplicates ?? 0),\n rejected: Array.isArray(j.rejected) ? (j.rejected as { id: string; reason: string }[]) : [],\n ...(typeof j.max_tier === \"number\" ? { max_tier: j.max_tier as Tier } : {}),\n status: r.status,\n };\n }\n const err = typeof j.reason === \"string\" ? j.reason : text.slice(0, 200);\n if (r.status === 400) return { ok: false, acknowledged: 0, status: 400, error: err, action: \"drop\" };\n if (r.status === 401) return { ok: false, acknowledged: 0, status: 401, error: err, action: \"pause\" };\n if (r.status === 403)\n return {\n ok: false,\n acknowledged: 0,\n status: 403,\n error: err,\n action: \"lower-tier\",\n ...(typeof j.max_tier === \"number\" ? { max_tier: j.max_tier as Tier } : {}),\n };\n if (r.status === 413) return { ok: false, acknowledged: 0, status: 413, error: err, action: \"split\" };\n if (r.status === 429)\n return {\n ok: false,\n acknowledged: 0,\n status: 429,\n error: err,\n action: \"retry\",\n retryAfterMs: retryAfterMs(r.headers.get(\"retry-after\")),\n };\n return { ok: false, acknowledged: 0, status: r.status, error: err, action: \"retry\" };\n } catch (e) {\n return { ok: false, acknowledged: 0, error: String((e as Error).message ?? e), action: \"retry\" };\n } finally {\n clearTimeout(t);\n }\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n/** sessionpipe-core/version \u2014 versions, and restarting onto a new one: how two\n * versions order, whether one is a release newer than another, the exit code that\n * asks a service manager to start a process again on the code now on disk, and the\n * parent that does so where no manager will. The control daemon updates itself with\n * these, and a receiver of the person's own can do the same. Node only (the parent\n * spawns its child), so never part of the root export. */\nimport { type ChildProcess, spawn } from \"node:child_process\";\n\n/** EX_TEMPFAIL: \"start me again, on the code now on disk\". Every plist and unit\n * sessionpipe-core/service writes restarts on it. */\nexport const UPDATE_EXIT = 75;\n\nconst VERSION_RE = /^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/;\n\nexport interface Parsed {\n n: [number, number, number];\n pre: string | null;\n}\n/** A version's numbers and its prerelease tag, or null when it isn't one. */\nexport function parseVersion(v: string): Parsed | null {\n const m = VERSION_RE.exec(String(v).trim());\n if (!m) return null;\n return { n: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] ?? null };\n}\n\n/** Order two versions: <0, 0, >0, or null if either isn't one. A release sorts above\n * its own prereleases; prereleases compare by their tag. */\nexport function compareVersions(a: string, b: string): number | null {\n const x = parseVersion(a);\n const y = parseVersion(b);\n if (!x || !y) return null;\n for (let i = 0; i < 3; i++) if (x.n[i] !== y.n[i]) return (x.n[i] as number) - (y.n[i] as number);\n if (x.pre === y.pre) return 0;\n if (x.pre === null) return 1;\n if (y.pre === null) return -1;\n return x.pre.localeCompare(y.pre, \"en\", { numeric: true });\n}\n\n/** `a` is a release newer than `b`. A prerelease is never offered as an update: the\n * `latest` dist-tag is a release, and anything else is someone's experiment.\n * Setup opts into prereleases when checking whether an installed build is newer. */\nexport function isNewer(a: string, b: string, includePrereleases = false): boolean {\n const x = parseVersion(a);\n if (!x || (!includePrereleases && x.pre !== null)) return false;\n const c = compareVersions(a, b);\n return c !== null && c > 0;\n}\n\n/** The parent left behind when no service manager will restart the daemon: runs\n * `control run` as a child with the same env and output, starts it again when it exits\n * UPDATE_EXIT (an update) or fails (after 5 s, like the service files), and exits\n * with it when it exits cleanly or is told to stop. */\nexport function supervise(o: {\n node: string;\n args: string[];\n env: NodeJS.ProcessEnv;\n log: (line: string) => void;\n spawn?: typeof spawn;\n exit?: (code: number) => void;\n failDelayMs?: number;\n}): { stop: (sig?: NodeJS.Signals) => void } {\n const run = o.spawn ?? spawn;\n const exit = o.exit ?? ((c: number) => process.exit(c));\n const env = { ...o.env, SESSIONPIPE_SERVICE: `supervisor:${process.pid}` };\n let child: ChildProcess | null = null;\n let stopping = false;\n let later: NodeJS.Timeout | null = null;\n const start = () => {\n later = null;\n const c = run(o.node, o.args, { env, stdio: \"inherit\", windowsHide: true });\n child = c;\n let done = false;\n const ended = (code: number | null, signal: NodeJS.Signals | null) => {\n if (done) return;\n done = true;\n child = null;\n if (stopping) return exit(code ?? 0);\n if (code === UPDATE_EXIT) {\n o.log(\"the daemon is restarting onto its new version\");\n return start();\n }\n if (code === 0) return exit(0);\n o.log(`the daemon exited (${signal ?? `code ${code}`}); starting it again in 5 s`);\n later = setTimeout(start, o.failDelayMs ?? 5000);\n };\n c.on(\"exit\", ended);\n c.on(\"error\", (e) => {\n o.log(`couldn't start the daemon: ${e.message}`);\n ended(1, null);\n });\n };\n const stop = (sig: NodeJS.Signals = \"SIGTERM\") => {\n stopping = true;\n if (later) clearTimeout(later);\n if (child) child.kill(sig);\n else exit(0);\n };\n start();\n return { stop };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// `sessionpipe control pair | mode | folders | keys | off | run | status` and `sessionpipe wait`.\nimport { existsSync, realpathSync, statSync, unwatchFile, watchFile } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n acpControl,\n antigravityControl,\n claudeControl,\n claudeDirs,\n codexControl,\n drivableHarnesses,\n machineName,\n Outbox,\n readConfig,\n stateDir,\n type Tier,\n writeConfig,\n} from \"@sessionpipe/core\";\n\nconst { claudeLogin, detectCaps, findClaude, runClaude } = claudeControl;\n\nimport { isBroad } from \"../connect.js\";\nimport { drain, VERSION } from \"../run.js\";\nimport { rerunGlobally, stableNode, viaNpx } from \"../runtime.js\";\nimport { controlAccount, secretGet, sinkWithSecrets } from \"../secrets.js\";\nimport { installedVersion, installVersion, latestVersion } from \"../update.js\";\nimport { AutoUpdater, autoUpdateOff, restartVia, supervise, UPDATE_EXIT, updateFile } from \"./autoupdate.js\";\nimport { ControlDaemon, DaemonRunning } from \"./daemon.js\";\nimport { ask, socketPath } from \"./local.js\";\nimport { installService, off, pair, removeKey, uninstallService, withoutInherit } from \"./pair.js\";\nimport { loadSdk } from \"./sdk.js\";\nimport { type ControlMode, controlFile, controlState, parseMode, readControl, writeControl } from \"./store.js\";\nimport { waitForMessage, waitSession } from \"./wait.js\";\n\nexport const CONTROL_HELP = ` sessionpipe control pair <receiver> [--folder DIR]\u2026 [--mode safe|auto|inherit] [--tier 0-3] [--token T] [--name N] [--no-service]\n sessionpipe control mode auto|safe|inherit (how sessions run when you message them)\n sessionpipe control folders [add|remove DIR\u2026] (where sessions you message may run)\n sessionpipe control status | keys [remove <id>] | off [<receiver>] | run\n sessionpipe wait [--session <harness>:<id>] (a session runs this in the background)`;\n\nconst MODE_TEXT = ` auto Claude Code's auto mode: the session reads, edits and runs commands, and Claude Code's\n own safety check stops what looks dangerous. Pick this to get work done from your phone.\n (Codex runs with --approve-for-me, Antigravity with --mode accept-edits.) Where Claude\n Code's settings turn auto mode off (permissions.disableAutoMode), Claude Code runs these\n sessions in its default mode instead, which refuses whatever needs approval; inherit\n runs them as your own sessions run.\n safe Only what each folder's Claude Code settings already allow: with no allow rules, a\n session can't even read a file. Pick this if this machine holds things no agent\n should touch unattended. (Codex runs in its workspace-write sandbox and never\n escalates; Antigravity is denied every tool call that would need approval.)\n inherit As your own sessions here run: no permission flag, so each harness starts in its own\n default on this machine. Claude Code takes permissions.defaultMode from its settings,\n whatever you set there, bypassPermissions included. Pick this if sessions you message\n should run the way you run them. (Codex follows the approval_policy and sandbox_mode in\n its config.toml; Antigravity gets no flag, as in safe.)`;\n\n/** What each mode means, in a few words: after pairing, and after `control mode` changes it. */\nconst MODE_IS: Record<ControlMode, string> = {\n safe: \"nothing that needs approval runs unattended\",\n auto: \"Claude Code's auto mode\",\n inherit: \"each harness's own default mode on this machine\",\n};\nconst MODE_NOW: Record<ControlMode, string> = {\n safe: \"only what each folder's settings already allow\",\n auto: \"Claude Code's auto mode decides what's safe\",\n inherit: \"as your own sessions here run: each harness's own default\",\n};\n\n/** Ask the person at this machine, once: auto, safe or inherit. Inherit only by its whole\n * name, never by a stray letter: it runs whatever the settings say, bypass included. Not\n * a terminal (an agent ran the pair command): safe, and say how to change it. */\nasync function askMode(out: (s?: string) => void): Promise<ControlMode> {\n if (!process.stdin.isTTY) {\n out(\" Mode: safe for now. Run `sessionpipe control mode auto` to let sessions you message work unattended.\");\n return \"safe\";\n }\n out(\"\");\n out(\" When you message a session on this machine from your phone, how may it run?\");\n out(MODE_TEXT);\n const { createInterface } = await import(\"node:readline/promises\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n for (;;) {\n const a = (await rl.question(\" auto, safe or inherit? [auto] \")).trim().toLowerCase();\n if (a === \"\" || a === \"a\" || a === \"auto\") return \"auto\";\n if (a === \"s\" || a === \"safe\") return \"safe\";\n if (a === \"inherit\") return \"inherit\";\n }\n } finally {\n rl.close();\n }\n}\n\n/** `control folders add|remove`: the new list, and a line per folder saying what became\n * of it. A folder to add must exist and be a project, never the home folder or above\n * it (pair's rule); folders are compared as real paths, as the daemon compares them. */\nexport function changeFolders(\n folders: string[],\n op: \"add\" | \"remove\",\n dirs: string[],\n home = os.homedir(),\n): { folders: string[]; said: string[] } {\n const real = (d: string) => {\n try {\n return realpathSync.native(d);\n } catch {\n return path.resolve(d);\n }\n };\n const next = [...folders];\n const said: string[] = [];\n for (const d of dirs) {\n const abs = path.resolve(d);\n const at = next.findIndex((f) => real(f) === real(abs));\n if (op === \"remove\") {\n if (at < 0) said.push(` \u00B7 ${abs} wasn't allowed`);\n else said.push(` \u2713 No longer allowed: ${next.splice(at, 1)[0]}`);\n continue;\n }\n let dir = false;\n try {\n dir = statSync(abs).isDirectory();\n } catch {}\n if (!dir) said.push(` \u2717 ${abs} isn't a folder on this machine`);\n else if (isBroad(abs, home))\n said.push(\n ` \u2717 Not allowing all of ${abs}: name a project folder inside it, so a message can't run anywhere you own`,\n );\n else if (at >= 0) said.push(` \u00B7 ${abs} is already allowed`);\n else {\n next.push(abs);\n said.push(` \u2713 Allowed ${abs}`);\n }\n }\n return { folders: next, said };\n}\n\nexport async function controlMain(argv: string[], out: (s?: string) => void, distDir: string): Promise<void> {\n const flag = (n: string) => {\n const i = argv.indexOf(n);\n return i >= 0 ? argv[i + 1] : undefined;\n };\n const flags = (n: string) => argv.flatMap((a, i) => (a === n && argv[i + 1] ? [argv[i + 1] as string] : []));\n const sub = argv[1];\n switch (sub) {\n case \"pair\": {\n // `spacesheep.dev` is enough: a bare host means https.\n const raw = argv[2];\n if (!raw || raw.startsWith(\"-\")) return out(`usage:\\n${CONTROL_HELP}`);\n if (viaNpx(distDir)) return rerunGlobally(argv, out);\n const url = (/^https?:\\/\\//.test(raw) ? raw : `https://${raw}`).replace(/\\/$/, \"\");\n const cfg = readConfig();\n const sink = cfg.sinks.find((s) => s.url.replace(/\\/$/, \"\") === url);\n // No token is fine where the receiver offers open pairing: the person approves the\n // link signed in, and that is the whole setup.\n const token = flag(\"--token\") ?? (sink ? sinkWithSecrets(sink)?.token : undefined) ?? null;\n if (token !== null && !/^[\\x21-\\x7e]+$/.test(token))\n return out(\n \" That token has a character a key never has (a placeholder like ss_\u2026 pasted as is?). Leave --token out to pair with a link instead.\",\n );\n const folders = flags(\"--folder\");\n const existing = readControl();\n // The folder this ran in \u2014 unless that is the home folder or above it, which\n // would let a message start a session anywhere you own.\n if (!folders.length && !existing?.folders.length) {\n if (!isBroad(process.cwd(), os.homedir())) folders.push(process.cwd());\n else\n out(\n ` ! Not allowing all of ${process.cwd()}: sessions you message may run only in folders you name. Pass --folder <project>, or run this from inside one.`,\n );\n }\n // How sessions run when a message arrives is the person's call, asked once here at\n // the machine \u2014 never a default they find out about when a session can't read a file.\n const mode =\n parseMode(flag(\"--mode\")) ?? (existing?.mode && existing.receivers.length ? existing.mode : await askMode(out));\n const tier = argv.includes(\"--tier\") ? (Math.max(0, Math.min(3, Number(flag(\"--tier\")) || 0)) as Tier) : 0;\n await pair({\n url,\n token,\n // The key the receiver handed over at pairing becomes this machine's sink for it,\n // at --tier (0 \u2014 session state only \u2014 unless given), unless one is configured.\n addSink: (t) => {\n const r = adoptSinkToken(url, t, tier);\n if (r === \"kept\") return;\n out(\n r === \"filled\"\n ? ` \u2713 Sink ${new URL(url).host} now carries the key the receiver handed over.`\n : tier >= 2\n ? ` \u2713 Sink ${new URL(url).host} added at tier ${tier}.`\n : ` \u2713 Sink ${new URL(url).host} added (tier ${tier}: ${tier ? \"tool activity\" : \"session state\"}, no conversation text). \\`sessionpipe sink add ${url} --tier 2\\` sends transcripts too.`,\n );\n },\n folders,\n mode,\n name: flag(\"--name\") ?? existing?.name ?? machineName(cfg, os.hostname()),\n out,\n });\n const c = readControl()!;\n out(` Folders sessions may run in: ${c.folders.join(\", \")}`);\n out(` Mode: ${c.mode} (${MODE_IS[c.mode]})`);\n let cli = path.join(distDir, \"cli.js\");\n try {\n cli = realpathSync(cli);\n } catch {}\n if (argv.includes(\"--no-service\"))\n out(\" Daemon: not installed as a service (--no-service); run `sessionpipe control run` yourself\");\n else out(` Daemon: ${installService({ node: stableNode(process.execPath), cli })}`);\n return;\n }\n case \"mode\": {\n const want = parseMode(argv[2]);\n if (!want) {\n const c = readControl();\n return out(\n ` mode: ${c?.mode ?? \"not set up\"}\\n usage: sessionpipe control mode auto|safe|inherit\\n${MODE_TEXT}`,\n );\n }\n const c = readControl();\n if (!c) return out(\" control isn't set up on this machine: run `sessionpipe control pair <receiver>` first\");\n // A receiver that doesn't know inherit would show this machine as safe (CONTROL.md \u00A72).\n if (want === \"inherit\" && c.mode !== \"inherit\") {\n const no = await withoutInherit(c.receivers.map((r) => r.url));\n if (no.length) {\n for (const why of no) out(` \u2717 ${why}.`);\n out(` Mode stays ${c.mode}. Inherit works once every receiver this machine is paired with knows it.`);\n process.exitCode = 1;\n return;\n }\n }\n c.mode = want;\n writeControl(c);\n // The running daemon reads control.json again within seconds; the next run uses it.\n return out(` \u2713 Sessions you message now run in ${want} mode (${MODE_NOW[want]}).`);\n }\n case \"folders\": {\n // The folders are the machine's own list, so they change here, at its keyboard, as\n // at pairing: no new pairing and no passkey. A message to a session in any other\n // folder is refused (\"that session's folder isn't one this machine allows\").\n const op = argv[2];\n const usage = \" usage: sessionpipe control folders [add|remove <folder>\u2026]\";\n if (op !== undefined && op !== \"add\" && op !== \"remove\") return out(usage);\n const c = readControl();\n if (!c) return out(\" control isn't set up on this machine: run `sessionpipe control pair <receiver>` first\");\n if (op) {\n const dirs = argv.slice(3);\n if (!dirs.length) return out(usage);\n const r = changeFolders(c.folders, op, dirs);\n for (const l of r.said) out(l);\n if (r.folders.join(\"\\n\") !== c.folders.join(\"\\n\")) {\n c.folders = r.folders;\n writeControl(c);\n // The running daemon reads control.json again within seconds and tells the\n // receiver the new list in a hello then.\n out(\" The control daemon uses the new list within seconds.\");\n }\n }\n return out(\n c.folders.length\n ? ` Sessions you message may run in:\\n${c.folders.map((f) => ` ${f}`).join(\"\\n\")}`\n : \" No folder is allowed: a message to a session here is refused until you add one.\",\n );\n }\n case \"keys\": {\n const c = readControl();\n if (argv[2] === \"remove\" && argv[3]) {\n const n = removeKey(argv[3]);\n return out(n ? ` removed ${n} key(s)` : \" no such key\");\n }\n if (!c?.receivers.length)\n return out(\" control isn't paired on this machine (`sessionpipe control pair <receiver>`)\");\n for (const r of c.receivers) {\n out(` ${r.url} \u00B7 machine ${r.machine}`);\n for (const k of r.keys)\n out(\n ` ${k.id.slice(0, 16)}\u2026 ${k.type === \"device\" ? \"device \" : \"passkey\"} ${k.alg === -7 ? \"ES256\" : \"RS256\"} added ${k.added_at.slice(0, 10)}${k.name ? ` ${k.name}` : \"\"}`,\n );\n }\n return;\n }\n case \"off\": {\n const c = await off({ out, ...(argv[2] ? { url: argv[2] } : {}) });\n if (c && !c.receivers.length) uninstallService();\n return;\n }\n case \"status\": {\n const r = await ask(socketPath(stateDir()), { op: \"status\" }, 2000);\n if (r?.op !== \"status\") return out(\" the control daemon isn't running\");\n return out(JSON.stringify(r.status, null, 2));\n }\n case \"run\":\n return runDaemon(out, distDir);\n default:\n return out(CONTROL_HELP);\n }\n}\n\n/** The harnesses set up on this machine, whose hooks an update re-arms. */\nexport function enabledHarnesses(harnesses: Record<string, { enabled?: boolean }>): string[] {\n return Object.entries(harnesses)\n .filter(([, h]) => h?.enabled !== false)\n .map(([n]) => n)\n .filter((n) => /^[a-z][a-z0-9-]{0,40}$/.test(n));\n}\n\nasync function runDaemon(out: (s?: string) => void, distDir: string): Promise<void> {\n const cfg = readControl();\n if (!cfg?.receivers.length) {\n out(\"control isn't paired on this machine; nothing to do (`sessionpipe control pair <receiver>`)\");\n return;\n }\n const log = (s: string) => out(`${new Date().toISOString()} ${s}`);\n let claude: { bin: string; caps: ReturnType<typeof detectCaps>; sig: string } | null = null;\n const claudeNow = () => {\n const bin = findClaude();\n if (!bin) return null;\n const sig = `${bin}:${existsSync(bin) ? realpathSync(bin) : \"\"}`;\n if (claude?.sig !== sig) claude = { bin, caps: detectCaps(bin), sig };\n return claude;\n };\n const sdk = await loadSdk({ claudeBin: findClaude(), env: process.env, log });\n let updater: AutoUpdater | null = null;\n const d = new ControlDaemon(cfg, controlState(), socketPath(stateDir()), {\n now: Date.now,\n fetch,\n log,\n claudeDirs: () => claudeDirs(),\n claude: claudeNow,\n codex: () => codexControl.findCodex(),\n agy: () => antigravityControl.findAgy(),\n codexLogin: (bin) => codexControl.codexLogin(bin),\n acp: (harness) => acpControl.findAcpAgent(harness),\n harnesses: () => drivableHarnesses(),\n run: runClaude,\n sdk,\n login: async (configDir) => {\n const c = claudeNow();\n return c ? claudeLogin(c.bin, configDir) : { loggedIn: null };\n },\n token: (r) => (r.token_in ? secretGet(r.token_in, controlAccount(r.machine)) : null),\n onRestart: () => updater?.restartWhenIdle() ?? false,\n updateStatus: () => (updater ? updater.record() : null),\n // Two daemons started at once and the other one holds the socket: leave it to it.\n onLostSocket: () => process.exit(0),\n });\n try {\n await d.start();\n } catch (e) {\n if (!(e instanceof DaemonRunning)) throw e;\n // Exit 0: no service manager restarts a daemon that stepped aside on purpose.\n log(`${e.message}; this one exits`);\n process.exit(0);\n }\n // Retry pending events even when a session has no more hooks. This also drains\n // what workers with a locked keychain left. The shared drain honours each sink's\n // wait and the machine-wide delivery lock, wherever its token lives.\n const drainTimer = setInterval(() => {\n const sinks = readConfig().sinks.filter((s) => !s.paused);\n if (sinks.length) void drain(stateDir(), sinks, new Outbox(stateDir())).catch(() => {});\n }, 60_000);\n drainTimer.unref();\n watchFile(controlFile(), { interval: 5000 }, () => {\n const next = readControl();\n if (next) d.reload(next);\n });\n let stopping = false;\n const bye = async () => {\n if (stopping) return;\n stopping = true;\n updater?.stop();\n await d.stop();\n process.exit(0);\n };\n const signals = [\"SIGTERM\", \"SIGINT\"] as const;\n for (const sig of signals) process.on(sig, bye);\n\n // Restart onto the code now on disk. The daemon is stopped first (its socket closed,\n // its long-polls ended), so two never poll at once.\n const restart = async (_from: string, to: string): Promise<void> => {\n stopping = true;\n updater?.stop();\n clearInterval(drainTimer);\n unwatchFile(controlFile());\n for (const sig of signals) process.off(sig, bye);\n await d.stop();\n const via = restartVia({ env: process.env, platform: process.platform, pid: process.pid, ppid: process.ppid });\n if (via) {\n log(`exiting ${UPDATE_EXIT} so ${via === \"supervisor\" ? \"the supervising sessionpipe\" : via} starts ${to}`);\n process.exit(UPDATE_EXIT);\n }\n // Nobody restarts this process: it stays, as the new daemon's parent.\n let cli = path.join(distDir, \"cli.js\");\n try {\n cli = realpathSync(cli);\n } catch {}\n log(`no service manager restarts this daemon: pid ${process.pid} now runs ${to} as its child`);\n const sup = supervise({ node: process.execPath, args: [cli, \"control\", \"run\"], env: process.env, log });\n for (const sig of [...signals, \"SIGHUP\"] as const) process.on(sig, () => sup.stop(sig));\n };\n updater = new AutoUpdater({\n now: Date.now,\n log,\n version: VERSION,\n file: updateFile(),\n off: () => autoUpdateOff({ env: process.env, config: readConfig(), distDir }),\n latest: () => latestVersion(fetch),\n installed: () => installedVersion({ node: process.execPath, distDir }),\n install: (v) =>\n installVersion(v, { node: process.execPath, distDir, harnesses: enabledHarnesses(readConfig().harnesses) }),\n daemon: d,\n restart,\n });\n updater.start();\n}\n\nexport async function waitMain(argv: string[], out: (s?: string) => void): Promise<void> {\n const i = argv.indexOf(\"--session\");\n const session = waitSession(i >= 0 ? argv[i + 1] : undefined);\n if (!session) {\n out(\"sessionpipe wait: which session? Pass --session <harness>:<id> (Claude Code sets CLAUDE_CODE_SESSION_ID).\");\n process.exitCode = 2;\n return;\n }\n out(await waitForMessage(session));\n}\n\n/** Give a sink the key a receiver handed over at pairing. A sink for the receiver that\n * has a key keeps it (\"kept\"); one without a key gets this one (\"filled\"); otherwise a\n * new sink at `tier` (\"added\"). */\nexport function adoptSinkToken(url: string, token: string, tier: Tier, file?: string): \"kept\" | \"filled\" | \"added\" {\n const now = file ? readConfig(file) : readConfig();\n const same = now.sinks.find((x) => x.url.replace(/\\/$/, \"\") === url);\n if (same && (same.token || same.token_in)) return \"kept\";\n if (same) same.token = token;\n else now.sinks.push({ name: new URL(url).host, url, tier, pii: false, token });\n if (file) writeConfig(now, file);\n else writeConfig(now);\n return same ? \"filled\" : \"added\";\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The control daemon (spec/CONTROL.md): one process per computer. It holds one\n// long-poll per paired receiver, verifies every command itself against the keys\n// enrolled at this terminal, and delivers each one the cheapest way the session\n// allows \u2014 to a parked waiter, at the session's next Stop, to a session it holds\n// through the Agent SDK, or by a headless resume or fork \u2014 then acks how. Claude Code,\n// Codex (`codex exec`) and Antigravity (`agy`) sessions can be resumed and started\n// headlessly, and so can any agent that speaks ACP (held like an SDK session, `api`\n// mode); the Agent SDK, waiters, Stop blocks and forks are Claude Code's.\n//\n// A receiver can queue a message; it can never make this process run one.\nimport { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, statSync, unlinkSync } from \"node:fs\";\nimport net from \"node:net\";\nimport path from \"node:path\";\nimport {\n acpControl,\n antigravityControl,\n claudeAccounts,\n claudeControl,\n codexControl,\n deniedNote,\n type HarnessAccount,\n HELLO_HARNESSES_MAX,\n JOB_TIMEOUT_MS,\n jobEnv,\n type Login,\n type Reading,\n type RunOptions,\n type RunResult,\n redactSecrets,\n safeId,\n shortId,\n untilde,\n} from \"@sessionpipe/core\";\nimport {\n type ControlCommand,\n KEY_TYPES,\n levelRank,\n narrower,\n parseSessionRef,\n type RunLevel,\n type StartPermission,\n verifyCommand,\n} from \"@sessionpipe/core/control\";\nimport { type Alias, type Aliases, aliasFile, readAliases, receiverIdOf, writeAliases } from \"./aliases.js\";\nimport { fetchFiles, withFiles, writeFiles } from \"./files.js\";\nimport { ask, type LocalReply, type LocalRequest } from \"./local.js\";\nimport { awaitAnswer, transcriptEnd } from \"./reply.js\";\nimport { type DeliveryMode, frame, frameStart, IN_PLACE_ANSWER, kindPath, routePrompt } from \"./route.js\";\nimport {\n type Ack,\n AckOutbox,\n type ControlConfig,\n type ControlMode,\n type DaemonState,\n NonceStore,\n type PairedReceiver,\n readState,\n type StartOptions,\n startOptionsOf,\n writeControl,\n writeState,\n} from \"./store.js\";\nimport { AnswerStream } from \"./stream.js\";\n\nconst {\n claudeArgs,\n claudeEnv,\n findTranscript,\n isUuid,\n liveProcess,\n loginHint,\n parseResult,\n recentlyWritten,\n sessionFolder,\n} = claudeControl;\ntype Caps = claudeControl.Caps;\ntype Transcript = claudeControl.Transcript;\n\n/** Where a session lives: its folder, and how the harness names it. */\ninterface Placed {\n folder: string;\n /** Claude Code's transcript. */\n transcript: Transcript | null;\n /** Codex / Antigravity: the harness's own id to resume (an alias's, else the command's). */\n target?: string;\n /** Codex: the session's rollout file, whose writes say whether it is in use. */\n file?: string | null;\n}\n\n/** A harness the daemon runs headlessly besides Claude Code (codex-control.ts,\n * antigravity-control.ts). */\ninterface Driver {\n label: string;\n cmd: string;\n bin: () => string | null;\n args: (o: { permission: RunLevel; prompt: string; cwd: string; resume?: string; model?: string }) => string[];\n /** The levels a start may ask for here, and the one it gets by default (CONTROL.md \u00A72). */\n levels: (mode: ControlMode) => StartPermission[];\n defaultLevel: (mode: ControlMode) => RunLevel;\n /** Model ids to suggest, when the harness takes a model at all. */\n models?: () => string[];\n reading: () => Reading & { warnings?: string[] };\n login?: (bin: string) => Promise<Login>;\n loginHint?: string;\n}\n\n/** One harness's entry in the hello's `start` (CONTROL.md \u00A72). */\nexport interface StartEntry {\n permissions: StartPermission[];\n /** What a start that names none gets: a level, or `inherit` on an inherit machine. */\n permission: RunLevel;\n models?: string[];\n any_model?: boolean;\n}\n\n/** The modes the Agent SDK takes for every level: a start through it is not limited by\n * what `claude --help` lists (sdk.ts maps each level to its `permissionMode`). */\nconst SDK_CAPS: Caps = {\n hasMode: true,\n modes: [\"plan\", \"dontAsk\", \"acceptEdits\", \"auto\"],\n promptsNone: false,\n fork: true,\n};\n\n/** A failure the harness puts down to the model it was asked to run. */\nconst MODEL_FAILURE_RE = /\\bmodel\\b/i;\n\n/** A start, read from the command before it is verified: only ever used to order a\n * prompt behind it, never to run anything. */\nfunction startNamed(cmd: unknown): string | null {\n if (typeof cmd !== \"string\" || cmd.length > 64 * 1024 || !cmd.includes('\"start\"')) return null;\n try {\n const c = JSON.parse(cmd) as { kind?: unknown; session?: unknown };\n return c?.kind === \"start\" && typeof c.session === \"string\" ? c.session : null;\n } catch {\n return null;\n }\n}\n\ndeclare const __SESSIONPIPE_VERSION__: string;\nconst VERSION = typeof __SESSIONPIPE_VERSION__ === \"string\" ? __SESSIONPIPE_VERSION__ : \"0.0.0\";\n\nconst MAX_REPLY = 20_000;\nconst HELLO_EVERY_MS = 10 * 60_000;\n/** A message waiting for a Stop that never comes goes another way after this. */\nconst TURN_FALLBACK_MS = 30 * 60_000;\n/** How long the daemon follows a session's turn for the answer to an in-place\n * message before acking it delivered without one. */\nconst ANSWER_WAIT_MS = 30 * 60_000;\n/** How long a Stop hook may take to be answered. */\nconst RECENT_ACKS_MS = 25 * 3600_000;\n/** Events that prove a pending permission prompt was resolved some other way. */\nconst CLOSES_ATTENTION = new Set([\n \"PostToolUse\",\n \"PostToolUseFailure\",\n \"Stop\",\n \"StopFailure\",\n \"UserPromptSubmit\",\n \"SessionEnd\",\n]);\n\n/** The message as the receiver carried it (control.json). */\nexport interface Carried {\n id: string;\n cmd: string;\n csig?: string | null;\n grant?: { str: string; cred: string; ad: string; cd: string; sig: string } | null;\n confirm?: { cred: string; ad: string; cd: string; sig: string } | null;\n at: string;\n expires_at: string;\n}\n\n/** A session the daemon holds: through the Agent SDK (sdk.ts; a fake in tests), or an\n * ACP agent it runs (core's acp-control.ts), which says so in `mode`. */\nexport interface SdkSession {\n /** Deliver one message; resolves with the agent's reply when the turn ends. */\n send(text: string): Promise<{ reply: string; error?: string }>;\n interrupt(): Promise<void>;\n close(): void;\n readonly busy: boolean;\n readonly lastUsed: number;\n /** How a message through it is acked; `sdk` when unsaid. */\n readonly mode?: DeliveryMode;\n /** Gone for good (the process left): drop it, a later message reopens the session. */\n readonly closed?: boolean;\n}\nexport interface SdkHost {\n start(o: {\n session: string;\n cwd: string;\n /** The level the session runs at (CONTROL.md \u00A73.1), as its `permissionMode`; none in inherit. */\n permission: RunLevel;\n /** The model, when the start asked for one. */\n model?: string;\n configDir?: string;\n allowedTools?: string[];\n }): SdkSession;\n}\n\nexport interface DaemonDeps {\n now: () => number;\n fetch: typeof fetch;\n log: (line: string) => void;\n claudeDirs: () => string[];\n claude: () => { bin: string; caps: Caps } | null;\n /** Codex CLI's `codex` and Antigravity's `agy` on this machine (null: not installed).\n * Absent: this daemon doesn't drive that harness. */\n codex?: () => string | null;\n agy?: () => string | null;\n /** Is Codex signed in as this process sees it? Asked before a run. */\n codexLogin?: (bin: string) => Promise<Login>;\n /** An ACP agent's CLI on this machine, by harness name (core's findAcpAgent; null:\n * not installed). Absent: this daemon drives none of them. */\n acp?: (harness: string) => { bin: string; args: string[] } | null;\n /** The harnesses every hello advertises (core's drivableHarnesses); by default, the\n * ones the finders above find. */\n harnesses?: () => string[];\n /** The harness accounts every hello names; by default, those signed in across\n * `claudeDirs`, read again for each hello. */\n accounts?: () => HarnessAccount[];\n /** The models a hello suggests for Codex; by default, its own models cache. */\n codexModels?: () => string[];\n run: (bin: string, args: string[], o: RunOptions) => Promise<RunResult>;\n sdk?: SdkHost | null;\n /** How long to follow a live session's turn for an in-place answer (tests shorten it). */\n answerWaitMs?: number;\n /** Close an SDK session idle this long (a held session costs ~300 MB). */\n sdkIdleMs?: number;\n /** How long one of a start's files may take to download (tests shorten it). */\n fileTimeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n /** Is Claude Code signed in for this account, as this process sees it? Asked before\n * a headless run, so a login the daemon can't read (a macOS keychain with nobody at\n * the screen) fails with what to do, not with Claude Code's \"please run /login\". */\n login?: (configDir?: string) => Promise<Login>;\n /** Read a receiver's machine token again: it may live in a keychain that was\n * locked when the daemon started and has unlocked since. */\n token?: (r: PairedReceiver) => string | null;\n platform?: NodeJS.Platform;\n /** `sessionpipe update` installed a new copy: restart onto it once idle. True when\n * accepted (autoupdate.ts). */\n onRestart?: () => boolean;\n /** The updater's view, for `control status`. */\n updateStatus?: () => unknown;\n /** Another daemon took the socket path: this one has stopped and should exit. */\n onLostSocket?: () => void;\n}\n\n/** Another daemon already answers on the socket: this one must not start. */\nexport class DaemonRunning extends Error {\n constructor(readonly other: { pid?: number; version?: string }) {\n super(\n `another control daemon already serves this machine (${other.pid ? `pid ${other.pid}, ` : \"\"}sessionpipe ${other.version ?? \"?\"})`,\n );\n }\n}\n\ninterface TurnPending {\n receiver: PairedReceiver;\n msgId: string;\n text: string;\n session: string;\n queuedAt: number;\n}\n\ninterface Live {\n midTurn: boolean;\n /** The Stop hook just delivered a block: the next Stop event continues the turn. */\n continued: boolean;\n waiter: net.Socket | null;\n turnQueue: TurnPending[];\n attentions: Map<string, net.Socket>;\n cwd?: string;\n transcript?: string;\n lastEvent: number;\n}\n\ninterface PollState {\n started: number;\n last: number | null;\n error: string | null;\n on: boolean;\n unauthorized: boolean;\n authBackoff: number;\n wake: (() => void) | null;\n}\n\nexport interface Status {\n version: string;\n pid: number;\n name: string;\n receivers: {\n url: string;\n machine: string;\n keys: number;\n polling: boolean;\n /** Last successful poll; failed responses must not conceal a control outage. */\n last_poll: number | null;\n /** Time since success, or since this loop started if it has never succeeded. */\n last_poll_age_ms: number;\n last_error: string | null;\n }[];\n waiting: string[];\n mid_turn: string[];\n attentions: { session: string; id: string }[];\n sdk: string[];\n nonces: number;\n acks_pending: number;\n delivered: Record<string, number>;\n /** What a start may carry per harness, as the last hello said (CONTROL.md \u00A72). */\n start: Record<string, StartEntry>;\n /** Null when the daemon could restart now (nothing in hand); otherwise what it holds. */\n busy: string | null;\n update?: unknown;\n}\n\n/** The machine's own caps (CONTROL.md \u00A76 `start`): every command is the owner's,\n * signed, but a burst of them must not start a crowd of agents. A start beyond the\n * caps is refused `start_limit`; a headless run beyond `headless` waits its turn. */\n/** What a receiver may let its sessions use without asking (CONTROL.md \u00A76): its own MCP\n * servers, by name \u2014 never a built-in tool. The receiver is where the message came\n * from, so answering it there (publishing a page, replying) is the job; anything else\n * still needs the person's approval rule. */\nexport function sessionToolsFrom(v: unknown): string[] {\n if (!Array.isArray(v)) return [];\n return [\n ...new Set(v.filter((t): t is string => typeof t === \"string\" && /^mcp__[A-Za-z0-9_-]{1,64}$/.test(t))),\n ].slice(0, 8);\n}\n\nexport const LIMITS = { startConcurrent: 2, startPerHour: 10, headless: 3 } as const;\n\nexport class ControlDaemon {\n private server: net.Server | null = null;\n private readonly live = new Map<string, Live>();\n private readonly sdkSessions = new Map<string, SdkSession>();\n private readonly nonces: NonceStore;\n private readonly acks: AckOutbox;\n private readonly recentAcks = new Map<string, { ack: Ack; at: number }>();\n private readonly inflight = new Set<string>();\n private readonly queues = new Map<string, Promise<unknown>>();\n private readonly lastEnd = new Map<string, number>();\n private state: DaemonState;\n private running = false;\n private readonly polling = new Map<string, PollState>();\n private readonly delivered: Record<string, number> = {};\n private helloTimer: NodeJS.Timeout | null = null;\n private helloSoon: NodeJS.Timeout | null = null;\n private readonly aborts = new Set<AbortController>();\n /** Per receiver: the MCP servers its sessions may use unattended (its well-known). */\n private readonly sessionTools = new Map<string, string[]>();\n /** Sessions a run of the daemon's own is working on right now (a start, a resume):\n * a message for one waits for that run and resumes it \u2014 never a copy, which would\n * set two agents on one task (2026-10-02: a \"just merge when ready\" sent while the\n * start still ran forked a second agent that raced the first toward main). */\n private readonly ownRuns = new Map<string, number>();\n private startsRunning = 0;\n private startTimes: number[] = [];\n private procs = 0;\n private readonly procWaiters: (() => void)[] = [];\n /** configDir \u2192 the last login answer and when (a yes is kept 10 minutes, a no 30 s). */\n private readonly logins = new Map<string, { at: number; login: Login }>();\n /** Intake paused for an update: the long-polls end and wait for this. */\n private paused: { until: Promise<void>; go: () => void } | null = null;\n /** Poll answers whose messages are being read and handed out. */\n private receiving = 0;\n /** The socket file this daemon created (dev:ino): stop() removes only that one, and a\n * different file at the path means another daemon took over. */\n private sockId: string | null = null;\n private ownTimer: NodeJS.Timeout | null = null;\n /** Every open local connection: stop() ends them, or the server's close would wait\n * on a client that never says anything. */\n private readonly conns = new Set<net.Socket>();\n /** Codex and Antigravity sessions the daemon started, under the start's id (aliases.ts). */\n private aliases: Aliases;\n /** Starts in hand, by the session they name, from the moment they arrive: a prompt\n * for that session that came in the same poll waits for its start rather than\n * finding no session (2026-10-04: a start and a prompt queued back to back). */\n private readonly startsPending = new Map<string, Promise<void>>();\n\n constructor(\n private cfg: ControlConfig,\n private readonly dir: string,\n private readonly sock: string,\n private readonly deps: DaemonDeps,\n ) {\n this.nonces = new NonceStore(path.join(dir, \"nonces.jsonl\"), deps.now);\n this.acks = new AckOutbox(path.join(dir, \"acks.jsonl\"));\n this.state = readState(path.join(dir, \"state.json\"));\n this.aliases = readAliases(aliasFile(dir));\n }\n\n // --- lifecycle ------------------------------------------------------------------\n\n async start(): Promise<void> {\n this.running = true;\n mkdirSync(this.dir, { recursive: true, mode: 0o700 });\n await this.listen();\n for (const r of this.cfg.receivers) void this.pollLoop(r);\n this.helloTimer = setInterval(() => void this.helloAll(), HELLO_EVERY_MS);\n this.helloTimer.unref();\n void this.helloAll();\n void this.flushAcks();\n const idle = setInterval(() => this.closeIdleSdk(), Math.min(60_000, this.deps.sdkIdleMs ?? 60_000));\n idle.unref();\n if (this.sockId) {\n this.ownTimer = setInterval(() => void this.checkSocket(), 10_000);\n this.ownTimer.unref();\n }\n this.deps.log(\n `control daemon ${VERSION} up \u00B7 pid ${process.pid} \u00B7 ${this.cfg.receivers.length} receiver(s) \u00B7 socket ${this.sock}`,\n );\n }\n\n /** `leaveSocket`: the socket path is another daemon's now. Closing a Unix-socket\n * server makes Node unlink its path whoever holds it, so this one's server is left\n * open for the process's exit to drop. */\n async stop(o: { leaveSocket?: boolean } = {}): Promise<void> {\n this.running = false;\n this.paused?.go();\n for (const a of this.aborts) a.abort();\n for (const st of this.polling.values()) st.wake?.();\n if (this.helloTimer) clearInterval(this.helloTimer);\n if (this.helloSoon) clearTimeout(this.helloSoon);\n if (this.ownTimer) clearInterval(this.ownTimer);\n for (const s of this.sdkSessions.values()) s.close();\n for (const l of this.live.values()) {\n l.waiter?.destroy();\n for (const a of l.attentions.values()) a.destroy();\n }\n for (const c of this.conns) c.destroy();\n if (o.leaveSocket) {\n this.sockId = null;\n return;\n }\n await new Promise<void>((r) => (this.server ? this.server.close(() => r()) : r()));\n this.server = null;\n // Only the socket file this daemon made: after a hand-over the path is someone else's.\n /* v8 ignore next -- Node unlinks a listening Unix socket's path in server.close(), so the file is gone by here; kept for a runtime that doesn't */\n if (process.platform !== \"win32\" && this.sockId && socketId(this.sock) === this.sockId)\n try {\n unlinkSync(this.sock);\n } catch {}\n this.sockId = null;\n }\n\n /** Null when nothing is in hand, so a restart would interrupt nothing; otherwise what\n * is. Parked waiters don't count: a waiter reconnects in silence (CONTROL.md \u00A78). A\n * session someone is working in mid-turn does (a restart forgets it is mid-turn, so a\n * message to it would fork rather than wait for its Stop), unless it has been silent\n * for ten minutes: a session killed mid-turn never sends its Stop. */\n busy(): string | null {\n if (this.inflight.size) return `${this.inflight.size} message(s) in hand`;\n if (this.procs || this.ownRuns.size) return \"a headless agent run\";\n if (this.startsRunning) return \"a session starting\";\n for (const s of this.sdkSessions.values()) if (s.busy) return \"an Agent SDK session mid-turn\";\n for (const l of this.live.values()) if (l.attentions.size) return \"a permission prompt waiting for an answer\";\n const now = this.deps.now();\n for (const l of this.live.values())\n if (l.midTurn && now - l.lastEvent < 10 * 60_000) return \"a session on this machine mid-turn\";\n if (this.receiving) return \"messages just received\";\n if (this.flushing) return \"acks being sent\";\n return null;\n }\n\n /** Stop taking messages: every long-poll ends now and waits for resumeIntake(). The\n * receiver keeps what arrives meanwhile; the local socket keeps answering. */\n pauseIntake(): void {\n if (this.paused) return;\n let go!: () => void;\n const until = new Promise<void>((r) => {\n go = r;\n });\n this.paused = { until, go };\n for (const a of this.aborts) a.abort();\n }\n\n resumeIntake(): void {\n const p = this.paused;\n this.paused = null;\n p?.go();\n }\n\n /** The socket path still holds this daemon's file. Gone: listen again. Replaced:\n * another daemon took over (two started at once), so this one steps aside. */\n private async checkSocket(): Promise<void> {\n if (!this.running || !this.sockId) return;\n const now = socketId(this.sock);\n if (now === this.sockId) return;\n if (now === null) {\n // Someone deleted the file. The old server keeps the connections it has (closing\n // it would wait on parked waiters, and unlink the path again); a new one takes it.\n this.deps.log(`the socket ${this.sock} vanished; listening again`);\n this.server?.unref();\n this.server = null;\n try {\n await this.listen();\n } catch (e) {\n this.deps.log(\n `couldn't listen again: ${String(/* v8 ignore next -- listen() throws Errors (net, DaemonRunning) */ (e as Error)?.message || e)}`,\n );\n }\n return;\n }\n this.deps.log(\"another control daemon took over the socket; this one stops\");\n await this.stop({ leaveSocket: true });\n this.deps.onLostSocket?.();\n }\n\n reload(cfg: ControlConfig): void {\n const known = new Set(this.cfg.receivers.map((r) => r.control + r.machine));\n const told = JSON.stringify([this.cfg.folders, this.cfg.mode, this.cfg.name]);\n this.cfg = cfg;\n for (const r of cfg.receivers) if (!known.has(r.control + r.machine)) void this.pollLoop(r);\n // `control folders`, `control mode` or a `--rename-machine` changed what a hello says:\n // say it now, so the receiver doesn't wait up to ten minutes for the next one.\n if (this.running && JSON.stringify([cfg.folders, cfg.mode, cfg.name]) !== told) void this.helloAll();\n }\n\n status(): Status {\n return {\n version: VERSION,\n pid: process.pid,\n name: this.cfg.name,\n receivers: this.cfg.receivers.map((r) => {\n const p = this.polling.get(r.control + r.machine);\n return {\n url: r.url,\n machine: r.machine,\n keys: r.keys.length,\n polling: !!p?.on,\n last_poll: p?.last ?? null,\n last_poll_age_ms: p ? Math.max(0, this.deps.now() - (p.last ?? p.started)) : 0,\n last_error: p?.error ?? null,\n };\n }),\n waiting: [...this.live].filter(([, l]) => l.waiter).map(([k]) => k),\n mid_turn: [...this.live].filter(([, l]) => l.midTurn).map(([k]) => k),\n attentions: [...this.live].flatMap(([k, l]) => [...l.attentions.keys()].map((id) => ({ session: k, id }))),\n sdk: [...this.sdkSessions.keys()],\n nonces: this.nonces.size,\n acks_pending: this.acks.all().length,\n delivered: { ...this.delivered },\n start: this.startOptions(),\n busy: this.busy(),\n ...(this.deps.updateStatus ? { update: this.deps.updateStatus() } : {}),\n };\n }\n\n // --- the local socket -----------------------------------------------------------\n\n /** One daemon per machine: a daemon that answers on the socket keeps it, and this\n * one doesn't start. A socket file nobody answers on is a dead daemon's; it goes. */\n private async listen(): Promise<void> {\n const other = await ask(this.sock, { op: \"status\" }, 1500);\n if (other?.op === \"status\") throw new DaemonRunning((other.status ?? {}) as { pid?: number; version?: string });\n if (process.platform !== \"win32\") {\n try {\n if (existsSync(this.sock)) unlinkSync(this.sock);\n } catch {}\n }\n this.server = net.createServer((s) => this.onConn(s));\n await new Promise<void>((resolve, reject) => {\n this.server!.once(\"error\", reject);\n this.server!.listen(this.sock, () => resolve());\n });\n if (process.platform !== \"win32\") {\n // The socket is this user's alone (CONTROL.md \u00A78: mode 0600), whatever the umask.\n chmodSync(this.sock, 0o600);\n this.sockId = socketId(this.sock);\n }\n }\n\n private onConn(s: net.Socket): void {\n let buf = \"\";\n let handled = false;\n this.conns.add(s);\n s.on(\"close\", () => this.conns.delete(s));\n s.on(\"error\", () => {});\n s.on(\"data\", (d) => {\n if (handled) return;\n buf += d.toString(\"utf8\");\n if (buf.length > 64 * 1024) return s.destroy();\n const i = buf.indexOf(\"\\n\");\n if (i < 0) return;\n handled = true;\n let req: LocalRequest;\n try {\n req = JSON.parse(buf.slice(0, i)) as LocalRequest;\n } catch {\n return s.destroy();\n }\n this.onRequest(req, s);\n });\n }\n\n private reply(s: net.Socket, r: LocalReply): void {\n try {\n s.end(`${JSON.stringify(r)}\\n`);\n } catch {}\n }\n\n private liveOf(session: string): Live {\n let l = this.live.get(session);\n if (!l) {\n l = {\n midTurn: false,\n continued: false,\n waiter: null,\n turnQueue: [],\n attentions: new Map(),\n lastEvent: this.deps.now(),\n };\n this.live.set(session, l);\n }\n return l;\n }\n\n private onRequest(req: LocalRequest, s: net.Socket): void {\n switch (req.op) {\n case \"status\":\n this.reply(s, { op: \"status\", status: this.status() });\n return;\n case \"wait\": {\n if (!parseSessionRef(req.session)) {\n this.reply(s, { op: \"none\" });\n return;\n }\n const l = this.liveOf(req.session);\n if (l.waiter && l.waiter !== s) this.reply(l.waiter, { op: \"replaced\" });\n l.waiter = s;\n s.on(\"close\", () => {\n if (l.waiter === s) {\n l.waiter = null;\n this.scheduleHello();\n }\n });\n this.scheduleHello();\n return;\n }\n case \"stop\": {\n const l = this.liveOf(req.session);\n l.lastEvent = this.deps.now();\n const p = this.takeTurn(l);\n if (!p) {\n this.reply(s, { op: \"none\" });\n return;\n }\n l.continued = true;\n const from = this.answerFrom(req.session);\n this.reply(s, { op: \"block\", reason: `${frame(p.text, p.receiver.url)}\\n\\n${IN_PLACE_ANSWER}`, id: p.msgId });\n this.followAnswer(p.receiver, p.msgId, \"turn\", req.session, from, p.queuedAt);\n return;\n }\n case \"permission\": {\n const l = this.liveOf(req.session);\n const prev = l.attentions.get(req.attention);\n if (prev && prev !== s) this.reply(prev, { op: \"none\" });\n l.attentions.set(req.attention, s);\n s.on(\"close\", () => {\n if (l.attentions.get(req.attention) === s) l.attentions.delete(req.attention);\n });\n return;\n }\n case \"event\":\n this.onEvent(req);\n this.reply(s, { op: \"ok\" });\n return;\n case \"restart\":\n this.reply(s, this.deps.onRestart?.() ? { op: \"ok\" } : { op: \"none\" });\n return;\n default:\n s.destroy();\n }\n }\n\n /** A queued turn message that hasn't expired. */\n private takeTurn(l: Live): TurnPending | null {\n while (l.turnQueue.length) {\n const p = l.turnQueue.shift()!;\n if (!this.inflight.has(p.msgId)) continue;\n return p;\n }\n return null;\n }\n\n private onEvent(e: Extract<LocalRequest, { op: \"event\" }>): void {\n // A worker that read the aliases a moment before a start recorded its session still\n // names the harness's own id; this daemon knows the start's.\n const l = this.liveOf(this.named(e.session));\n l.lastEvent = this.deps.now();\n if (e.cwd) l.cwd = e.cwd;\n if (e.transcript) l.transcript = e.transcript;\n if (CLOSES_ATTENTION.has(e.event) && l.attentions.size) {\n for (const s of l.attentions.values()) this.reply(s, { op: \"none\" });\n l.attentions.clear();\n }\n if (e.event === \"UserPromptSubmit\" || e.event === \"SessionStart\") {\n if (e.event === \"UserPromptSubmit\") l.midTurn = true;\n return;\n }\n if (e.event === \"Stop\" && l.continued) {\n l.continued = false;\n return;\n }\n if (e.event === \"Stop\" || e.event === \"StopFailure\" || e.event === \"SessionEnd\") {\n l.midTurn = false;\n l.continued = false;\n // A message queued for a Stop that came and went without taking it (it\n // arrived after the hook asked, or the turn failed) goes another way.\n const left = l.turnQueue.splice(0);\n for (const p of left) if (this.inflight.has(p.msgId)) void this.reroute(p);\n }\n }\n\n // --- receivers ------------------------------------------------------------------\n\n private async pollLoop(first: PairedReceiver): Promise<void> {\n const key = first.control + first.machine;\n const st: PollState = {\n started: this.deps.now(),\n last: null,\n error: null,\n on: true,\n unauthorized: false,\n authBackoff: 0,\n wake: null,\n };\n this.polling.set(key, st);\n // Unlike a bare sleep, this wait can end as soon as a hello proves the token\n // works, or the daemon stops. Keep exactly one poll loop per receiver.\n const retry = (ms: number) =>\n new Promise<void>((resolve) => {\n st.on = false;\n if (!this.running) {\n resolve();\n return;\n }\n const timer = setTimeout(() => st.wake?.(), ms);\n timer.unref();\n st.wake = () => {\n clearTimeout(timer);\n st.wake = null;\n resolve();\n };\n });\n let backoff = 0;\n let downSince = 0;\n // A deploy takes the receiver away for seconds, not minutes: retry soon, capped at\n // 15 s (one request per machine), with jitter so every machine a deploy dropped\n // doesn't come back in the same instant. The old 60 s / 5 min steps left a\n // machine blind for minutes after a 30-second outage.\n const steps = [1000, 2000, 5000, 10_000, 15_000];\n const pause = (n: number) => (steps[Math.min(n, steps.length - 1)] as number) * (0.75 + Math.random() * 0.5);\n for (;;) {\n // The current record every round: `control pair` may have added a key since.\n const r = this.cfg.receivers.find((x) => x.control + x.machine === key);\n if (!this.running || !r) break;\n if (this.paused) {\n st.on = false;\n await this.paused.until;\n continue;\n }\n if (!r.token) {\n // Its token lives in a keychain this process can't read yet (locked, or nobody\n // logged in): ask again every 30 s rather than poll with no bearer.\n const t = this.deps.token?.(r) ?? null;\n if (t) {\n r.token = t;\n this.deps.log(`${r.url}: machine token readable again`);\n } else {\n if (!st.error?.startsWith(\"can't read\"))\n this.deps.log(`${r.url}: can't read this machine's token from ${r.token_in ?? \"its store\"}; retrying`);\n st.error = `can't read this machine's token from ${r.token_in ?? \"its store\"} (locked?); retrying every 30 s`;\n await retry(30_000);\n continue;\n }\n }\n const ctl = new AbortController();\n st.on = true;\n this.aborts.add(ctl);\n // A poll held past wait + 10 s is a dead connection (a laptop that slept, a\n // network that changed): give up on it and ask again.\n const t = setTimeout(() => ctl.abort(), 35_000);\n try {\n const u = new URL(r.control);\n u.searchParams.set(\"machine\", r.machine);\n u.searchParams.set(\"wait\", \"25\");\n const asked = this.deps.now();\n const res = await this.deps.fetch(u, { headers: { authorization: `Bearer ${r.token}` }, signal: ctl.signal });\n // The request deadline applies to reading the response, never to a retry\n // delay (which can be much longer than a long-poll).\n if (res.status !== 200) clearTimeout(t);\n st.unauthorized = res.status === 401;\n if (downSince && (res.status === 200 || res.status === 204)) {\n // Timed to when this poll was sent: a long-poll that reconnected is then held\n // up to `wait` before it answers.\n this.deps.log(`${r.url}: back after ${Math.round((asked - downSince) / 1000)} s (${backoff} failed tries)`);\n downSince = 0;\n }\n if (res.status === 401) {\n st.error = \"the receiver no longer knows this machine (401); run `sessionpipe control pair` again\";\n this.deps.log(`${r.url}: ${st.error}`);\n downSince ||= this.deps.now();\n backoff++;\n const delay = Math.min(60_000 * 2 ** st.authBackoff, 30 * 60_000);\n st.authBackoff = Math.min(st.authBackoff + 1, 5);\n await retry(delay);\n continue;\n }\n if (res.status === 200) {\n let fresh = 0;\n this.receiving++;\n try {\n const body = (await res.json()) as { messages?: Carried[] };\n // Looked up again: a key may have been added while this poll was parked.\n const cur = this.cfg.receivers.find((x) => x.control + x.machine === key) ?? r;\n // Not awaited: a headless turn can run for half an hour, and the next\n // message (for another session, or a permission answer) must not wait\n // behind it. handle() orders what must be ordered (one session's prompts).\n for (const m of body.messages ?? []) {\n if (m && !this.inflight.has(m.id)) fresh++;\n void this.handle(cur, m).catch((e) =>\n this.deps.log(\n `handle ${String(m?.id).slice(-8)}: ${String(/* v8 ignore next -- handle() rejects with an Error (the ack file) */ (e as Error)?.message || e)}`,\n ),\n );\n }\n } finally {\n this.receiving--;\n }\n clearTimeout(t);\n st.last = this.deps.now();\n st.error = null;\n st.authBackoff = 0;\n backoff = 0;\n // Only messages already in hand (a receiver that ignores `taken`): don't\n // turn the long-poll into a spin.\n if (!fresh) await sleep(2000);\n } else if (res.status === 204) {\n st.last = this.deps.now();\n st.error = null;\n st.authBackoff = 0;\n backoff = 0;\n } else {\n st.error = `HTTP ${res.status}`;\n downSince ||= this.deps.now();\n let delay = pause(backoff++);\n if (res.status === 503) {\n const after = res.headers.get(\"retry-after\");\n const ms = after && /^\\d+$/.test(after) ? Number(after) * 1000 : Date.parse(after ?? \"\") - this.deps.now();\n if (Number.isFinite(ms)) delay = Math.max(delay, ms);\n }\n // Node treats an overflowing timeout as 1 ms; a long Retry-After must\n // not accidentally become a tight loop.\n await retry(Math.min(delay, 2_147_483_647));\n }\n } catch (e) {\n if (!this.running) break;\n // Paused for an update: the abort was ours, not the network's.\n if (this.paused) continue;\n st.error = String((e as Error)?.message || e).slice(0, 120);\n st.unauthorized = false;\n downSince ||= this.deps.now();\n clearTimeout(t);\n await retry(pause(backoff++));\n } finally {\n clearTimeout(t);\n this.aborts.delete(ctl);\n }\n }\n st.on = false;\n }\n\n private scheduleHello(): void {\n if (this.helloSoon) return;\n this.helloSoon = setTimeout(() => {\n this.helloSoon = null;\n void this.helloAll();\n }, 1500);\n this.helloSoon.unref();\n }\n\n /** Read each receiver's well-known for its session tools (at start, then with every hello). */\n private async refreshSessionTools(): Promise<void> {\n for (const r of this.cfg.receivers) {\n try {\n const res = await this.deps.fetch(`${r.url.replace(/\\/$/, \"\")}/.well-known/sessionpipe`, {\n signal: AbortSignal.timeout(8000),\n });\n if (!res.ok) continue;\n const wk = (await res.json()) as { control?: { session_tools?: unknown } };\n const tools = sessionToolsFrom(wk.control?.session_tools);\n const key = r.control + r.machine;\n if (JSON.stringify(tools) !== JSON.stringify(this.sessionTools.get(key) ?? []))\n this.deps.log(\n `${r.url}: sessions it messages may use ${tools.length ? tools.join(\", \") : \"nothing extra\"} without asking`,\n );\n this.sessionTools.set(key, tools);\n } catch {}\n }\n }\n\n private allowedFor(r: PairedReceiver): string[] {\n return this.sessionTools.get(r.control + r.machine) ?? [];\n }\n\n private async helloAll(): Promise<void> {\n void this.refreshSessionTools();\n const waiting = [...this.live].filter(([, l]) => l.waiter).map(([k]) => k);\n const harnesses = this.harnesses();\n const modes: DeliveryMode[] = [\n \"waiter\",\n \"turn\",\n \"resume\",\n \"fork\",\n ...(this.deps.sdk ? ([\"sdk\"] as const) : []),\n // Every ACP agent's turn is acked `api` (\u00A76).\n ...(harnesses.some((h) => acpControl.acpAgent(h)) ? ([\"api\"] as const) : []),\n ];\n const accounts = this.accounts();\n const start = this.startOptions(harnesses);\n for (const r of this.cfg.receivers) {\n const body = {\n name: this.cfg.name,\n harnesses,\n modes,\n keys: r.keys.map((k) => k.id),\n version: VERSION,\n waiting,\n folders: this.cfg.folders,\n mode: this.cfg.mode,\n ...(accounts.length ? { accounts } : {}),\n // This daemon takes `files` on a start (an older one would start without them).\n files: true,\n // \u2026and on a prompt (CONTROL.md \u00A76 `prompt`): an older daemon refuses those.\n prompt_files: true,\n start,\n // And device keys (CONTROL.md \u00A72): an app offers one only to a machine that says so.\n key_types: [...KEY_TYPES],\n };\n const res = await this.post(r, \"/hello\", body).catch(() => null);\n const st = this.polling.get(r.control + r.machine);\n if (res?.ok && st?.unauthorized) {\n st.unauthorized = false;\n st.authBackoff = 0;\n st.error = null;\n this.deps.log(`${r.url}: hello accepted; retrying control poll now`);\n st.wake?.();\n }\n }\n }\n\n private async post(r: PairedReceiver, sub: string, body: unknown): Promise<Response> {\n const ctl = new AbortController();\n const t = setTimeout(() => ctl.abort(), 15_000);\n try {\n return await this.deps.fetch(`${r.control.replace(/\\/$/, \"\")}${sub}`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${r.token}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: ctl.signal,\n });\n } finally {\n clearTimeout(t);\n }\n }\n\n // --- acks -----------------------------------------------------------------------\n\n private finish(r: PairedReceiver, id: string, a: Omit<Ack, \"receiver\" | \"id\" | \"at\">, since?: number): void {\n const ack: Ack = { receiver: r.control + r.machine, id, at: new Date(this.deps.now()).toISOString(), ...a };\n if (ack.reply) ack.reply = redactSecrets(ack.reply).slice(0, MAX_REPLY);\n if (ack.detail) ack.detail = redactSecrets(ack.detail).slice(0, 500);\n if (a.outcome !== \"taken\") {\n this.inflight.delete(id);\n this.recentAcks.set(id, { ack, at: this.deps.now() });\n this.delivered[a.mode ?? a.outcome] = (this.delivered[a.mode ?? a.outcome] ?? 0) + 1;\n this.deps.log(\n `ack ${id.slice(-8)} ${a.outcome}${a.mode ? ` via ${a.mode}` : \"\"}${a.code ? ` (${a.code})` : \"\"}${since ? ` send\u2192${a.outcome} ${this.deps.now() - since} ms` : \"\"}`,\n );\n }\n this.acks.add(ack);\n void this.flushAcks();\n }\n\n private flushing = false;\n private async flushAcks(): Promise<void> {\n if (this.flushing) return;\n this.flushing = true;\n try {\n for (let round = 0; round < 5; round++) {\n const all = this.acks.all();\n if (!all.length) return;\n const left: Ack[] = [];\n for (const r of this.cfg.receivers) {\n const mine = all.filter((a) => a.receiver === r.control + r.machine);\n if (!mine.length) continue;\n const acks = mine.map(({ receiver: _r, ...a }) => a);\n const ok = await this.post(r, \"/ack\", { acks })\n .then((res) => res.status >= 200 && res.status < 300)\n .catch(() => false);\n if (!ok) left.push(...mine);\n }\n // Acks for a receiver no longer paired are dropped.\n const now = this.acks.all();\n const added = now.slice(all.length);\n this.acks.keep([...left, ...added]);\n if (!left.length && !added.length) return;\n if (left.length) await sleep(2000 * (round + 1));\n }\n } finally {\n this.flushing = false;\n }\n }\n\n // --- one message ----------------------------------------------------------------\n\n async handle(r: PairedReceiver, m: Carried): Promise<void> {\n if (!m || typeof m.id !== \"string\") return;\n if (this.inflight.has(m.id)) return; // redelivered while we work on it\n const prior = this.recentAcks.get(m.id);\n if (prior && this.deps.now() - prior.at < RECENT_ACKS_MS) {\n this.acks.add(prior.ack);\n void this.flushAcks();\n return;\n }\n // In hand from here, before anything is awaited: a redelivery that arrives while\n // this one verifies must not verify too and come back `replay`. Every path below\n // ends in finish(), which lets go of it.\n this.inflight.add(m.id);\n // A start is marked now too, before its verification: messages of one poll are\n // handled side by side, and a prompt queued right behind its start may finish\n // verifying first. Marked unverified, it only ever makes such a prompt wait.\n const starting = startNamed(m.cmd);\n let done = (): void => {};\n if (starting) {\n const mine = new Promise<void>((res) => {\n done = res;\n });\n const before = this.startsPending.get(starting);\n const all = before ? Promise.all([before, mine]).then(() => undefined) : mine;\n this.startsPending.set(starting, all);\n void all.then(() => {\n if (this.startsPending.get(starting) === all) this.startsPending.delete(starting);\n });\n }\n try {\n await this.handleVerified(r, m);\n } finally {\n done();\n }\n }\n\n private async handleVerified(r: PairedReceiver, m: Carried): Promise<void> {\n const sent = Date.parse(m.at) || this.deps.now();\n if (Date.parse(m.expires_at) <= this.deps.now()) return this.finish(r, m.id, { outcome: \"expired\" });\n const v = await verifyCommand(\n { cmd: m.cmd, csig: m.csig ?? null, grant: m.grant ?? null, confirm: m.confirm ?? null },\n { machine: r.machine, rpId: r.rpId, trusted: r.keys, now: this.deps.now(), seenNonce: this.nonces.seen },\n );\n if (!v.ok) {\n this.deps.log(`refused ${m.id.slice(-8)}: ${v.code} \u2014 ${v.why}`);\n return this.finish(r, m.id, { outcome: \"refused\", code: v.code, detail: v.why });\n }\n const cmd = v.cmd;\n // A device this machine already trusts vouched for a new one (CONTROL.md \u00A72): the\n // signature just verified against an enrolled key, so the new key joins the store.\n if (cmd.kind === \"key.add\") return this.addKey(r, m.id, cmd, sent);\n const ref = parseSessionRef(cmd.session)!;\n const kp = kindPath(cmd.kind, ref.harness);\n if (typeof kp === \"object\") return this.finish(r, m.id, { outcome: \"unsupported\", detail: kp.unsupported });\n try {\n if (kp === \"start\") return await this.startSession(r, m.id, cmd, sent);\n let place = this.place(cmd.session);\n // A session the daemon is still starting may have no transcript (or, for Codex and\n // Antigravity, no name) yet: wait for that start, then place it again.\n const starting = kp === \"prompt\" ? this.startsPending.get(cmd.session) : undefined;\n if (\"refused\" in place && (starting || this.ownRuns.has(ref.id))) {\n this.finish(r, m.id, { outcome: \"taken\" });\n await starting;\n await this.serial(ref.id, async () => {});\n place = this.place(cmd.session);\n }\n if (\"refused\" in place)\n return this.finish(r, m.id, { outcome: \"refused\", code: place.refused, detail: place.why });\n if (kp === \"permission\") return this.permission(r, m.id, cmd, sent);\n if (kp === \"cancel\") return await this.cancel(r, m.id, cmd, sent);\n // One session's prompts in the order they came, each routed only once the one\n // before it has landed (a second message to a session the first one forked\n // goes to the copy). Other sessions don't wait.\n return await this.serial(`deliver:${cmd.session}`, async () => {\n // Read again: the message before this one may have moved the session (a fork).\n const now = this.place(cmd.session);\n if (\"refused\" in now) return this.finish(r, m.id, { outcome: \"refused\", code: now.refused, detail: now.why });\n // A prompt's files are on disk, and listed in its text, before any mode hands it over.\n if (cmd.files) {\n this.finish(r, m.id, { outcome: \"taken\" });\n const text = await this.attached(r, m.id, cmd, ref, now.folder, cmd.nonce);\n if (text === null) return;\n return this.prompt(r, m.id, { ...cmd, text }, now, sent);\n }\n return this.prompt(r, m.id, cmd, now, sent);\n });\n } catch (e) {\n this.finish(r, m.id, { outcome: \"failed\", detail: String((e as Error)?.message || e) });\n }\n }\n\n /** Where the session lives, and whether its folder is allowed \u2014 read from the\n * session's own transcript (Claude Code, Codex), the folder its start recorded, or\n * the hooks' cwd, never the command. */\n private place(session: string): { refused: string; why: string } | Placed {\n const ref = parseSessionRef(session)!;\n if (ref.harness === \"codex\" || ref.harness === \"antigravity\" || acpControl.acpAgent(ref.harness))\n return this.placeDriven(session, ref);\n if (ref.harness === \"claude-code\") {\n const target = this.state.copies[ref.id] ?? ref.id;\n const t = findTranscript(target, this.deps.claudeDirs()) ?? findTranscript(ref.id, this.deps.claudeDirs());\n if (!t)\n return { refused: \"no_session\", why: `no Claude Code session ${shortId(ref.harness, ref.id)} on this machine` };\n const folder = sessionFolder(t);\n const ok = folder && this.allowed(folder);\n if (!ok) return { refused: \"folder\", why: \"that session's folder isn't one this machine allows\" };\n return { folder: ok, transcript: t };\n }\n const cwd = this.live.get(session)?.cwd;\n const ok = cwd && this.allowed(cwd);\n if (!ok) return { refused: cwd ? \"folder\" : \"no_session\", why: \"no allowed folder known for that session\" };\n return { folder: ok, transcript: null };\n }\n\n /** A Codex, Antigravity or ACP-driven session: one the daemon started is its alias\n * (the harness's id and the start's folder); one the hooks reported is Codex's\n * rollout (its `session_meta` cwd) or, for the others, the folder its hooks gave. */\n private placeDriven(\n session: string,\n ref: { harness: string; id: string },\n ): { refused: string; why: string } | Placed {\n const a = this.aliasOf(ref.harness, ref.id);\n const target = a?.id ?? ref.id;\n let cwd: string | undefined = a?.cwd || undefined;\n let file: string | null = null;\n if (ref.harness === \"codex\") {\n file = isUuid(target) ? codexControl.findRollout(target, this.deps.env ?? process.env) : null;\n if (!a && !file)\n return { refused: \"no_session\", why: `no Codex session ${shortId(ref.harness, ref.id)} on this machine` };\n cwd ||= file ? codexControl.codexFacts(file).cwd : undefined;\n } else cwd ||= this.live.get(session)?.cwd || this.factsCwd(ref.harness, ref.id);\n if (!cwd)\n return {\n refused: \"no_session\",\n why: `no folder known for ${this.label(ref.harness)} session ${shortId(ref.harness, ref.id)}`,\n };\n const ok = this.allowed(cwd);\n if (!ok) return { refused: \"folder\", why: \"that session's folder isn't one this machine allows\" };\n return { folder: ok, transcript: null, target, file };\n }\n\n /** The folder the worker recorded for a session from its hooks (run.ts, facts). */\n private factsCwd(harness: string, id: string): string | undefined {\n try {\n const f = path.join(path.dirname(this.dir), \"facts\", safeId(harness), `${safeId(id)}.json`);\n const cwd = (JSON.parse(readFileSync(f, \"utf8\")) as { cwd?: unknown }).cwd;\n return typeof cwd === \"string\" && path.isAbsolute(cwd) ? cwd : undefined;\n } catch {\n return undefined;\n }\n }\n\n /** A driven harness, as the person knows it. */\n private label(harness: string): string {\n const agent = acpControl.acpAgent(harness);\n return agent ? agent.label : harness === \"codex\" ? \"Codex\" : \"Antigravity\";\n }\n\n private aliasOf(harness: string, id: string): Alias | null {\n return this.aliases[`${harness}:${id}`] ?? null;\n }\n\n /** The harness revealed its own id for a session the command named: from now on that\n * is where the command's id leads (aliases.ts). Written before anything else reads it. */\n private setAlias(harness: string, id: string, real: string, cwd: string, o: StartOptions | null): void {\n this.aliases = {\n ...this.aliases,\n [`${harness}:${id}`]: { id: real, cwd, at: new Date(this.deps.now()).toISOString(), ...o },\n };\n try {\n writeAliases(aliasFile(this.dir), this.aliases);\n } catch (e) {\n this.deps.log(\n `couldn't record ${harness}:${id.slice(0, 8)} \u2192 ${real.slice(0, 8)}: ${String(/* v8 ignore next -- writeAliases throws fs Errors */ (e as Error)?.message || e)}`,\n );\n }\n }\n\n /** `<harness>:<harness's id>` \u2192 `<harness>:<the start's id>` for a session the daemon named. */\n private named(session: string): string {\n const i = session.indexOf(\":\");\n if (i <= 0) return session;\n const harness = session.slice(0, i);\n const as = receiverIdOf(this.aliases, harness, session.slice(i + 1));\n return as ? `${harness}:${as}` : session;\n }\n\n private driver(harness: string): Driver | null {\n if (harness === \"codex\")\n return {\n label: \"Codex\",\n cmd: \"codex\",\n bin: () => this.deps.codex?.() ?? null,\n args: ({ cwd, resume, ...o }) => codexControl.codexArgs(resume ? { ...o, resume } : { ...o, cwd }),\n levels: codexControl.offeredLevels,\n defaultLevel: codexControl.defaultLevel,\n models: () => this.deps.codexModels?.() ?? codexControl.codexModels(this.deps.env ?? process.env),\n reading: () => codexControl.reading(),\n ...(this.deps.codexLogin ? { login: this.deps.codexLogin } : {}),\n loginHint: codexControl.LOGIN_HINT,\n };\n /* v8 ignore else -- only a HEADLESS harness gets here (route.ts): Claude Code never asks for a driver */\n if (harness === \"antigravity\")\n return {\n label: \"Antigravity\",\n cmd: \"agy\",\n bin: () => this.deps.agy?.() ?? null,\n args: ({ permission, prompt, resume }) =>\n antigravityControl.agyArgs(resume ? { permission, prompt, resume } : { permission, prompt }),\n levels: antigravityControl.offeredLevels,\n defaultLevel: antigravityControl.defaultLevel,\n reading: () => antigravityControl.reading(),\n };\n /* v8 ignore next -- see above */\n return null;\n }\n\n /** Who is signed in here, for hello. A bad .claude.json names nobody, never fails a hello. */\n private accounts(): HarnessAccount[] {\n try {\n return this.deps.accounts ? this.deps.accounts() : claudeAccounts(this.deps.claudeDirs());\n } catch {\n return [];\n }\n }\n\n /** The harnesses this machine can run a message in, for hello: at most\n * HELLO_HARNESSES_MAX, the three with their own drivers first. */\n private harnesses(): string[] {\n if (this.deps.harnesses) return this.deps.harnesses().slice(0, HELLO_HARNESSES_MAX);\n const acp = this.deps.acp;\n return [\n ...(this.deps.claude() ? [\"claude-code\"] : []),\n ...(this.deps.codex?.() ? [\"codex\"] : []),\n ...(this.deps.agy?.() ? [\"antigravity\"] : []),\n ...(acp ? acpControl.ACP_HARNESSES.filter((h) => acp(h)) : []),\n ].slice(0, HELLO_HARNESSES_MAX);\n }\n\n /** The caps a new Claude Code session is started with: the Agent SDK's when the\n * daemon has it, else what this machine's `claude --help` lists. */\n private startCaps(): Caps | null {\n return this.deps.sdk ? SDK_CAPS : (this.deps.claude()?.caps ?? null);\n }\n\n /** What a start may carry for one harness here (CONTROL.md \u00A72 `start`), capped by the\n * machine's mode; null when it takes neither option, or when a start without one\n * would be refused (an auto machine whose Claude Code has no auto mode). */\n private startEntry(harness: string): StartEntry | null {\n const mode = this.cfg.mode;\n if (harness === \"claude-code\") {\n const caps = this.startCaps();\n if (!caps) return null;\n const permissions = claudeControl.offeredLevels(mode, caps);\n const permission = claudeControl.defaultLevel(mode);\n return permission === \"inherit\" || permissions.includes(permission)\n ? { permissions, permission, any_model: true }\n : null;\n }\n if (harness !== \"codex\" && harness !== \"antigravity\") return null;\n const drv = this.driver(harness)!;\n const models = drv.models?.() ?? null;\n return {\n permissions: drv.levels(mode),\n permission: drv.defaultLevel(mode),\n ...(models ? { any_model: true, ...(models.length ? { models } : {}) } : {}),\n };\n }\n\n /** The hello's `start`: an entry for each harness it lists that takes options. */\n private startOptions(harnesses = this.harnesses()): Record<string, StartEntry> {\n const out: Record<string, StartEntry> = {};\n for (const h of harnesses) {\n const e = this.startEntry(h);\n if (e) out[h] = e;\n }\n return out;\n }\n\n /** The options a start runs with, or the refusal (CONTROL.md \u00A75 step 8): a level the\n * machine offers for that harness, never above its mode, and a model only where the\n * harness takes one. Never another level or model than the one asked for. */\n private startChoice(\n harness: string,\n cmd: ControlCommand,\n ): { options: StartOptions } | { code: \"permission\" | \"model\"; detail: string } {\n const mode = this.cfg.mode;\n const claude = harness === \"claude-code\";\n // An ACP agent takes neither option here: it runs as the machine's mode says (\u00A76).\n if (acpControl.acpAgent(harness)) {\n if (cmd.permission !== undefined || cmd.model !== undefined)\n return {\n code: cmd.permission !== undefined ? \"permission\" : \"model\",\n detail: `${this.label(harness)} takes no permission level or model choice on this machine`,\n };\n return { options: { permission: mode } };\n }\n const level: RunLevel =\n cmd.permission ?? (claude ? claudeControl.defaultLevel(mode) : this.driver(harness)!.defaultLevel(mode));\n const ask = { permission: level, ...(cmd.model !== undefined ? { model: cmd.model } : {}) };\n // No Claude Code here at all: the start fails on that, in words, a step later.\n if (claude && !this.startCaps()) return { options: ask };\n const entry = this.startEntry(harness);\n // `inherit` is never asked for, only a default: the person chose it at the machine.\n if (level !== \"inherit\" && !entry?.permissions.includes(level)) {\n if (levelRank(level) > levelRank(claudeControl.ceilingLevel(mode)))\n return {\n code: \"permission\",\n detail:\n mode === \"inherit\"\n ? `this machine runs in inherit mode, where a message may only name read or safe; ${level} needs \\`sessionpipe control mode auto\\` at the machine`\n : `this machine runs in ${mode} mode; ${level} needs \\`sessionpipe control mode auto\\` at the machine`,\n };\n return { code: \"permission\", detail: this.levelMissing(harness, level) };\n }\n // Every harness that takes a model here takes any well-formed one (`any_model`); the\n // models it lists are suggestions, so no list here is closed.\n if (cmd.model !== undefined && !entry?.any_model)\n return {\n code: \"model\",\n detail: `${claude ? /* v8 ignore next -- Claude Code always takes a model */ \"Claude Code\" : this.driver(harness)!.label} takes no model choice on this machine`,\n };\n return { options: ask };\n }\n\n /** Why a harness has no such level here, though the machine's mode would allow it. */\n private levelMissing(harness: string, level: StartPermission): string {\n if (harness === \"codex\") return \"Codex has no edits level: its safe level, the workspace sandbox, already edits\";\n if (harness === \"antigravity\")\n return level === \"read\" ? \"Antigravity has no read-only mode\" : \"Antigravity's widest level is edits\";\n // startChoice() returned before this for a Claude Code with no caps at all.\n const mf = claudeControl.modeFlags(level, this.startCaps()!);\n /* v8 ignore next -- only a level its caps lack is ever missing */\n return \"error\" in mf ? mf.error : `this machine's Claude Code can't start at ${level}`;\n }\n\n /** The options a later run of a session gets: the narrower of what its start recorded\n * and what the machine's mode means now, with the recorded model. A session with no\n * record (the hooks reported it, or it predates 0.10.0) runs at the machine's mode. */\n private laterOptions(harness: string, recorded: StartOptions | null | undefined): StartOptions {\n const mode = this.cfg.mode;\n const now = harness === \"claude-code\" ? claudeControl.defaultLevel(mode) : this.driver(harness)!.defaultLevel(mode);\n const model = recorded?.model ? { model: recorded.model } : {};\n // No level of its own (none recorded, or the start inherited): the machine's mode now.\n if (!recorded || recorded.permission === \"inherit\") return { permission: now, ...model };\n // A level of its own, on an inherit machine now: at most what a start there may name.\n const cap = now === \"inherit\" ? claudeControl.ceilingLevel(mode) : now;\n return { permission: narrower(recorded.permission, cap), ...model };\n }\n\n /** What the acks carry as `applied`: the model only when one was asked for. */\n private applied(o: StartOptions): StartOptions {\n return { permission: o.permission, ...(o.model ? { model: o.model } : {}) };\n }\n\n /** A failed run that asked for a model, put down to the model: acked with code `model`. */\n private failedRun(why: string, o: StartOptions): Omit<Ack, \"receiver\" | \"id\" | \"at\"> {\n return { outcome: \"failed\", ...(o.model && MODEL_FAILURE_RE.test(why) ? { code: \"model\" } : {}), detail: why };\n }\n\n /** The real folder a command or a session names, when it is one this machine allows:\n * absolute, or under this user's home as `~/\u2026` (a start's `cwd` may say either). */\n private allowed(folder: string): string | null {\n const dir = untilde(folder);\n if (!path.isAbsolute(dir)) return null;\n let r: string;\n try {\n r = realpathSync.native(dir);\n if (!statSync(r).isDirectory()) return null;\n } catch {\n return null;\n }\n for (const f of this.cfg.folders) {\n let rf = f;\n try {\n rf = realpathSync.native(f);\n } catch {}\n if (r === rf || r.startsWith(rf.endsWith(path.sep) ? rf : rf + path.sep)) return r;\n }\n return null;\n }\n\n private permission(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number) {\n const l = this.live.get(cmd.session);\n const hook = l?.attentions.get(cmd.for as string);\n if (!hook) {\n // Nothing is ever auto-allowed: an allow needs a prompt open right now.\n if (cmd.decision === \"allow\")\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"no_attention\",\n detail: \"no permission prompt open for that id\",\n });\n this.finish(r, id, { outcome: \"expired\", detail: \"the prompt was already answered or closed\" });\n return;\n }\n l!.attentions.delete(cmd.for as string);\n this.reply(hook, {\n op: \"decision\",\n behavior: cmd.decision as \"allow\" | \"deny\",\n ...(cmd.note ? { message: cmd.note } : {}),\n id,\n });\n this.finish(r, id, { outcome: \"delivered\", mode: \"turn\" }, sent);\n }\n\n private async cancel(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number): Promise<void> {\n const ref = parseSessionRef(cmd.session)!;\n const held = this.sdkSessions.get(ref.id);\n if (!held)\n return this.finish(r, id, {\n outcome: \"unsupported\",\n detail: \"no cancel path for a session the daemon doesn't hold\",\n });\n await held.interrupt();\n this.finish(r, id, { outcome: \"delivered\", mode: held.mode ?? \"sdk\" }, sent);\n }\n\n private view(session: string, place: Placed) {\n const ref = parseSessionRef(session)!;\n const l = this.live.get(session);\n if (ref.harness !== \"claude-code\") {\n // Codex: a rollout someone else wrote in the last 90 s is a session in use.\n // Antigravity keeps no file that says so: only the daemon's own run (whose\n // messages wait in line behind it) holds one.\n const live =\n !this.ownRuns.has(ref.id) &&\n !!place.file &&\n recentlyWritten(place.file, this.lastEnd.get(ref.id), this.deps.now());\n return {\n harness: ref.harness,\n sdk: this.sdkSessions.has(ref.id),\n waiter: !!l?.waiter && !l.waiter.destroyed,\n midTurn: !!l?.midTurn,\n live,\n known: true,\n canFork: false,\n api: false,\n };\n }\n const transcript = place.transcript;\n const claude =\n ref.harness === \"claude-code\"\n ? this.deps.claude()\n : /* v8 ignore next -- every other harness returned above */ null;\n const target = this.state.copies[ref.id] ?? ref.id;\n const t = transcript;\n // The daemon's own run holding it is not \"someone else's live process\": the message\n // queues behind that run (serial per session) and resumes it.\n const live =\n !this.ownRuns.has(target) &&\n !!t &&\n (liveProcess(target, t.configDir) || recentlyWritten(t.file, this.lastEnd.get(target), this.deps.now()));\n return {\n harness: ref.harness,\n sdk: this.sdkSessions.has(ref.id),\n waiter: !!l?.waiter && !l.waiter.destroyed,\n midTurn: !!l?.midTurn,\n live,\n known: !!t,\n canFork: !!claude?.caps.fork,\n api: false,\n };\n }\n\n private async prompt(r: PairedReceiver, id: string, cmd: ControlCommand, place: Placed, sent: number): Promise<void> {\n const route = routePrompt(this.view(cmd.session, place));\n if (\"unsupported\" in route) return this.finish(r, id, { outcome: \"unsupported\", detail: route.unsupported });\n /* v8 ignore next -- place() already refused a session with no transcript (`known` is never false here) */\n if (\"refused\" in route) return this.finish(r, id, { outcome: \"refused\", code: route.refused });\n const ref = parseSessionRef(cmd.session)!;\n const text = cmd.text as string;\n switch (route.mode) {\n case \"waiter\": {\n const l = this.live.get(cmd.session)!;\n const w = l.waiter!;\n l.waiter = null;\n const from = this.answerFrom(cmd.session);\n this.reply(w, { op: \"message\", text: frame(text, r.url), id });\n this.scheduleHello();\n return this.followAnswer(r, id, \"waiter\", cmd.session, from, sent);\n }\n case \"turn\": {\n const l = this.liveOf(cmd.session);\n const p: TurnPending = { receiver: r, msgId: id, text, session: cmd.session, queuedAt: sent };\n l.turnQueue.push(p);\n // It waits for the session's Stop: the receiver must not keep handing it back.\n this.finish(r, id, { outcome: \"taken\" });\n const t = setTimeout(() => {\n if (this.inflight.has(id) && l.turnQueue.includes(p)) {\n l.turnQueue.splice(l.turnQueue.indexOf(p), 1);\n void this.reroute(p);\n }\n }, TURN_FALLBACK_MS);\n t.unref();\n return;\n }\n case \"sdk\": {\n const s = this.sdkSessions.get(ref.id)!;\n this.finish(r, id, { outcome: \"taken\" });\n const out = await this.sendHeld(ref.id, s, frame(text, r.url));\n return this.finish(\n r,\n id,\n out.error\n ? { outcome: \"failed\", detail: out.error }\n : { outcome: \"delivered\", mode: s.mode ?? \"sdk\", reply: out.reply },\n sent,\n );\n }\n case \"resume\":\n case \"fork\":\n return this.headless(r, id, cmd, place, route.mode, sent);\n /* v8 ignore next -- no harness has an input API wired yet (view() says api: false) */\n case \"api\":\n return this.finish(r, id, { outcome: \"unsupported\", detail: \"no input API wired for this harness\" });\n }\n }\n\n /** One message through a held session; one whose process left is let go of, so the\n * next message reopens the session instead of finding it closed. */\n private async sendHeld(id: string, s: SdkSession, text: string): Promise<{ reply: string; error?: string }> {\n const out = await s.send(text);\n if (s.closed) {\n s.close();\n this.sdkSessions.delete(id);\n }\n return out;\n }\n\n /** A turn message whose Stop never took it: route again, now that it isn't mid-turn. */\n private async reroute(p: TurnPending): Promise<void> {\n const l = this.liveOf(p.session);\n l.midTurn = false;\n const place = this.place(p.session);\n if (\"refused\" in place) return this.finish(p.receiver, p.msgId, { outcome: \"refused\", code: place.refused });\n const cmd = { kind: \"prompt\", session: p.session, text: p.text } as ControlCommand;\n this.inflight.delete(p.msgId);\n this.inflight.add(p.msgId);\n await this.prompt(p.receiver, p.msgId, cmd, place, p.queuedAt).catch((e) =>\n this.finish(p.receiver, p.msgId, { outcome: \"failed\", detail: String((e as Error)?.message || e) }),\n );\n }\n\n /** Jobs for one session (and its copy) run one at a time, in order. */\n private serial<T>(key: string, task: () => Promise<T>): Promise<T> {\n const prev = this.queues.get(key) ?? Promise.resolve();\n const next = prev.then(task, task);\n this.queues.set(\n key,\n next.catch(() => {}),\n );\n return next;\n }\n\n /** Null when Claude Code is signed in for this account (or can't say); otherwise what\n * to tell the person. */\n private async loginProblem(configDir?: string): Promise<string | null> {\n const login = this.deps.login;\n if (!login) return null;\n if (await this.signedIn(configDir ?? \"\", () => login(configDir))) return null;\n this.deps.log(`claude isn't signed in for ${configDir ?? \"the default account\"} as the daemon sees it`);\n return loginHint(configDir, this.deps.platform ?? process.platform);\n }\n\n /** One harness account's login, asked at most every 10 minutes (30 s after a no). */\n private async signedIn(key: string, ask: () => Promise<Login>): Promise<boolean> {\n const now = this.deps.now();\n const hit = this.logins.get(key);\n let login = hit && now - hit.at < (hit.login.loggedIn === false ? 30_000 : 600_000) ? hit.login : null;\n if (!login) {\n login = await ask().catch((): Login => ({ loggedIn: null }));\n this.logins.set(key, { at: now, login });\n }\n return login.loggedIn !== false;\n }\n\n /** Null when a Codex or Antigravity run may go ahead; otherwise what to tell the person. */\n private async drivenProblem(drv: Driver): Promise<{ bin: string } | { failed: string }> {\n const bin = drv.bin();\n if (!bin) return { failed: `${drv.label} isn't installed on this machine` };\n const login = drv.login;\n if (login && !(await this.signedIn(`${drv.cmd}:`, () => login(bin)))) {\n this.deps.log(`${drv.cmd} isn't signed in as the daemon sees it`);\n return {\n failed:\n /* v8 ignore next -- only Codex has a login check, and it has a hint */ drv.loginHint ??\n `${drv.label} isn't signed in on this machine`,\n };\n }\n return { bin };\n }\n\n /** A Codex or Antigravity session's next message: a headless turn resumed under the\n * harness's own id, after any run of the daemon's own that holds it. */\n private async resumeDriven(r: PairedReceiver, id: string, cmd: ControlCommand, place: Placed, sent: number) {\n const ref = parseSessionRef(cmd.session)!;\n const drv = this.driver(ref.harness)!;\n const ready = await this.drivenProblem(drv);\n if (\"failed\" in ready) return this.finish(r, id, { outcome: \"failed\", detail: ready.failed });\n this.finish(r, id, { outcome: \"taken\" });\n await this.serial(ref.id, async () => {\n // Read again: the start this waited for may have named the session meanwhile.\n const alias = this.aliasOf(ref.harness, ref.id);\n /* v8 ignore next -- placeDriven() always names a target; the last fallback is for the type */\n const target = alias?.id ?? place.target ?? ref.id;\n const recorded = alias ? startOptionsOf(alias) : null;\n const o = this.laterOptions(ref.harness, recorded);\n const args = drv.args({\n permission: o.permission,\n prompt: frame(cmd.text as string, r.url),\n cwd: place.folder,\n resume: target,\n ...(o.model ? { model: o.model } : {}),\n });\n this.deps.log(`${id.slice(-8)}: ${drv.cmd} resume ${target.slice(0, 8)} (${o.permission}) in ${place.folder}`);\n await this.drive(r, id, ref, drv, ready.bin, args, place.folder, sent, target, o, recorded);\n });\n }\n\n /** Run one Codex or Antigravity turn and ack it: `progress` as its answer grows, then\n * `delivered` (mode `resume`) with the reply. The moment the harness names the session\n * \u2014 a start's new one, or a fresh one for an id it didn't know \u2014 the command's id\n * becomes its alias, so the next message resumes it. */\n private async drive(\n r: PairedReceiver,\n id: string,\n ref: { harness: string; id: string },\n drv: Driver,\n bin: string,\n args: string[],\n cwd: string,\n sent: number,\n asked: string | null,\n o: StartOptions,\n /** What the session's alias records (a start records `o`): kept when it is renamed. */\n record: StartOptions | null,\n ): Promise<void> {\n const stream = this.answerStream(r, id);\n const reading = drv.reading();\n let named: string | null = null;\n const name = () => {\n const s = reading.session;\n if (!s || s === named) return;\n named = s;\n if (s !== asked) this.setAlias(ref.harness, ref.id, s, cwd, record);\n };\n const onLine = (l: string) => {\n if (reading.feed(l)) stream.set(reading.text);\n name();\n };\n const res = await this.owning(ref.id, () =>\n this.slot(() =>\n this.deps.run(bin, args, {\n cwd,\n env: jobEnv(this.deps.env),\n timeoutMs: JOB_TIMEOUT_MS,\n onLine,\n keep: () => false,\n }),\n ),\n );\n // A runner that doesn't stream hands the whole output over at the end.\n if (!reading.lines && res.stdout) for (const l of res.stdout.split(\"\\n\")) if (l.trim()) onLine(l);\n stream.close();\n this.lastEnd.set(ref.id, this.deps.now());\n if (reading.warnings?.length)\n this.deps.log(`${id.slice(-8)}: ${drv.cmd} warned: ${reading.warnings.join(\" \u00B7 \").slice(0, 400)}`);\n const out = reading.outcome(res);\n if (\"failed\" in out) return this.finish(r, id, this.failedRun(out.failed, o));\n const moved =\n asked && named && named !== asked\n ? `\\n\\n(${drv.label} didn't find that session on this machine, so this ran in a new one; later messages continue there.)`\n : \"\";\n this.finish(\n r,\n id,\n {\n outcome: \"delivered\",\n mode: \"resume\",\n reply: out.reply + moved,\n ...(asked ? {} : { applied: this.applied(o) }),\n },\n sent,\n );\n }\n\n private async headless(\n r: PairedReceiver,\n id: string,\n cmd: ControlCommand,\n place: Placed,\n mode: \"resume\" | \"fork\",\n sent: number,\n ): Promise<void> {\n const harness = parseSessionRef(cmd.session)?.harness;\n if (acpControl.acpAgent(harness as string)) return this.resumeAcp(r, id, cmd, place, sent);\n if (harness !== \"claude-code\") return this.resumeDriven(r, id, cmd, place, sent);\n const claude = this.deps.claude();\n if (!claude)\n return this.finish(r, id, { outcome: \"failed\", detail: \"Claude Code isn't installed on this machine\" });\n const ref = parseSessionRef(cmd.session)!;\n // The session's own record (its start's level, narrowed to the machine's mode now).\n const o = this.laterOptions(\"claude-code\", this.state.started[ref.id]);\n const mf = claudeControl.modeFlags(o.permission, claude.caps);\n if (\"error\" in mf) return this.finish(r, id, { outcome: \"refused\", code: \"permission\", detail: mf.error });\n const signedOut = await this.loginProblem(place.transcript?.configDir);\n if (signedOut) return this.finish(r, id, { outcome: \"failed\", detail: signedOut });\n this.finish(r, id, { outcome: \"taken\" });\n await this.serial(ref.id, async () => {\n const target = this.state.copies[ref.id] ?? ref.id;\n const built = claudeArgs({\n caps: claude.caps,\n level: o.permission,\n prompt: frame(cmd.text as string, r.url),\n resume: target,\n fork: mode === \"fork\",\n allowedTools: this.allowedFor(r),\n ...(o.model ? { model: o.model } : {}),\n });\n /* v8 ignore next -- the same caps and level passed modeFlags above */\n const args = \"args\" in built ? built.args : [];\n this.deps.log(\n `${id.slice(-8)}: claude -p (${o.permission}) --resume ${target}${mode === \"fork\" ? \" --fork-session\" : \"\"} in ${place.folder}`,\n );\n const stream = this.answerStream(r, id);\n const res = await this.owning(target, () =>\n this.slot(() =>\n this.deps.run(claude.bin, args, {\n cwd: place.folder,\n env: claudeEnv(place.transcript?.configDir, this.deps.env),\n timeoutMs: JOB_TIMEOUT_MS,\n ...(claude.caps.stream ? { onLine: (l: string) => stream.feed(l) } : {}),\n }),\n ),\n );\n stream.close();\n this.lastEnd.set(target, this.deps.now());\n const out = this.outcome(res);\n if (\"failed\" in out) return this.finish(r, id, this.failedRun(out.failed, o));\n const ran = isUuid(out.session) ? out.session : target;\n if (mode === \"fork\" && ran !== target) {\n this.state.copies[ref.id] = ran;\n writeState(path.join(this.dir, \"state.json\"), this.state);\n this.lastEnd.set(ran, this.deps.now());\n }\n this.finish(\n r,\n id,\n { outcome: \"delivered\", mode, reply: out.reply, ...(ran !== ref.id ? { session: `claude-code:${ran}` } : {}) },\n sent,\n );\n });\n }\n\n private outcome(res: RunResult): { failed: string } | { reply: string; session?: string } {\n if (res.error) return { failed: `couldn't start Claude Code: ${res.error}` };\n if (res.timedOut) return { failed: \"Claude Code was still working after 30 minutes, so it was stopped\" };\n if (res.tooBig) return { failed: \"Claude Code's answer was too large to read\" };\n const j = parseResult(res.stdout);\n if (!j) {\n const why = String(res.stderr || \"\")\n .trim()\n .split(\"\\n\")\n .slice(-3)\n .join(\" \");\n return {\n failed: `Claude Code exited (${res.signal || `code ${res.code}`}) without an answer${why ? `: ${why}` : \"\"}`,\n };\n }\n if (j.is_error) return { failed: String(j.result || j.subtype || \"Claude Code reported an error\") };\n const denials = Array.isArray(j.permission_denials) ? j.permission_denials : [];\n const names = [...new Set(denials.map((d) => d?.tool_name).filter((n): n is string => typeof n === \"string\"))];\n const tail = deniedNote(names, denials.length);\n const text =\n typeof j.result === \"string\" && j.result.trim() ? j.result : \"(Claude Code finished without a written reply.)\";\n return { reply: text + tail, ...(typeof j.session_id === \"string\" ? { session: j.session_id } : {}) };\n }\n\n private addKey(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number) {\n const k = cmd.key!;\n const name = typeof cmd.name === \"string\" ? cmd.name.trim().slice(0, 80) : undefined;\n /* v8 ignore next -- the receiver that handed the message over is in cfg, unless `control off` ran mid-flight */\n const rec = this.cfg.receivers.find((x) => x.control === r.control && x.machine === r.machine) ?? r;\n if (rec.keys.some((x) => x.id === k.id))\n return this.finish(r, id, { outcome: \"delivered\", detail: \"that device was already trusted\" }, sent);\n // The whole key, as the verifier checked it (keyUsable): a device key keeps its\n // type, store and uv, so its signatures are verified as a device key's.\n const device = k.type === \"device\";\n rec.keys.push({\n id: k.id,\n alg: k.alg,\n spki: k.spki,\n ...(device ? { type: k.type, store: k.store, uv: k.uv } : {}),\n ...(name ? { name } : {}),\n added_at: new Date(this.deps.now()).toISOString(),\n });\n try {\n writeControl(this.cfg, this.deps.env);\n } catch (e) {\n rec.keys = rec.keys.filter((x) => x.id !== k.id);\n return this.finish(r, id, {\n outcome: \"failed\",\n detail: `couldn't save the key: ${String(/* v8 ignore next -- writeControl throws fs Errors */ (e as Error)?.message || e)}`,\n });\n }\n this.deps.log(\n `trusted a new ${device ? \"device key (hardware, verified each use)\" : \"device\"}${name ? ` (${name})` : \"\"} on ${r.url}: ${k.id.slice(0, 12)}\u2026, vouched for by a key it already trusted`,\n );\n this.finish(r, id, { outcome: \"delivered\", detail: `trusted ${name || \"a new device\"}` }, sent);\n }\n\n /** Where the session's transcript ends right now: its answer starts after this. */\n private answerFrom(session: string): { file: string; offset: number } | null {\n const ref = parseSessionRef(session);\n if (!ref || ref.harness !== \"claude-code\") return null;\n const t = findTranscript(this.state.copies[ref.id] ?? ref.id, this.deps.claudeDirs());\n return t ? { file: t.file, offset: transcriptEnd(t.file) } : null;\n }\n\n /** A message handed to a live session (a waiter, a Stop block) is `taken` now; the\n * session answers in its own turn, which the daemon reads from the transcript and\n * sends back as the final ack's `reply` \u2014 so the person sees the answer where they\n * asked. A turn that doesn't end within ANSWER_WAIT_MS is acked delivered without. */\n private followAnswer(\n r: PairedReceiver,\n id: string,\n mode: \"waiter\" | \"turn\",\n session: string,\n from: { file: string; offset: number } | null,\n sent: number,\n ): void {\n this.deps.log(`${id.slice(-8)}: in ${session.slice(0, 24)} via ${mode} ${this.deps.now() - sent} ms after send`);\n this.finish(r, id, { outcome: \"taken\" });\n const stream = this.answerStream(r, id);\n void (async () => {\n const answer = from\n ? await awaitAnswer(from.file, from.offset, {\n timeoutMs: this.deps.answerWaitMs ?? ANSWER_WAIT_MS,\n now: this.deps.now,\n onText: (t) => stream.set(t),\n })\n : null;\n stream.close();\n this.finish(r, id, { outcome: \"delivered\", mode, ...(answer ? { reply: answer } : {}) }, sent);\n })().catch((e) =>\n this.finish(r, id, {\n outcome: \"delivered\",\n mode,\n detail: String(/* v8 ignore next -- awaitAnswer throws fs Errors */ (e as Error)?.message || e),\n }),\n );\n }\n\n /** The answer so far, sent as a `progress` ack: whole, with a rising seq, at most\n * one in flight. Fire-and-forget \u2014 the final ack carries everything. */\n private answerStream(r: PairedReceiver, id: string): AnswerStream {\n return new AnswerStream(async (text, seq) => {\n await this.post(r, \"/ack\", {\n acks: [\n {\n id,\n outcome: \"progress\",\n at: new Date(this.deps.now()).toISOString(),\n seq,\n reply: redactSecrets(text).slice(0, MAX_REPLY),\n },\n ],\n });\n });\n }\n\n /** Mark a session as held by one of the daemon's runs while `fn` runs. */\n private async owning<T>(session: string, fn: () => Promise<T>): Promise<T> {\n this.ownRuns.set(session, (this.ownRuns.get(session) ?? 0) + 1);\n try {\n return await fn();\n } finally {\n /* v8 ignore next -- a session being let go of was always held */\n const n = (this.ownRuns.get(session) ?? 1) - 1;\n if (n > 0) this.ownRuns.set(session, n);\n else this.ownRuns.delete(session);\n }\n }\n\n private limits() {\n const l = this.cfg.limits ?? {};\n const n = (v: unknown, d: number) => (typeof v === \"number\" && Number.isInteger(v) && v >= 0 ? v : d);\n return {\n startConcurrent: n(l.start_concurrent, LIMITS.startConcurrent),\n startPerHour: n(l.start_per_hour, LIMITS.startPerHour),\n headless: Math.max(1, n(l.headless, LIMITS.headless)),\n };\n }\n\n /** One headless Claude Code process at a time per slot; the rest wait in order. */\n private async slot<T>(fn: () => Promise<T>): Promise<T> {\n while (this.procs >= this.limits().headless) await new Promise<void>((r) => this.procWaiters.push(r));\n this.procs++;\n try {\n return await fn();\n } finally {\n this.procs--;\n this.procWaiters.shift()?.();\n }\n }\n\n private async startSession(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number): Promise<void> {\n const lim = this.limits();\n const now = this.deps.now();\n this.startTimes = this.startTimes.filter((t) => now - t < 3_600_000);\n if (this.startsRunning >= lim.startConcurrent || this.startTimes.length >= lim.startPerHour) {\n const detail =\n this.startsRunning >= lim.startConcurrent\n ? `this machine is already starting ${this.startsRunning} new session(s); it starts at most ${lim.startConcurrent} at once`\n : `this machine started ${this.startTimes.length} new sessions in the last hour, its limit`;\n this.deps.log(`refused ${id.slice(-8)}: start_limit \u2014 ${detail}`);\n return this.finish(r, id, { outcome: \"refused\", code: \"start_limit\", detail });\n }\n this.startsRunning++;\n this.startTimes.push(now);\n const sid = parseSessionRef(cmd.session)!.id;\n try {\n // On the session's own queue, and held as the daemon's own: a message sent while\n // the start still runs waits for it and resumes the session, never forks it.\n await this.serial(sid, () => this.owning(sid, () => this.startOne(r, id, cmd, sent)));\n } finally {\n this.startsRunning--;\n }\n }\n\n private async startOne(r: PairedReceiver, id: string, cmd: ControlCommand, sent: number): Promise<void> {\n const ref = parseSessionRef(cmd.session)!;\n const cwd = this.allowed(cmd.cwd as string);\n if (!cwd)\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"folder\",\n detail: \"that folder isn't one this machine allows\",\n });\n // The level and model, checked before anything is taken (CONTROL.md \u00A75 step 8).\n const choice = this.startChoice(ref.harness, cmd);\n if (\"code\" in choice) {\n this.deps.log(`refused ${id.slice(-8)}: ${choice.code} \u2014 ${choice.detail}`);\n return this.finish(r, id, { outcome: \"refused\", code: choice.code, detail: choice.detail });\n }\n const o = choice.options;\n if (acpControl.acpAgent(ref.harness)) return this.startAcp(r, id, cmd, ref, cwd, sent);\n if (ref.harness !== \"claude-code\") return this.startDriven(r, id, cmd, ref, cwd, sent, o);\n if (findTranscript(ref.id, this.deps.claudeDirs()) || this.sdkSessions.has(ref.id))\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"bad_session\",\n detail: \"that new session's id is already taken\",\n });\n const claude = this.deps.sdk ? null : this.deps.claude();\n if (!this.deps.sdk && !claude)\n return this.finish(r, id, { outcome: \"failed\", detail: \"Claude Code isn't installed on this machine\" });\n const signedOut = await this.loginProblem(this.deps.env?.CLAUDE_CONFIG_DIR);\n if (signedOut) return this.finish(r, id, { outcome: \"failed\", detail: signedOut });\n this.recordStart(ref.id, o);\n this.finish(r, id, { outcome: \"taken\", applied: this.applied(o) });\n const text = await this.attached(r, id, cmd, ref, cwd);\n if (text === null) return;\n if (this.deps.sdk) {\n const sdk = this.deps.sdk;\n const out = await this.slot(async () => {\n const s = sdk.start({\n session: ref.id,\n cwd,\n permission: o.permission,\n ...(o.model ? { model: o.model } : {}),\n allowedTools: this.allowedFor(r),\n });\n this.sdkSessions.set(ref.id, s);\n return s.send(frameStart(text, r.url));\n });\n return this.finish(\n r,\n id,\n out.error\n ? this.failedRun(out.error, o)\n : { outcome: \"delivered\", mode: \"sdk\", reply: out.reply, applied: this.applied(o) },\n sent,\n );\n }\n const c = claude!;\n const built = claudeArgs({\n caps: c.caps,\n level: o.permission,\n prompt: frameStart(text, r.url),\n session: ref.id,\n allowedTools: this.allowedFor(r),\n ...(o.model ? { model: o.model } : {}),\n });\n /* v8 ignore next -- startChoice() offered this level from these same caps */\n const args = \"args\" in built ? built.args : [];\n const stream = this.answerStream(r, id);\n const res = await this.slot(() =>\n this.deps.run(c.bin, args, {\n cwd,\n env: claudeEnv(undefined, this.deps.env),\n timeoutMs: JOB_TIMEOUT_MS,\n ...(c.caps.stream ? { onLine: (l: string) => stream.feed(l) } : {}),\n }),\n );\n stream.close();\n // The transcript this run just wrote is ours: the next message must not read it as a\n // live session (a fork instead of a resume).\n this.lastEnd.set(ref.id, this.deps.now());\n const out = this.outcome(res);\n if (\"failed\" in out) return this.finish(r, id, this.failedRun(out.failed, o));\n this.finish(r, id, { outcome: \"delivered\", mode: \"resume\", reply: out.reply, applied: this.applied(o) }, sent);\n }\n\n /** A Claude Code session the daemon starts: what it runs with, for its later runs. */\n private recordStart(session: string, o: StartOptions): void {\n this.state.started[session] = o;\n try {\n writeState(path.join(this.dir, \"state.json\"), this.state);\n } catch (e) {\n this.deps.log(\n `couldn't record what ${session.slice(0, 8)} runs with: ${String(/* v8 ignore next -- writeState throws fs Errors */ (e as Error)?.message || e)}`,\n );\n }\n }\n\n /** A new Codex or Antigravity session: the harness picks its id, and the start's id\n * becomes its name (aliases.ts) as soon as the run says what it picked. */\n private async startDriven(\n r: PairedReceiver,\n id: string,\n cmd: ControlCommand,\n ref: { harness: string; id: string },\n cwd: string,\n sent: number,\n o: StartOptions,\n ): Promise<void> {\n const drv = this.driver(ref.harness)!;\n const env = this.deps.env ?? process.env;\n if (\n this.aliasOf(ref.harness, ref.id) ||\n this.live.get(cmd.session)?.cwd ||\n (ref.harness === \"codex\" && isUuid(ref.id) && codexControl.findRollout(ref.id, env))\n )\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"bad_session\",\n detail: \"that new session's id is already taken\",\n });\n const ready = await this.drivenProblem(drv);\n if (\"failed\" in ready) return this.finish(r, id, { outcome: \"failed\", detail: ready.failed });\n this.finish(r, id, { outcome: \"taken\", applied: this.applied(o) });\n const text = await this.attached(r, id, cmd, ref, cwd);\n if (text === null) return;\n const args = drv.args({\n permission: o.permission,\n prompt: frameStart(text, r.url),\n cwd,\n ...(o.model ? { model: o.model } : {}),\n });\n this.deps.log(\n `${id.slice(-8)}: ${drv.cmd} new session for ${shortId(ref.harness, ref.id)} (${o.permission}) in ${cwd}`,\n );\n await this.drive(r, id, ref, drv, ready.bin, args, cwd, sent, null, o, o);\n }\n\n /** A new session of an ACP agent (CONTROL.md \u00A76): the agent's CLI as a child the\n * daemon keeps, the start's id as the session's name the moment the agent names its\n * own (aliases.ts), and the first turn through it. Acked `delivered` in `api` mode;\n * later messages go through the same process while it is held. */\n private async startAcp(\n r: PairedReceiver,\n id: string,\n cmd: ControlCommand,\n ref: { harness: string; id: string },\n cwd: string,\n sent: number,\n ): Promise<void> {\n const label = this.label(ref.harness);\n if (this.aliasOf(ref.harness, ref.id) || this.live.get(cmd.session)?.cwd || this.sdkSessions.has(ref.id))\n return this.finish(r, id, {\n outcome: \"refused\",\n code: \"bad_session\",\n detail: \"that new session's id is already taken\",\n });\n const found = this.deps.acp?.(ref.harness) ?? null;\n if (!found) return this.finish(r, id, { outcome: \"failed\", detail: `${label} isn't installed on this machine` });\n this.finish(r, id, { outcome: \"taken\" });\n const text = await this.attached(r, id, cmd, ref, cwd);\n if (text === null) return;\n this.deps.log(\n `${id.slice(-8)}: ${found.bin} new session for ${shortId(ref.harness, ref.id)} (${this.cfg.mode}) in ${cwd}`,\n );\n const stream = this.answerStream(r, id);\n const out = await this.slot(async () => {\n const opened = await this.openAcp(id, found, cwd, label, stream);\n if (\"failed\" in opened) return { reply: \"\", error: opened.failed };\n /* v8 ignore next -- unsupported only comes of a session/load, which a start never asks for */\n if (\"unsupported\" in opened) return { reply: \"\", error: opened.unsupported };\n this.sdkSessions.set(ref.id, opened.held);\n this.setAlias(ref.harness, ref.id, opened.held.session, cwd, null);\n return this.sendHeld(ref.id, opened.held, frameStart(text, r.url));\n });\n stream.close();\n this.finish(\n r,\n id,\n out.error ? { outcome: \"failed\", detail: out.error } : { outcome: \"delivered\", mode: \"api\", reply: out.reply },\n sent,\n );\n }\n\n /** The next message for an ACP-driven session no process holds: the agent run again\n * and the session reopened in it (`session/load`), then held like a new one. Acked\n * `resume`, as any cold start. An agent that can't reopen one is `unsupported`. */\n private async resumeAcp(r: PairedReceiver, id: string, cmd: ControlCommand, place: Placed, sent: number) {\n const ref = parseSessionRef(cmd.session)!;\n const label = this.label(ref.harness);\n const found = this.deps.acp?.(ref.harness) ?? null;\n if (!found) return this.finish(r, id, { outcome: \"failed\", detail: `${label} isn't installed on this machine` });\n this.finish(r, id, { outcome: \"taken\" });\n await this.serial(ref.id, async () => {\n /* v8 ignore next -- placeDriven() always names a target; the last fallback is for the type */\n const target = this.aliasOf(ref.harness, ref.id)?.id ?? place.target ?? ref.id;\n this.deps.log(\n `${id.slice(-8)}: ${found.bin} reopens ${target.slice(0, 8)} (${this.cfg.mode}) in ${place.folder}`,\n );\n const stream = this.answerStream(r, id);\n const out = await this.owning(ref.id, () =>\n this.slot(async () => {\n const opened = await this.openAcp(id, found, place.folder, label, stream, target);\n if (\"unsupported\" in opened) return { reply: \"\", unsupported: opened.unsupported };\n if (\"failed\" in opened) return { reply: \"\", error: opened.failed };\n this.sdkSessions.set(ref.id, opened.held);\n return this.sendHeld(ref.id, opened.held, frame(cmd.text as string, r.url));\n }),\n );\n stream.close();\n if (\"unsupported\" in out) return this.finish(r, id, { outcome: \"unsupported\", detail: out.unsupported });\n this.finish(\n r,\n id,\n out.error\n ? { outcome: \"failed\", detail: out.error }\n : { outcome: \"delivered\", mode: \"resume\", reply: out.reply },\n sent,\n );\n });\n }\n\n private openAcp(\n id: string,\n found: { bin: string; args: string[] },\n cwd: string,\n label: string,\n stream: AnswerStream,\n load?: string,\n ): Promise<acpControl.AcpStart> {\n return acpControl.startAcp({\n ...found,\n cwd,\n mode: this.cfg.mode,\n label,\n env: this.deps.env ?? process.env,\n ...(load ? { load } : {}),\n onText: (t) => stream.set(t),\n log: (l) => this.deps.log(`${id.slice(-8)}: ${l}`),\n now: this.deps.now,\n });\n }\n\n /** A start's or a prompt's text, with its files (CONTROL.md \u00A76) fetched, checked and\n * written under `cwd` first (a prompt's in a folder of its own, named by its signed\n * nonce) \u2014 every check in \u00A75 passed and the nonce is recorded by now, so the `taken`\n * ack is out and the download may take its time. Null when a file failed: the command\n * is acked `failed` with code `file`, nothing is kept, no session starts and no\n * message is delivered. */\n private async attached(\n r: PairedReceiver,\n id: string,\n cmd: ControlCommand,\n ref: { id: string },\n cwd: string,\n message?: string,\n ): Promise<string | null> {\n const text = cmd.text as string;\n if (!cmd.files) return text;\n try {\n const got = await fetchFiles(cmd.files, {\n control: r.control,\n token: r.token,\n fetch: this.deps.fetch,\n timeoutMs: this.deps.fileTimeoutMs,\n });\n const rel = writeFiles(cwd, ref.id, got, message);\n this.deps.log(\n `${id.slice(-8)}: ${got.length} file(s) saved in ${cwd}/.sessionpipe/files/${ref.id}${message ? `/${message}` : \"\"}`,\n );\n return withFiles(text, got, rel);\n } catch (e) {\n // fetchFiles and writeFiles throw nothing but a FileProblem, and its message is the detail.\n const detail = (e as Error).message;\n this.deps.log(`${id.slice(-8)}: file \u2014 ${detail}`);\n this.finish(r, id, { outcome: \"failed\", code: \"file\", detail });\n return null;\n }\n }\n\n private closeIdleSdk(): void {\n const idle = this.deps.sdkIdleMs ?? 10 * 60_000;\n for (const [id, s] of this.sdkSessions)\n if (!s.busy && this.deps.now() - s.lastUsed > idle) {\n s.close();\n this.sdkSessions.delete(id);\n this.deps.log(\n `sdk session ${id.slice(0, 8)} closed after ${Math.round(idle / 60_000)} min idle (it resumes on the next message)`,\n );\n }\n }\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms).unref?.());\n\n/** dev:ino of the file at `p`, or null when there is none. */\nfunction socketId(p: string): string | null {\n try {\n const st = statSync(p);\n return `${st.dev}:${st.ino}`;\n } catch {\n return null;\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Attachments on a `start` or a `prompt` (spec/CONTROL.md \u00A73.1, \u00A76): the signed command\n// names each file by its SHA-256; the bytes wait on the receiver. The daemon fetches\n// each one with the machine's token, stops reading past the signed size, checks length\n// and hash, and only then writes it \u2014 under <cwd>/.sessionpipe/files/<session>/ for a\n// start, <session>/<nonce>/ for a prompt \u2014 never through a symlink, never over an\n// existing path, mode 0600. Any problem: nothing is kept, and the session doesn't start\n// or the message isn't delivered. The same for every harness and every delivery mode:\n// the files are in `cwd` before the run, and nothing about them is the harness's.\nimport { createHash } from \"node:crypto\";\nimport { existsSync, lstatSync, mkdirSync, realpathSync, rmSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { ControlFile } from \"@sessionpipe/core/control\";\n\n/** One file's download may take this long (25 MiB on a slow link). */\nexport const FETCH_TIMEOUT_MS = 5 * 60_000;\n\n/** A file could not be fetched, checked or written: the ack's `detail`, code `file`. */\nexport class FileProblem extends Error {}\n\nexport interface Fetched {\n file: ControlFile;\n /** The name as written: NFC. */\n name: string;\n bytes: Uint8Array;\n}\n\nexport interface FetchOptions {\n control: string;\n token: string;\n fetch: typeof fetch;\n /** Per file; tests shorten it. */\n timeoutMs?: number | undefined;\n}\n\nconst b64url = (b: Buffer) => b.toString(\"base64\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\nconst reason = (e: unknown) => (e instanceof Error ? e.message : String(e)).slice(0, 160);\n\n/** Fetch every file, in order, and check each against the signed size and hash.\n * Every failure is a FileProblem naming the file. */\nexport async function fetchFiles(files: ControlFile[], o: FetchOptions): Promise<Fetched[]> {\n const out: Fetched[] = [];\n for (const file of files) {\n let bytes: Uint8Array;\n try {\n bytes = await fetchOne(file, o);\n } catch (e) {\n if (e instanceof FileProblem) throw e;\n throw new FileProblem(`couldn't download ${JSON.stringify(file.name)}: ${reason(e)}`);\n }\n out.push({ file, name: file.name.normalize(\"NFC\"), bytes });\n }\n return out;\n}\n\nasync function fetchOne(f: ControlFile, o: FetchOptions): Promise<Uint8Array> {\n const label = JSON.stringify(f.name);\n const ctl = new AbortController();\n const t = setTimeout(() => ctl.abort(), o.timeoutMs ?? FETCH_TIMEOUT_MS);\n try {\n const res = await o.fetch(`${o.control.replace(/\\/$/, \"\")}/files/${f.sha256}`, {\n headers: { authorization: `Bearer ${o.token}` },\n signal: ctl.signal,\n });\n if (res.status === 404) throw new FileProblem(`${label} isn't on the receiver (never uploaded, or expired)`);\n if (res.status !== 200) throw new FileProblem(`couldn't download ${label}: HTTP ${res.status}`);\n // A declared length past the signed size: not a byte of it is read.\n if (Number(res.headers.get(\"content-length\")) > f.size) throw tooLong(label, f);\n const buf = new Uint8Array(f.size);\n let got = 0;\n const reader = res.body!.getReader();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n // Past the signed size: stop reading, whatever the receiver keeps sending.\n if (got + value.length > f.size) throw tooLong(label, f);\n buf.set(value, got);\n got += value.length;\n }\n if (got !== f.size) throw new FileProblem(`${label} is ${got} bytes, not its signed ${f.size}`);\n const hash = b64url(createHash(\"sha256\").update(buf).digest());\n if (hash !== f.sha256) throw new FileProblem(`${label} doesn't match its signed hash: it was changed`);\n return buf;\n } finally {\n clearTimeout(t);\n // Done or failed: whatever the receiver is still sending is cut off here.\n ctl.abort();\n }\n}\n\nconst tooLong = (label: string, f: ControlFile) =>\n new FileProblem(`${label} is larger than its signed size (${f.size} bytes)`);\n\n/** A directory that must be real (not a symlink) \u2014 made when absent. Anything else in\n * the way (a file of that name) fails the mkdir, and the files with it. */\nfunction realDir(p: string, why: string): void {\n mkdirSync(p, { recursive: true, mode: 0o700 });\n if (lstatSync(p).isSymbolicLink()) throw new FileProblem(`${why} is a symlink`);\n}\n\n/**\n * Write the checked files to <cwd>/.sessionpipe/files/<session>/ (a start's, which must\n * be new) or <session>/<message>/ (a prompt's: the session's folder may be there, the\n * message's must be new), and answer their paths relative to cwd. `cwd` is already\n * resolved (realpath) and allowed. On any problem everything written here is removed\n * and FileProblem thrown.\n */\nexport function writeFiles(cwd: string, session: string, files: Fetched[], message?: string): string[] {\n const top = path.join(cwd, \".sessionpipe\");\n const parent = path.join(top, \"files\");\n const sub = message ? `${session}/${message}` : session;\n const dir = path.join(parent, session, ...(message ? [message] : []));\n let made = false;\n try {\n // Names the protocol allows in an id that are no folder of their own.\n for (const part of [session, message])\n if (part === \".\" || part === \"..\") throw new FileProblem(`no folder ${part}`);\n realDir(top, \".sessionpipe\");\n // The folder ignores itself, so a repository never picks it up.\n const ignore = path.join(top, \".gitignore\");\n if (!existsSync(ignore)) writeFileSync(ignore, \"*\\n\", { flag: \"wx\", mode: 0o600 });\n realDir(parent, \".sessionpipe/files\");\n if (message) realDir(path.join(parent, session), `.sessionpipe/files/${session}`);\n if (existsSync(dir)) throw new FileProblem(`.sessionpipe/files/${sub} already exists`);\n mkdirSync(dir, { mode: 0o700 });\n made = true;\n // Every parent between cwd and here is a real directory right now.\n if (realpathSync.native(dir) !== dir) throw new FileProblem(\".sessionpipe leads outside the session's folder\");\n const rel: string[] = [];\n for (const f of files) {\n // wx: exclusive create, which also refuses to open through a symlink.\n writeFileSync(path.join(dir, f.name), f.bytes, { flag: \"wx\", mode: 0o600 });\n rel.push(`.sessionpipe/files/${sub}/${f.name}`);\n }\n return rel;\n } catch (e) {\n if (made) rmSync(dir, { recursive: true, force: true });\n if (e instanceof FileProblem) throw e;\n throw new FileProblem(`couldn't save the files: ${reason(e)}`);\n }\n}\n\n/** 183402 \u2192 \"179 KB\", 1258291 \u2192 \"1.2 MB\" (units of 1024). */\nexport function humanSize(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1_048_576) return `${Math.round(n / 1024)} KB`;\n return `${(n / 1_048_576).toFixed(1)} MB`;\n}\n\n/** The command's text followed by the list of files the session can read. */\nexport function withFiles(text: string, files: Fetched[], rel: string[]): string {\n const lines = files.map((f, i) => `- ${rel[i]} (${f.file.type}, ${humanSize(f.file.size)})`);\n return `${text}\\n\\nAttached files (saved in this folder):\\n${lines.join(\"\\n\")}`;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The answer to a message delivered in place (spec/CONTROL.md \u00A76 `prompt`). A waiter or\n// a Stop block hands the message to the live session, which answers in its own turn;\n// the daemon reads that turn from the session's own transcript and sends it back as the\n// ack's `reply`, so the person sees the answer where they asked. Only the bytes the\n// transcript gained after the delivery are read: a long session's file is never parsed\n// whole, and nothing from before the message can be mistaken for its answer.\nimport { closeSync, openSync, readSync, statSync } from \"node:fs\";\n\n/** The transcript's size now: where its answer will start. */\nexport function transcriptEnd(file: string): number {\n try {\n return statSync(file).size;\n } catch {\n return 0;\n }\n}\n\n/** Claude Code records after the delivery \u2192 the turn's answer once the turn ended\n * (an assistant record with `stop_reason: \"end_turn\"`), else null. The answer is the\n * turn's assistant text, in order; sidechains (subagents) are not the session's words. */\nexport function answerIn(lines: string[]): { done: boolean; text: string } {\n const parts: string[] = [];\n for (const line of lines) {\n let j: {\n type?: string;\n isSidechain?: boolean;\n message?: { stop_reason?: string; content?: unknown };\n };\n try {\n j = JSON.parse(line);\n } catch {\n continue;\n }\n if (j.type !== \"assistant\" || j.isSidechain) continue;\n const content = j.message?.content;\n if (Array.isArray(content))\n for (const c of content as { type?: string; text?: unknown }[])\n if (c?.type === \"text\" && typeof c.text === \"string\" && c.text.trim()) parts.push(c.text.trim());\n if (j.message?.stop_reason === \"end_turn\") return { done: true, text: parts.join(\"\\n\\n\") };\n }\n return { done: false, text: parts.join(\"\\n\\n\") };\n}\n\n/** Wait for the turn that follows a delivery to end, reading the transcript from\n * `from` (its size at delivery). Resolves the answer, or null when the turn doesn't\n * end within `timeoutMs` (an interrupted turn, a session closed mid-answer). */\nexport async function awaitAnswer(\n file: string,\n from: number,\n o: {\n timeoutMs: number;\n pollMs?: number;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n /** The turn's text so far, each time it grows (for the progress ack). */\n onText?: (text: string) => void;\n },\n): Promise<string | null> {\n const now = o.now ?? Date.now;\n const sleep = o.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms).unref?.()));\n const until = now() + o.timeoutMs;\n let offset = from;\n let partial = \"\";\n const lines: string[] = [];\n while (now() < until) {\n const size = transcriptEnd(file);\n if (size < offset) return null; // rewritten under us: nothing we can trust\n if (size > offset) {\n const fd = openSync(file, \"r\");\n try {\n const buf = Buffer.alloc(Math.min(size - offset, 4 * 1024 * 1024));\n const n = readSync(fd, buf, 0, buf.length, offset);\n offset += n;\n const chunk = partial + buf.subarray(0, n).toString(\"utf8\");\n const cut = chunk.lastIndexOf(\"\\n\");\n partial = cut < 0 ? chunk : chunk.slice(cut + 1);\n if (cut >= 0) lines.push(...chunk.slice(0, cut).split(\"\\n\").filter(Boolean));\n } finally {\n closeSync(fd);\n }\n const a = answerIn(lines);\n if (a.done) return a.text || null;\n if (a.text) o.onText?.(a.text);\n }\n await sleep(o.pollMs ?? 500);\n }\n return null;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The routing rule (spec/CONTROL.md \u00A76): the first delivery mode that fits, top to\n// bottom. Pure, so every branch is a unit test.\nimport { acpControl } from \"@sessionpipe/core\";\nimport type { ControlKind } from \"@sessionpipe/core/control\";\n\nexport type DeliveryMode = \"sdk\" | \"waiter\" | \"turn\" | \"api\" | \"resume\" | \"fork\";\n\nexport interface SessionView {\n harness: string;\n /** The daemon holds this session through the Agent SDK right now. */\n sdk: boolean;\n /** A `sessionpipe wait` for it is parked on the socket. */\n waiter: boolean;\n /** Between a turn's start and its Stop (the Stop hook will ask). */\n midTurn: boolean;\n /** A live process holds the session (registry entry or a fresh transcript write). */\n live: boolean;\n /** The transcript exists on this machine (Codex, Antigravity: the session was placed). */\n known: boolean;\n /** This Claude Code can copy a session (`--fork-session`); no other harness can. */\n canFork: boolean;\n /** The harness has an input API (OpenCode, Codex app-server) \u2014 none is wired yet. */\n api: boolean;\n}\n\nexport type Route = { mode: DeliveryMode } | { unsupported: string } | { refused: \"no_session\" };\n\n/** The harnesses the daemon can run a turn of by itself: resume an idle session, start a\n * new one (`claude -p`, `codex exec`, `agy -p`, or any ACP agent as its client). */\nexport const HEADLESS = new Set([\"claude-code\", \"codex\", \"antigravity\", ...acpControl.ACP_HARNESSES]);\n\n/** Where a prompt (or a start) goes. Never two writers on one transcript: a live\n * session gets a fork, never a resume. */\nexport function routePrompt(s: SessionView): Route {\n if (s.sdk) return { mode: \"sdk\" };\n if (s.waiter) return { mode: \"waiter\" };\n if (s.midTurn) return { mode: \"turn\" };\n if (s.api) return { mode: \"api\" };\n if (!HEADLESS.has(s.harness)) return { unsupported: `no idle delivery for ${s.harness} yet` };\n if (!s.known) return { refused: \"no_session\" };\n if (!s.live) return { mode: \"resume\" };\n if (s.canFork) return { mode: \"fork\" };\n return {\n unsupported:\n s.harness === \"claude-code\"\n ? \"the session is open and this Claude Code can't copy it (no --fork-session)\"\n : `the session is open in ${s.harness} right now, and a ${s.harness} session can't be copied: send it again once it has been idle a couple of minutes`,\n };\n}\n\n/** How each kind is delivered, before the session's state is looked at. */\nexport function kindPath(\n kind: ControlKind,\n harness: string,\n): \"prompt\" | \"permission\" | \"cancel\" | \"start\" | { unsupported: string } {\n switch (kind) {\n case \"prompt\":\n return \"prompt\";\n case \"permission.answer\":\n return harness === \"gemini-cli\"\n ? { unsupported: \"Gemini CLI has no permission answer channel\" }\n : harness === \"devin\"\n ? { unsupported: \"Devin has no permission answer channel\" }\n : \"permission\";\n case \"cancel\":\n return \"cancel\";\n case \"start\":\n return HEADLESS.has(harness) ? \"start\" : { unsupported: `can't start a ${harness} session` };\n default:\n return { unsupported: `unknown kind ${String(kind)}` };\n }\n}\n\n/** The framed text a session receives (CONTROL.md \u00A76): the model and the person can\n * tell where it came from. */\n/** Said with every message that reaches a live session: the answer goes back by\n * itself (the daemon reads it from the transcript), so the model never invents a\n * command to reply with (a real session tried \\`sessionpipe send\\`, 2026-10-01). */\nexport const IN_PLACE_ANSWER =\n \"Answer it right here, as you would answer the person at the keyboard: your reply is sent back to them automatically. Don't run a command or call a tool just to send it.\";\n\nexport function frame(text: string, receiver: string): string {\n let host = receiver;\n try {\n host = new URL(receiver).host;\n } catch {}\n return `Message via ${host} (sessionpipe control, signed on the sender's device):\\n\\n${text}`;\n}\n\n/** A new session's first message: the person's words first, where they come from after.\n * Claude Code names a session from the start of its first message, so a header in front\n * named every started session \"Message via spacesheep.dev (sessionpipe control, s\u2026\"\n * (2026-10-02). In a new session there is no one else's conversation to tell it apart\n * from, so the source line can follow the ask. */\nexport function frameStart(text: string, receiver: string): string {\n let host = receiver;\n try {\n host = new URL(receiver).host;\n } catch {}\n return `${text}\\n\\n(Sent via ${host} with sessionpipe control, signed on the sender's device.)`;\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The answer as it is written (spec/CONTROL.md \u00A710, the `progress` ack). A headless run\n// streams Claude Code's output (`--output-format stream-json --include-partial-\n// messages`) and a live session's transcript grows message by message; either way the\n// daemon sends the receiver the answer SO FAR, whole, with a rising seq. Reliability\n// comes from that shape, not from delivery: a progress ack is fire-and-forget, a lost\n// one is covered by the next, and the final `delivered` ack always carries the full\n// answer. At most one is in flight, at most one every `everyMs`.\n\n/** One stream-json line \u2192 text to append, or a message boundary (a new assistant\n * message after a tool step: its text starts a new paragraph). */\nexport function streamJsonPiece(line: string): { text?: string; boundary?: boolean } | null {\n let j: {\n type?: string;\n parent_tool_use_id?: unknown;\n event?: { type?: string; delta?: { type?: string; text?: unknown } };\n };\n try {\n j = JSON.parse(line);\n } catch {\n return null;\n }\n if (j.type !== \"stream_event\" || !j.event) return null;\n // A subagent's stream (a Task tool's) is not the session's answer.\n if (j.parent_tool_use_id) return null;\n const e = j.event;\n if (e.type === \"content_block_delta\" && e.delta?.type === \"text_delta\" && typeof e.delta.text === \"string\")\n return { text: e.delta.text };\n if (e.type === \"message_start\") return { boundary: true };\n return null;\n}\n\nexport class AnswerStream {\n private text = \"\";\n private sent = \"\";\n private seq = 0;\n private timer: NodeJS.Timeout | null = null;\n private inFlight = false;\n private closed = false;\n\n constructor(\n private readonly send: (text: string, seq: number) => Promise<void>,\n private readonly everyMs = 400,\n ) {}\n\n /** A stream-json line from a headless run. */\n feed(line: string): void {\n const p = streamJsonPiece(line);\n if (!p) return;\n if (p.boundary) {\n if (this.text && !this.text.endsWith(\"\\n\\n\")) this.text += \"\\n\\n\";\n return;\n }\n if (p.text) {\n this.text += p.text;\n this.schedule();\n }\n }\n\n /** The whole answer so far (a live session's transcript). */\n set(text: string): void {\n if (text === this.text) return;\n this.text = text;\n this.schedule();\n }\n\n /** No more progress: the final ack follows. */\n close(): void {\n this.closed = true;\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n }\n\n private schedule(): void {\n if (this.closed || this.timer || this.inFlight) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n void this.flush();\n }, this.everyMs);\n this.timer.unref?.();\n }\n\n private async flush(): Promise<void> {\n const t = this.text.trim();\n if (this.closed || !t || t === this.sent) return;\n this.inFlight = true;\n this.sent = t;\n try {\n await this.send(t, ++this.seq);\n } catch {\n // Best effort: the next one, or the final ack, carries everything.\n } finally {\n this.inFlight = false;\n }\n if (this.text.trim() !== this.sent) this.schedule();\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// `sessionpipe control pair <receiver>`: a key enters this machine's trust store only\n// from this terminal (spec/CONTROL.md \u00A72). The receiver hands back a passkey and a\n// proof over sha256(\"sessionpipe.pair:<machine>:<code>\"); the key is trusted only once\n// the proof verifies here. Also the service files (launchd / systemd) that keep the\n// daemon running, and `control off`.\nimport { randomBytes } from \"node:crypto\";\nimport { mkdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n acpControl,\n claudeAccounts,\n claudeDirs,\n drivableHarnesses,\n type HarnessAccount,\n HELLO_HARNESSES_MAX,\n} from \"@sessionpipe/core\";\nimport { KEY_TYPES, type TrustedKey, verifyEnrollment } from \"@sessionpipe/core/control\";\nimport type { Exec } from \"@sessionpipe/core/service\";\nimport * as core from \"@sessionpipe/core/service\";\nimport {\n type ControlConfig,\n type ControlMode,\n controlState,\n dropControlSecret,\n type PairedReceiver,\n readControl,\n writeControl,\n} from \"./store.js\";\n\ndeclare const __SESSIONPIPE_VERSION__: string;\nconst VERSION = typeof __SESSIONPIPE_VERSION__ === \"string\" ? __SESSIONPIPE_VERSION__ : \"0.0.0\";\n\nexport interface PairOptions {\n url: string;\n /** The person's sink token for this receiver (from `sink add`, or --token). Null:\n * open pairing, where the receiver offers it \u2014 the person approves a link and that\n * is the whole setup (CONTROL.md \u00A72). */\n token: string | null;\n folders: string[];\n mode: ControlMode;\n name: string;\n out: (s: string) => void;\n fetch?: typeof fetch;\n sleep?: (ms: number) => Promise<void>;\n env?: NodeJS.ProcessEnv;\n /** Called with a sessions key the receiver handed over at pairing. */\n addSink?: (token: string) => void;\n /** The harnesses this machine can run a message in (default: those installed here). */\n harnesses?: string[];\n /** The harness accounts signed in here (default: every Claude Code config dir's). */\n accounts?: HarnessAccount[];\n /** How long expired codes are renewed for (default RENEW_FOR_MS). */\n renewFor?: number;\n}\n\n/** How long `control pair` keeps asking for fresh codes when nobody approves one. */\nexport const RENEW_FOR_MS = 60 * 60_000;\n\nasync function json(r: Response): Promise<Record<string, unknown>> {\n try {\n return (await r.json()) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nexport async function discover(\n url: string,\n f: typeof fetch,\n): Promise<{ control: string; rpId: string; open: boolean; inherit: boolean; events: string | null }> {\n const base = url.replace(/\\/$/, \"\");\n const r = await f(`${base}/.well-known/sessionpipe`);\n if (!r.ok) throw new Error(`${base} has no sessionpipe well-known file (HTTP ${r.status})`);\n const wk = (await r.json()) as {\n capabilities?: string[];\n endpoints?: { control?: string; events?: string };\n control?: { signing?: { rp_id?: string }; open_pairing?: boolean; inherit?: boolean };\n };\n if (!wk.capabilities?.includes(\"control\") || !wk.endpoints?.control || !wk.control?.signing?.rp_id)\n throw new Error(`${base} doesn't serve control yet (its well-known file lists no control.signing)`);\n const abs = (ep: string) => (/^https?:\\/\\//.test(ep) ? ep : base + ep);\n return {\n control: abs(wk.endpoints.control),\n rpId: wk.control.signing.rp_id,\n open: wk.control.open_pairing === true,\n inherit: wk.control.inherit === true,\n events: wk.endpoints.events ? abs(wk.endpoints.events) : null,\n };\n}\n\n/** Why a machine won't run in inherit mode with this receiver (CONTROL.md \u00A72): a\n * receiver that doesn't know the mode would show the machine as safe. */\nexport const inheritRefused = (url: string) =>\n `${url} doesn't know inherit mode yet; it would show this machine as safe while the sessions you message run with no permission flag`;\n\n/** The paired receivers that don't say they show inherit mode (`control.inherit` in\n * their well-known file), with why. A receiver that can't be read counts as one. */\nexport async function withoutInherit(urls: string[], f: typeof fetch = fetch): Promise<string[]> {\n const out: string[] = [];\n for (const url of urls) {\n try {\n if (!(await discover(url, f)).inherit) out.push(inheritRefused(url));\n } catch (e) {\n out.push(`couldn't check that ${url} knows inherit mode (${(e as Error).message})`);\n }\n }\n return out;\n}\n\n/** Pair (or add a key to) this machine with one receiver. Returns the saved config. */\nexport async function pair(o: PairOptions): Promise<ControlConfig> {\n const f = o.fetch ?? fetch;\n const sleep = o.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)));\n const { control, rpId, open, inherit } = await discover(o.url, f);\n if (o.mode === \"inherit\" && !inherit)\n throw new Error(\n `${inheritRefused(o.url)}. Pair with --mode safe or --mode auto (\\`sessionpipe control mode safe\\` first, if this machine is in inherit already).`,\n );\n if (!o.token && !open)\n throw new Error(\n `${o.url} needs a key to pair: add it as a sink first (\\`sessionpipe sink add ${o.url} --token \u2026\\`) or pass --token.`,\n );\n // Open pairing: a secret only this terminal knows. The receiver keeps its hash, and\n // the status poll that hands over the machine's token must present it \u2014 so the link,\n // which the person opens elsewhere, is not a credential by itself.\n const pollKey = o.token ? null : randomBytes(32).toString(\"base64url\");\n const cfg: ControlConfig = readControl(o.env) ?? { name: o.name, folders: [], mode: o.mode, receivers: [] };\n cfg.name = o.name || cfg.name;\n cfg.mode = o.mode;\n cfg.folders = [...new Set([...cfg.folders, ...o.folders.map((d) => path.resolve(d))])];\n const existing = cfg.receivers.find((r) => r.control === control);\n let accounts = o.accounts;\n if (!accounts)\n try {\n const e = o.env ?? process.env;\n accounts = claudeAccounts(claudeDirs(e), e.HOME);\n } catch {\n accounts = [];\n }\n const auth = { authorization: `Bearer ${o.token ?? pollKey}`, \"content-type\": \"application/json\" };\n const harnesses = (o.harnesses ?? drivableHarnesses(o.env ?? process.env)).slice(0, HELLO_HARNESSES_MAX);\n const hello = {\n ...(pollKey ? { poll_key: pollKey } : {}),\n name: cfg.name,\n harnesses,\n // Every ACP agent's turn is acked `api` (CONTROL.md \u00A76).\n modes: [\"waiter\", \"turn\", \"resume\", \"fork\", ...(harnesses.some((h) => acpControl.acpAgent(h)) ? [\"api\"] : [])],\n version: VERSION,\n folders: cfg.folders,\n mode: cfg.mode,\n ...(accounts.length ? { accounts } : {}),\n // This daemon takes `files` on a start (an older one would start without them).\n files: true,\n // And device keys (CONTROL.md \u00A72): an app offers one only to a machine that says so.\n key_types: [...KEY_TYPES],\n };\n /** One pairing code from the receiver. `machine` names the row a previous code\n * made, so a renewal adds no second machine. */\n const start = async (machine: string | undefined) => {\n const started = await f(`${control}/pair`, {\n method: \"POST\",\n headers: o.token ? auth : { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ...hello, ...(machine ? { machine } : {}) }),\n });\n const s = await json(started);\n if (started.status !== 201 && started.status !== 200)\n throw new Error(\n `the receiver refused to start pairing (HTTP ${started.status}${s.reason ? `: ${String(s.reason)}` : \"\"})`,\n );\n return {\n machine: String(s.machine),\n code: String(s.code),\n url: String(s.url),\n check: String(s.check),\n until: Date.parse(String(s.expires_at)) || Date.now() + 10 * 60_000,\n };\n };\n const host = new URL(o.url).host;\n const announce = (p: { url: string; check: string; until: number }) => {\n const spaced = /^\\d{6}$/.test(p.check) ? `${p.check.slice(0, 3)} ${p.check.slice(3)}` : p.check;\n o.out(\"\");\n // The approval happens on whatever device holds the person's passkey, which is\n // rarely the machine being paired (a server may have no screen at all): say so, or\n // the \"Touch ID\" line reads as \"do it here\" (2026-10-02, four machines, one headless).\n o.out(` On any phone or computer where you're signed in to ${host} (it doesn't have to be this one),`);\n if (pollKey) {\n // Open pairing: one address for everyone, and the digits are what the person types.\n o.out(` open ${p.url} and enter: ${spaced}`);\n o.out(\" then approve with that device's passkey (Touch ID, Face ID, a security key).\");\n o.out(\" Pairing several machines? Run this on each one: every machine shows its own digits.\");\n } else {\n o.out(\" open this link and approve with that device's passkey (Touch ID, Face ID, a security key):\");\n o.out(` ${p.url}`);\n o.out(` The page shows these digits too: ${p.check}`);\n }\n const mins = Math.max(1, Math.round((p.until - Date.now()) / 60_000));\n o.out(` This code is good for ${mins} minute${mins === 1 ? \"\" : \"s\"}; if it runs out, a fresh one appears here.`);\n o.out(\"\");\n };\n // A code lives ten minutes on the receiver. A person approving three headless\n // machines from a phone ran out of them (2026-10-08). A code nobody approved in time\n // is renewed from this terminal, with fresh digits, for up to RENEW_FOR_MS: the old\n // code is dead on the receiver, so no code lives longer than it did.\n const renewUntil = Date.now() + (o.renewFor ?? RENEW_FOR_MS);\n let cur = await start(existing?.machine);\n announce(cur);\n for (;;) {\n await sleep(2000);\n let p: Record<string, unknown> = {};\n let expired = Date.now() > cur.until;\n if (!expired) {\n const r = await f(`${control}/pair?code=${encodeURIComponent(cur.code)}`, { headers: auth }).catch(() => null);\n if (!r) continue;\n if (r.status === 404) throw new Error(\"the receiver lost the pairing; run `sessionpipe control pair` again\");\n p = await json(r);\n if (p.status === \"expired\") expired = true;\n else if (p.status !== \"paired\") continue;\n }\n if (expired) {\n if (Date.now() >= renewUntil) throw new Error(\"the pairing link expired; run `sessionpipe control pair` again\");\n // A keyed pairing keeps the machine row its first code made; an open one starts\n // clean under the same poll key (the receiver names the machine at approval).\n cur = await start(o.token ? cur.machine : existing?.machine);\n o.out(\" Nobody approved that code before it expired. Here is a fresh one; the old digits no longer work.\");\n announce(cur);\n continue;\n }\n const { machine, code } = cur;\n const key = p.key as TrustedKey;\n const proof = p.proof as { cred: string; ad: string; cd: string; sig: string } | { cred: string; sig: string };\n const v = await verifyEnrollment({ machine, code, key, proof, rpId });\n if (!v.ok) throw new Error(`the receiver's key didn't prove itself (${v.why}); nothing was trusted`);\n const token = existing?.token || (typeof p.token === \"string\" ? p.token : \"\");\n if (!token) throw new Error(\"the receiver didn't hand this machine its token\");\n const rec: PairedReceiver = existing ?? {\n url: o.url.replace(/\\/$/, \"\"),\n control,\n rpId,\n machine,\n token,\n keys: [],\n paired_at: new Date().toISOString(),\n };\n if (!rec.keys.some((k) => k.id === key.id)) rec.keys.push({ ...key, added_at: new Date().toISOString() });\n if (!existing) cfg.receivers.push(rec);\n writeControl(cfg, o.env);\n o.out(` \u2713 Paired with ${rec.url} as ${machine} \u00B7 ${rec.keys.length} key(s) trusted on this machine`);\n // Say so when the approving key is an app's device key rather than a passkey.\n if (key.type === \"device\") o.out(\" It approved with an app's device key: held in hardware, verified each use.\");\n const named = accounts.flatMap((a) => (a.email ? [a.email] : a.name ? [a.name] : []));\n if (named.length)\n o.out(` Its session board names your Claude Code account${named.length > 1 ? \"s\" : \"\"}: ${named.join(\", \")}`);\n // Whose passkey this machine now trusts: with open pairing, whoever approved the link.\n if (typeof p.account === \"string\")\n o.out(` Approved by ${p.account}. If that isn't you, run \\`sessionpipe control off\\` now.`);\n // The receiver may hand over a sessions-only key for the events lane, so its session\n // board shows this machine without a second step.\n if (typeof p.sink_token === \"string\" && o.addSink) o.addSink(p.sink_token);\n return cfg;\n }\n}\n\n/** `control off [<receiver>]`: tell the receiver, forget its token and keys. */\nexport async function off(o: {\n url?: string;\n out: (s: string) => void;\n fetch?: typeof fetch;\n env?: NodeJS.ProcessEnv;\n}) {\n const f = o.fetch ?? fetch;\n const cfg = readControl(o.env);\n if (!cfg) return o.out(\" control isn't set up on this machine\");\n const gone = cfg.receivers.filter((r) => !o.url || r.url === o.url.replace(/\\/$/, \"\"));\n for (const r of gone) {\n await f(`${r.control}/off`, { method: \"POST\", headers: { authorization: `Bearer ${r.token}` } }).catch(() => null);\n dropControlSecret(r);\n o.out(` removed ${r.url} (${r.machine}, ${r.keys.length} key(s))`);\n }\n cfg.receivers = cfg.receivers.filter((r) => !gone.includes(r));\n writeControl(cfg, o.env);\n return cfg;\n}\n\nexport function removeKey(id: string, env?: NodeJS.ProcessEnv): number {\n const cfg = readControl(env);\n if (!cfg) return 0;\n let n = 0;\n for (const r of cfg.receivers) {\n const before = r.keys.length;\n r.keys = r.keys.filter((k) => k.id !== id && !k.id.startsWith(id));\n n += before - r.keys.length;\n }\n writeControl(cfg, env);\n return n;\n}\n\n// --- the service -------------------------------------------------------------------\n// The launchd agent and the systemd user unit are core's (sessionpipe-core/service);\n// this is the daemon's: its label, its command line, and what to tell the person.\n\nconst LABEL = \"org.sessionpipe.control\";\nconst UNIT = \"sessionpipe-control.service\";\nconst DESCRIPTION = \"sessionpipe control daemon (signed messages to your coding sessions)\";\n\nexport { type Exec, ensureLinger } from \"@sessionpipe/core/service\";\n\n/** The daemon's service: `<node> <cli> control run`, logging to the state dir. Both files\n * restart it when it exits non-zero; an update exits UPDATE_EXIT (75) to come back on\n * the new code. SESSIONPIPE_SERVICE tells the daemon which manager that is. */\nconst spec = (o: { node: string; cli: string; logDir: string; home?: string }) => ({\n label: LABEL,\n unit: UNIT,\n description: DESCRIPTION,\n argv: [o.node, o.cli, \"control\", \"run\"],\n logPath: path.join(o.logDir, \"daemon.log\"),\n ...(o.home ? { home: o.home } : {}),\n});\n\nexport function serviceFiles(o: { node: string; cli: string; logDir: string; home?: string }) {\n return core.serviceFiles(spec(o));\n}\n\n/** Write and start the service for this platform. Returns what it did, in words. */\nexport function installService(o: {\n node: string;\n cli: string;\n env?: NodeJS.ProcessEnv;\n exec?: Exec;\n platform?: NodeJS.Platform;\n}): string {\n const logDir = controlState(o.env);\n mkdirSync(logDir, { recursive: true, mode: 0o700 });\n const log = path.join(logDir, \"daemon.log\");\n const r = core.installService({\n ...spec({ node: o.node, cli: o.cli, logDir }),\n ...(o.exec ? { exec: o.exec } : {}),\n ...(o.platform ? { platform: o.platform } : {}),\n });\n if (r.manager === \"launchd\")\n return r.domain === \"gui\"\n ? `launchd agent ${LABEL} (log: ${log})`\n : `launchd agent ${LABEL} in the background domain, since nobody is logged in at this Mac's screen; after a restart it starts again when someone logs in there (log: ${log})`;\n if (r.manager === \"systemd\") return `systemd user unit ${UNIT}; ${r.linger?.note} (journalctl --user -u ${UNIT})`;\n if (r.unreachable)\n return `wrote ${r.unreachable}, but systemd --user isn't reachable here; run \\`sessionpipe control run\\` yourself (tmux, screen)`;\n return \"no service manager for this platform yet; run `sessionpipe control run` yourself\";\n}\n\nexport function uninstallService(_env?: NodeJS.ProcessEnv): void {\n core.uninstallService({ label: LABEL, unit: UNIT });\n}\n", "// SPDX-License-Identifier: Apache-2.0\n/** sessionpipe-core/service \u2014 a per-user background service for a sessionpipe process:\n * a launchd agent on macOS, a systemd user unit on Linux. The control daemon runs\n * under it (`org.sessionpipe.control`), and so can a receiver of the person's own (a\n * board on their machine), with the same files and the same commands. Node only: it\n * writes files and runs launchctl, systemctl and loginctl, so it is never part of the\n * root export, which stays Worker- and browser-safe.\n *\n * Both files restart the process when it exits non-zero, and when it exits\n * UPDATE_EXIT (75, sessionpipe-core/version) to come back on new code. The process is\n * told which manager that is in SESSIONPIPE_SERVICE (`launchd`, `systemd`). Nothing\n * here needs root, and a dry run touches nothing: it answers the files it would write\n * and the commands it would run. */\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n/** One service, as both managers need it. */\nexport interface ServiceSpec {\n /** The launchd label, also the plist's name: `org.sessionpipe.control`. */\n label: string;\n /** The systemd user unit's file name: `sessionpipe-control.service`. */\n unit: string;\n /** The unit's Description line. */\n description: string;\n /** The program and its arguments, each one argument (never through a shell). */\n argv: string[];\n /** More environment for the process, beside SESSIONPIPE_SERVICE. */\n env?: Record<string, string>;\n /** Where launchd writes its stdout and stderr (journald keeps a unit's). */\n logPath: string;\n /** The home the files go under; the user's own by default. */\n home?: string;\n}\n\n/** A file the service writes, and what is in it. */\nexport interface ServiceFile {\n path: string;\n text: string;\n}\n\n/** Runs one command and answers its stdout; throws when it fails. */\nexport type Exec = (cmd: string, args: string[]) => string;\n\nconst execQuiet: Exec = (cmd, args) =>\n execFileSync(cmd, args, { encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"], timeout: 15_000 });\n\nconst xml = (s: string) => s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\n/** One systemd argument, quoted: backslashes and quotes escaped, `%` doubled (a specifier otherwise). */\nconst sd = (s: string) => `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/%/g, \"%%\")}\"`;\n\n/** The plist and the unit for a service, and where each goes. */\nexport function serviceFiles(s: ServiceSpec): { plist: ServiceFile; unit: ServiceFile } {\n const home = s.home ?? os.homedir();\n const env = (manager: string) => ({ SESSIONPIPE_SERVICE: manager, ...s.env });\n const plistEnv = Object.entries(env(\"launchd\"))\n .map(([k, v]) => `<key>${xml(k)}</key><string>${xml(v)}</string>`)\n .join(\"\");\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>${xml(s.label)}</string>\n <key>ProgramArguments</key>\n <array>${s.argv.map((a) => `<string>${xml(a)}</string>`).join(\"\")}</array>\n <key>EnvironmentVariables</key><dict>${plistEnv}</dict>\n <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>ProcessType</key><string>Background</string>\n <key>StandardOutPath</key><string>${xml(s.logPath)}</string>\n <key>StandardErrorPath</key><string>${xml(s.logPath)}</string>\n</dict>\n</plist>\n`;\n const unitEnv = Object.entries(env(\"systemd\"))\n .map(([k, v]) => `Environment=${k === \"SESSIONPIPE_SERVICE\" ? `${k}=${v}` : sd(`${k}=${v}`)}`)\n .join(\"\\n\");\n const unit = `[Unit]\nDescription=${s.description.replace(/\\n/g, \" \")}\nAfter=network-online.target\n\n[Service]\nExecStart=${s.argv.map(sd).join(\" \")}\n${unitEnv}\nRestart=on-failure\nRestartForceExitStatus=75\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n`;\n return {\n plist: { path: path.join(home, \"Library\", \"LaunchAgents\", `${s.label}.plist`), text: plist },\n unit: { path: path.join(home, \".config\", \"systemd\", \"user\", s.unit), text: unit },\n };\n}\n\n/** A systemd user service stops when its person's last login ends \u2014 closing the ssh\n * session to a lab workstation or a cloud machine stopped the daemon with it \u2014 unless\n * the user lingers. `loginctl enable-linger` for yourself needs no root on systemd's\n * default policy; where it does, say the one command that does it. */\nexport function ensureLinger(user: string, exec: Exec = execQuiet): { on: boolean; note: string } {\n const lingering = () => {\n try {\n return /^Linger=yes/m.test(exec(\"loginctl\", [\"show-user\", user, \"--property=Linger\"]));\n } catch {\n return false;\n }\n };\n if (lingering()) return { on: true, note: \"it keeps running after you log out (linger was already on)\" };\n try {\n exec(\"loginctl\", [\"enable-linger\", user]);\n } catch {}\n if (lingering()) return { on: true, note: \"it keeps running after you log out (turned linger on)\" };\n return {\n on: false,\n note: `it stops when you log out: run \\`sudo loginctl enable-linger ${user}\\` once to keep it running`,\n };\n}\n\n/** What an install did, or would do in a dry run. */\nexport interface ServicePlan {\n /** The files written (or that would be). */\n files: ServiceFile[];\n /** The commands run (or that would be), one string each, in order. */\n commands: string[];\n /** Which manager runs it now: null on a platform with none, or where it isn't reachable. */\n manager: \"launchd\" | \"systemd\" | null;\n /** launchd: `gui` when someone is at the screen, else `user` (it starts again at the next login there). */\n domain?: \"gui\" | \"user\";\n /** systemd: whether it outlives the login, in words. */\n linger?: { on: boolean; note: string };\n /** The file that was written for a manager that couldn't be reached. */\n unreachable?: string;\n}\n\nexport interface InstallOptions extends ServiceSpec {\n /** Answer the plan and touch nothing. */\n dryRun?: boolean;\n exec?: Exec;\n platform?: NodeJS.Platform;\n /** The user's id (launchd's domains) and name (linger); this process's by default. */\n uid?: string;\n user?: string;\n}\n\nconst line = (cmd: string, args: string[]) => [cmd, ...args].join(\" \");\n\n/** Write the service for this platform and start it now; a service already there is\n * replaced (launchd: booted out first). */\nexport function installService(o: InstallOptions): ServicePlan {\n const f = serviceFiles(o);\n const platform = o.platform ?? process.platform;\n const uid = o.uid ?? String(process.getuid?.() ?? \"\");\n const commands: string[] = [];\n const real = o.exec ?? execQuiet;\n const run: Exec = (cmd, args) => {\n commands.push(line(cmd, args));\n return o.dryRun ? \"\" : real(cmd, args);\n };\n const write = (file: ServiceFile) => {\n if (o.dryRun) return;\n mkdirSync(path.dirname(file.path), { recursive: true });\n writeFileSync(file.path, file.text);\n };\n if (platform === \"darwin\") {\n write(f.plist);\n for (const d of [\"gui\", \"user\"])\n try {\n run(\"launchctl\", [\"bootout\", `${d}/${uid}/${o.label}`]);\n } catch {}\n try {\n run(\"launchctl\", [\"bootstrap\", `gui/${uid}`, f.plist.path]);\n return { files: [f.plist], commands, manager: \"launchd\", domain: \"gui\" };\n } catch {}\n // No one logged in at the screen (an ssh session to a Mac mini): the gui domain\n // doesn't exist. The user domain runs it now; after a restart it starts again at\n // the next login at the screen.\n run(\"launchctl\", [\"bootstrap\", `user/${uid}`, f.plist.path]);\n return { files: [f.plist], commands, manager: \"launchd\", domain: \"user\" };\n }\n if (platform === \"linux\") {\n write(f.unit);\n try {\n run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n run(\"systemctl\", [\"--user\", \"enable\", \"--now\", o.unit]);\n } catch {\n return { files: [f.unit], commands, manager: null, unreachable: f.unit.path };\n }\n const user = o.user ?? os.userInfo().username;\n if (o.dryRun) {\n commands.push(line(\"loginctl\", [\"enable-linger\", user]));\n return { files: [f.unit], commands, manager: \"systemd\", linger: { on: false, note: \"dry run\" } };\n }\n return { files: [f.unit], commands, manager: \"systemd\", linger: ensureLinger(user, run) };\n }\n return { files: [], commands, manager: null };\n}\n\nexport interface UninstallOptions {\n label: string;\n unit: string;\n home?: string;\n dryRun?: boolean;\n exec?: Exec;\n platform?: NodeJS.Platform;\n uid?: string;\n}\n\n/** Stop the service and remove its file, where this platform has one; nothing where\n * there is none. A manager that says it wasn't loaded is no failure. */\nexport function uninstallService(o: UninstallOptions): { files: string[]; commands: string[] } {\n const f = serviceFiles({ ...o, description: \"\", argv: [], logPath: \"\" });\n const platform = o.platform ?? process.platform;\n const uid = o.uid ?? String(process.getuid?.() ?? \"\");\n const commands: string[] = [];\n const files: string[] = [];\n const real = o.exec ?? execQuiet;\n const run = (cmd: string, args: string[]) => {\n commands.push(line(cmd, args));\n if (o.dryRun) return;\n try {\n real(cmd, args);\n } catch {}\n };\n const remove = (file: string) => {\n files.push(file);\n if (!o.dryRun) unlinkSync(file);\n };\n if (platform === \"darwin\" && existsSync(f.plist.path)) {\n run(\"launchctl\", [\"bootout\", `gui/${uid}/${o.label}`]);\n run(\"launchctl\", [\"bootout\", `user/${uid}/${o.label}`]);\n remove(f.plist.path);\n }\n if (platform === \"linux\" && existsSync(f.unit.path)) {\n run(\"systemctl\", [\"--user\", \"disable\", \"--now\", o.unit]);\n remove(f.unit.path);\n run(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n }\n return { files, commands };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// The `sdk` delivery mode (spec/CONTROL.md \u00A76): a session the daemon starts itself\n// through the Claude Agent SDK's streaming input, and keeps while it is in use, so\n// the next message lands in the same process with no cold start. Optional: the SDK\n// is a large package with its own binary, so sessionpipe does not depend on it. When\n// it can be imported (installed beside sessionpipe, or SESSIONPIPE_AGENT_SDK names\n// it), `start` goes through it; otherwise `start` is a headless `claude -p`.\n//\n// Measured (P1 spike 4, Claude Code 2.1.286): first token 1.5 s cold, 1.1 s warm;\n// zero turns while idle; but ~300 MB resident per held session, so the daemon\n// closes one that has been idle for ten minutes and a later message resumes it.\nimport type { RunLevel, StartPermission } from \"@sessionpipe/core/control\";\nimport type { SdkHost, SdkSession } from \"./daemon.js\";\n\n/** Each level (CONTROL.md \u00A73.1) as the SDK's `permissionMode`. Never bypassPermissions.\n * Inherit gives none: the SDK then starts the session in its settings'\n * permissions.defaultMode, as `claude -p` does (0.3.310, measured with bypassPermissions\n * there, which needed no allowDangerouslySkipPermissions). */\nconst PERMISSION_MODE: Record<StartPermission, string> = {\n read: \"plan\",\n safe: \"dontAsk\",\n edits: \"acceptEdits\",\n auto: \"auto\",\n};\n\ntype SdkQuery = AsyncIterable<{ type: string; subtype?: string; result?: unknown; is_error?: boolean }> & {\n interrupt(): Promise<void>;\n close(): void;\n};\ntype QueryFn = (p: { prompt: AsyncIterable<unknown>; options: Record<string, unknown> }) => SdkQuery;\n\nexport async function loadSdk(o: {\n claudeBin: string | null;\n env?: NodeJS.ProcessEnv;\n log: (s: string) => void;\n}): Promise<SdkHost | null> {\n const spec = o.env?.SESSIONPIPE_AGENT_SDK || \"@anthropic-ai/claude-agent-sdk\";\n let query: QueryFn;\n try {\n const mod = (await import(/* @vite-ignore */ spec)) as { query?: QueryFn };\n if (typeof mod.query !== \"function\") return null;\n query = mod.query;\n } catch {\n return null;\n }\n o.log(`Agent SDK found (${spec}): new sessions start in place`);\n return {\n start({\n session,\n cwd,\n permission,\n model,\n allowedTools,\n }: {\n session: string;\n cwd: string;\n permission: RunLevel;\n model?: string;\n configDir?: string;\n allowedTools?: string[];\n }): SdkSession {\n const queue: unknown[] = [];\n let wake: (() => void) | null = null;\n let closed = false;\n async function* input() {\n while (!closed) {\n while (queue.length) yield queue.shift();\n await new Promise<void>((r) => {\n wake = r;\n });\n }\n }\n const q = query({\n prompt: input(),\n options: {\n sessionId: session,\n cwd,\n ...(permission === \"inherit\" ? {} : { permissionMode: PERMISSION_MODE[permission] }),\n ...(model ? { model } : {}),\n ...(allowedTools?.length ? { allowedTools } : {}),\n ...(o.claudeBin ? { pathToClaudeCodeExecutable: o.claudeBin } : {}),\n env: { ...(o.env ?? process.env), SESSIONPIPE_CONTROL_JOB: \"1\" },\n },\n });\n const waiting: { resolve: (v: { reply: string; error?: string }) => void }[] = [];\n let busy = false;\n let lastUsed = Date.now();\n void (async () => {\n try {\n for await (const m of q) {\n if (m.type !== \"result\") continue;\n busy = waiting.length > 1;\n lastUsed = Date.now();\n const w = waiting.shift();\n const text =\n typeof m.result === \"string\" && m.result.trim() ? m.result : \"(finished without a written reply)\";\n w?.resolve(m.is_error ? { reply: \"\", error: text } : { reply: text });\n }\n } catch (e) {\n for (const w of waiting.splice(0)) w.resolve({ reply: \"\", error: String((e as Error)?.message || e) });\n }\n })();\n return {\n send(text: string) {\n busy = true;\n lastUsed = Date.now();\n return new Promise((resolve) => {\n waiting.push({ resolve });\n queue.push({ type: \"user\", message: { role: \"user\", content: text }, parent_tool_use_id: null });\n wake?.();\n });\n },\n interrupt: () => q.interrupt(),\n close() {\n closed = true;\n wake?.();\n try {\n q.close();\n } catch {}\n },\n get busy() {\n return busy;\n },\n get lastUsed() {\n return lastUsed;\n },\n };\n },\n };\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// `sessionpipe wait` (spec/CONTROL.md \u00A78): run by a session as a BACKGROUND command.\n// It blocks on the daemon's local socket \u2014 no network, no polling, no output \u2014 until\n// a verified message for this session arrives, prints it and exits 0; the harness\n// then wakes the session with it. If the daemon restarts, it reconnects in silence.\nimport { stateDir } from \"@sessionpipe/core\";\nimport { parseSessionRef } from \"@sessionpipe/core/control\";\nimport { ask, socketPath } from \"./local.js\";\n\nexport const RE_ARM =\n \"(Answer it right here, as you would answer the person at the keyboard: your reply is sent back to them automatically, so don't run a command or call a tool just to send it. Then, without mentioning it, start `sessionpipe wait` again as a background command, with the longest timeout your harness allows, to keep receiving messages.)\";\n\n/** The session to wait for: --session, else the harness's own env. */\nexport function waitSession(flag: string | undefined, env: NodeJS.ProcessEnv = process.env): string | null {\n if (flag) return parseSessionRef(flag) ? flag : null;\n if (env.CLAUDE_CODE_SESSION_ID) return `claude-code:${env.CLAUDE_CODE_SESSION_ID}`;\n if (env.CODEX_SESSION_ID) return `codex:${env.CODEX_SESSION_ID}`;\n return null;\n}\n\nexport async function waitForMessage(\n session: string,\n o: { env?: NodeJS.ProcessEnv; retryMs?: number } = {},\n): Promise<string> {\n const sock = socketPath(stateDir(o.env), o.env);\n for (;;) {\n // No timeout of our own: the harness's background deadline is the only clock.\n const r = await ask(sock, { op: \"wait\", session, pid: process.pid }, 2 ** 31 - 1);\n if (r?.op === \"message\") return `${r.text}\\n\\n${RE_ARM}`;\n if (r?.op === \"replaced\")\n return \"(Another `sessionpipe wait` for this session took over; this one stopped. Nothing to do.)\";\n await new Promise((res) => setTimeout(res, o.retryMs ?? 1000));\n }\n}\n", "// SPDX-License-Identifier: Apache-2.0\n// Usage is data: asking for it must never enter a command's implementation. The site's\n// docs page reads the same table, so a command's usage is written in one place.\nexport function usageTable(harnesses: readonly string[]): Record<string, string> {\n return {\n connect:\n \"connect <receiver> [--machine NAME] [--rename-machine] [--allow-downgrade] [--tier 0-3] [--mode safe|auto|inherit] [--folder DIR]\u2026 [--no-service]\",\n install: `install [${harnesses.map((h) => `--${h}`).join(\" \")}] [--machine NAME] [--rename-machine] [--allow-downgrade] [--backfill DAYS] [--sink URL --tier N]`,\n sink: \"sink add|list|remove|test (use --help after a subcommand for its options)\",\n \"sink add\": \"sink add <url|file:PATH|stdout> [--tier 0-3] [--token T] [--secret S] [--pii] [--name N]\",\n \"sink list\": \"sink list\",\n \"sink remove\": \"sink remove <name>\",\n \"sink test\": \"sink test <name>\",\n secrets: \"secrets [move keychain|secret-service|file]\",\n \"secrets move\": \"secrets move keychain|secret-service|file\",\n status: \"status [--json]\",\n doctor: \"doctor [--json]\",\n tail: \"tail [--session ID] [--tier 0-3] [--harness NAME] [--all] [--json]\",\n backfill: `backfill [--days 30] [${harnesses.map((h) => `--${h}`).join(\" \")}]`,\n forget: \"forget <harness> <session>\",\n replay: \"replay [--sink NAME] [--from-start]\",\n update: \"update [off|on] (install the latest now; off/on: the daemon's daily update)\",\n \"update off\": \"update off\",\n \"update on\": \"update on\",\n control: \"control pair|mode|status|keys|off|run (use --help after a subcommand for its options)\",\n \"control pair\":\n \"control pair <receiver> [--folder DIR]\u2026 [--mode safe|auto|inherit] [--tier 0-3] [--token T] [--name N] [--no-service]\",\n \"control mode\": \"control mode auto|safe|inherit\",\n \"control status\": \"control status\",\n \"control keys\": \"control keys [remove <id>]\",\n \"control keys remove\": \"control keys remove <id>\",\n \"control off\": \"control off [<receiver>]\",\n \"control run\": \"control run\",\n wait: \"wait [--session <harness>:<id>]\",\n worker: \"worker <job-file> (internal: process one queued job)\",\n hook: \"hook (internal: harnesses run dist/hook.js directly)\",\n version: \"version (print the installed version)\",\n \"--version\": \"--version (print the installed version)\",\n \"-v\": \"-v (print the installed version)\",\n };\n}\n\nexport function commandHelp(args: string[], harnesses: readonly string[]): string | undefined {\n const usage = usageTable(harnesses);\n for (let n = Math.min(args.length, 3); n > 0; n--) {\n const line = usage[args.slice(0, n).join(\" \")];\n if (line) return `Usage: sessionpipe ${line}\\n\\n -h, --help Show help without running the command.`;\n }\n return undefined;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["execFileSync", "spawnSync", "existsSync", "readdirSync", "readFileSync", "realpathSync", "rmSync", "statSync", "unlinkSync", "os", "path", "spawn", "path", "args", "out", "line", "path", "log", "spawn", "line", "tail", "existsSync", "mkdirSync", "readdirSync", "readFileSync", "statSync", "unlinkSync", "writeFileSync", "path", "os", "path", "statSync", "path", "tail", "cap", "out", "line", "out", "path", "settings", "entry", "path", "out", "existsSync", "mkdirSync", "writeFileSync", "unlinkSync", "readFileSync", "rows", "readdirSync", "statSync", "tail", "line", "os", "path", "os", "path", "line", "str", "out", "execFileSync", "existsSync", "readdirSync", "readFileSync", "statSync", "path", "args", "out", "NAME", "out", "path", "readdirSync", "existsSync", "validTool", "prune", "readFileSync", "state", "rows", "has", "pid", "execFileSync", "statSync", "tail", "ask", "claudeLogin", "defaultLevel", "offeredLevels", "execFileSync", "closeSync", "openSync", "readdirSync", "readFileSync", "readSync", "statSync", "os", "path", "out", "str", "has", "UUID_RE", "os", "path", "readdirSync", "help", "flag", "out", "args", "offeredLevels", "defaultLevel", "claudeLogin", "execFileSync", "statSync", "cap", "line", "openSync", "readSync", "closeSync", "readFileSync", "existsSync", "mkdirSync", "readdirSync", "readFileSync", "writeFileSync", "path", "OURS", "line", "tail", "NAME", "OPTS", "eventsFor", "path", "hooksFile", "configFile", "validTool", "endReason", "readFileSync", "line", "mkdirSync", "writeFileSync", "OURS", "readdirSync", "existsSync", "out", "id", "r", "prune", "rows", "tail", "defaultLevel", "offeredLevels", "reading", "execFile", "readFileSync", "os", "path", "LABEL", "os", "path", "offeredLevels", "defaultLevel", "readFileSync", "out", "execFile", "line", "str", "reading", "createHash", "existsSync", "path", "execFileSync", "existsSync", "out", "bad", "NAME", "OPTS", "eventsFor", "bad", "path", "configFile", "validTool", "endReason", "pickSource", "errText", "existsSync", "state", "createHash", "prune", "out", "rows", "line", "execFileSync", "existsSync", "readFileSync", "path", "NAME", "OPTS", "path", "validTool", "eventsFor", "readFileSync", "execFileSync", "existsSync", "state", "prune", "out", "tail", "line", "existsSync", "mkdirSync", "readFileSync", "writeFileSync", "path", "readFileSync", "mkdirSync", "path", "writeFileSync", "existsSync", "out", "closeSync", "existsSync", "mkdirSync", "openSync", "readdirSync", "readFileSync", "readSync", "statSync", "unlinkSync", "writeFileSync", "path", "path", "readFileSync", "mkdirSync", "writeFileSync", "existsSync", "out", "readdirSync", "statSync", "openSync", "readSync", "line", "closeSync", "unlinkSync", "sink", "createHash", "out", "out", "out", "out", "createHash", "appendFileSync", "mkdirSync", "path", "path", "flag", "readFileSync", "path", "spawn", "accessSync", "constants", "existsSync", "realpathSync", "path", "execFileSync", "readFileSync", "realpathSync", "os", "path", "accessSync", "chmodSync", "constants", "mkdirSync", "readFileSync", "renameSync", "writeFileSync", "os", "path", "path", "os", "readFileSync", "chmodSync", "writeFileSync", "renameSync", "mkdirSync", "accessSync", "constants", "appendFileSync", "existsSync", "mkdirSync", "readdirSync", "readFileSync", "renameSync", "statSync", "unlinkSync", "writeFileSync", "os", "path", "chmodSync", "mkdirSync", "readFileSync", "renameSync", "writeFileSync", "path", "appendFileSync", "chmodSync", "closeSync", "existsSync", "mkdirSync", "openSync", "readFileSync", "renameSync", "writeFileSync", "path", "createHash", "randomBytes", "args", "createHash", "randomBytes", "path", "mkdirSync", "writeFileSync", "renameSync", "chmodSync", "readFileSync", "cut", "line", "openSync", "appendFileSync", "closeSync", "existsSync", "path", "readFileSync", "out", "mkdirSync", "writeFileSync", "renameSync", "chmodSync", "os", "path", "state", "createHash", "state", "existsSync", "state", "mkdirSync", "path", "writeFileSync", "unlinkSync", "state", "line", "mkdirSync", "path", "statSync", "renameSync", "appendFileSync", "readFileSync", "writeFileSync", "out", "os", "existsSync", "unlinkSync", "sink", "state", "path", "realpathSync", "distDir", "execFileSync", "path", "os", "installed", "readFileSync", "out", "spawn", "distDir", "path", "existsSync", "accessSync", "constants", "realpathSync", "spawn", "LABEL", "path", "readFileSync", "off", "ms", "existsSync", "realpathSync", "statSync", "os", "path", "chmodSync", "existsSync", "mkdirSync", "readFileSync", "realpathSync", "statSync", "unlinkSync", "net", "path", "createHash", "existsSync", "mkdirSync", "realpathSync", "rmSync", "writeFileSync", "path", "b64url", "out", "closeSync", "openSync", "readSync", "statSync", "line", "sleep", "cut", "line", "claudeArgs", "claudeEnv", "findTranscript", "isUuid", "liveProcess", "loginHint", "parseResult", "recentlyWritten", "sessionFolder", "VERSION", "path", "mkdirSync", "unlinkSync", "existsSync", "net", "chmodSync", "t", "sleep", "ok", "readFileSync", "out", "ask", "entry", "cap", "realpathSync", "statSync", "live", "args", "reading", "tail", "randomBytes", "mkdirSync", "path", "execFileSync", "existsSync", "mkdirSync", "unlinkSync", "writeFileSync", "os", "path", "args", "VERSION", "out", "sleep", "randomBytes", "path", "LABEL", "UNIT", "installService", "mkdirSync", "log", "path", "LABEL", "UNIT", "uninstallService", "spec", "flag", "claudeLogin", "detectCaps", "findClaude", "runClaude", "out", "os", "realpathSync", "path", "statSync", "distDir", "flag", "sink", "installService", "c", "no", "uninstallService", "log", "existsSync", "args", "line", "path", "realpathSync", "existsSync", "os", "rows", "statSync", "sink", "status", "json", "update", "readdirSync", "spawnSync", "rmSync", "readFileSync", "execFileSync", "w", "unlinkSync"]
|
|
7
7
|
}
|