@letrquan/book 0.2.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.
Files changed (103) hide show
  1. package/CHANGELOG.md +2504 -0
  2. package/LICENSE +123 -0
  3. package/README.md +1383 -0
  4. package/dist/app-MOXXWEOY.js +18945 -0
  5. package/dist/app-MOXXWEOY.js.map +1 -0
  6. package/dist/chunk-24AXE6SP.js +12 -0
  7. package/dist/chunk-24AXE6SP.js.map +1 -0
  8. package/dist/chunk-3U5IBM24.js +213 -0
  9. package/dist/chunk-3U5IBM24.js.map +1 -0
  10. package/dist/chunk-574C6MQR.js +743 -0
  11. package/dist/chunk-574C6MQR.js.map +1 -0
  12. package/dist/chunk-5GDZ22YP.js +449 -0
  13. package/dist/chunk-5GDZ22YP.js.map +1 -0
  14. package/dist/chunk-5KLVH3PY.js +167 -0
  15. package/dist/chunk-5KLVH3PY.js.map +1 -0
  16. package/dist/chunk-5RDRAO4B.js +92 -0
  17. package/dist/chunk-5RDRAO4B.js.map +1 -0
  18. package/dist/chunk-7N4J557C.js +10 -0
  19. package/dist/chunk-7N4J557C.js.map +1 -0
  20. package/dist/chunk-A7JLBK2Y.js +3506 -0
  21. package/dist/chunk-A7JLBK2Y.js.map +1 -0
  22. package/dist/chunk-ANSJPYGI.js +84 -0
  23. package/dist/chunk-ANSJPYGI.js.map +1 -0
  24. package/dist/chunk-BTZZUCLI.js +264 -0
  25. package/dist/chunk-BTZZUCLI.js.map +1 -0
  26. package/dist/chunk-C7D4NJ2D.js +217 -0
  27. package/dist/chunk-C7D4NJ2D.js.map +1 -0
  28. package/dist/chunk-CAGOB2N4.js +208 -0
  29. package/dist/chunk-CAGOB2N4.js.map +1 -0
  30. package/dist/chunk-DGMQEI6Y.js +98 -0
  31. package/dist/chunk-DGMQEI6Y.js.map +1 -0
  32. package/dist/chunk-E75IPST5.js +289 -0
  33. package/dist/chunk-E75IPST5.js.map +1 -0
  34. package/dist/chunk-EYGD6X2T.js +180 -0
  35. package/dist/chunk-EYGD6X2T.js.map +1 -0
  36. package/dist/chunk-GTVB4HEM.js +765 -0
  37. package/dist/chunk-GTVB4HEM.js.map +1 -0
  38. package/dist/chunk-J7MIZ5CA.js +1907 -0
  39. package/dist/chunk-J7MIZ5CA.js.map +1 -0
  40. package/dist/chunk-KWHQ2XXL.js +626 -0
  41. package/dist/chunk-KWHQ2XXL.js.map +1 -0
  42. package/dist/chunk-L6LK2QIQ.js +657 -0
  43. package/dist/chunk-L6LK2QIQ.js.map +1 -0
  44. package/dist/chunk-MAQXCUR4.js +1007 -0
  45. package/dist/chunk-MAQXCUR4.js.map +1 -0
  46. package/dist/chunk-S4XL7HOM.js +402 -0
  47. package/dist/chunk-S4XL7HOM.js.map +1 -0
  48. package/dist/chunk-URLQAXTR.js +60 -0
  49. package/dist/chunk-URLQAXTR.js.map +1 -0
  50. package/dist/chunk-V4BOYR52.js +3504 -0
  51. package/dist/chunk-V4BOYR52.js.map +1 -0
  52. package/dist/chunk-VZQXX3WW.js +210 -0
  53. package/dist/chunk-VZQXX3WW.js.map +1 -0
  54. package/dist/chunk-WKBO5R4O.js +34 -0
  55. package/dist/chunk-WKBO5R4O.js.map +1 -0
  56. package/dist/chunk-XIFFTATU.js +15753 -0
  57. package/dist/chunk-XIFFTATU.js.map +1 -0
  58. package/dist/command-approvals-6Y57VCWZ.js +28 -0
  59. package/dist/command-approvals-6Y57VCWZ.js.map +1 -0
  60. package/dist/context-ZC5IFEAX.js +25 -0
  61. package/dist/context-ZC5IFEAX.js.map +1 -0
  62. package/dist/hook-approvals-CTUFKEJT.js +22 -0
  63. package/dist/hook-approvals-CTUFKEJT.js.map +1 -0
  64. package/dist/index.d.ts +1 -0
  65. package/dist/index.js +2582 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/interactive-assets-CCAAWVKH.js +31 -0
  68. package/dist/interactive-assets-CCAAWVKH.js.map +1 -0
  69. package/dist/job-runner.d.ts +2 -0
  70. package/dist/job-runner.js +235 -0
  71. package/dist/job-runner.js.map +1 -0
  72. package/dist/loader-4IDS2RIE.js +15 -0
  73. package/dist/loader-4IDS2RIE.js.map +1 -0
  74. package/dist/mcp-approvals-WNPH65BK.js +18 -0
  75. package/dist/mcp-approvals-WNPH65BK.js.map +1 -0
  76. package/dist/mcp-config-YIJIES2C.js +16 -0
  77. package/dist/mcp-config-YIJIES2C.js.map +1 -0
  78. package/dist/model-window-store-YFVNXCIP.js +27 -0
  79. package/dist/model-window-store-YFVNXCIP.js.map +1 -0
  80. package/dist/openai-compatible-RHZUBHV6.js +10 -0
  81. package/dist/openai-compatible-RHZUBHV6.js.map +1 -0
  82. package/dist/permission-approvals-76PVREFD.js +14 -0
  83. package/dist/permission-approvals-76PVREFD.js.map +1 -0
  84. package/dist/permissions-CHCKTFQQ.js +28 -0
  85. package/dist/permissions-CHCKTFQQ.js.map +1 -0
  86. package/dist/sandbox-CNVAQDA7.js +23 -0
  87. package/dist/sandbox-CNVAQDA7.js.map +1 -0
  88. package/dist/scrollback-LUKLIBVI.js +136 -0
  89. package/dist/scrollback-LUKLIBVI.js.map +1 -0
  90. package/dist/sdk.d.ts +4574 -0
  91. package/dist/sdk.js +665 -0
  92. package/dist/sdk.js.map +1 -0
  93. package/dist/settings-loader-M2QP5TX2.js +21 -0
  94. package/dist/settings-loader-M2QP5TX2.js.map +1 -0
  95. package/dist/settings-removed-JWWPT4WA.js +19 -0
  96. package/dist/settings-removed-JWWPT4WA.js.map +1 -0
  97. package/dist/shell-selection-V6QAYXPX.js +17 -0
  98. package/dist/shell-selection-V6QAYXPX.js.map +1 -0
  99. package/package.json +143 -0
  100. package/patches/ink+6.8.0.patch +13 -0
  101. package/scripts/apply-ink-patch.mjs +29 -0
  102. package/scripts/ink-patch.mjs +59 -0
  103. package/scripts/verify-ink-patch.mjs +11 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/run-status.ts","../src/commands/print-dispatch.ts","../src/stream-json.ts","../src/headless.ts","../src/mcp.ts","../src/project-approval-notices.ts"],"sourcesContent":["import {\r\n closeSync,\r\n mkdirSync,\r\n openSync,\r\n readFileSync,\r\n renameSync,\r\n rmSync,\r\n statfsSync,\r\n writeSync,\r\n} from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { resolveBookHome } from './book-home.js';\r\n\r\n/**\r\n * A small, always-current file saying what a run is doing right now.\r\n *\r\n * `book status` answers \"what was this asked to do and what has it spent\" from the\r\n * session JSONL, which is durable and never rewritten. What the JSONL cannot\r\n * answer is *liveness*: at hour 90 the only on-disk signal that a run is healthy\r\n * is the transcript's mtime, and that advances at exactly the same rate for a\r\n * productive run, a refusal spin, and a run wedged on a permission prompt. The\r\n * default `--output-format text` writes nothing at all until the run terminates,\r\n * and the alternative is a firehose. Between silence and every reasoning delta\r\n * there was nothing an operator could leave on.\r\n *\r\n * So: one bounded record, rewritten at each turn boundary, carrying the handful of\r\n * facts a supervisor needs to decide \"is this stuck\" — plus a crash record written\r\n * from the exit path, because when a long run dies today nothing durable says why.\r\n *\r\n * Deliberately synchronous. The file is ~1 KB against turns that take seconds, and\r\n * the crash path runs inside `process.on('exit')`, where nothing async can run at\r\n * all. Written to a temp file and renamed, so a reader never sees a torn record.\r\n */\r\n\r\nexport const RUN_STATUS_VERSION = 1;\r\n\r\nexport interface RunStatusRecord {\r\n readonly version: typeof RUN_STATUS_VERSION;\r\n readonly sessionId: string;\r\n readonly runId: string;\r\n /** The process holding this run, so a reader can test liveness itself. */\r\n readonly pid: number;\r\n readonly startedAt: number;\r\n readonly updatedAt: number;\r\n readonly turn: number;\r\n readonly elapsedMs: number;\r\n /** Canonical name of the most recent tool call, if any. */\r\n readonly lastTool?: string;\r\n /** The todo currently marked in progress, if any. */\r\n readonly currentTodo?: string;\r\n readonly openTodos: number;\r\n readonly costUsd: number | null;\r\n readonly budgetUsd?: number;\r\n /** Free bytes on the volume holding the workspace, when the platform reports it. */\r\n readonly freeDiskBytes?: number;\r\n /** Set once the run has stopped, so a reader can tell finished from wedged. */\r\n readonly terminal?: {\r\n readonly status: string;\r\n readonly reason: string;\r\n readonly message?: string;\r\n };\r\n /**\r\n * Set when the process died without a terminal outcome. This is the difference\r\n * between \"the objective finished\" and \"the socket died\", which a supervisor\r\n * otherwise cannot tell apart.\r\n */\r\n readonly crash?: { readonly message: string; readonly at: number };\r\n}\r\n\r\nexport function runStatusDir(home = resolveBookHome()): string {\r\n return join(home, 'runs');\r\n}\r\n\r\nexport function runStatusPath(sessionId: string, home = resolveBookHome()): string {\r\n // Session ids are uuids, but a caller could pass anything; keep it a filename.\r\n const safe = sessionId.replace(/[^A-Za-z0-9_-]/g, '_');\r\n return join(runStatusDir(home), `${safe}.json`);\r\n}\r\n\r\n/** Free bytes on the volume holding `path`, or undefined where unavailable. */\r\nexport function freeDiskBytes(path: string): number | undefined {\r\n try {\r\n const stats = statfsSync(path);\r\n const free = Number(stats.bavail) * Number(stats.bsize);\r\n return Number.isFinite(free) && free >= 0 ? free : undefined;\r\n } catch {\r\n // statfs is not available on every platform or filesystem, and a status write\r\n // must never be the thing that ends a run.\r\n return undefined;\r\n }\r\n}\r\n\r\n/** Write atomically: a reader either sees the previous record or this one. */\r\nexport function writeRunStatus(record: RunStatusRecord, home = resolveBookHome()): void {\r\n const target = runStatusPath(record.sessionId, home);\r\n const temp = `${target}.${process.pid}.tmp`;\r\n try {\r\n mkdirSync(runStatusDir(home), { recursive: true });\r\n const fd = openSync(temp, 'w');\r\n try {\r\n writeSync(fd, JSON.stringify(record, null, 2));\r\n } finally {\r\n closeSync(fd);\r\n }\r\n renameSync(temp, target);\r\n } catch {\r\n // Observability must never take the run down with it.\r\n try {\r\n rmSync(temp, { force: true });\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n}\r\n\r\nexport function readRunStatus(\r\n sessionId: string,\r\n home = resolveBookHome(),\r\n): RunStatusRecord | undefined {\r\n try {\r\n const parsed: unknown = JSON.parse(readFileSync(runStatusPath(sessionId, home), 'utf8'));\r\n if (!parsed || typeof parsed !== 'object') return undefined;\r\n const record = parsed as RunStatusRecord;\r\n return record.version === RUN_STATUS_VERSION ? record : undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport function clearRunStatus(sessionId: string, home = resolveBookHome()): void {\r\n try {\r\n rmSync(runStatusPath(sessionId, home), { force: true });\r\n } catch {\r\n /* ignore */\r\n }\r\n}\r\n\r\nexport interface RunStatusSeed {\r\n readonly sessionId: string;\r\n readonly runId: string;\r\n readonly workspace: string;\r\n readonly budgetUsd?: number;\r\n readonly startedAt: number;\r\n readonly home?: string;\r\n}\r\n\r\nexport interface RunStatusUpdate {\r\n readonly turn: number;\r\n readonly lastTool?: string;\r\n readonly currentTodo?: string;\r\n readonly openTodos: number;\r\n readonly costUsd: number | null;\r\n readonly terminal?: RunStatusRecord['terminal'];\r\n}\r\n\r\n/**\r\n * Keeps one run's status file current.\r\n *\r\n * Created by a host rather than by the loop: a subagent and a managed agent both\r\n * call `runAgentLoop` directly, and each writing its own liveness file would make\r\n * \"is the run alive\" ambiguous. The host that owns the session owns the file.\r\n */\r\nexport class RunStatusWriter {\r\n private readonly seed: RunStatusSeed;\r\n private last: RunStatusRecord;\r\n private crashHandlerInstalled = false;\r\n\r\n constructor(seed: RunStatusSeed) {\r\n this.seed = seed;\r\n this.last = {\r\n version: RUN_STATUS_VERSION,\r\n sessionId: seed.sessionId,\r\n runId: seed.runId,\r\n pid: process.pid,\r\n startedAt: seed.startedAt,\r\n updatedAt: seed.startedAt,\r\n turn: 0,\r\n elapsedMs: 0,\r\n openTodos: 0,\r\n costUsd: null,\r\n budgetUsd: seed.budgetUsd,\r\n freeDiskBytes: freeDiskBytes(seed.workspace),\r\n };\r\n writeRunStatus(this.last, seed.home);\r\n }\r\n\r\n update(update: RunStatusUpdate, now = Date.now()): void {\r\n this.last = {\r\n ...this.last,\r\n updatedAt: now,\r\n elapsedMs: now - this.seed.startedAt,\r\n turn: update.turn,\r\n lastTool: update.lastTool ?? this.last.lastTool,\r\n currentTodo: update.currentTodo,\r\n openTodos: update.openTodos,\r\n costUsd: update.costUsd,\r\n freeDiskBytes: freeDiskBytes(this.seed.workspace),\r\n terminal: update.terminal ?? this.last.terminal,\r\n };\r\n writeRunStatus(this.last, this.seed.home);\r\n }\r\n\r\n /**\r\n * Record that the process is dying without a terminal outcome.\r\n *\r\n * Synchronous by necessity: this runs from `process.on('exit')`, where the event\r\n * loop is already closed and no promise will ever settle.\r\n */\r\n recordCrash(message: string, now = Date.now()): void {\r\n if (this.last.terminal) return; // finished properly; not a crash\r\n if (this.last.crash) return;\r\n this.last = { ...this.last, updatedAt: now, crash: { message, at: now } };\r\n writeRunStatus(this.last, this.seed.home);\r\n }\r\n\r\n /**\r\n * Install last-resort handlers so an unhandled fault leaves a record.\r\n *\r\n * There is no `uncaughtException` or `unhandledRejection` handler anywhere in the\r\n * codebase, and `index.ts` ends in a bare `program.parse()` whose returned promise\r\n * nothing awaits — so a rejection escaping the action handler becomes an unhandled\r\n * rejection and the operator gets a stack trace on a stderr they may have\r\n * redirected days ago. Returns a disposer.\r\n */\r\n installCrashHandlers(): () => void {\r\n if (this.crashHandlerInstalled) return () => {};\r\n this.crashHandlerInstalled = true;\r\n // ONLY `exit`. Registering an `uncaughtException` or `unhandledRejection`\r\n // listener REPLACES Node's default print-and-exit(1) with whatever the listener\r\n // does — and a listener that merely records would swallow the fault, leave the\r\n // awaited chain unsettled so this writer's own disposer never runs, and let the\r\n // process drain and exit 0. A supervisor polling for a terminal outcome would\r\n // read a hard crash as success. Node fires `exit` during its default death\r\n // anyway, so this handler alone already captures the record, at no cost to the\r\n // exit code.\r\n const onExit = (): void => {\r\n this.recordCrash('The process exited before the run reached a terminal outcome.');\r\n };\r\n process.on('exit', onExit);\r\n return () => {\r\n process.off('exit', onExit);\r\n this.crashHandlerInstalled = false;\r\n };\r\n }\r\n\r\n snapshot(): RunStatusRecord {\r\n return this.last;\r\n }\r\n}\r\n","/**\r\n * Slash-command dispatch for hosts that have no interactive surface: print /\r\n * headless mode (`book -p …`) and the SDK.\r\n *\r\n * The TUI resolves a submitted `/name` in three ordered steps — the built-in\r\n * registry (`createBuiltinCommandRegistry`), then the user/project command\r\n * files (`discoverCommands`), then \"not a command, send the text as typed\".\r\n * This module walks the same three steps against the same registries and the\r\n * same `resolveCommandBody`, so print mode cannot fork command semantics. What\r\n * differs is only what a non-interactive host may do with the resulting effect.\r\n *\r\n * A print host can send a prompt. It cannot open a modal, toggle a panel,\r\n * switch themes, or resume a session, so a command whose effect needs an\r\n * interactive host is refused *before* its `execute` runs: several built-ins\r\n * write settings or files as a side effect (`/config`, `/export`, `/memory\r\n * approve`), and running one only to discover the host cannot show its result\r\n * would be worse than not running it at all. The gate is the declarative\r\n * `nonInteractive` flag on the command definition, never a guess about the\r\n * effect a given argument string happens to produce.\r\n */\r\n\r\nimport type { AgentConfig, PermissionMode } from '../types/runtime.js';\r\nimport type { CommandContext, SlashCommand } from '../types/commands.js';\r\nimport { commandEnforcementContext, parseSlashInput, resolveCommandBody } from './resolve.js';\r\nimport { discoverCommands } from './loader.js';\r\nimport {\r\n createBuiltinCommandRegistry,\r\n type BuiltinCommandContext,\r\n type BuiltinCommandEffect,\r\n} from './builtins.js';\r\nimport type { CommandRegistry } from './registry.js';\r\nimport type { AgentManager } from '../agents/manager.js';\r\nimport type { AgentRunContext } from '../types/runs.js';\r\nimport { reviewRunnerFor } from '../review/runner.js';\r\nimport { reviewReportJson, runHostReview } from '../review/host.js';\r\n\r\nexport type BuiltinPrintRegistry = CommandRegistry<BuiltinCommandContext, BuiltinCommandEffect>;\r\n\r\n/** Ambient facts a non-interactive host can state truthfully about its run. */\r\nexport interface PrintCommandEnvironment {\r\n /** Frozen run config; supplies workspace, model, and provider. */\r\n config: AgentConfig;\r\n /** Permission mode of the run. */\r\n mode: PermissionMode;\r\n /** Session the command is resolved against (`${BOOK_SESSION_ID}`). */\r\n sessionId: string;\r\n /** Cancels in-flight shell substitution, exactly as the TUI's does. */\r\n signal?: AbortSignal;\r\n /**\r\n * The managed-agent runtime for commands the host performs by running agents\r\n * rather than by sending a prompt (`/review`), together with the run those\r\n * agents belong to. A host that omits it refuses those commands instead of\r\n * pretending.\r\n *\r\n * `manager` is a factory so an ordinary print run never pays to build one, and\r\n * `runContext` is required alongside it rather than optional: budget\r\n * enforcement is keyed by `rootRunId` (`RunAccounting.checkBeforeModelCall`),\r\n * so a manager supplied without one would spawn agents under a fresh, unbudgeted\r\n * root and quietly spend past `--max-budget-usd`. Coupling them in one field\r\n * makes that combination unrepresentable.\r\n */\r\n agents?: {\r\n manager: () => AgentManager;\r\n runContext: AgentRunContext;\r\n };\r\n}\r\n\r\n/** What the host should do with one submitted line. */\r\nexport type PrintCommandDispatch =\r\n /** Run this text as the user turn. Set for prompt-body commands. */\r\n | {\r\n kind: 'prompt';\r\n prompt: string;\r\n /** Frontmatter enforcement (allowed-tools / model), as the TUI passes it. */\r\n commandContext?: CommandContext;\r\n /** Non-fatal shell-substitution failures, exactly as the TUI collects them. */\r\n shellErrors?: string[];\r\n }\r\n /** The effect handler already did the work; the host runs no model turn. */\r\n | {\r\n kind: 'handled';\r\n command: string;\r\n /** Human-readable rendering, used by `--output-format text`. */\r\n output?: string;\r\n /**\r\n * Machine-readable rendering for `--output-format json` / `stream-json`.\r\n * A maintained output contract: see `review/host.ts#ReviewJsonReport`.\r\n */\r\n data?: unknown;\r\n }\r\n /** Not a command: send the line to the model unchanged. */\r\n | { kind: 'passthrough'; prompt: string };\r\n\r\n/**\r\n * Performs one built-in effect in a non-interactive host. Returning `handled`\r\n * means the work is done and no model turn should run for this input. The third\r\n * argument is the name the user actually typed (an alias, possibly), so a\r\n * handler can name it in an error.\r\n */\r\nexport type PrintEffectHandler<Type extends BuiltinCommandEffect['type']> = (\r\n effect: Extract<BuiltinCommandEffect, { type: Type }>,\r\n env: PrintCommandEnvironment,\r\n command: string,\r\n) => PrintCommandDispatch | Promise<PrintCommandDispatch>;\r\n\r\ntype AnyPrintEffectHandler = (\r\n effect: BuiltinCommandEffect,\r\n env: PrintCommandEnvironment,\r\n command: string,\r\n) => PrintCommandDispatch | Promise<PrintCommandDispatch>;\r\n\r\n/**\r\n * Effect-type → handler map. An effect with no registered handler is refused\r\n * loudly rather than degraded into \"send the slash string to the model\".\r\n */\r\nexport class PrintEffectRegistry {\r\n private readonly handlers = new Map<BuiltinCommandEffect['type'], AnyPrintEffectHandler>();\r\n\r\n register<Type extends BuiltinCommandEffect['type']>(\r\n type: Type,\r\n handler: PrintEffectHandler<Type>,\r\n ): this {\r\n // Sound in this direction: the stored handler is only ever invoked with an\r\n // effect whose `type` matches the key it was registered under.\r\n this.handlers.set(type, handler as AnyPrintEffectHandler);\r\n return this;\r\n }\r\n\r\n has(type: BuiltinCommandEffect['type']): boolean {\r\n return this.handlers.has(type);\r\n }\r\n\r\n handledTypes(): BuiltinCommandEffect['type'][] {\r\n return [...this.handlers.keys()];\r\n }\r\n\r\n handle(\r\n effect: BuiltinCommandEffect,\r\n env: PrintCommandEnvironment,\r\n command: string,\r\n ): Promise<PrintCommandDispatch> | undefined {\r\n const handler = this.handlers.get(effect.type);\r\n return handler ? Promise.resolve(handler(effect, env, command)) : undefined;\r\n }\r\n}\r\n\r\n/** A slash command exists but this host cannot run it. Never falls back to prose. */\r\nexport class UnsupportedPrintCommandError extends Error {\r\n readonly command: string;\r\n\r\n constructor(command: string, message: string) {\r\n super(message);\r\n this.name = 'UnsupportedPrintCommandError';\r\n this.command = command;\r\n }\r\n}\r\n\r\n/**\r\n * The command ran and rejected its own invocation (bad flag, bad argument).\r\n *\r\n * Separate from {@link UnsupportedPrintCommandError} because the command *is*\r\n * supported here; it is the arguments that are wrong. Both end the run non-zero:\r\n * a print host that printed \"✕ Unknown review option: --dep\" and exited 0 would\r\n * let a CI job believe a review it never ran had passed.\r\n */\r\nexport class PrintCommandUsageError extends Error {\r\n readonly command: string;\r\n\r\n constructor(command: string, message: string) {\r\n super(message);\r\n this.name = 'PrintCommandUsageError';\r\n this.command = command;\r\n }\r\n}\r\n\r\n/**\r\n * Why `--fix` stops here rather than running unattended.\r\n *\r\n * `applyReviewFixes` spawns patcher agents that edit files and then commits the\r\n * verified patch into the user's repository. A non-interactive host cannot\r\n * answer a managed-agent permission prompt — `AgentManager` denies every one\r\n * when no interactive host is attached — so an unattended `--fix` would either\r\n * fail every patch on a denial or, under `--permission-mode bypassPermissions`,\r\n * commit unreviewed changes with nobody watching. The read-only review is wired\r\n * end to end; the applying half stays where a human can see it.\r\n */\r\nconst FIX_REFUSAL = [\r\n '✕ /review --fix needs an interactive session.',\r\n '',\r\n '--fix spawns patcher agents that edit files and commit verified patches. A non-interactive',\r\n 'host cannot approve those tool calls, so the fix pass would either be denied outright or',\r\n 'commit unreviewed changes with no one watching.',\r\n '',\r\n 'Run `book` interactively and use /review --fix there, or run `book -p \"/review --deep\"`',\r\n 'and apply the reported fixes yourself.',\r\n].join('\\n');\r\n\r\n/**\r\n * Run `/review` from a host with no interactive surface.\r\n *\r\n * The target is resolved host-side by the pipeline (`runHostReview` →\r\n * `resolveReviewTarget`) from `env.config.workspace` and the parsed scope, so\r\n * `--base`, path scoping and `<base>...<head>` behave exactly as in the TUI and\r\n * the reviewer agents still get an immutable diff they cannot re-select.\r\n */\r\nasync function performPrintReview(\r\n effect: Extract<BuiltinCommandEffect, { type: 'review' }>,\r\n env: PrintCommandEnvironment,\r\n command: string,\r\n): Promise<PrintCommandDispatch> {\r\n if (effect.scope.fix) throw new UnsupportedPrintCommandError(command, FIX_REFUSAL);\r\n if (!env.agents) {\r\n throw new UnsupportedPrintCommandError(\r\n command,\r\n `✕ /${command} needs the managed-agent runtime, and this host did not provide one.`,\r\n );\r\n }\r\n\r\n const result = await runHostReview({\r\n scope: effect.scope,\r\n workspace: env.config.workspace,\r\n // Every reviewer, lens and verifier agent is spawned under the host's run,\r\n // so the whole pipeline is billed and budgeted as one root.\r\n runner: reviewRunnerFor(env.agents.manager(), {\r\n rootRunId: env.agents.runContext.rootRunId,\r\n parentRunId: env.agents.runContext.runId,\r\n }),\r\n });\r\n // A review that could not run at all must end the run non-zero. An\r\n // inconclusive *verdict* is different: the review ran, its coverage warnings\r\n // are in the report, and the caller gates on `verdict`.\r\n if (result.error) throw new Error(result.segments.join('\\n\\n'));\r\n return {\r\n kind: 'handled',\r\n command,\r\n output: result.segments.join('\\n\\n'),\r\n data: reviewReportJson(result),\r\n };\r\n}\r\n\r\n/**\r\n * The effects a plain print host can perform on its own: send a prompt, print a\r\n * message the command produced, and run the host-orchestrated review. Anything\r\n * that needs to mutate host state or open a surface stays unregistered, and an\r\n * unregistered effect is refused rather than degraded.\r\n */\r\nexport function createPrintEffectRegistry(): PrintEffectRegistry {\r\n return new PrintEffectRegistry()\r\n .register('send-prompt', (effect) => ({\r\n kind: 'prompt',\r\n prompt: effect.prompt,\r\n commandContext: effect.context,\r\n }))\r\n .register('local-message', (effect, _env, command) => {\r\n if (effect.isError) throw new PrintCommandUsageError(command, effect.content);\r\n return { kind: 'handled', command, output: effect.content };\r\n })\r\n .register('review', performPrintReview);\r\n}\r\n\r\nexport interface PrintCommandDeps {\r\n /** Defaults to the shared built-in registry the TUI uses. */\r\n builtins?: BuiltinPrintRegistry;\r\n /** Defaults to the `send-prompt`-only registry. */\r\n effects?: PrintEffectRegistry;\r\n /** Defaults to `discoverCommands(workspace)` — the TUI's loader. */\r\n commands?: SlashCommand[];\r\n}\r\n\r\n/**\r\n * Context handed to a built-in's `execute` in print mode.\r\n *\r\n * Only fields a non-interactive host knows are populated; conversation state\r\n * is empty because resolution happens before the turn exists. A command may\r\n * therefore be marked `nonInteractive` only when it depends on nothing beyond\r\n * workspace, session id, model, provider, permission mode, and config.\r\n */\r\nfunction printBuiltinContext(\r\n env: PrintCommandEnvironment,\r\n commands: SlashCommand[],\r\n): BuiltinCommandContext {\r\n return {\r\n workspace: env.config.workspace,\r\n sessionId: env.sessionId,\r\n model: env.config.model,\r\n provider: env.config.provider,\r\n currentTurn: 0,\r\n messages: [],\r\n lastError: null,\r\n runtimeConfig: env.config,\r\n mode: env.mode,\r\n usage: null,\r\n turnDurationMs: 0,\r\n contextHistory: [],\r\n compactBoundaries: [],\r\n commandCount: commands.length,\r\n skillCount: 0,\r\n resolveAmbientContext: () => ({\r\n subagentCount: 0,\r\n hasMemoryIndex: false,\r\n hasClaudeMdLoader: false,\r\n }),\r\n };\r\n}\r\n\r\nfunction supportedCommandHelp(builtins: BuiltinPrintRegistry, commands: SlashCommand[]): string[] {\r\n const lines = ['Commands supported in print mode:'];\r\n for (const definition of builtins.getDefinitions()) {\r\n if (definition.nonInteractive) lines.push(` /${definition.name} — ${definition.description}`);\r\n }\r\n const custom = commands.map((command) => `/${command.name}`);\r\n lines.push(\r\n custom.length > 0\r\n ? ` custom commands from .book/commands: ${custom.slice(0, 12).join(' ')}${custom.length > 12 ? ' …' : ''}`\r\n : ' plus any custom command in .book/commands/ or ~/.book/commands/',\r\n );\r\n return lines;\r\n}\r\n\r\nfunction unsupported(\r\n command: string,\r\n reason: string,\r\n builtins: BuiltinPrintRegistry,\r\n commands: SlashCommand[],\r\n): UnsupportedPrintCommandError {\r\n return new UnsupportedPrintCommandError(\r\n command,\r\n [\r\n `✕ /${command} ${reason}`,\r\n '',\r\n ...supportedCommandHelp(builtins, commands),\r\n '',\r\n `Run book without --print (interactive mode) to use /${command}.`,\r\n ].join('\\n'),\r\n );\r\n}\r\n\r\n/**\r\n * Resolve one submitted line for a non-interactive host.\r\n *\r\n * Throws {@link UnsupportedPrintCommandError} when the line names a real\r\n * command this host cannot perform. An unknown `/name` is not a command at all\r\n * — the TUI sends it to the model unchanged, and so does this.\r\n */\r\nexport async function resolvePrintCommand(\r\n input: string,\r\n env: PrintCommandEnvironment,\r\n deps: PrintCommandDeps = {},\r\n): Promise<PrintCommandDispatch> {\r\n const parsed = parseSlashInput(input);\r\n if (!parsed || !parsed.name) return { kind: 'passthrough', prompt: input };\r\n\r\n const builtins = deps.builtins ?? createBuiltinCommandRegistry();\r\n const effects = deps.effects ?? createPrintEffectRegistry();\r\n const commands = deps.commands ?? discoverCommands(env.config.workspace);\r\n const context = printBuiltinContext(env, commands);\r\n\r\n const resolved = builtins.resolve(parsed.name, context);\r\n if (resolved) {\r\n if (!resolved.definition.nonInteractive) {\r\n throw unsupported(\r\n parsed.name,\r\n 'needs an interactive session: it changes host state instead of producing a prompt.',\r\n builtins,\r\n commands,\r\n );\r\n }\r\n if (!resolved.available) {\r\n throw unsupported(\r\n parsed.name,\r\n `is unavailable: ${resolved.unavailableReason ?? 'no reason given'}`,\r\n builtins,\r\n commands,\r\n );\r\n }\r\n const effect = resolved.definition.execute(\r\n { name: resolved.invokedName, rawArguments: parsed.rawArguments },\r\n context,\r\n );\r\n const dispatch = await effects.handle(effect, env, resolved.invokedName);\r\n if (!dispatch) {\r\n throw unsupported(\r\n parsed.name,\r\n `resolved to the '${effect.type}' effect, which a non-interactive host cannot perform.`,\r\n builtins,\r\n commands,\r\n );\r\n }\r\n return dispatch.kind === 'handled' ? { ...dispatch, command: parsed.name } : dispatch;\r\n }\r\n\r\n const custom = commands.find((command) => command.name === parsed.name);\r\n if (!custom) return { kind: 'passthrough', prompt: input };\r\n\r\n // Same resolver, same order (shell substitution, then variables), same trust\r\n // model as the TUI. A repository-declared body that substitutes shell is\r\n // refused here exactly as it is there: this host cannot prompt for the\r\n // decision, so an unapproved command ends the run instead of running its\r\n // shell unattended.\r\n const { resolved: body, shellErrors } = await resolveCommandBody(\r\n custom,\r\n parsed.rawArguments,\r\n {\r\n sessionId: env.sessionId,\r\n workspace: env.config.workspace,\r\n model: env.config.model,\r\n projectCommands: env.config.settings.commands.projectCommands,\r\n },\r\n env.signal,\r\n );\r\n return {\r\n kind: 'prompt',\r\n prompt: body,\r\n commandContext: commandEnforcementContext(custom, body),\r\n shellErrors,\r\n };\r\n}\r\n","/** Known event types in the stream-json wire format. */\r\nexport type StreamJsonEvent =\r\n | { type: 'user'; content: string }\r\n | { type: 'system'; model?: string; cwd?: string; [key: string]: unknown }\r\n | { type: 'session'; session_id?: string }\r\n | { type: 'run_start'; run?: unknown }\r\n | { type: 'assistant'; text?: string }\r\n | { type: 'reasoning'; text?: string }\r\n | { type: 'tool_use'; tool_call?: unknown }\r\n | { type: 'tool_result'; tool_result?: unknown }\r\n | { type: 'user_question'; request?: unknown; status?: 'pending' | 'unavailable' }\r\n | { type: 'user_question_result'; request_id?: string; response?: unknown }\r\n | { type: 'agent_start' | 'agent_update' | 'agent_result'; agent?: unknown }\r\n | {\r\n type: 'background_job_start' | 'background_job_update' | 'background_job_result';\r\n job?: unknown;\r\n }\r\n | { type: 'background_job_output'; jobId?: string; revision?: number }\r\n | { type: 'background_job_dismiss'; jobId?: string }\r\n | { type: 'agent_question'; agentId?: string; request?: unknown }\r\n | { type: 'agent_status'; agent?: unknown }\r\n | { type: 'agent_activity'; agentId?: string; activity?: unknown }\r\n | { type: 'agent_text_delta'; agentId?: string; text?: string }\r\n | { type: 'agent_message'; agentId?: string; message?: unknown }\r\n | { type: 'agent_completion'; notification?: unknown }\r\n | { type: 'agent_permission'; agentId?: string; request?: unknown }\r\n | { type: 'evidence_update'; evidence?: unknown }\r\n /**\r\n * The turn is being retried; discard every `assistant`/`reasoning` delta\r\n * emitted for it so far. Only the replacement attempt reaches the transcript,\r\n * so a consumer that concatenates blindly would keep text no history records.\r\n */\r\n | { type: 'attempt_discarded'; reason?: string }\r\n | { type: 'agent_apply'; agentId?: string; evidenceId?: string; status?: string }\r\n | { type: 'hook_event'; event?: string; [key: string]: unknown }\r\n | { type: 'mode_change'; mode?: string }\r\n | { type: 'plan_approval'; status?: string }\r\n /**\r\n * A slash command the host performed itself, instead of running a model turn.\r\n * `output` is the human rendering; `data` is the command's machine contract\r\n * (for `/review`, `ReviewJsonReport` from `review/host.ts`).\r\n */\r\n | { type: 'command_result'; command?: string; output?: string; data?: unknown }\r\n | { type: 'prompt_suggestions'; suggestions?: string[] }\r\n | { type: 'error'; error?: string }\r\n | { type: 'result'; result?: unknown; stopReason?: string }\r\n | { type: 'done' };\r\n\r\nexport type StreamJsonDiagnosticCode = 'invalid-json' | 'invalid-shape' | 'oversized-line';\r\n\r\nexport interface StreamJsonDiagnostic {\r\n code: StreamJsonDiagnosticCode;\r\n message: string;\r\n line?: string;\r\n}\r\n\r\nexport interface StreamParserOptions {\r\n maxBufferedLineBytes?: number;\r\n onDiagnostic?: (diagnostic: StreamJsonDiagnostic) => void;\r\n}\r\n\r\nconst EVENT_TYPES = new Set<StreamJsonEvent['type']>([\r\n 'user',\r\n 'system',\r\n 'session',\r\n 'run_start',\r\n 'assistant',\r\n 'reasoning',\r\n 'tool_use',\r\n 'tool_result',\r\n 'user_question',\r\n 'user_question_result',\r\n 'agent_start',\r\n 'background_job_start',\r\n 'background_job_update',\r\n 'background_job_output',\r\n 'background_job_result',\r\n 'background_job_dismiss',\r\n 'agent_update',\r\n 'agent_result',\r\n 'agent_question',\r\n 'agent_status',\r\n 'agent_activity',\r\n 'agent_text_delta',\r\n 'agent_message',\r\n 'agent_completion',\r\n 'agent_permission',\r\n 'evidence_update',\r\n 'agent_apply',\r\n 'hook_event',\r\n 'mode_change',\r\n 'plan_approval',\r\n 'prompt_suggestions',\r\n 'error',\r\n 'result',\r\n 'done',\r\n]);\r\n\r\nconst DEFAULT_MAX_BUFFERED_LINE_BYTES = 1024 * 1024;\r\n\r\nexport function parseStreamLineDetailed(line: string): {\r\n event?: StreamJsonEvent;\r\n diagnostic?: StreamJsonDiagnostic;\r\n} {\r\n const trimmed = line.trim();\r\n if (!trimmed) return {};\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(trimmed);\r\n } catch (error) {\r\n return {\r\n diagnostic: {\r\n code: 'invalid-json',\r\n message: `Invalid stream-json record: ${error instanceof Error ? error.message : String(error)}`,\r\n line: trimmed,\r\n },\r\n };\r\n }\r\n\r\n if (\r\n parsed === null ||\r\n typeof parsed !== 'object' ||\r\n Array.isArray(parsed) ||\r\n !('type' in parsed) ||\r\n typeof parsed.type !== 'string' ||\r\n !EVENT_TYPES.has(parsed.type as StreamJsonEvent['type']) ||\r\n (parsed.type === 'user' && typeof (parsed as { content?: unknown }).content !== 'string')\r\n ) {\r\n return {\r\n diagnostic: {\r\n code: 'invalid-shape',\r\n message: 'Stream-json records must be objects with a supported type and valid fields.',\r\n line: trimmed,\r\n },\r\n };\r\n }\r\n\r\n return { event: parsed as StreamJsonEvent };\r\n}\r\n\r\nexport function createStreamParser(\r\n onEvent: (event: StreamJsonEvent) => void,\r\n options: StreamParserOptions = {},\r\n) {\r\n const maxBufferedLineBytes = options.maxBufferedLineBytes ?? DEFAULT_MAX_BUFFERED_LINE_BYTES;\r\n if (!Number.isSafeInteger(maxBufferedLineBytes) || maxBufferedLineBytes < 1) {\r\n throw new Error('maxBufferedLineBytes must be a positive safe integer');\r\n }\r\n\r\n let buffer = '';\r\n let discardingOversizedLine = false;\r\n\r\n const emitLine = (line: string): void => {\r\n const { event, diagnostic } = parseStreamLineDetailed(line.replace(/\\r$/, ''));\r\n if (event) onEvent(event);\r\n if (diagnostic) options.onDiagnostic?.(diagnostic);\r\n };\r\n\r\n const append = (segment: string, terminated: boolean): void => {\r\n if (discardingOversizedLine) {\r\n if (terminated) discardingOversizedLine = false;\r\n return;\r\n }\r\n\r\n if (Buffer.byteLength(buffer) + Buffer.byteLength(segment) > maxBufferedLineBytes) {\r\n buffer = '';\r\n options.onDiagnostic?.({\r\n code: 'oversized-line',\r\n message: `Stream-json record exceeds the ${maxBufferedLineBytes}-byte limit.`,\r\n });\r\n discardingOversizedLine = !terminated;\r\n return;\r\n }\r\n\r\n buffer += segment;\r\n if (terminated) {\r\n emitLine(buffer);\r\n buffer = '';\r\n }\r\n };\r\n\r\n return {\r\n feed(chunk: string | Buffer): void {\r\n const segments = chunk.toString().split('\\n');\r\n for (let index = 0; index < segments.length; index++) {\r\n append(segments[index] ?? '', index < segments.length - 1);\r\n }\r\n },\r\n\r\n flush(): void {\r\n if (!discardingOversizedLine && buffer.length > 0) emitLine(buffer);\r\n buffer = '';\r\n discardingOversizedLine = false;\r\n },\r\n };\r\n}\r\n","import type { AgentConfig } from './types/runtime.js';\r\nimport { planWasLost } from './agent/session-state.js';\r\nimport { RunStatusWriter } from './run-status.js';\r\nimport type { CompactResult, CompactBoundary } from './types/sessions.js';\r\nimport type { ImageAttachment, Message, Usage } from './types/messages.js';\r\nimport type { HeadlessOptions, HeadlessPlanOutcome, HeadlessResult } from './types/public-sdk.js';\r\nimport type {\r\n PlanApprovalResult,\r\n UserQuestionRequest,\r\n UserQuestionResponse,\r\n} from './types/tools.js';\r\nimport {\r\n buildPlanApprovalQuestion,\r\n planApprovalFromUserQuestionResponse,\r\n planStopDecision,\r\n} from './tools/plan-mode.js';\r\nimport { resolvePrintCommand, type PrintCommandDispatch } from './commands/print-dispatch.js';\r\nimport type { CommandContext, HostCommandResult } from './types/commands.js';\r\nimport type { AgentCompletionNotification } from './agents/types.js';\r\nimport { createTerminalOutcome, type AgentTerminalOutcome } from './types/terminal.js';\r\nimport { createAgentRunContext, type AgentRunContext, type AgentRunResult } from './types/runs.js';\r\nimport { shouldCompact, usagePressureTokens } from './agent/compact.js';\r\nimport { resolveContextLimit } from './models.js';\r\nimport type { ToolRegistry } from './tools/registry.js';\r\nimport { observationKey } from './tools/file-provenance.js';\r\nimport { normalizePersistedTodos } from './tools/todo.js';\r\nimport { estimateUsageCost } from './pricing.js';\r\nimport { createSessionHistoryTools } from './tools/session-history.js';\r\nimport {\r\n createStreamParser,\r\n type StreamJsonDiagnostic,\r\n type StreamJsonEvent,\r\n} from './stream-json.js';\r\nimport { AgentSession, type AgentSessionRunRequest } from './session/agent-session.js';\r\nimport type { AgentEvent } from './session/agent-events.js';\r\nimport {\r\n buildAgentCompletionMessage,\r\n takeAgentCompletionBatch,\r\n} from './agents/completion-notification.js';\r\nimport { getOrCreateAgentManager } from './agents/manager.js';\r\nimport { resolvePermissionMode } from './permission-mode.js';\r\n\r\n/**\r\n * Re-price restored tokens.\r\n *\r\n * The tokens are one pool but may have been spent across several models, and the\r\n * records do not attribute them. Charging the whole pool at the most expensive\r\n * model's rate keeps the restored total an upper bound — the safe direction for a\r\n * spend ceiling. Any unpriceable model makes the total unknown.\r\n */\r\nfunction carriedCostUsd(usage: Usage, models: readonly string[]): number | null {\r\n let worst: number | null = null;\r\n for (const model of models) {\r\n const quote = estimateUsageCost(model, usage);\r\n if (quote.status !== 'known') return null;\r\n worst = worst === null ? quote.costUsd : Math.max(worst, quote.costUsd);\r\n }\r\n return worst;\r\n}\r\n\r\n/**\r\n * Read a whole piped prompt for the `text` input format.\r\n *\r\n * `-p` has always documented \"reads prompt from the flag or stdin\", but stdin was\r\n * only consumed for `--input-format stream-json`, so `book -p < prompt.txt` failed\r\n * on a prompt it had been handed. A long prompt had to be interpolated into argv.\r\n *\r\n * A TTY is left alone and reported as no prompt: an interactive `book -p` with no\r\n * argument would otherwise block on a read the user has no reason to expect,\r\n * looking like a hang rather than the usage error it is.\r\n */\r\nasync function readPipedPrompt(stream: NodeJS.ReadableStream): Promise<string | undefined> {\r\n if ((stream as NodeJS.ReadStream).isTTY) return undefined;\r\n const chunks: string[] = [];\r\n for await (const chunk of stream) {\r\n chunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8'));\r\n }\r\n const prompt = chunks.join('').trim();\r\n return prompt || undefined;\r\n}\r\n\r\nexport async function runHeadless(\r\n config: AgentConfig,\r\n registry: ToolRegistry,\r\n opts: HeadlessOptions,\r\n): Promise<HeadlessResult> {\r\n const mode = resolvePermissionMode(config.settings, opts.mode);\r\n const stdout = opts.stdout ?? process.stdout;\r\n const emit = (obj: unknown) => {\r\n if (obj && typeof obj === 'object' && 'type' in obj) {\r\n opts.onEvent?.(obj as StreamJsonEvent);\r\n }\r\n stdout.write(JSON.stringify(obj) + '\\n');\r\n };\r\n /** Set once the run's liveness file exists; released in the outer `finally`. */\r\n let disposeCrashHandlers: (() => void) | undefined;\r\n const agentSession = new AgentSession();\r\n const runtime = agentSession.getRuntime();\r\n // Seed the plan from the resumed session. Both lists are mutated in place by\r\n // their tools, so pushing into the runtime's arrays is what makes the plan\r\n // visible to the loop — reassigning would detach the runtime from the\r\n // ToolContext the loop seeds from.\r\n runtime.todos.push(...normalizePersistedTodos(opts.plan?.todos));\r\n if (opts.plan?.tasks?.length) runtime.tasks.push(...opts.plan.tasks);\r\n // Resuming prior work with nothing to show for it is the case worth naming: an\r\n // empty list renders as no list at all, so without this the model cannot tell a\r\n // dropped plan from a task that never had one.\r\n // `plan === undefined` means no plan record was ever written — an ordinary\r\n // conversation that never called TodoWrite. Reporting that as \"your plan did not\r\n // survive\" told every such resumed session to rebuild a plan it never had, and\r\n // pushed the model to invent one. Only a record that came back empty is a loss.\r\n runtime.planUnrestored = planWasLost({\r\n planRecordExisted: opts.plan !== undefined,\r\n priorMessages: opts.history.length,\r\n todos: runtime.todos.length,\r\n tasks: runtime.tasks.length,\r\n });\r\n\r\n try {\r\n if (opts.outputFormat === 'stream-json') {\r\n emit({ type: 'system', model: config.model, cwd: config.workspace });\r\n }\r\n\r\n // Resolve or create a session for persistence.\r\n const store = opts.persistSession === false ? undefined : opts.sessionStore;\r\n let sessionId = opts.sessionId;\r\n if (store && !sessionId && opts.sessionName) {\r\n sessionId = store.findByName(opts.sessionName)?.id;\r\n }\r\n if (store && sessionId && opts.forkSession) {\r\n sessionId = undefined; // start a new session, copy history only\r\n }\r\n let sessionName = opts.sessionName;\r\n let sessionCreated = opts.sessionCreated === true;\r\n if (store && !sessionId) {\r\n sessionId = store.create({ cwd: config.workspace, name: sessionName });\r\n sessionCreated = true;\r\n }\r\n if (store && sessionId && !sessionName) {\r\n sessionName = store.findById(sessionId)?.name;\r\n }\r\n if (sessionCreated && sessionId && opts.outputFormat === 'stream-json') {\r\n emit({ type: 'session', session_id: sessionId });\r\n }\r\n if (store && sessionId) {\r\n registry.registerAll(\r\n createSessionHistoryTools({ store, sessionId: () => sessionId as string }),\r\n );\r\n }\r\n\r\n if (sessionId) {\r\n await agentSession.startLifecycle(\r\n config,\r\n sessionId,\r\n opts.history.length > 0 ? 'resume' : 'startup',\r\n {\r\n onHookEvent: createHookEventHandler(opts, emit),\r\n },\r\n );\r\n }\r\n const runtimeSessionId = sessionId ?? crypto.randomUUID();\r\n\r\n // The run's liveness file. Headless is the host that most needs it: the\r\n // default `--output-format text` emits nothing at all until termination, so\r\n // without this an unattended run is completely opaque while it works. Owned\r\n // here rather than in the loop because subagents and managed agents call the\r\n // loop directly and must not each claim to be \"the run\".\r\n const statusWriter = new RunStatusWriter({\r\n sessionId: runtimeSessionId,\r\n runId: runtimeSessionId,\r\n workspace: config.workspace,\r\n budgetUsd: opts.maxBudgetUsd,\r\n startedAt: Date.now(),\r\n });\r\n disposeCrashHandlers = statusWriter.installCrashHandlers();\r\n\r\n // Headless permission policy: if a prompt would be shown and no rule resolves\r\n // it, deny the tool — headless can't interactively prompt. Callers who want\r\n // full autonomy should pass mode: 'bypassPermissions'.\r\n const permissionRequired = async (): Promise<'deny'> => 'deny';\r\n\r\n // The one interactive escape hatch this host has. Everything that needs a\r\n // human decision (AskUserQuestion, plan approval) goes through it, so\r\n // `userQuestionStatus` describes both.\r\n const userQuestionStatus = opts.onUserQuestionRequired ? 'pending' : 'unavailable';\r\n const askUser = async (\r\n request: UserQuestionRequest,\r\n context: { signal?: AbortSignal },\r\n ): Promise<UserQuestionResponse> => {\r\n try {\r\n return opts.onUserQuestionRequired\r\n ? await opts.onUserQuestionRequired(request, context)\r\n : {\r\n action: 'decline',\r\n message: 'User input is unavailable in non-interactive mode.',\r\n };\r\n } catch (error) {\r\n return {\r\n action: 'cancel',\r\n message: `User question handler failed: ${error instanceof Error ? error.message : String(error)}`,\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Plan approval without a terminal. `bypassPermissions` still auto-approves.\r\n * A host that supplied a question handler answers the plan through it. A\r\n * host with no handler cannot approve anything, so the run stops at the\r\n * first plan instead of retrying ExitPlanMode until --max-turns is gone.\r\n */\r\n const decidePlanApproval = async (plan: string): Promise<PlanApprovalResult> => {\r\n if (mode === 'bypassPermissions') return 'approve';\r\n if (!opts.onUserQuestionRequired) return planStopDecision('approval_unavailable');\r\n const request = buildPlanApprovalQuestion(plan, crypto.randomUUID());\r\n emitAgentEvent({ type: 'user_question', request, status: userQuestionStatus }, opts, emit);\r\n const response = await askUser(request, { signal: opts.signal });\r\n emitAgentEvent({ type: 'user_question_result', requestId: request.id, response }, opts, emit);\r\n return planApprovalFromUserQuestionResponse(request, response);\r\n };\r\n /**\r\n * Set once a plan ends the run because this host could not approve it. Held\r\n * in a box: the plan-approval callback assigns it from a closure, and a\r\n * plain `let` would still read as `null` at the output sites below.\r\n */\r\n const planNotApplied: { outcome?: HeadlessPlanOutcome } = {};\r\n\r\n let lastUsage: Usage | null = null;\r\n let lastOutcome: AgentTerminalOutcome | null = null;\r\n const runResults: AgentRunResult[] = [];\r\n const recordRunResult = (result: AgentRunResult): void => {\r\n const existing = runResults.findIndex(\r\n (candidate) => candidate.context.runId === result.context.runId,\r\n );\r\n if (existing >= 0) runResults[existing] = result;\r\n else runResults.push(result);\r\n };\r\n const recordManagedRunResult = (\r\n agent: Extract<AgentEvent, { type: 'agent_result' }>['agent'],\r\n ): void => {\r\n if (!agent.runId) return;\r\n const context = createAgentRunContext({\r\n sessionId: agent.parentSessionId ?? runtimeSessionId,\r\n runId: agent.runId,\r\n rootRunId: agent.rootRunId ?? agent.runId,\r\n parentRunId: agent.parentRunId,\r\n source: 'internal',\r\n startedAt: agent.runStartedAt ?? agent.startedAt ?? agent.createdAt,\r\n });\r\n const outcome =\r\n agent.runOutcome ??\r\n (agent.status === 'completed'\r\n ? createTerminalOutcome('completed', 'normal_completion', { partialOutput: false })\r\n : createTerminalOutcome('failed', 'runtime_error', {\r\n partialOutput: Boolean(agent.result),\r\n message: agent.error ?? `Managed agent ended with status ${agent.status}.`,\r\n }));\r\n recordRunResult({\r\n context,\r\n outcome,\r\n usage: agent.runUsage ?? null,\r\n accounting: runtime.runAccounting.snapshotRun(agent.runId),\r\n ambient: runtime.snapshotRunAmbient(agent.runId),\r\n });\r\n };\r\n const recordManagedCompletionResult = (notification: AgentCompletionNotification): void => {\r\n if (\r\n !notification.runId ||\r\n runResults.some((candidate) => candidate.context.runId === notification.runId)\r\n )\r\n return;\r\n const completion = notification.completion;\r\n const outcome =\r\n notification.outcome ??\r\n (completion.status === 'completed'\r\n ? createTerminalOutcome('completed', 'normal_completion', { partialOutput: false })\r\n : completion.status === 'stopped'\r\n ? createTerminalOutcome('cancelled', 'user_cancelled', {\r\n partialOutput: Boolean(completion.summary),\r\n message: completion.error,\r\n })\r\n : completion.status === 'interrupted'\r\n ? createTerminalOutcome('interrupted', 'transport_interrupted', {\r\n partialOutput: Boolean(completion.summary),\r\n message: completion.error,\r\n })\r\n : createTerminalOutcome('failed', 'runtime_error', {\r\n partialOutput: Boolean(completion.summary),\r\n message: completion.error,\r\n }));\r\n recordRunResult({\r\n context: createAgentRunContext({\r\n sessionId: notification.parentSessionId ?? runtimeSessionId,\r\n runId: notification.runId,\r\n rootRunId: notification.rootRunId ?? notification.runId,\r\n parentRunId: notification.parentRunId,\r\n source: 'internal',\r\n startedAt: completion.startedAt ?? completion.createdAt,\r\n }),\r\n outcome,\r\n usage: completion.usage ?? null,\r\n accounting: runtime.runAccounting.snapshotRun(notification.runId),\r\n ambient: runtime.snapshotRunAmbient(notification.runId),\r\n });\r\n };\r\n const rootContexts = new Map<string, AgentRunContext>();\r\n let lastHostCompactAttemptKey: string | null = null;\r\n const contextHistory: Message[] = [...opts.history];\r\n const transcript: Message[] = [...(opts.transcript ?? opts.history)];\r\n const compactBoundaries: CompactBoundary[] = [...(opts.compactBoundaries ?? [])];\r\n for (const message of transcript) {\r\n for (const observation of message.fileObservations ?? []) {\r\n const key = observationKey(observation.workspaceId, observation.path);\r\n const current = runtime.fileObservationLedger.get(key);\r\n if (!current || current.timestamp <= observation.timestamp) {\r\n runtime.fileObservationLedger.set(key, observation);\r\n }\r\n }\r\n }\r\n\r\n const loopConfig: AgentConfig = {\r\n ...config,\r\n maxTurns: opts.maxTurns ?? config.maxTurns,\r\n };\r\n const createRunCallbacks = (\r\n runContext: AgentRunContext,\r\n onOutcome: (outcome: AgentTerminalOutcome) => void,\r\n ): AgentSessionRunRequest['callbacks'] => ({\r\n onEvent: (event) => {\r\n if (event.type === 'agent_result') recordManagedRunResult(event.agent);\r\n if (event.type === 'terminal') {\r\n lastOutcome = event.outcome;\r\n onOutcome(event.outcome);\r\n }\r\n emitAgentEvent(event, opts, emit);\r\n },\r\n // No header rewrite at turn boundaries: load() derives updatedAt from\r\n // the last appended record, so the on-disk header is never authoritative.\r\n onTurnStart: () => {},\r\n onDone: () => {},\r\n onPermissionRequired: permissionRequired,\r\n onModeChange: (newMode) => {\r\n if (opts.outputFormat === 'stream-json') {\r\n emit({ type: 'mode_change', mode: newMode });\r\n }\r\n },\r\n onPlanApprovalRequired: async (plan) => {\r\n const decision = await decidePlanApproval(plan);\r\n if (typeof decision === 'object' && decision.decision === 'stop') {\r\n planNotApplied.outcome = {\r\n status: 'not_applied',\r\n reason: decision.reason,\r\n plan,\r\n message: decision.message,\r\n };\r\n }\r\n if (opts.outputFormat === 'stream-json') {\r\n emit({ type: 'plan_approval', status: planApprovalStatus(decision) });\r\n }\r\n return decision;\r\n },\r\n onUserQuestionRequired: askUser,\r\n userQuestionStatus,\r\n onHookEvent: createHookEventHandler(opts, emit),\r\n onUsage: (nextUsage) => {\r\n lastUsage = nextUsage;\r\n lastHostCompactAttemptKey = null;\r\n },\r\n onCompact: async (history, usage, hints) => {\r\n const outcome = await agentSession.compact({\r\n config,\r\n history,\r\n compactBoundaries,\r\n sessionId,\r\n transcriptOrdinal: transcript.length,\r\n runContext,\r\n runtime,\r\n timelineStore: store,\r\n onCommitted: (_result, boundary) => compactBoundaries.push(boundary),\r\n options: {\r\n ...hints,\r\n trigger: 'auto',\r\n preContextTokens: usage ? usagePressureTokens(usage) : undefined,\r\n signal: opts.signal,\r\n onHookEvent: createHookEventHandler(opts, emit),\r\n },\r\n });\r\n if (outcome.result.status === 'compacted') {\r\n emitCompactBoundary(opts.outputFormat, emit, outcome.result);\r\n lastUsage = null;\r\n }\r\n return outcome.result;\r\n },\r\n onAssistantMessageComplete: (message) => {\r\n if (!transcript.some((item) => item.id === message.id)) transcript.push(message);\r\n // The completed turn, always. `--include-partial-messages` adds the deltas\r\n // on top of this; it does not decide whether the stream carries assistant\r\n // text at all. Emitting only deltas made the flag load-bearing for the\r\n // basic contract, which is why leaving it off had to mean \"maximum volume\".\r\n if (opts.outputFormat === 'stream-json' && message.content) {\r\n emit({ type: 'assistant', text: message.content, complete: true });\r\n }\r\n },\r\n });\r\n const runParentTurn = async (\r\n prompt: string,\r\n displayMessage: string,\r\n userMessage: Message,\r\n runContext: AgentRunContext,\r\n commandContext?: CommandContext,\r\n ): Promise<void> => {\r\n let runOutcome: AgentTerminalOutcome | undefined;\r\n lastUsage = null;\r\n let updated: Message[];\r\n try {\r\n updated = await agentSession.run({\r\n config: loopConfig,\r\n registry,\r\n prompt,\r\n history: contextHistory,\r\n compactBoundaries,\r\n mode,\r\n sessionId: runtimeSessionId,\r\n timelineStore: store,\r\n signal: opts.signal,\r\n callbacks: createRunCallbacks(runContext, (outcome) => {\r\n runOutcome = outcome;\r\n }),\r\n runContext,\r\n maxBudgetUsd: opts.maxBudgetUsd,\r\n options: {\r\n displayMessage,\r\n userMessageId: userMessage.id,\r\n userMessageTimestamp: userMessage.timestamp,\r\n userFileObservations: userMessage.fileObservations,\r\n userAttachments: userMessage.attachments,\r\n userMessageKind: userMessage.kind,\r\n manageSessionHooks: sessionId ? false : undefined,\r\n // Completion messages are host-generated notifications, not user\r\n // prompts. Keep UserPromptSubmit hooks from rewriting or blocking them.\r\n skipUserPromptHooks: userMessage.kind === 'agent-notification',\r\n parentSessionId: runtimeSessionId,\r\n runContext,\r\n runtime,\r\n // Command frontmatter enforcement, exactly as the TUI passes it.\r\n allowedTools: commandContext?.allowedTools,\r\n modelOverride: commandContext?.modelOverride,\r\n commands: commandContext ? [commandContext.command] : undefined,\r\n statusWriter,\r\n // No human can resolve a permission prompt here: `permissionRequired`\r\n // answers `deny` unconditionally.\r\n unattended: true,\r\n },\r\n });\r\n } catch (error) {\r\n const failedOutcome =\r\n runOutcome ??\r\n createTerminalOutcome('interrupted', 'missing_terminal', { partialOutput: false });\r\n recordRunResult({\r\n context: runContext,\r\n outcome: failedOutcome,\r\n usage: runtime.runAccounting.snapshotRun(runContext.runId)?.directUsage ?? lastUsage,\r\n accounting: runtime.runAccounting.snapshotRun(runContext.runId),\r\n ambient: runtime.snapshotRunAmbient(runContext.runId),\r\n });\r\n throw error;\r\n }\r\n const priorIds = new Set(transcript.map((message) => message.id));\r\n transcript.push(\r\n ...updated.filter((message) => !priorIds.has(message.id) && message.role === 'assistant'),\r\n );\r\n contextHistory.length = 0;\r\n contextHistory.push(...updated);\r\n const turnOutcome =\r\n runOutcome ??\r\n createTerminalOutcome('interrupted', 'missing_terminal', {\r\n partialOutput: updated.some((message) => message.role === 'assistant'),\r\n });\r\n recordRunResult({\r\n context: runContext,\r\n outcome: turnOutcome,\r\n usage: runtime.runAccounting.snapshotRun(runContext.runId)?.directUsage ?? lastUsage,\r\n accounting: runtime.runAccounting.snapshotRun(runContext.runId),\r\n ambient: runtime.snapshotRunAmbient(runContext.runId),\r\n });\r\n };\r\n\r\n /**\r\n * Expand one submitted line's leading `/command` through the same\r\n * registries and the same `resolveCommandBody` the TUI uses. A command\r\n * whose effect this host cannot perform throws\r\n * `UnsupportedPrintCommandError` instead of reaching the model as a\r\n * literal \"/name\" string.\r\n *\r\n * `runContext` is the root this line is accounted under — the same one a\r\n * model turn for it would use — so a command the host performs by spawning\r\n * agents is billed and budget-checked exactly like a turn.\r\n */\r\n const dispatchSubmittedPrompt = (\r\n submitted: string,\r\n runContext: AgentRunContext,\r\n ): Promise<PrintCommandDispatch> =>\r\n opts.expandSlashCommands === false\r\n ? Promise.resolve({ kind: 'passthrough', prompt: submitted })\r\n : resolvePrintCommand(submitted, {\r\n config,\r\n mode,\r\n sessionId: runtimeSessionId,\r\n signal: opts.signal,\r\n agents: {\r\n // Built only when an agent-backed command (`/review`) asks for it,\r\n // and attached to this session's runtime so it is disposed with the\r\n // run. Its events join the same stream-json output as the main loop,\r\n // and its finished runs land in `runs` like any other execution.\r\n manager: () =>\r\n getOrCreateAgentManager(config, registry.getDefinitions(), {\r\n runtime,\r\n permissionMode: mode,\r\n eventSink: (event) => {\r\n if (event.type === 'agent_result') recordManagedRunResult(event.agent);\r\n emitAgentEvent(event, opts, emit);\r\n },\r\n hookEventSink: createHookEventHandler(opts, emit),\r\n }),\r\n runContext,\r\n },\r\n });\r\n\r\n /**\r\n * Slash commands the host performed itself, in submission order. A run made\r\n * only of those never produces a turn outcome, and reporting it as\r\n * `interrupted` would tell a machine caller that a review which completed\r\n * had been cut short.\r\n */\r\n const commandResults: HostCommandResult[] = [];\r\n /**\r\n * Inclusive spend of the most recent host-performed command — the same\r\n * \"latest unit of work\" `lastUsage` reports for a model turn.\r\n *\r\n * Kept separate rather than folded into `lastUsage`, which drives the\r\n * cross-turn compaction decision: a review's child-agent totals were never\r\n * in the parent's context window, and adding them there would compact the\r\n * parent history against tokens it does not hold.\r\n */\r\n let commandUsage: Usage | null = null;\r\n\r\n // Collect prompts: text input -> single prompt, from the flag or stdin;\r\n // stream-json -> read stdin.\r\n const prompts: string[] = [];\r\n if (opts.inputFormat === 'text') {\r\n const prompt = opts.prompt ?? (await readPipedPrompt(opts.stdin ?? process.stdin));\r\n if (!prompt) {\r\n throw new Error(\r\n 'print mode requires a prompt: pass one to -p, pipe one on stdin, or use --input-format stream-json',\r\n );\r\n }\r\n prompts.push(prompt);\r\n } else {\r\n // stream-json input: newline-delimited {type:'user', content} from stdin.\r\n const stream = opts.stdin ?? process.stdin;\r\n const diagnostics: StreamJsonDiagnostic[] = [];\r\n const parser = createStreamParser(\r\n (event) => {\r\n if (event.type === 'user') prompts.push(event.content);\r\n },\r\n {\r\n maxBufferedLineBytes: opts.maxInputLineBytes,\r\n onDiagnostic: (diagnostic) => diagnostics.push(diagnostic),\r\n },\r\n );\r\n for await (const chunk of stream) {\r\n parser.feed(chunk as string | Buffer);\r\n }\r\n parser.flush();\r\n if (diagnostics.length > 0) throw new Error(diagnostics[0]?.message);\r\n if (opts.prompt) prompts.unshift(opts.prompt);\r\n }\r\n\r\n // A USD cap has to bound the OBJECTIVE, not one prompt. Every submitted line\r\n // mints a fresh root and `startRoot` seeds the full cap into it, so a hundred\r\n // stream-json prompts under a $50 cap would authorise $5000 inside a single\r\n // process. Carry the accumulated spend into each subsequent root through the\r\n // same seam that already carries it across processes.\r\n let carriedSpend: { usage: Usage | null; costUsd: number | null } | undefined =\r\n opts.carriedUsage\r\n ? {\r\n usage: opts.carriedUsage,\r\n costUsd: carriedCostUsd(\r\n opts.carriedUsage,\r\n opts.carriedModels?.length ? opts.carriedModels : [config.model],\r\n ),\r\n }\r\n : undefined;\r\n\r\n for (const submitted of prompts) {\r\n // The run exists before dispatch, not after it. A host-performed command\r\n // spawns managed agents of its own, and those agents are only budgeted and\r\n // accounted when they are spawned under a root that already carries\r\n // `maxBudgetUsd` — resolving the command first would leave `/review`\r\n // spending outside every cap the caller set.\r\n const runId = crypto.randomUUID();\r\n const runContext = createAgentRunContext({\r\n sessionId: runtimeSessionId,\r\n runId,\r\n source: opts.runSource ?? 'headless',\r\n resumedFromRunId:\r\n runResults.length === 0\r\n ? (opts.resumedFromRunId ??\r\n (opts.history.length > 0\r\n ? [...opts.history].reverse().find((message) => message.role === 'user')?.id\r\n : undefined))\r\n : undefined,\r\n });\r\n runtime.runAccounting.startRoot(runContext, opts.maxBudgetUsd);\r\n // Carry spend forward from earlier processes of this session, so a USD cap\r\n // bounds the objective rather than one process.\r\n if (carriedSpend) {\r\n runtime.runAccounting.seedRoot(runContext.rootRunId, carriedSpend);\r\n }\r\n\r\n const dispatch = await dispatchSubmittedPrompt(submitted, runContext);\r\n if (dispatch.kind === 'prompt' && dispatch.shellErrors?.length) {\r\n // The TUI drops these silently; a non-interactive host that swallowed\r\n // them would ship \"[shell error: …]\" into the prompt with no trace.\r\n for (const shellError of dispatch.shellErrors) {\r\n process.stderr.write(`warning: ${shellError}\\n`);\r\n }\r\n }\r\n if (dispatch.kind === 'handled') {\r\n // The effect handler already did the work: no model turn for this line.\r\n const handled: HostCommandResult = {\r\n command: dispatch.command,\r\n output: dispatch.output,\r\n data: dispatch.data,\r\n };\r\n commandResults.push(handled);\r\n const accounting = runtime.runAccounting.snapshotRoot(runContext.rootRunId);\r\n commandUsage = accounting.inclusiveUsage ?? commandUsage;\r\n recordRunResult({\r\n context: runContext,\r\n outcome: createTerminalOutcome('completed', 'normal_completion', {\r\n partialOutput: false,\r\n }),\r\n // The host itself made no provider call; everything spent here was\r\n // spent by the agents this command ran, which is the inclusive figure.\r\n usage: accounting.inclusiveUsage,\r\n accounting,\r\n ambient: runtime.snapshotRunAmbient(runContext.runId),\r\n });\r\n if (opts.outputFormat === 'text') {\r\n if (dispatch.output) stdout.write(`${dispatch.output}\\n`);\r\n } else if (\r\n opts.outputFormat === 'stream-json' &&\r\n (dispatch.output !== undefined || dispatch.data !== undefined)\r\n ) {\r\n // One record carries both renderings: `output` for a human reading the\r\n // stream, `data` for the machine contract (see review/host.ts).\r\n // Only on the line-delimited wire: `json` is a single-document format,\r\n // and a second top-level object there breaks `JSON.parse(stdout)`.\r\n emit({ type: 'command_result', ...handled });\r\n }\r\n continue;\r\n }\r\n const prompt = dispatch.prompt;\r\n const commandContext = dispatch.kind === 'prompt' ? dispatch.commandContext : undefined;\r\n const userMessage: Message = {\r\n id: runId,\r\n role: 'user',\r\n content: prompt,\r\n // With a command context, `prompt` is a resolved command body, not typed\r\n // input -- repository-authored for a project command. Marking it keeps\r\n // print and SDK runs on the same footing as the TUI.\r\n derivedContent: commandContext ? true : undefined,\r\n includeInContext: true,\r\n kind: 'conversation',\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Cross-turn auto-compact before appending the new user message.\r\n const contextLimit = resolveContextLimit(config);\r\n const hostCompactAttemptKey = `${usagePressureTokens(lastUsage)}:${contextHistory.length}`;\r\n if (\r\n config.autoCompactEnabled !== false &&\r\n contextLimit != null &&\r\n shouldCompact(lastUsage, contextLimit) &&\r\n lastHostCompactAttemptKey !== hostCompactAttemptKey\r\n ) {\r\n lastHostCompactAttemptKey = hostCompactAttemptKey;\r\n try {\r\n const outcome = await agentSession.compact({\r\n config,\r\n history: contextHistory,\r\n compactBoundaries,\r\n sessionId,\r\n transcriptOrdinal: transcript.length,\r\n runContext,\r\n runtime,\r\n timelineStore: store,\r\n onCommitted: (compactResult, boundary) => {\r\n contextHistory.length = 0;\r\n contextHistory.push(...compactResult.replacementHistory);\r\n compactBoundaries.push(boundary);\r\n lastUsage = null;\r\n },\r\n options: {\r\n trigger: 'auto',\r\n preContextTokens: usagePressureTokens(lastUsage),\r\n signal: opts.signal,\r\n upcomingUserIntent: prompt,\r\n onHookEvent: createHookEventHandler(opts, emit),\r\n },\r\n });\r\n if (outcome.result.status === 'compacted') {\r\n emitCompactBoundary(opts.outputFormat, emit, outcome.result);\r\n }\r\n } catch {\r\n // non-fatal\r\n }\r\n }\r\n\r\n const recorded = await agentSession.recordUserMessage({\r\n config,\r\n sessionId: runtimeSessionId,\r\n displayMessage: prompt,\r\n userMessage,\r\n sessionName,\r\n timelineStore: store && sessionId ? store : undefined,\r\n expandShellInput: false,\r\n runtime,\r\n signal: opts.signal,\r\n });\r\n sessionName = recorded.sessionName;\r\n const contextMessage = recorded.contextMessage;\r\n transcript.push(userMessage);\r\n rootContexts.set(runContext.rootRunId, runContext);\r\n await runParentTurn(contextMessage, prompt, userMessage, runContext, commandContext);\r\n // Fold this prompt's inclusive spend into the carry so the next root starts\r\n // where this one finished instead of back at zero.\r\n const spentSoFar = runtime.runAccounting.snapshotRoot(runContext.rootRunId);\r\n carriedSpend = {\r\n usage: spentSoFar.inclusiveUsage,\r\n costUsd: spentSoFar.inclusiveCostUsd,\r\n };\r\n // An unapprovable plan is the deliverable: queued prompts would only\r\n // re-plan against a workspace nothing is allowed to change.\r\n if (planNotApplied.outcome) break;\r\n }\r\n\r\n // Background children outlive the root tool call. Keep the runtime alive,\r\n // feed each completion back through the parent model, and acknowledge only\r\n // after that continuation turn succeeds.\r\n const managedAgentManager = planNotApplied.outcome ? undefined : runtime.agentManager;\r\n if (managedAgentManager) {\r\n const deliveredCompletionIds = new Set(\r\n transcript.flatMap((message) =>\r\n (message.agentNotifications ?? [])\r\n .map((notification) => notification.deliveryId)\r\n .filter((id): id is string => Boolean(id)),\r\n ),\r\n );\r\n while (true) {\r\n await managedAgentManager.waitForIdle();\r\n const pending = (await managedAgentManager.listPendingCompletions()).filter(\r\n (notification) => notification.parentSessionId === runtimeSessionId,\r\n );\r\n if (pending.length === 0) break;\r\n const alreadyDelivered = pending.filter((notification) =>\r\n deliveredCompletionIds.has(notification.deliveryId),\r\n );\r\n for (const notification of alreadyDelivered) {\r\n await managedAgentManager.acknowledgeCompletion(notification.deliveryId);\r\n }\r\n const fresh = pending.filter(\r\n (notification) => !deliveredCompletionIds.has(notification.deliveryId),\r\n );\r\n if (fresh.length === 0) continue;\r\n const firstRootRunId = fresh[0]?.rootRunId;\r\n const sameRoot = firstRootRunId\r\n ? fresh.filter((notification) => notification.rootRunId === firstRootRunId)\r\n : fresh;\r\n const batch = takeAgentCompletionBatch(sameRoot);\r\n for (const notification of batch) recordManagedCompletionResult(notification);\r\n const built = batch.map((notification: AgentCompletionNotification) =>\r\n buildAgentCompletionMessage(notification),\r\n );\r\n const displayMessage = built.map((item) => item.displayMessage).join('\\n');\r\n const userMessage: Message = {\r\n id: crypto.randomUUID(),\r\n role: 'user',\r\n content: displayMessage,\r\n contextContent: built.map((item) => item.contextMessage).join('\\n'),\r\n includeInContext: true,\r\n kind: 'agent-notification',\r\n agentNotifications: built.map((item) => item.display),\r\n timestamp: Date.now(),\r\n };\r\n const recorded = await agentSession.recordUserMessage({\r\n config,\r\n sessionId: runtimeSessionId,\r\n displayMessage,\r\n contextMessage: userMessage.contextContent,\r\n userMessage,\r\n timelineStore: store && sessionId ? store : undefined,\r\n expandShellInput: false,\r\n runtime,\r\n signal: opts.signal,\r\n });\r\n transcript.push(userMessage);\r\n const parentContext = batch[0]?.rootRunId\r\n ? rootContexts.get(batch[0].rootRunId)\r\n : undefined;\r\n const runContext = createAgentRunContext({\r\n sessionId: runtimeSessionId,\r\n source: opts.runSource ?? 'headless',\r\n rootRunId: parentContext?.rootRunId ?? batch[0]?.rootRunId,\r\n parentRunId: batch[0]?.runId ?? parentContext?.runId,\r\n });\r\n if (parentContext) rootContexts.set(runContext.rootRunId, parentContext);\r\n else rootContexts.set(runContext.rootRunId, runContext);\r\n await runParentTurn(recorded.contextMessage, displayMessage, userMessage, runContext);\r\n for (const notification of batch) {\r\n deliveredCompletionIds.add(notification.deliveryId);\r\n await managedAgentManager.acknowledgeCompletion(notification.deliveryId);\r\n }\r\n }\r\n }\r\n\r\n const outcome =\r\n lastOutcome ??\r\n (commandResults.length > 0\r\n ? createTerminalOutcome('completed', 'normal_completion', { partialOutput: false })\r\n : createTerminalOutcome('interrupted', 'missing_terminal', {\r\n partialOutput: transcript.some((message) => message.role === 'assistant'),\r\n }));\r\n runResults.sort((left, right) => left.context.startedAt - right.context.startedAt);\r\n // A run made only of host-performed commands has no last turn, so reporting\r\n // `null` would say \"this cost nothing\" about work that really spent tokens.\r\n const reportedUsage = lastUsage ?? commandUsage;\r\n const result: HeadlessResult = {\r\n messages: contextHistory,\r\n transcript,\r\n compactBoundaries,\r\n usage: reportedUsage,\r\n accounting: runtime.runAccounting.snapshotAll(),\r\n outcome,\r\n runs: runResults,\r\n sessionId,\r\n plan: planNotApplied.outcome,\r\n commandResults,\r\n };\r\n\r\n if (opts.jsonSchema) {\r\n const text = lastAssistantText(contextHistory);\r\n try {\r\n result.structured = JSON.parse(text);\r\n } catch {\r\n result.structuredError = 'Failed to parse JSON from assistant output';\r\n }\r\n }\r\n\r\n // Prompt suggestions: ask model for follow-up prompts.\r\n if (opts.promptSuggestions && opts.outputFormat === 'stream-json') {\r\n try {\r\n const suggestions = await generatePromptSuggestions(\r\n config,\r\n registry,\r\n contextHistory,\r\n opts.signal,\r\n store?.readImageAttachment\r\n ? (attachment) => store.readImageAttachment!(runtimeSessionId, attachment)\r\n : undefined,\r\n );\r\n if (suggestions.length > 0) {\r\n emit({ type: 'prompt_suggestions', suggestions });\r\n }\r\n } catch {\r\n // Non-fatal: suggestions are best-effort.\r\n }\r\n }\r\n\r\n if (opts.outputFormat === 'text') {\r\n const stopped = planNotApplied.outcome;\r\n if (stopped) {\r\n // The plan is the deliverable when nothing could approve it; the\r\n // trailing status line keeps \"produced a plan\" from reading as\r\n // \"did the work\".\r\n stdout.write(`${stopped.plan}\\n\\n${stopped.message}\\n`);\r\n } else {\r\n const last = lastAssistantText(contextHistory);\r\n if (last) stdout.write(last + '\\n');\r\n }\r\n } else if (opts.outputFormat === 'json') {\r\n // Exactly one top-level document: everything the run produced, including\r\n // commands the host performed itself, is carried here.\r\n emit({\r\n result: {\r\n messages: contextHistory,\r\n usage: reportedUsage,\r\n accounting: result.accounting,\r\n outcome,\r\n stopReason: outcome.reason,\r\n runs: runResults,\r\n structured: result.structured,\r\n structuredError: result.structuredError,\r\n plan: result.plan,\r\n commandResults,\r\n },\r\n });\r\n } else if (opts.outputFormat === 'stream-json') {\r\n emit({\r\n type: 'result',\r\n stopReason: outcome.reason,\r\n result: {\r\n messages: contextHistory,\r\n usage: reportedUsage,\r\n accounting: result.accounting,\r\n outcome,\r\n stopReason: outcome.reason,\r\n runs: runResults,\r\n structured: result.structured,\r\n structuredError: result.structuredError,\r\n plan: result.plan,\r\n commandResults,\r\n },\r\n });\r\n }\r\n\r\n if (sessionId) {\r\n await agentSession.endLifecycle(config, sessionId, 'completion', {\r\n onHookEvent: createHookEventHandler(opts, emit),\r\n });\r\n }\r\n\r\n return result;\r\n } finally {\r\n disposeCrashHandlers?.();\r\n agentSession.dispose('headless_complete');\r\n }\r\n}\r\n\r\nfunction lastAssistantText(history: Message[]): string {\r\n for (let i = history.length - 1; i >= 0; i--) {\r\n const m = history[i];\r\n if (m.role === 'assistant' && m.content) return m.content;\r\n }\r\n return '';\r\n}\r\n\r\n/** Wire status for the `plan_approval` stream-json event: approve | approve-fresh | reject | revise | stop. */\r\nfunction planApprovalStatus(decision: PlanApprovalResult): string {\r\n return typeof decision === 'string' ? decision : decision.decision;\r\n}\r\n\r\ntype HeadlessEmit = (event: unknown) => void;\r\n\r\nfunction createHookEventHandler(\r\n opts: HeadlessOptions,\r\n emit: HeadlessEmit,\r\n): ((event: string, payload: Record<string, unknown>) => void) | undefined {\r\n if (!opts.includeHookEvents || opts.outputFormat !== 'stream-json') return undefined;\r\n return (event, payload) => emit({ type: 'hook_event', event, ...payload });\r\n}\r\n\r\nfunction emitAgentEvent(event: AgentEvent, opts: HeadlessOptions, emit: HeadlessEmit): void {\r\n if (event.type === 'terminal') return;\r\n if (event.type === 'agent_text_delta' && opts.forwardSubagentText !== true) return;\r\n opts.onAgentEvent?.(event);\r\n if (event.type === 'error') {\r\n if (opts.outputFormat === 'stream-json') emit({ type: 'error', error: event.error });\r\n else process.stderr.write(`error: ${event.error}\\n`);\r\n return;\r\n }\r\n if (opts.outputFormat !== 'stream-json') return;\r\n\r\n switch (event.type) {\r\n case 'run_started':\r\n emit({ type: 'run_start', run: event.context, ambient: event.ambient });\r\n break;\r\n case 'text':\r\n // Deltas are opt IN, and are additional to the completed message emitted at\r\n // turn end. Commander leaves an unpassed boolean `undefined`, so the old\r\n // `!== false` gate meant the flag did nothing and every run paid maximum\r\n // stream volume whether or not anyone asked for them.\r\n if (opts.includePartialMessages === true)\r\n emit({ type: 'assistant', text: event.content, complete: false });\r\n break;\r\n case 'reasoning':\r\n if (opts.includePartialMessages === true) emit({ type: 'reasoning', text: event.content });\r\n break;\r\n case 'tool_use':\r\n emit({ type: 'tool_use', tool_call: event.toolCall });\r\n break;\r\n case 'tool_result':\r\n emit({ type: 'tool_result', tool_result: event.toolResult });\r\n break;\r\n case 'user_question':\r\n emit({ type: 'user_question', request: event.request, status: event.status });\r\n break;\r\n case 'user_question_result':\r\n emit({\r\n type: 'user_question_result',\r\n request_id: event.requestId,\r\n response: event.response,\r\n });\r\n break;\r\n case 'agent_start':\r\n case 'background_job_start':\r\n case 'background_job_update':\r\n case 'background_job_output':\r\n case 'background_job_result':\r\n case 'background_job_dismiss':\r\n case 'agent_update':\r\n case 'agent_result':\r\n case 'agent_question':\r\n case 'agent_status':\r\n case 'agent_activity':\r\n case 'agent_text_delta':\r\n case 'agent_message':\r\n case 'agent_completion':\r\n case 'agent_permission':\r\n case 'agent_apply':\r\n case 'evidence_update':\r\n case 'skill_lifecycle':\r\n case 'attempt_discarded':\r\n emit(event);\r\n break;\r\n case 'system':\r\n case 'session':\r\n case 'result':\r\n case 'done':\r\n break;\r\n }\r\n}\r\n\r\nfunction emitCompactBoundary(\r\n outputFormat: HeadlessOptions['outputFormat'],\r\n emit: HeadlessEmit,\r\n result: Extract<CompactResult, { status: 'compacted' }>,\r\n): void {\r\n if (outputFormat !== 'stream-json') return;\r\n emit({\r\n type: 'system',\r\n subtype: 'compact_boundary',\r\n trigger: result.trigger,\r\n pre_tokens: result.preContextTokens,\r\n compact_id: result.compactId,\r\n generation: result.generation,\r\n pre_messages: result.preMessageCount,\r\n post_messages: result.replacementHistory.length,\r\n post_tokens: result.postContextTokens,\r\n checkpoint_version: 2,\r\n strategy: result.strategy,\r\n model_calls: result.modelCalls,\r\n degraded: result.degraded,\r\n coverage_status: result.checkpoint.coverage?.status ?? 'complete',\r\n // This generation's status above; the conversation's accumulated one here.\r\n coverage_lifetime_status: result.checkpoint.coverage?.lifetime?.status ?? 'complete',\r\n coverage: result.checkpoint.coverage,\r\n warning: result.warning,\r\n });\r\n}\r\n\r\nasync function generatePromptSuggestions(\r\n config: AgentConfig,\r\n _registry: ToolRegistry,\r\n history: Message[],\r\n signal?: AbortSignal,\r\n resolveAttachment?: (attachment: ImageAttachment) => Promise<Uint8Array> | Uint8Array,\r\n): Promise<string[]> {\r\n const { chatCompletionStream } = await import('./provider/openai-compatible.js');\r\n const { buildMessages } = await import('./agent/context.js');\r\n\r\n const suggestionMessages = await buildMessages(\r\n config,\r\n [\r\n ...history,\r\n {\r\n id: crypto.randomUUID(),\r\n role: 'user' as const,\r\n content:\r\n 'Based on the conversation above, suggest 1-3 follow-up prompts the user might want to ask next. Keep each suggestion under 80 characters. Return ONLY a JSON array of strings, no other text.',\r\n includeInContext: true,\r\n timestamp: Date.now(),\r\n },\r\n ],\r\n undefined,\r\n undefined,\r\n signal,\r\n undefined,\r\n undefined,\r\n resolveAttachment,\r\n );\r\n\r\n const stream = chatCompletionStream(config, suggestionMessages, [], { signal });\r\n let content = '';\r\n for await (const event of stream) {\r\n if (event.type === 'text' && event.content) {\r\n content += event.content;\r\n }\r\n }\r\n\r\n // Parse JSON array from the response.\r\n try {\r\n const jsonMatch = content.match(/\\[[\\s\\S]*?\\]/);\r\n if (jsonMatch) {\r\n const parsed = JSON.parse(jsonMatch[0]);\r\n if (Array.isArray(parsed)) {\r\n return parsed.filter((s) => typeof s === 'string' && s.length > 0).slice(0, 3);\r\n }\r\n }\r\n } catch {\r\n // Fallback: try to extract quoted strings.\r\n const quoted = content.match(/\"([^\"]+)\"/g);\r\n if (quoted) {\r\n return quoted.map((s) => s.replace(/^\"|\"$/g, '')).slice(0, 3);\r\n }\r\n }\r\n return [];\r\n}\r\n","/**\r\n * MCP client host: connects declared servers over stdio, Streamable HTTP, or\r\n * legacy SSE and exposes their tools as `mcp__<server>__<tool>` definitions.\r\n *\r\n * The protocol layer (handshake/version negotiation, request lifecycle,\r\n * cancellation notifications, result validation) is the official\r\n * `@modelcontextprotocol/sdk` `Client`. Remote transports come from the SDK.\r\n * The stdio transport stays in-repo so Book retains child-process observation,\r\n * bounded stderr capture, deterministic listener cleanup, and\r\n * SIGTERM→SIGKILL escalation on shutdown.\r\n */\r\nimport spawn from 'cross-spawn';\r\nimport type { ChildProcess } from 'child_process';\r\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\r\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\r\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\r\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\r\nimport { ReadBuffer, serializeMessage } from '@modelcontextprotocol/sdk/shared/stdio.js';\r\nimport {\r\n ElicitRequestSchema,\r\n ErrorCode,\r\n McpError,\r\n ToolListChangedNotificationSchema,\r\n type JSONRPCMessage,\r\n} from '@modelcontextprotocol/sdk/types.js';\r\nimport type {\r\n ElicitationHandler,\r\n ElicitationResponse,\r\n ToolDefinition,\r\n ToolContext,\r\n} from './types/tools.js';\r\nimport { toElicitationFields, validateElicitationContent } from './mcp-elicitation.js';\r\nimport { toolFailure, toolSuccess } from './tools/result.js';\r\nimport { getPackageVersion } from './version-info.js';\r\nimport {\r\n consoleMcpDiagnosticSink,\r\n resolveMcpServerList,\r\n type McpDiagnosticSink,\r\n type McpServerConfig,\r\n} from './mcp-config.js';\r\n\r\nexport {\r\n loadMcpConfig,\r\n resolveMcpServerList,\r\n formatMcpServerCommand,\r\n consoleMcpDiagnosticSink,\r\n} from './mcp-config.js';\r\nexport type {\r\n McpServerConfig,\r\n McpServerSource,\r\n ResolvedMcpServer,\r\n McpDiagnostic,\r\n McpDiagnosticSink,\r\n} from './mcp-config.js';\r\n\r\nexport interface McpToolDef {\r\n name: string;\r\n description: string;\r\n inputSchema: Record<string, unknown>;\r\n}\r\n\r\nexport interface McpConnection {\r\n name: string;\r\n client: Client;\r\n /** Present only for locally spawned stdio servers. */\r\n process?: ChildProcess;\r\n tools: McpToolDef[];\r\n /** In-flight requests issued through this host, visible to hosts and tests. */\r\n pending: Map<number, { method: string }>;\r\n closed: boolean;\r\n /** Bounded tail of the server's stderr output. */\r\n readonly stderr: string;\r\n /** Negotiated protocol revision reported by the server. */\r\n protocolVersion?: string;\r\n serverInfo?: { name: string; version: string };\r\n capabilities?: Record<string, unknown>;\r\n /** Gracefully terminate any remote session and close the owned transport. */\r\n close(): Promise<void>;\r\n}\r\n\r\nexport interface McpConnectionOptions {\r\n home?: string;\r\n signal?: AbortSignal;\r\n initializationTimeoutMs?: number;\r\n requestTimeoutMs?: number;\r\n maxStderrBytes?: number;\r\n /** Lifecycle observer used by hosts/tests that account for owned child processes. */\r\n onProcessSpawn?: (name: string, process: ChildProcess) => void;\r\n /**\r\n * Explicit servers to connect. A host that has evaluated project-server\r\n * approval passes the approved subset here.\r\n *\r\n * When omitted, only user-scoped servers (<BOOK_HOME>/mcp.json) are\r\n * connected: they are user-owned, so no approval gate applies. Project\r\n * servers from <workspace>/.mcp.json are repository-controlled and are\r\n * skipped, because approval cannot be evaluated without settings. Omitting\r\n * this therefore fails closed rather than connecting whatever the workspace\r\n * declared.\r\n */\r\n servers?: Record<string, McpServerConfig>;\r\n /** Warning sink; defaults to stderr. Ink hosts must supply a non-console sink. */\r\n onDiagnostic?: McpDiagnosticSink;\r\n /** Invoked after this host refreshes `connection.tools` for a list_changed notification. */\r\n onToolListChanged?: (serverName: string) => void;\r\n /** Invoked when a successfully initialized server later disconnects. */\r\n onConnectionClosed?: (serverName: string) => void;\r\n /**\r\n * Host prompt for MCP form elicitation. Supplying it is what declares the\r\n * `elicitation` client capability, so a host that cannot reach a user never\r\n * advertises one — servers then fail the request themselves instead of\r\n * waiting on a prompt nobody will see.\r\n */\r\n onElicit?: ElicitationHandler;\r\n}\r\n\r\nconst DEFAULT_INITIALIZATION_TIMEOUT_MS = 10_000;\r\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\r\nconst DEFAULT_MAX_STDERR_BYTES = 8_192;\r\n\r\ntype ResolvedConnectionOptions = McpConnectionOptions &\r\n Required<Pick<McpConnectionOptions, 'initializationTimeoutMs' | 'requestTimeoutMs'>> & {\r\n onDiagnostic: McpDiagnosticSink;\r\n };\r\n\r\nfunction waitForProcessExit(child: ChildProcess, timeoutMs: number): Promise<boolean> {\r\n if (child.exitCode !== null || child.signalCode !== null) return Promise.resolve(true);\r\n return new Promise((resolve) => {\r\n let settled = false;\r\n const finish = (exited: boolean) => {\r\n if (settled) return;\r\n settled = true;\r\n clearTimeout(timer);\r\n child.removeListener('exit', onExit);\r\n resolve(exited);\r\n };\r\n const onExit = () => finish(true);\r\n const timer = setTimeout(() => finish(false), timeoutMs);\r\n timer.unref();\r\n child.once('exit', onExit);\r\n });\r\n}\r\n\r\nasync function terminateProcess(child: ChildProcess): Promise<void> {\r\n child.stdin?.end();\r\n if (child.exitCode === null && child.signalCode === null) child.kill();\r\n if (!(await waitForProcessExit(child, 250))) {\r\n child.kill('SIGKILL');\r\n await waitForProcessExit(child, 750);\r\n }\r\n child.stdin?.destroy();\r\n child.stdout?.destroy();\r\n child.stderr?.destroy();\r\n child.unref();\r\n}\r\n\r\n/**\r\n * Newline-delimited JSON-RPC transport over a child process this host spawns\r\n * and owns. Mirrors the SDK's stdio transport contract while keeping the\r\n * ChildProcess observable and the shutdown path deterministic.\r\n */\r\nclass StdioProcessTransport implements Transport {\r\n onclose?: () => void;\r\n onerror?: (error: Error) => void;\r\n onmessage?: (message: JSONRPCMessage) => void;\r\n\r\n private child?: ChildProcess;\r\n private readonly readBuffer = new ReadBuffer();\r\n private stderrTail = '';\r\n private closed = false;\r\n private cleanupListeners: () => void = () => {};\r\n protocolVersion?: string;\r\n\r\n constructor(\r\n private readonly name: string,\r\n private readonly config: McpServerConfig,\r\n private readonly options: {\r\n maxStderrBytes: number;\r\n onSpawn?: (child: ChildProcess) => void;\r\n },\r\n ) {}\r\n\r\n get process(): ChildProcess | undefined {\r\n return this.child;\r\n }\r\n\r\n get stderr(): string {\r\n return this.stderrTail;\r\n }\r\n\r\n setProtocolVersion(version: string): void {\r\n this.protocolVersion = version;\r\n }\r\n\r\n start(): Promise<void> {\r\n if (this.child) {\r\n return Promise.reject(new Error(`MCP server ${this.name} transport already started`));\r\n }\r\n if (!this.config.command) {\r\n return Promise.reject(new Error(`MCP server ${this.name} is not a stdio server`));\r\n }\r\n const child = spawn(this.config.command, this.config.args ?? [], {\r\n env: { ...process.env, ...this.config.env },\r\n cwd: this.config.cwd,\r\n stdio: ['pipe', 'pipe', 'pipe'],\r\n });\r\n this.child = child;\r\n this.options.onSpawn?.(child);\r\n\r\n const onStdoutData = (data: Buffer) => {\r\n this.readBuffer.append(data);\r\n while (true) {\r\n let message: JSONRPCMessage | null;\r\n try {\r\n message = this.readBuffer.readMessage();\r\n } catch (error) {\r\n // readMessage consumes the offending line before throwing, so the\r\n // loop always advances past malformed output.\r\n this.onerror?.(error instanceof Error ? error : new Error(String(error)));\r\n continue;\r\n }\r\n if (!message) break;\r\n this.onmessage?.(message);\r\n }\r\n };\r\n const onStderrData = (data: Buffer) => {\r\n this.stderrTail = (this.stderrTail + data.toString()).slice(-this.options.maxStderrBytes);\r\n };\r\n const onChildError = (error: Error) => {\r\n this.onerror?.(error);\r\n this.teardown();\r\n };\r\n // Swallowed here; write failures surface through the send() callback.\r\n const onStdinError = () => {};\r\n const onExit = () => this.teardown();\r\n const onClose = () => this.teardown();\r\n\r\n this.cleanupListeners = () => {\r\n child.stdout?.removeListener('data', onStdoutData);\r\n child.stderr?.removeListener('data', onStderrData);\r\n child.removeListener('error', onChildError);\r\n child.stdin?.removeListener('error', onStdinError);\r\n child.removeListener('exit', onExit);\r\n child.removeListener('close', onClose);\r\n this.cleanupListeners = () => {};\r\n };\r\n child.stdout?.on('data', onStdoutData);\r\n child.stderr?.on('data', onStderrData);\r\n child.once('error', onChildError);\r\n child.stdin?.on('error', onStdinError);\r\n child.once('exit', onExit);\r\n child.once('close', onClose);\r\n return Promise.resolve();\r\n }\r\n\r\n send(message: JSONRPCMessage): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const stdin = this.child?.stdin;\r\n if (this.closed || !stdin || stdin.destroyed) {\r\n reject(new Error(`MCP server ${this.name} stdin is closed`));\r\n return;\r\n }\r\n try {\r\n stdin.write(serializeMessage(message), (error) => {\r\n if (error) reject(error);\r\n else resolve();\r\n });\r\n } catch (error) {\r\n reject(error instanceof Error ? error : new Error(String(error)));\r\n }\r\n });\r\n }\r\n\r\n /** Child died or streams closed underneath us: settle pending work, then reap. */\r\n private teardown(): void {\r\n if (this.closed) return;\r\n this.closed = true;\r\n this.cleanupListeners();\r\n this.onclose?.();\r\n if (this.child) void terminateProcess(this.child).catch(() => {});\r\n }\r\n\r\n async close(): Promise<void> {\r\n if (this.closed) return;\r\n this.closed = true;\r\n this.cleanupListeners();\r\n // Reject pending requests before the (graceful, up to ~1s) process reap.\r\n this.onclose?.();\r\n if (this.child) await terminateProcess(this.child).catch(() => {});\r\n }\r\n}\r\n\r\nfunction isMcpErrorWithCode(error: unknown, code: ErrorCode): boolean {\r\n return error instanceof McpError && error.code === code;\r\n}\r\n\r\nfunction withStderrContext(message: string, transport: { stderr: string }): string {\r\n const tail = transport.stderr.trim();\r\n return tail ? `${message} (stderr: ${tail})` : message;\r\n}\r\n\r\nfunction createSecretRedactor(config: McpServerConfig): (message: string) => string {\r\n let queryValues: string[] = [];\r\n try {\r\n queryValues = config.url ? [...new URL(config.url).searchParams.values()] : [];\r\n } catch {\r\n // Explicit configs are validated by the transport path; redaction remains best effort.\r\n }\r\n const secrets = [\r\n ...Object.values(config.env ?? {}),\r\n ...Object.values(config.headers ?? {}),\r\n ...queryValues,\r\n ]\r\n .filter((value) => value.length > 0)\r\n .sort((left, right) => right.length - left.length);\r\n return (message) => {\r\n let redacted = message;\r\n for (const secret of secrets) redacted = redacted.replaceAll(secret, '<redacted>');\r\n return redacted;\r\n };\r\n}\r\n\r\ninterface McpContentBlock {\r\n type?: string;\r\n text?: string;\r\n mimeType?: string;\r\n uri?: string;\r\n resource?: { uri?: string; text?: string; mimeType?: string };\r\n}\r\n\r\n/** Flatten MCP content blocks into the plain-text tool output Book renders. */\r\nexport function renderMcpContent(result: Record<string, unknown>): {\r\n text: string;\r\n isError: boolean;\r\n} {\r\n const blocks = Array.isArray(result.content) ? (result.content as McpContentBlock[]) : [];\r\n const parts: string[] = [];\r\n for (const block of blocks) {\r\n if (!block || typeof block !== 'object') continue;\r\n switch (block.type) {\r\n case 'text':\r\n if (typeof block.text === 'string') parts.push(block.text);\r\n break;\r\n case 'image':\r\n case 'audio':\r\n parts.push(`[${block.type}${block.mimeType ? `: ${block.mimeType}` : ''}]`);\r\n break;\r\n case 'resource_link':\r\n parts.push(`[resource_link: ${block.uri ?? 'unknown'}]`);\r\n break;\r\n case 'resource': {\r\n const resource = block.resource;\r\n if (resource && typeof resource.text === 'string') parts.push(resource.text);\r\n else if (resource?.uri) {\r\n parts.push(\r\n `[resource: ${resource.uri}${resource.mimeType ? ` (${resource.mimeType})` : ''}]`,\r\n );\r\n }\r\n break;\r\n }\r\n default:\r\n break;\r\n }\r\n }\r\n if (parts.length === 0 && result.structuredContent !== undefined) {\r\n parts.push(JSON.stringify(result.structuredContent, null, 2));\r\n }\r\n return { text: parts.join('\\n'), isError: result.isError === true };\r\n}\r\n\r\nasync function listAllTools(\r\n client: Client,\r\n requestTimeoutMs: number,\r\n signal?: AbortSignal,\r\n): Promise<McpToolDef[]> {\r\n const tools: McpToolDef[] = [];\r\n let cursor: string | undefined;\r\n do {\r\n const page = await client.listTools(cursor ? { cursor } : undefined, {\r\n timeout: requestTimeoutMs,\r\n signal,\r\n });\r\n for (const tool of page.tools) {\r\n tools.push({\r\n name: tool.name,\r\n description: tool.description ?? '',\r\n inputSchema: (tool.inputSchema ?? { type: 'object', properties: {} }) as Record<\r\n string,\r\n unknown\r\n >,\r\n });\r\n }\r\n cursor = page.nextCursor;\r\n } while (cursor);\r\n return tools;\r\n}\r\n\r\ninterface LiveConnection extends McpConnection {\r\n requestCounter: number;\r\n redact: (message: string) => string;\r\n}\r\n\r\ntype OwnedTransport = Transport & {\r\n process?: ChildProcess;\r\n protocolVersion?: string;\r\n terminateSession?: () => Promise<void>;\r\n};\r\n\r\ninterface TransportHandle {\r\n transport: OwnedTransport;\r\n getStderr: () => string;\r\n getProtocolVersion: () => string | undefined;\r\n}\r\n\r\nfunction isRemoteConfig(config: McpServerConfig): boolean {\r\n return config.type === 'http' || config.type === 'sse' || Boolean(config.url && !config.command);\r\n}\r\n\r\nfunction createTransport(\r\n name: string,\r\n cfg: McpServerConfig,\r\n options: ResolvedConnectionOptions,\r\n): TransportHandle {\r\n if (isRemoteConfig(cfg)) {\r\n if (!cfg.url) throw new Error(`MCP server ${name} has no URL`);\r\n const url = new URL(cfg.url);\r\n const headers = { ...(cfg.headers ?? {}) };\r\n if (cfg.type === 'sse') {\r\n let protocolVersion: string | undefined;\r\n const transport = new SSEClientTransport(url, {\r\n // The SDK derives the SSE GET headers from requestInit too. Supplying\r\n // them here therefore covers both the initial stream and later POSTs.\r\n requestInit: { headers },\r\n });\r\n const sdkSetProtocolVersion = transport.setProtocolVersion.bind(transport);\r\n transport.setProtocolVersion = (version: string) => {\r\n protocolVersion = version;\r\n sdkSetProtocolVersion(version);\r\n };\r\n return {\r\n transport,\r\n getStderr: () => '',\r\n getProtocolVersion: () => protocolVersion,\r\n };\r\n }\r\n const transport = new StreamableHTTPClientTransport(url, {\r\n requestInit: { headers },\r\n });\r\n return {\r\n transport,\r\n getStderr: () => '',\r\n getProtocolVersion: () => transport.protocolVersion,\r\n };\r\n }\r\n\r\n const transport = new StdioProcessTransport(name, cfg, {\r\n maxStderrBytes: options.maxStderrBytes ?? DEFAULT_MAX_STDERR_BYTES,\r\n onSpawn: (child) => options.onProcessSpawn?.(name, child),\r\n });\r\n return {\r\n transport,\r\n getStderr: () => transport.stderr,\r\n getProtocolVersion: () => transport.protocolVersion,\r\n };\r\n}\r\n\r\n/**\r\n * Route `elicitation/create` to the host prompt. Anything Book cannot present\r\n * faithfully — URL mode, or a schema outside the renderable subset — is\r\n * declined, which is a protocol-legal answer the server already handles.\r\n */\r\nfunction registerElicitationHandler(\r\n client: Client,\r\n name: string,\r\n options: ResolvedConnectionOptions,\r\n): void {\r\n const onElicit = options.onElicit;\r\n if (!onElicit) return;\r\n let counter = 0;\r\n\r\n client.setRequestHandler(\r\n ElicitRequestSchema,\r\n async (request, extra): Promise<ElicitationResponse> => {\r\n const params = request.params;\r\n if (params.mode === 'url') {\r\n options.onDiagnostic({\r\n level: 'warn',\r\n message: `MCP server \"${name}\" requested URL elicitation, which Book does not support`,\r\n server: name,\r\n });\r\n return { action: 'decline' };\r\n }\r\n\r\n const converted = toElicitationFields(params.requestedSchema);\r\n if ('error' in converted) {\r\n options.onDiagnostic({\r\n level: 'warn',\r\n message: `Declined an elicitation from MCP server \"${name}\": ${converted.error}`,\r\n server: name,\r\n });\r\n return { action: 'decline' };\r\n }\r\n\r\n const response = await onElicit(\r\n {\r\n id: `${name}:${++counter}`,\r\n server: name,\r\n message: params.message,\r\n fields: converted.fields,\r\n },\r\n { signal: extra?.signal },\r\n );\r\n if (response.action !== 'accept') return { action: response.action };\r\n\r\n const validated = validateElicitationContent(converted.fields, response.content);\r\n if ('error' in validated) {\r\n options.onDiagnostic({\r\n level: 'warn',\r\n message: `Discarded an elicitation answer for MCP server \"${name}\": ${validated.error}`,\r\n server: name,\r\n });\r\n return { action: 'cancel' };\r\n }\r\n return { action: 'accept', content: validated.content };\r\n },\r\n );\r\n}\r\n\r\nasync function connectMcpServer(\r\n name: string,\r\n cfg: McpServerConfig,\r\n options: ResolvedConnectionOptions,\r\n): Promise<McpConnection | null> {\r\n let handle: TransportHandle | undefined;\r\n let liveConnection: LiveConnection | undefined;\r\n let transportClosed = false;\r\n const redact = createSecretRedactor(cfg);\r\n\r\n try {\r\n handle = createTransport(name, cfg, options);\r\n const { transport, getStderr, getProtocolVersion } = handle;\r\n // Protocol.connect wraps these callbacks and preserves the callbacks that\r\n // were installed first. Keep the host's lifecycle state in that preserved\r\n // callback so a remote disconnect or a child exit removes stale tools from\r\n // the next provider request.\r\n transport.onclose = () => {\r\n transportClosed = true;\r\n if (!liveConnection || liveConnection.closed) return;\r\n liveConnection.closed = true;\r\n options.onConnectionClosed?.(name);\r\n };\r\n transport.onerror = (error) => {\r\n options.onDiagnostic({\r\n level: 'warn',\r\n message: redact(`MCP server \"${name}\" transport error: ${error.message}`),\r\n server: name,\r\n });\r\n };\r\n const client = new Client(\r\n { name: 'book', version: getPackageVersion() },\r\n { capabilities: options.onElicit ? { elicitation: { form: {} } } : {} },\r\n );\r\n registerElicitationHandler(client, name, options);\r\n\r\n await client.connect(transport, {\r\n timeout: options.initializationTimeoutMs,\r\n signal: options.signal,\r\n });\r\n const supportsTools = client.getServerCapabilities()?.tools !== undefined;\r\n const tools = supportsTools\r\n ? await listAllTools(client, options.requestTimeoutMs, options.signal)\r\n : [];\r\n if (transportClosed) throw new Error('connection closed during initialization');\r\n\r\n const conn: LiveConnection = {\r\n name,\r\n client,\r\n process: transport.process,\r\n tools,\r\n pending: new Map(),\r\n closed: false,\r\n requestCounter: 0,\r\n redact,\r\n get stderr() {\r\n return redact(getStderr());\r\n },\r\n protocolVersion: getProtocolVersion(),\r\n serverInfo: client.getServerVersion(),\r\n capabilities: client.getServerCapabilities() as Record<string, unknown> | undefined,\r\n async close() {\r\n try {\r\n await transport.terminateSession?.();\r\n } catch (error) {\r\n options.onDiagnostic({\r\n level: 'warn',\r\n message: redact(\r\n `Failed to terminate MCP server \"${name}\" session: ${error instanceof Error ? error.message : String(error)}`,\r\n ),\r\n server: name,\r\n });\r\n } finally {\r\n await client.close();\r\n }\r\n },\r\n };\r\n liveConnection = conn;\r\n\r\n if (supportsTools) {\r\n let refreshing = false;\r\n client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {\r\n if (refreshing || conn.closed) return;\r\n refreshing = true;\r\n try {\r\n conn.tools = await listAllTools(client, options.requestTimeoutMs);\r\n options.onToolListChanged?.(name);\r\n } catch (error) {\r\n options.onDiagnostic({\r\n level: 'warn',\r\n message: redact(\r\n `Failed to refresh tools for MCP server \"${name}\": ${error instanceof Error ? error.message : String(error)}`,\r\n ),\r\n server: name,\r\n });\r\n } finally {\r\n refreshing = false;\r\n }\r\n });\r\n }\r\n\r\n return conn;\r\n } catch (error) {\r\n const message = redact(error instanceof Error ? error.message : String(error));\r\n options.onDiagnostic({\r\n level: 'warn',\r\n message: withStderrContext(`Failed to connect to MCP server \"${name}\": ${message}`, {\r\n stderr: redact(handle?.getStderr() ?? ''),\r\n }),\r\n server: name,\r\n });\r\n if (handle?.transport.terminateSession) {\r\n await handle.transport.terminateSession().catch(() => {});\r\n }\r\n await handle?.transport.close().catch(() => {});\r\n return null;\r\n }\r\n}\r\n\r\nfunction buildToolDefinition(\r\n conn: McpConnection,\r\n tool: McpToolDef,\r\n requestTimeoutMs: number,\r\n): ToolDefinition {\r\n const prefixedName = `mcp__${conn.name}__${tool.name}`;\r\n const live = conn as LiveConnection;\r\n return {\r\n name: prefixedName,\r\n description: `[MCP:${conn.name}] ${tool.description || tool.name}`,\r\n parameters: tool.inputSchema || { type: 'object', properties: {} },\r\n execute: async (args: Record<string, unknown>, ctx: ToolContext) => {\r\n const requestId = ++live.requestCounter;\r\n conn.pending.set(requestId, { method: tool.name });\r\n try {\r\n const result = await conn.client.callTool({ name: tool.name, arguments: args }, undefined, {\r\n timeout: requestTimeoutMs,\r\n resetTimeoutOnProgress: true,\r\n signal: ctx.signal,\r\n });\r\n const rendered = renderMcpContent(result as Record<string, unknown>);\r\n if (rendered.isError) {\r\n return toolFailure(\r\n `MCP tool ${prefixedName} failed: ${rendered.text || 'the server reported an error'}`,\r\n { code: 'mcp_tool_error', content: rendered.text },\r\n );\r\n }\r\n return toolSuccess(rendered.text, { data: result });\r\n } catch (error) {\r\n let message: string;\r\n if (ctx.signal?.aborted) {\r\n message = `MCP request aborted: ${tool.name}`;\r\n } else if (conn.closed && isMcpErrorWithCode(error, ErrorCode.ConnectionClosed)) {\r\n message = `MCP server ${conn.name} disconnected`;\r\n } else {\r\n message = live.redact(error instanceof Error ? error.message : String(error));\r\n }\r\n const tail = conn.stderr.trim();\r\n return toolFailure(\r\n `MCP tool ${prefixedName} failed: ${message}${tail ? ` (stderr: ${tail})` : ''}`,\r\n { code: 'mcp_tool_failed' },\r\n );\r\n } finally {\r\n conn.pending.delete(requestId);\r\n }\r\n },\r\n };\r\n}\r\n\r\n/** Current tool definitions for live connections; hosts rebuild per turn to pick up list changes. */\r\nexport function buildMcpToolDefinitions(\r\n connections: McpConnection[],\r\n requestTimeoutMs: number = DEFAULT_REQUEST_TIMEOUT_MS,\r\n): ToolDefinition[] {\r\n const tools: ToolDefinition[] = [];\r\n for (const conn of connections) {\r\n if (conn.closed) continue;\r\n for (const tool of conn.tools) tools.push(buildToolDefinition(conn, tool, requestTimeoutMs));\r\n }\r\n return tools;\r\n}\r\n\r\nexport async function connectMcpServers(\r\n workspace: string,\r\n options: McpConnectionOptions = {},\r\n): Promise<{ connections: McpConnection[]; tools: ToolDefinition[] }> {\r\n const resolved: ResolvedConnectionOptions = {\r\n ...options,\r\n initializationTimeoutMs: options.initializationTimeoutMs ?? DEFAULT_INITIALIZATION_TIMEOUT_MS,\r\n requestTimeoutMs: options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\r\n onDiagnostic: options.onDiagnostic ?? consoleMcpDiagnosticSink,\r\n };\r\n let servers: Array<{ name: string; config: McpServerConfig }>;\r\n if (options.servers) {\r\n servers = Object.entries(options.servers).map(([name, config]) => ({ name, config }));\r\n } else {\r\n // No caller-supplied subset means no host evaluated project-server\r\n // approval, so repository-controlled servers cannot be trusted here.\r\n // Fail closed: connect user-scoped servers only and name what was skipped.\r\n const declared = resolveMcpServerList(workspace, {\r\n home: options.home,\r\n onDiagnostic: resolved.onDiagnostic,\r\n });\r\n for (const server of declared) {\r\n if (server.source === 'user') continue;\r\n resolved.onDiagnostic({\r\n level: 'warn',\r\n message: `Skipping project-declared MCP server \"${server.name}\" (${server.path}): it requires approval, and this caller supplied no approved server list.`,\r\n server: server.name,\r\n });\r\n }\r\n servers = declared.filter((server) => server.source === 'user');\r\n }\r\n\r\n const results = await Promise.allSettled(\r\n servers.map(({ name, config }) => connectMcpServer(name, config, resolved)),\r\n );\r\n const connections: McpConnection[] = [];\r\n for (const [index, result] of results.entries()) {\r\n if (result.status === 'rejected') {\r\n const server = servers[index];\r\n resolved.onDiagnostic({\r\n level: 'warn',\r\n message: `Failed to connect to MCP server \"${server.name}\": ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`,\r\n server: server.name,\r\n });\r\n continue;\r\n }\r\n if (!result.value) continue;\r\n connections.push(result.value);\r\n }\r\n return { connections, tools: buildMcpToolDefinitions(connections, resolved.requestTimeoutMs) };\r\n}\r\n\r\nexport async function disconnectMcpServers(connections: McpConnection[]): Promise<void> {\r\n const closing = connections.map(async (conn) => {\r\n if (conn.closed) return;\r\n conn.closed = true;\r\n await conn.close().catch(() => {});\r\n });\r\n await Promise.all(closing);\r\n}\r\n","/**\r\n * What a non-interactive host says about repository-declared configuration the\r\n * resolver withheld.\r\n *\r\n * Project-declared allow rules and hook entries need a one-time decision from\r\n * the user. Print and SDK runs cannot ask for one, so they report what they are\r\n * skipping and continue — otherwise the only symptom is a hook that silently\r\n * never fires. The two hosts said the same thing in the same twenty lines, and\r\n * each re-read and re-parsed `.book/settings.json` once per gate; the notice\r\n * lives here so there is one wording and one read.\r\n */\r\nimport { join } from 'path';\r\nimport { collectDeclaredHooks, partitionProjectHooks } from './hook-approvals.js';\r\nimport { partitionProjectAllowRules } from './permission-approvals.js';\r\nimport { loadSettingsFile } from './settings-loader.js';\r\nimport type { ResolvedSettings } from './settings.js';\r\n\r\nexport interface WithheldProjectDeclarations {\r\n workspace: string;\r\n settings: ResolvedSettings;\r\n /** False under `--no-settings`, where no layer was read in the first place. */\r\n settingsEnabled: boolean;\r\n}\r\n\r\n/**\r\n * One warning per withheld declaration, in the order a host should print them.\r\n *\r\n * Empty under `--no-settings`: nothing was withheld for want of approval there,\r\n * because no settings layer was read at all. Reporting a pending approval then\r\n * would send the user after a decision that changes nothing — and, since the\r\n * decision store is the empty default too, would also announce hooks the user\r\n * has already approved as if they were awaiting a first decision.\r\n */\r\nexport function collectWithheldProjectNotices(input: WithheldProjectDeclarations): string[] {\r\n if (!input.settingsEnabled) return [];\r\n\r\n const projectSettings = loadSettingsFile(join(input.workspace, '.book', 'settings.json'));\r\n const notices: string[] = [];\r\n\r\n const allow = partitionProjectAllowRules(\r\n projectSettings?.permissions?.allow ?? [],\r\n input.settings.permissions.projectAllowRules,\r\n );\r\n for (const rule of allow.pending) {\r\n notices.push(\r\n `⚠ Ignoring project-declared permission rule \"${rule}\": it requires approval. Run \\`book doctor\\` to see how to grant it.`,\r\n );\r\n }\r\n\r\n const hooks = partitionProjectHooks(\r\n collectDeclaredHooks(projectSettings),\r\n input.settings.hooks.projectEntries,\r\n );\r\n if (hooks.pending.length > 0) {\r\n const byEvent = new Map<string, number>();\r\n for (const hook of hooks.pending) {\r\n byEvent.set(hook.event, (byEvent.get(hook.event) ?? 0) + 1);\r\n }\r\n const summary = [...byEvent].map(([event, count]) => `${event} x${count}`).join(', ');\r\n notices.push(\r\n `⚠ Ignoring ${hooks.pending.length} project-declared hook(s) (${summary}):` +\r\n ' hooks require approval. Run `book doctor` to approve them.',\r\n );\r\n }\r\n\r\n return notices;\r\n}\r\n"],"mappings":"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","names":["result","outcome","transport","join","join"]}