@letrquan/book 0.2.0 → 0.4.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3771 -40
- package/README.md +135 -1311
- package/dist/additional-roots-VAWRQ625.js +32 -0
- package/dist/{app-MOXXWEOY.js → app-J7BVPSUH.js} +9648 -5509
- package/dist/app-J7BVPSUH.js.map +1 -0
- package/dist/chunk-2AAOF5B5.js +28 -0
- package/dist/chunk-2AAOF5B5.js.map +1 -0
- package/dist/chunk-32WBCUAN.js +660 -0
- package/dist/chunk-32WBCUAN.js.map +1 -0
- package/dist/chunk-4DKHLZRI.js +120 -0
- package/dist/chunk-4DKHLZRI.js.map +1 -0
- package/dist/{chunk-CAGOB2N4.js → chunk-62EEAUID.js} +6 -4
- package/dist/chunk-62EEAUID.js.map +1 -0
- package/dist/chunk-AHC7OU75.js +1124 -0
- package/dist/chunk-AHC7OU75.js.map +1 -0
- package/dist/{chunk-E75IPST5.js → chunk-AJZWLKLQ.js} +73 -70
- package/dist/chunk-AJZWLKLQ.js.map +1 -0
- package/dist/chunk-B5FC3MYZ.js +395 -0
- package/dist/chunk-B5FC3MYZ.js.map +1 -0
- package/dist/{chunk-KWHQ2XXL.js → chunk-DNFQTSMJ.js} +55 -13
- package/dist/chunk-DNFQTSMJ.js.map +1 -0
- package/dist/{chunk-J7MIZ5CA.js → chunk-E5WLQSKA.js} +719 -89
- package/dist/chunk-E5WLQSKA.js.map +1 -0
- package/dist/chunk-ECLC4CIJ.js +1181 -0
- package/dist/chunk-ECLC4CIJ.js.map +1 -0
- package/dist/chunk-EEX6QNXV.js +127 -0
- package/dist/chunk-EEX6QNXV.js.map +1 -0
- package/dist/chunk-EFXVSQ5J.js +931 -0
- package/dist/chunk-EFXVSQ5J.js.map +1 -0
- package/dist/{chunk-V4BOYR52.js → chunk-ENLB7NYV.js} +1304 -326
- package/dist/chunk-ENLB7NYV.js.map +1 -0
- package/dist/chunk-FPR7SKIE.js +6926 -0
- package/dist/chunk-FPR7SKIE.js.map +1 -0
- package/dist/{chunk-DGMQEI6Y.js → chunk-HFB74CLM.js} +30 -9
- package/dist/chunk-HFB74CLM.js.map +1 -0
- package/dist/{chunk-5RDRAO4B.js → chunk-HOZXKOE3.js} +37 -1
- package/dist/chunk-HOZXKOE3.js.map +1 -0
- package/dist/chunk-IDYWN37T.js +36 -0
- package/dist/chunk-IDYWN37T.js.map +1 -0
- package/dist/chunk-J4F2QLM2.js +273 -0
- package/dist/chunk-J4F2QLM2.js.map +1 -0
- package/dist/chunk-JGF5HLSI.js +1065 -0
- package/dist/chunk-JGF5HLSI.js.map +1 -0
- package/dist/{chunk-XIFFTATU.js → chunk-KDNWMKXV.js} +7166 -4237
- package/dist/chunk-KDNWMKXV.js.map +1 -0
- package/dist/chunk-KXAYUIKP.js +90 -0
- package/dist/chunk-KXAYUIKP.js.map +1 -0
- package/dist/{chunk-3U5IBM24.js → chunk-MEOB2DZA.js} +12 -2
- package/dist/chunk-MEOB2DZA.js.map +1 -0
- package/dist/{chunk-WKBO5R4O.js → chunk-MV5PQNIA.js} +2 -2
- package/dist/chunk-MV5PQNIA.js.map +1 -0
- package/dist/chunk-N2G4Q7ME.js +2672 -0
- package/dist/chunk-N2G4Q7ME.js.map +1 -0
- package/dist/chunk-OJBMDM5H.js +299 -0
- package/dist/chunk-OJBMDM5H.js.map +1 -0
- package/dist/{chunk-URLQAXTR.js → chunk-PTDC7ZUP.js} +2 -2
- package/dist/chunk-PTDC7ZUP.js.map +1 -0
- package/dist/{chunk-574C6MQR.js → chunk-REASC2QG.js} +173 -64
- package/dist/chunk-REASC2QG.js.map +1 -0
- package/dist/{chunk-7N4J557C.js → chunk-RT5SATF7.js} +1 -1
- package/dist/chunk-RT5SATF7.js.map +1 -0
- package/dist/chunk-SBTU5BEC.js +114 -0
- package/dist/chunk-SBTU5BEC.js.map +1 -0
- package/dist/{chunk-5KLVH3PY.js → chunk-SWPDKLNM.js} +5 -3
- package/dist/chunk-SWPDKLNM.js.map +1 -0
- package/dist/chunk-UCFJ43OS.js +520 -0
- package/dist/chunk-UCFJ43OS.js.map +1 -0
- package/dist/{chunk-VZQXX3WW.js → chunk-W7SLYS3M.js} +80 -16
- package/dist/chunk-W7SLYS3M.js.map +1 -0
- package/dist/{chunk-ANSJPYGI.js → chunk-WV3O5PGX.js} +3 -3
- package/dist/chunk-WV3O5PGX.js.map +1 -0
- package/dist/chunk-XHAO3K7I.js +18 -0
- package/dist/chunk-XHAO3K7I.js.map +1 -0
- package/dist/chunk-XJRJVXJR.js +1050 -0
- package/dist/chunk-XJRJVXJR.js.map +1 -0
- package/dist/chunk-YIL6HTJX.js +663 -0
- package/dist/chunk-YIL6HTJX.js.map +1 -0
- package/dist/{chunk-24AXE6SP.js → chunk-ZPSZZUWF.js} +1 -1
- package/dist/chunk-ZPSZZUWF.js.map +1 -0
- package/dist/{command-approvals-6Y57VCWZ.js → command-approvals-ZRY66LCW.js} +7 -5
- package/dist/context-C3RAP6K5.js +41 -0
- package/dist/{hook-approvals-CTUFKEJT.js → hook-approvals-DPQD5H65.js} +6 -5
- package/dist/index.js +947 -203
- package/dist/index.js.map +1 -1
- package/dist/{interactive-assets-CCAAWVKH.js → interactive-assets-73AQO5WP.js} +18 -9
- package/dist/interactive-assets-73AQO5WP.js.map +1 -0
- package/dist/job-runner.js +166 -111
- package/dist/job-runner.js.map +1 -1
- package/dist/job-supervisor.d.ts +2 -0
- package/dist/job-supervisor.js +121 -0
- package/dist/job-supervisor.js.map +1 -0
- package/dist/loader-DQNPDKOX.js +27 -0
- package/dist/{mcp-approvals-WNPH65BK.js → mcp-approvals-27LJYADQ.js} +6 -5
- package/dist/{mcp-config-YIJIES2C.js → mcp-config-GXSODNCM.js} +4 -3
- package/dist/memory-store-I6Z54VUN.js +51 -0
- package/dist/{model-window-store-YFVNXCIP.js → model-window-store-6VKXXTPJ.js} +9 -4
- package/dist/openai-compatible-IPUNBJ53.js +16 -0
- package/dist/permission-approvals-Q5IMFEZI.js +15 -0
- package/dist/permissions-7Y35X6HZ.js +62 -0
- package/dist/provider-approvals-5AGH3RVT.js +76 -0
- package/dist/sandbox-N2RY72GN.js +42 -0
- package/dist/{scrollback-LUKLIBVI.js → scrollback-GD76GNM4.js} +44 -26
- package/dist/scrollback-GD76GNM4.js.map +1 -0
- package/dist/sdk.d.ts +2739 -2069
- package/dist/sdk.js +77 -42
- package/dist/sdk.js.map +1 -1
- package/dist/settings-loader-KDBH45AQ.js +43 -0
- package/dist/settings-loader-KDBH45AQ.js.map +1 -0
- package/dist/{settings-removed-JWWPT4WA.js → settings-removed-3ATWJEF3.js} +2 -2
- package/dist/settings-removed-3ATWJEF3.js.map +1 -0
- package/dist/shell-selection-Z5WORZU4.js +31 -0
- package/dist/shell-selection-Z5WORZU4.js.map +1 -0
- package/package.json +25 -24
- package/dist/app-MOXXWEOY.js.map +0 -1
- package/dist/chunk-24AXE6SP.js.map +0 -1
- package/dist/chunk-3U5IBM24.js.map +0 -1
- package/dist/chunk-574C6MQR.js.map +0 -1
- package/dist/chunk-5GDZ22YP.js +0 -449
- package/dist/chunk-5GDZ22YP.js.map +0 -1
- package/dist/chunk-5KLVH3PY.js.map +0 -1
- package/dist/chunk-5RDRAO4B.js.map +0 -1
- package/dist/chunk-7N4J557C.js.map +0 -1
- package/dist/chunk-A7JLBK2Y.js +0 -3506
- package/dist/chunk-A7JLBK2Y.js.map +0 -1
- package/dist/chunk-ANSJPYGI.js.map +0 -1
- package/dist/chunk-BTZZUCLI.js +0 -264
- package/dist/chunk-BTZZUCLI.js.map +0 -1
- package/dist/chunk-C7D4NJ2D.js +0 -217
- package/dist/chunk-C7D4NJ2D.js.map +0 -1
- package/dist/chunk-CAGOB2N4.js.map +0 -1
- package/dist/chunk-DGMQEI6Y.js.map +0 -1
- package/dist/chunk-E75IPST5.js.map +0 -1
- package/dist/chunk-EYGD6X2T.js +0 -180
- package/dist/chunk-EYGD6X2T.js.map +0 -1
- package/dist/chunk-GTVB4HEM.js +0 -765
- package/dist/chunk-GTVB4HEM.js.map +0 -1
- package/dist/chunk-J7MIZ5CA.js.map +0 -1
- package/dist/chunk-KWHQ2XXL.js.map +0 -1
- package/dist/chunk-L6LK2QIQ.js +0 -657
- package/dist/chunk-L6LK2QIQ.js.map +0 -1
- package/dist/chunk-MAQXCUR4.js +0 -1007
- package/dist/chunk-MAQXCUR4.js.map +0 -1
- package/dist/chunk-S4XL7HOM.js +0 -402
- package/dist/chunk-S4XL7HOM.js.map +0 -1
- package/dist/chunk-URLQAXTR.js.map +0 -1
- package/dist/chunk-V4BOYR52.js.map +0 -1
- package/dist/chunk-VZQXX3WW.js.map +0 -1
- package/dist/chunk-WKBO5R4O.js.map +0 -1
- package/dist/chunk-XIFFTATU.js.map +0 -1
- package/dist/context-ZC5IFEAX.js +0 -25
- package/dist/interactive-assets-CCAAWVKH.js.map +0 -1
- package/dist/loader-4IDS2RIE.js +0 -15
- package/dist/openai-compatible-RHZUBHV6.js +0 -10
- package/dist/permission-approvals-76PVREFD.js +0 -14
- package/dist/permissions-CHCKTFQQ.js +0 -28
- package/dist/sandbox-CNVAQDA7.js +0 -23
- package/dist/scrollback-LUKLIBVI.js.map +0 -1
- package/dist/settings-loader-M2QP5TX2.js +0 -21
- package/dist/shell-selection-V6QAYXPX.js +0 -17
- package/patches/ink+6.8.0.patch +0 -13
- package/scripts/apply-ink-patch.mjs +0 -29
- package/scripts/ink-patch.mjs +0 -59
- package/scripts/verify-ink-patch.mjs +0 -11
- /package/dist/{command-approvals-6Y57VCWZ.js.map → additional-roots-VAWRQ625.js.map} +0 -0
- /package/dist/{context-ZC5IFEAX.js.map → command-approvals-ZRY66LCW.js.map} +0 -0
- /package/dist/{hook-approvals-CTUFKEJT.js.map → context-C3RAP6K5.js.map} +0 -0
- /package/dist/{loader-4IDS2RIE.js.map → hook-approvals-DPQD5H65.js.map} +0 -0
- /package/dist/{mcp-approvals-WNPH65BK.js.map → loader-DQNPDKOX.js.map} +0 -0
- /package/dist/{mcp-config-YIJIES2C.js.map → mcp-approvals-27LJYADQ.js.map} +0 -0
- /package/dist/{model-window-store-YFVNXCIP.js.map → mcp-config-GXSODNCM.js.map} +0 -0
- /package/dist/{openai-compatible-RHZUBHV6.js.map → memory-store-I6Z54VUN.js.map} +0 -0
- /package/dist/{permission-approvals-76PVREFD.js.map → model-window-store-6VKXXTPJ.js.map} +0 -0
- /package/dist/{permissions-CHCKTFQQ.js.map → openai-compatible-IPUNBJ53.js.map} +0 -0
- /package/dist/{sandbox-CNVAQDA7.js.map → permission-approvals-Q5IMFEZI.js.map} +0 -0
- /package/dist/{settings-loader-M2QP5TX2.js.map → permissions-7Y35X6HZ.js.map} +0 -0
- /package/dist/{settings-removed-JWWPT4WA.js.map → provider-approvals-5AGH3RVT.js.map} +0 -0
- /package/dist/{shell-selection-V6QAYXPX.js.map → sandbox-N2RY72GN.js.map} +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime-env.ts","../src/index.ts","../src/cli/status-cmd.ts","../src/cli/exit.ts","../src/cli/doctor.ts","../src/agents/diagnostics.ts","../src/cli/tool-stats.ts","../src/cli/config-cmd.ts","../src/cli/trust-cmd.ts","../src/cli/run.ts","../src/mcp-host.ts","../src/rewind/snapshot-store.ts","../src/rewind/environment.ts","../src/cli/ink-patch.ts","../src/cli/tui-renderer-mode.ts","../src/cli/mcp.ts"],"sourcesContent":["/**\r\n * Default NODE_ENV to \"production\" before any dependency loads.\r\n *\r\n * React and react-reconciler pick their development or production build from\r\n * NODE_ENV at import time. A CLI normally runs with NODE_ENV unset, which\r\n * silently loads the development renderer — 2-3x slower per render pass.\r\n * This must be the first import of the CLI entry so it runs before ink/react\r\n * are evaluated. An explicitly set NODE_ENV always wins.\r\n */\r\nif (!process.env.NODE_ENV) {\r\n process.env.NODE_ENV = 'production';\r\n}\r\n\r\nexport {};\r\n","#!/usr/bin/env node\r\nimport './runtime-env.js';\r\nimport { InvalidArgumentError, program } from 'commander';\r\nimport { EFFORT_LEVELS, isEffortLevel } from './commands/effort.js';\r\nimport { runStatusCommand } from './cli/status-cmd.js';\r\nimport { exit } from './cli/exit.js';\r\nimport { runDoctorCommand } from './cli/doctor.js';\r\nimport { runToolStatsCommand } from './cli/tool-stats.js';\r\nimport { runConfigCommand } from './cli/config-cmd.js';\r\nimport { runTrustCommand } from './cli/trust-cmd.js';\r\nimport { runMainAction } from './cli/run.js';\r\nimport { getPackageVersion } from './version-info.js';\r\nimport { formatSettingsKeyHelp } from './settings-repository.js';\r\nimport {\r\n runMcpAddCommand,\r\n runMcpGetCommand,\r\n runMcpListCommand,\r\n runMcpRemoveCommand,\r\n} from './cli/mcp.js';\r\n\r\nfunction collectOption(value: string, previous: string[]): string[] {\r\n return [...previous, value];\r\n}\r\n\r\n/**\r\n * Reject a bad effort level at parse time, where commander can name the option.\r\n * Reaching the provider with an unchecked level costs a round trip and returns\r\n * an opaque HTTP 400 for a mistake stated precisely here.\r\n */\r\nfunction parseEffortOption(value: string): string {\r\n const normalized = value.trim().toLowerCase();\r\n if (!isEffortLevel(normalized)) {\r\n throw new InvalidArgumentError(`Valid levels: ${EFFORT_LEVELS.join(', ')}.`);\r\n }\r\n return normalized;\r\n}\r\n\r\n/**\r\n * Resolve the workspace a subcommand should act on.\r\n *\r\n * The root and every subcommand declare -w/--workspace, and positional option\r\n * parsing hands each placement to a different command object: `book -w X sub`\r\n * is parsed by the root, `book sub -w X` by the subcommand, and neither can see\r\n * the other's value. Defaulting the subcommand option to process.cwd() made an\r\n * unset one indistinguishable from a deliberate `.`, so a root-side flag was\r\n * silently overridden and the command acted on the current directory while\r\n * reporting the flagged path. Leaving the subcommand option undefaulted lets an\r\n * unset one fall through to the root, which still carries the cwd default.\r\n */\r\nfunction resolveWorkspace(workspace: string | undefined): string {\r\n return workspace ?? (program.opts().workspace as string);\r\n}\r\n\r\nprogram\r\n .name('book')\r\n .description('AI coding agent with rich TUI')\r\n // Root and subcommands both declare -w/--workspace. Without positional\r\n // option parsing, commander 15 routes a -w that follows a subcommand to the\r\n // root command, leaving the subcommand on its process.cwd() default: every\r\n // `book <subcommand> --workspace <path>` silently acted on the wrong\r\n // directory, and `book config set` wrote settings into the current one.\r\n // The other placement is handled by resolveWorkspace(); positional parsing\r\n // also means a root option written after a subcommand name is an error, so\r\n // any root option a subcommand's action reads must be re-declared on it.\r\n .enablePositionalOptions()\r\n .version(getPackageVersion())\r\n .option('-w, --workspace <path>', 'Workspace root directory', process.cwd())\r\n .option('-m, --model <model>', 'Model to use')\r\n .option(\r\n '-p, --print [prompt]',\r\n 'Print mode (non-interactive). Reads prompt from the flag or stdin.',\r\n )\r\n .option('--output-format <format>', 'text | json | stream-json (print mode)', 'text')\r\n .option('--input-format <format>', 'text | stream-json (print mode)', 'text')\r\n .option('--max-turns <n>', 'Max agent turns (print mode; omit for unlimited)')\r\n .option('--max-budget-usd <amount>', 'Max USD spend (print mode)')\r\n .option(\r\n '--permission-mode <mode>',\r\n 'default | acceptEdits | plan | auto | dontAsk | bypassPermissions (overrides settings.defaultMode)',\r\n )\r\n .option('--verbose', 'Full turn-by-turn output')\r\n .option('--json-schema <schema>', 'Return validated JSON matching a JSON Schema (print mode)')\r\n .option('-r, --resume <id|name>', 'Resume a session by id or name')\r\n .option('-c, --continue', 'Resume the most recent session in this directory')\r\n .option('--session-id <uuid>', 'Use a specific session id')\r\n .option('-n, --name <name>', 'Set a display name for the session')\r\n .option('--no-session-persistence', 'Do not save the session to disk')\r\n .option('--fork-session', 'On resume, create a new session id instead of reusing')\r\n .option('--include-hook-events', 'Emit hook lifecycle events in stream-json output')\r\n .option('--include-partial-messages', 'Emit partial assistant text deltas in stream-json output')\r\n .option('--prompt-suggestions', 'Ask model for follow-up prompt suggestions after completion')\r\n .option('--agents <mode>', 'Managed agents: adaptive, manual, off')\r\n .option('--scrollback', 'Use terminal-native scrollback instead of the full-screen TUI')\r\n .option('--settings <path>', 'Path to an ad-hoc settings file (overrides all scopes)')\r\n .option('--no-settings', 'Skip all settings.json layers (use defaults + legacy .bookrc.json)')\r\n // No commander default: \"the user passed --effort\" has to stay observable, or\r\n // the flag cannot be told apart from the fallback and can never count as an\r\n // explicit choice. `high` is still the fallback, resolved in loadConfig after\r\n // BOOK_EFFORT, settings.effort, and model metadata have had their turn.\r\n .option(\r\n '--effort <level>',\r\n 'Thinking effort: low, medium, high, xhigh, max (default: high)',\r\n parseEffortOption,\r\n )\r\n .option('--provider <type>', 'Provider: anthropic, openai, auto (default: auto-detect)');\r\n\r\n// ---- book doctor ----\r\nprogram\r\n .command('doctor')\r\n .description('Diagnose configuration and environment')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n // Doctor exists for a configuration that does not work, so it needs the way\r\n // past one that will not even load. Positional option parsing means a root\r\n // option written after a subcommand is an error, so it is re-declared here.\r\n .option('--no-settings', 'Skip all settings.json layers (use defaults + legacy .bookrc.json)')\r\n .action(async (options: { workspace?: string; settings?: boolean }) => {\r\n await runDoctorCommand(resolveWorkspace(options.workspace), {\r\n noSettings: options.settings === false,\r\n });\r\n });\r\n\r\n// ---- book status ----\r\nprogram\r\n .command('status')\r\n .description('Report what a session is working on and what it has spent (no credentials needed)')\r\n .argument('[session]', 'Session id or name (defaults to the most recent in this workspace)')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--json', 'Emit the status as JSON')\r\n .action((session: string | undefined, options: { workspace?: string; json?: boolean }) => {\r\n const code = runStatusCommand({\r\n session,\r\n workspace: resolveWorkspace(options.workspace),\r\n json: options.json,\r\n });\r\n if (code !== 0) exit(code);\r\n });\r\n\r\n// ---- book tool-stats ----\r\nprogram\r\n .command('tool-stats')\r\n .description(\r\n 'Inspect and measure tool use recorded across sessions (fail counts, rates, durations)',\r\n )\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--json', 'Emit the aggregate as JSON')\r\n .option('--since <days>', 'Only include records from the last N days')\r\n .option('--all', 'Include the full history, ignoring the retention window')\r\n .option('--prune', 'Drop records older than the window from disk before reporting')\r\n .action(\r\n async (options: {\r\n workspace?: string;\r\n json?: boolean;\r\n since?: string;\r\n all?: boolean;\r\n prune?: boolean;\r\n }) => {\r\n await runToolStatsCommand({ ...options, workspace: resolveWorkspace(options.workspace) });\r\n },\r\n );\r\n\r\n// ---- book mcp ----\r\nconst mcpCommand = program.command('mcp').description('Manage MCP server configurations');\r\n\r\nmcpCommand\r\n .command('list')\r\n .description('List resolved MCP servers without revealing secret values')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--json', 'Emit JSON')\r\n .action((options: { workspace?: string; json?: boolean }) =>\r\n runMcpListCommand({ ...options, workspace: resolveWorkspace(options.workspace) }),\r\n );\r\n\r\nmcpCommand\r\n .command('get')\r\n .description('Show one resolved MCP server without revealing secret values')\r\n .argument('<name>', 'Server name')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--json', 'Emit JSON')\r\n .action((name: string, options: { workspace?: string; json?: boolean }) =>\r\n runMcpGetCommand(name, { ...options, workspace: resolveWorkspace(options.workspace) }),\r\n );\r\n\r\nmcpCommand\r\n .command('add')\r\n .description('Add an MCP server (use -- before stdio arguments that start with a dash)')\r\n .argument('<name>', 'Server name')\r\n .argument('<command-or-url>', 'Stdio executable or HTTP/SSE URL')\r\n .argument('[server-args...]', 'Arguments for a stdio server')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--scope <scope>', 'user | project', 'user')\r\n .option('--transport <type>', 'stdio | http | sse')\r\n .option('-e, --env <KEY=VALUE>', 'Stdio environment entry (repeatable)', collectOption, [])\r\n .option('-H, --header <KEY=VALUE>', 'HTTP header (repeatable)', collectOption, [])\r\n .option('--cwd <path>', 'Working directory for a stdio server')\r\n .option('--force', 'Replace an existing same-scope server')\r\n .action(\r\n (\r\n name: string,\r\n target: string,\r\n serverArgs: string[],\r\n options: {\r\n workspace?: string;\r\n scope: 'user' | 'project';\r\n transport?: 'stdio' | 'http' | 'sse';\r\n env: string[];\r\n header: string[];\r\n cwd?: string;\r\n force?: boolean;\r\n },\r\n ) =>\r\n runMcpAddCommand(name, target, serverArgs, {\r\n ...options,\r\n workspace: resolveWorkspace(options.workspace),\r\n }),\r\n );\r\n\r\nmcpCommand\r\n .command('remove')\r\n .alias('rm')\r\n .description('Remove an MCP server from its effective scope')\r\n .argument('<name>', 'Server name')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--scope <scope>', 'user | project')\r\n .action((name: string, options: { workspace?: string; scope?: 'user' | 'project' }) =>\r\n runMcpRemoveCommand(name, { ...options, workspace: resolveWorkspace(options.workspace) }),\r\n );\r\n\r\n// ---- book trust ----\r\nconst trustCommand = program\r\n .command('trust')\r\n .description('Record decisions about configuration a repository declared');\r\n\r\ntrustCommand\r\n .command('hook')\r\n .description('Approve or reject a project-declared hook (see `book doctor`)')\r\n .argument('[fingerprint]', 'Hook fingerprint reported by `book doctor`')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--all-pending', 'Apply to every hook currently awaiting a decision')\r\n .option('--reject', 'Record a refusal instead of an approval')\r\n .action(\r\n async (\r\n fingerprint: string | undefined,\r\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\r\n ) => {\r\n await runTrustCommand('hook', fingerprint, {\r\n ...options,\r\n workspace: resolveWorkspace(options.workspace),\r\n });\r\n },\r\n );\r\n\r\ntrustCommand\r\n .command('command')\r\n .description('Approve or reject a project command that substitutes shell into its prompt')\r\n .argument('[name]', 'Command name, with or without the leading slash')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--all-pending', 'Apply to every command currently awaiting a decision')\r\n .option('--reject', 'Record a refusal instead of an approval')\r\n .action(\r\n async (\r\n name: string | undefined,\r\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\r\n ) => {\r\n await runTrustCommand('command', name, {\r\n ...options,\r\n workspace: resolveWorkspace(options.workspace),\r\n });\r\n },\r\n );\r\n\r\ntrustCommand\r\n .command('rule')\r\n .description('Approve or reject a project-declared permissions.allow rule')\r\n .argument('[rule]', 'Rule text exactly as the project declared it')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n .option('--all-pending', 'Apply to every rule currently awaiting a decision')\r\n .option('--reject', 'Record a refusal instead of an approval')\r\n .action(\r\n async (\r\n rule: string | undefined,\r\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\r\n ) => {\r\n await runTrustCommand('rule', rule, {\r\n ...options,\r\n workspace: resolveWorkspace(options.workspace),\r\n });\r\n },\r\n );\r\n\r\n// ---- book config ----\r\nprogram\r\n .command('config')\r\n .description('Read and write settings')\r\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\r\n // Re-declared from the root because this action reads them: positional option\r\n // parsing rejects a root option written after the subcommand name, so without\r\n // these `book config get model --settings <path>` fails with \"unknown option\".\r\n // Declared in this order so commander leaves `settings` undefined when neither\r\n // flag is passed, letting an unset one fall through to the root's value.\r\n .option('--settings <path>', 'Path to an ad-hoc settings file (overrides all scopes)')\r\n .option('--no-settings', 'Skip all settings.json layers (use defaults + legacy .bookrc.json)')\r\n // Writes default to the user layer so a setting follows the person, not the\r\n // directory. The two workspace layers stay reachable, but have to be asked\r\n // for -- the shortest command is the one that stays consistent everywhere.\r\n .option('-g, --global', 'Act on user-global settings (<BOOK_HOME>/settings.json) [default]')\r\n .option('--project', 'Act on checked-in project settings (.book/settings.json)')\r\n .option('--local', 'Act on gitignored project-local settings (.book/settings.local.json)')\r\n .argument('[action]', 'get <key>, set <key> <value>, unset <key>, or list')\r\n .argument('[key]', 'Dot-separated key path (e.g. permissions.deny)')\r\n .argument('[value]', 'Value to set (JSON-parsed)')\r\n .addHelpText('after', `\\n${formatSettingsKeyHelp()}`)\r\n .action(\r\n async (\r\n action: string | undefined,\r\n key: string | undefined,\r\n value: string | undefined,\r\n options: {\r\n workspace?: string;\r\n settings?: string | false;\r\n global?: boolean;\r\n project?: boolean;\r\n local?: boolean;\r\n },\r\n ) => {\r\n const rootSettings = program.opts().settings as string | false | undefined;\r\n const settings = options.settings ?? rootSettings;\r\n const selected = (\r\n [\r\n ['user', options.global],\r\n ['project', options.project],\r\n ['local', options.local],\r\n ] as const\r\n ).filter(([, on]) => on === true);\r\n if (selected.length > 1) {\r\n console.error(\r\n 'Pass at most one of --global, --project, --local. ' +\r\n 'Writes default to --global; reads without one report the resolved merge.',\r\n );\r\n exit(1);\r\n }\r\n await runConfigCommand(resolveWorkspace(options.workspace), action, key, value, {\r\n settingsOverridePath: typeof settings === 'string' ? settings : undefined,\r\n noSettings: settings === false,\r\n scope: selected[0]?.[0],\r\n });\r\n },\r\n );\r\n\r\n// ---- main (interactive / headless) ----\r\nprogram.action(async (options: Record<string, unknown>) => {\r\n await runMainAction(options);\r\n});\r\n\r\nprogram.parse();\r\n","import { join } from 'node:path';\r\nimport { SessionStore } from '../session/store.js';\r\nimport { resolveBookHome } from '../book-home.js';\r\nimport { estimateUsageCost } from '../pricing.js';\r\nimport { readRunStatus, type RunStatusRecord } from '../run-status.js';\r\nimport type { LoadedSession, SessionMeta } from '../types/sessions.js';\r\nimport type { Message } from '../types/messages.js';\r\n\r\n/**\r\n * `book status` — what a long-running session is working on and what it has cost,\r\n * answerable without a provider credential.\r\n *\r\n * The question this exists for is asked at hour 180, often by a supervisor script\r\n * or by someone who has just walked back to the machine: *what was this asked to\r\n * do, how far has it got, and what has it spent?* Every input is already on disk.\r\n *\r\n * Credential-free by construction, and asserted so in\r\n * `src/cli/subcommands.contract.test.ts`: a run whose provider is misconfigured is\r\n * exactly when someone needs to read its state.\r\n *\r\n * The objective is read from the transcript rather than a summary because the\r\n * transcript is never rewritten by compaction — `SessionStore.load` truncates it\r\n * only for a rewind record — so the user's first words survive verbatim however\r\n * many generations have passed.\r\n *\r\n * The session JSONL answers \"what was this asked to do and what has it spent\".\r\n * What it cannot answer is *liveness*, which is the half a supervisor actually\r\n * needs mid-run: whether the process is alive, which turn it is on, what tool it\r\n * last called, and whether it finished cleanly or died. `src/run-status.ts` has\r\n * been writing exactly that to `<BOOK_HOME>/runs/<session-id>.json` at every turn\r\n * boundary, and nothing read it — a 20-minute print run that had done the work\r\n * correctly and one that died at turn 16 looked identical from outside, and the\r\n * only way to tell them apart was `jq` on a file with no documented reader. That\r\n * record is folded in here rather than into a new command: this is the surface\r\n * someone looks at, and it already runs without a credential.\r\n */\r\n\r\n/**\r\n * What the liveness record says about the process, once the pid is tested.\r\n *\r\n * `died` is the case the record exists for: no terminal outcome and no crash\r\n * note, and the process is gone. Silence and a clean finish are indistinguishable\r\n * without it, which is the whole complaint.\r\n */\r\nexport type RunLiveness = 'running' | 'completed' | 'crashed' | 'died';\r\n\r\nexport interface RunStatus {\r\n liveness: RunLiveness;\r\n pid: number;\r\n /** True when the pid answers a signal-0 probe right now. */\r\n processAlive: boolean;\r\n runId: string;\r\n turn: number;\r\n elapsedMs: number;\r\n /** When the record was last rewritten — a running record that is old is wedged. */\r\n updatedAt: number;\r\n lastTool?: string;\r\n currentTodo?: string;\r\n openTodos: number;\r\n costUsd: number | null;\r\n budgetUsd?: number;\r\n freeDiskBytes?: number;\r\n terminal?: { status: string; reason: string; message?: string };\r\n crash?: { message: string; at: number };\r\n}\r\n\r\n/**\r\n * Does this pid still answer? Signal 0 performs the permission and existence\r\n * checks without delivering anything. `EPERM` means it exists under another\r\n * user, which is still alive; only `ESRCH` means gone.\r\n */\r\nfunction isProcessAlive(pid: number): boolean {\r\n if (!Number.isInteger(pid) || pid <= 0) return false;\r\n try {\r\n process.kill(pid, 0);\r\n return true;\r\n } catch (error) {\r\n return (error as NodeJS.ErrnoException).code === 'EPERM';\r\n }\r\n}\r\n\r\nexport function buildRunStatus(record: RunStatusRecord): RunStatus {\r\n const processAlive = isProcessAlive(record.pid);\r\n const liveness: RunLiveness = record.terminal\r\n ? 'completed'\r\n : record.crash\r\n ? 'crashed'\r\n : processAlive\r\n ? 'running'\r\n : 'died';\r\n\r\n return {\r\n liveness,\r\n pid: record.pid,\r\n processAlive,\r\n runId: record.runId,\r\n turn: record.turn,\r\n elapsedMs: record.elapsedMs,\r\n updatedAt: record.updatedAt,\r\n lastTool: record.lastTool,\r\n currentTodo: record.currentTodo,\r\n openTodos: record.openTodos,\r\n costUsd: record.costUsd,\r\n budgetUsd: record.budgetUsd,\r\n freeDiskBytes: record.freeDiskBytes,\r\n terminal: record.terminal ? { ...record.terminal } : undefined,\r\n crash: record.crash ? { ...record.crash } : undefined,\r\n };\r\n}\r\n\r\nexport interface SessionStatus {\r\n sessionId: string;\r\n sessionName?: string;\r\n workspace: string;\r\n createdAt: number;\r\n updatedAt: number;\r\n /** Byte-exact text of the first user turn. */\r\n objective?: string;\r\n transcriptMessages: number;\r\n contextMessages: number;\r\n compactions: number;\r\n /** Newest checkpoint generation, or 0 when the session has never compacted. */\r\n generation: number;\r\n usage?: {\r\n promptTokens: number;\r\n completionTokens: number;\r\n cacheReadInputTokens: number;\r\n cacheCreationInputTokens: number;\r\n };\r\n costUsd: number | null;\r\n costModels: string[];\r\n plan?: {\r\n todos: Array<{ content: string; status: string }>;\r\n tasks: Array<{ id: string; subject: string; status: string; blockedBy: string[] }>;\r\n };\r\n /** Absent when no run of this session ever wrote a liveness record. */\r\n run?: RunStatus;\r\n}\r\n\r\nfunction firstUserTurn(transcript: readonly Message[]): string | undefined {\r\n for (const message of transcript) {\r\n if (message.role !== 'user') continue;\r\n // Skip host-authored turns: checkpoints, agent notifications, and the loop's\r\n // own continuation and work-state messages are not what anyone asked for.\r\n if (message.kind && message.kind !== 'conversation') continue;\r\n if (message.content.startsWith('[continuation]')) continue;\r\n if (message.content.startsWith('[work-state]')) continue;\r\n if (message.agentNotifications?.length) continue;\r\n return message.content;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function buildSessionStatus(\r\n meta: SessionMeta,\r\n loaded: LoadedSession,\r\n runRecord?: RunStatusRecord,\r\n): SessionStatus {\r\n const usage = loaded.carriedUsage;\r\n const models = loaded.carriedModels ?? [];\r\n // Price at the most expensive model involved: the records do not attribute\r\n // tokens per model, so an upper bound is the honest reading.\r\n let costUsd: number | null = models.length > 0 && usage ? 0 : null;\r\n if (usage) {\r\n for (const model of models) {\r\n const quote = estimateUsageCost(model, {\r\n promptTokens: usage.promptTokens,\r\n completionTokens: usage.completionTokens,\r\n totalTokens: usage.totalTokens,\r\n cacheReadInputTokens: usage.cacheReadInputTokens,\r\n cacheCreationInputTokens: usage.cacheCreationInputTokens,\r\n });\r\n if (quote.status !== 'known') {\r\n costUsd = null;\r\n break;\r\n }\r\n costUsd = Math.max(costUsd ?? 0, quote.costUsd);\r\n }\r\n }\r\n\r\n return {\r\n sessionId: meta.id,\r\n sessionName: meta.name,\r\n workspace: meta.cwd,\r\n createdAt: meta.createdAt,\r\n updatedAt: meta.updatedAt,\r\n objective: firstUserTurn(loaded.transcript),\r\n transcriptMessages: loaded.transcript.length,\r\n contextMessages: loaded.contextHistory.length,\r\n compactions: loaded.compactBoundaries.length,\r\n generation: loaded.compactBoundaries.at(-1)?.generation ?? 0,\r\n usage: usage\r\n ? {\r\n promptTokens: usage.promptTokens,\r\n completionTokens: usage.completionTokens,\r\n cacheReadInputTokens: usage.cacheReadInputTokens ?? 0,\r\n cacheCreationInputTokens: usage.cacheCreationInputTokens ?? 0,\r\n }\r\n : undefined,\r\n costUsd,\r\n costModels: models,\r\n plan: loaded.plan\r\n ? {\r\n todos: (loaded.plan.todos ?? []).map((todo) => ({\r\n content: todo.content,\r\n status: todo.status,\r\n })),\r\n tasks: (loaded.plan.tasks ?? []).map((task) => ({\r\n id: task.id,\r\n subject: task.subject,\r\n status: task.status,\r\n blockedBy: task.blockedBy,\r\n })),\r\n }\r\n : undefined,\r\n run: runRecord ? buildRunStatus(runRecord) : undefined,\r\n };\r\n}\r\n\r\nfunction truncate(text: string, max: number): string {\r\n const single = text.replace(/\\s+/g, ' ').trim();\r\n return single.length <= max ? single : `${single.slice(0, max - 1)}…`;\r\n}\r\n\r\nfunction since(timestamp: number, now: number): string {\r\n const minutes = Math.max(0, Math.round((now - timestamp) / 60_000));\r\n if (minutes < 60) return `${minutes}m ago`;\r\n const hours = Math.round(minutes / 60);\r\n return hours < 48 ? `${hours}h ago` : `${Math.round(hours / 24)}d ago`;\r\n}\r\n\r\nfunction duration(ms: number): string {\r\n const seconds = Math.max(0, Math.round(ms / 1000));\r\n if (seconds < 60) return `${seconds}s`;\r\n const minutes = Math.floor(seconds / 60);\r\n if (minutes < 60) return `${minutes}m ${seconds % 60}s`;\r\n return `${Math.floor(minutes / 60)}h ${minutes % 60}m`;\r\n}\r\n\r\nfunction gibibytes(bytes: number): string {\r\n return `${(bytes / 1024 ** 3).toFixed(1)} GiB`;\r\n}\r\n\r\n/**\r\n * The liveness half of the report.\r\n *\r\n * Led by the one fact the session JSONL cannot supply — whether the process is\r\n * still there — because that is the question being asked when someone runs this\r\n * mid-run. A `running` record whose last write is old is the wedged case, and is\r\n * called out rather than left for the reader to compute from two timestamps.\r\n */\r\nfunction renderRunStatus(run: RunStatus, now: number): string[] {\r\n const lines: string[] = [];\r\n const headline: Record<RunLiveness, string> = {\r\n running: `running (pid ${run.pid})`,\r\n completed: `finished — ${run.terminal?.status ?? 'unknown'} (${run.terminal?.reason ?? 'no reason recorded'})`,\r\n crashed: 'crashed without a terminal outcome',\r\n died: `no longer running, and recorded no outcome (pid ${run.pid} is gone)`,\r\n };\r\n lines.push(`Run: ${headline[run.liveness]}`);\r\n\r\n if (run.terminal?.message) lines.push(` ${run.terminal.message}`);\r\n if (run.crash) lines.push(` ${run.crash.message}`);\r\n\r\n lines.push(` turn ${run.turn} • elapsed ${duration(run.elapsedMs)}`);\r\n lines.push(` last update: ${since(run.updatedAt, now)}`);\r\n // Wall clock, and it has to be: `updatedAt` comes from the run's status file,\r\n // written by another process. This is why the line hedges — \"may be wedged\" —\r\n // rather than asserting. A wall-clock correction between the writer's stamp and\r\n // this read can produce the warning on a healthy run, and the cost of that is\r\n // one cautious sentence, which is the right trade for a diagnostic.\r\n if (run.liveness === 'running' && now - run.updatedAt > STALE_RUN_MS) {\r\n lines.push(\r\n ` ⚠ the process is alive but has not written a turn boundary in ${duration(now - run.updatedAt)} —` +\r\n ' it may be wedged on a long tool call or a permission prompt.',\r\n );\r\n }\r\n if (run.lastTool) lines.push(` last tool: ${run.lastTool}`);\r\n if (run.currentTodo) lines.push(` in progress: ${truncate(run.currentTodo, 120)}`);\r\n if (run.openTodos > 0) lines.push(` open todos: ${run.openTodos}`);\r\n\r\n if (run.costUsd !== null) {\r\n lines.push(\r\n ` spend: ~$${run.costUsd.toFixed(4)}` +\r\n (run.budgetUsd !== undefined ? ` of $${run.budgetUsd.toFixed(2)} budget` : ''),\r\n );\r\n }\r\n if (run.freeDiskBytes !== undefined) lines.push(` free disk: ${gibibytes(run.freeDiskBytes)}`);\r\n\r\n return lines;\r\n}\r\n\r\n/** How long a live process may go without a turn boundary before it is worth naming. */\r\nconst STALE_RUN_MS = 15 * 60_000;\r\n\r\nexport function renderSessionStatus(status: SessionStatus, now = Date.now()): string {\r\n const lines: string[] = [];\r\n lines.push(`Session: ${status.sessionName ?? status.sessionId}`);\r\n if (status.sessionName) lines.push(` id: ${status.sessionId}`);\r\n lines.push(` workspace: ${status.workspace}`);\r\n lines.push(` last activity: ${since(status.updatedAt, now)}`);\r\n lines.push('');\r\n\r\n // Before the objective: someone running this mid-run wants liveness first, and\r\n // someone reading it afterwards wants to know how the run ended before they\r\n // read what it was for.\r\n if (status.run) {\r\n lines.push(...renderRunStatus(status.run, now));\r\n lines.push('');\r\n }\r\n lines.push(\r\n status.objective\r\n ? `Objective: ${truncate(status.objective, 300)}`\r\n : 'Objective: (no user turn recorded)',\r\n );\r\n lines.push('');\r\n lines.push(\r\n `History: ${status.transcriptMessages} messages, ${status.contextMessages} in context` +\r\n (status.compactions > 0\r\n ? ` • ${status.compactions} compaction${status.compactions === 1 ? '' : 's'} (generation ${status.generation})`\r\n : ' • never compacted'),\r\n );\r\n\r\n if (status.usage) {\r\n const { promptTokens, completionTokens, cacheReadInputTokens, cacheCreationInputTokens } =\r\n status.usage;\r\n lines.push(\r\n `Tokens: prompt ${promptTokens.toLocaleString()} • completion ${completionTokens.toLocaleString()} • cache read ${cacheReadInputTokens.toLocaleString()} • cache write ${cacheCreationInputTokens.toLocaleString()}`,\r\n );\r\n lines.push(\r\n status.costUsd !== null\r\n ? `Spend: ~$${status.costUsd.toFixed(4)} (upper bound across ${status.costModels.join(', ') || 'unknown model'})`\r\n : 'Spend: (pricing unknown for at least one model used)',\r\n );\r\n } else {\r\n lines.push('Tokens: (none recorded — this session predates usage records, or never ran)');\r\n }\r\n\r\n if (status.plan) {\r\n const open = status.plan.todos.filter((todo) => todo.status !== 'completed');\r\n const openTasks = status.plan.tasks.filter(\r\n (task) => task.status !== 'completed' && task.status !== 'deleted',\r\n );\r\n lines.push('');\r\n lines.push(`Plan: ${open.length} open todo(s), ${openTasks.length} open task(s)`);\r\n for (const todo of open.slice(0, 10)) lines.push(` [${todo.status}] ${todo.content}`);\r\n for (const task of openTasks.slice(0, 10)) {\r\n const blockers = task.blockedBy.length ? ` (blocked by ${task.blockedBy.join(', ')})` : '';\r\n lines.push(` [${task.status}] ${task.subject}${blockers}`);\r\n }\r\n } else {\r\n lines.push('');\r\n lines.push('Plan: (none persisted)');\r\n }\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\nexport interface StatusCommandOptions {\r\n session?: string;\r\n workspace: string;\r\n json?: boolean;\r\n /** Injectable so the contract test can run without touching a real BOOK_HOME. */\r\n store?: SessionStore;\r\n /** Where `runs/<session-id>.json` lives; injectable for the same reason. */\r\n home?: string;\r\n stdout?: { write: (text: string) => unknown };\r\n}\r\n\r\nexport function runStatusCommand(options: StatusCommandOptions): number {\r\n const stdout = options.stdout ?? process.stdout;\r\n const home = options.home ?? resolveBookHome();\r\n const store = options.store ?? new SessionStore(join(home, 'sessions'));\r\n\r\n const meta = options.session\r\n ? (store.findById(options.session) ?? store.findByName(options.session))\r\n : store.mostRecentInCwd(options.workspace);\r\n\r\n if (!meta) {\r\n stdout.write(\r\n options.session\r\n ? `No session found matching \"${options.session}\".\\n`\r\n : `No session has run in ${options.workspace} yet.\\n`,\r\n );\r\n return 1;\r\n }\r\n\r\n const status = buildSessionStatus(meta, store.load(meta.id), readRunStatus(meta.id, home));\r\n stdout.write(\r\n options.json ? `${JSON.stringify(status, null, 2)}\\n` : `${renderSessionStatus(status)}\\n`,\r\n );\r\n return 0;\r\n}\r\n","/**\r\n * Test-injectable process.exit() abstraction.\r\n *\r\n * All CLI modules should use `exit()` instead of `process.exit()` so that\r\n * tests can capture exit codes without actually terminating the process.\r\n */\r\n\r\nlet exitFn: (code: number) => never = (code: number): never => {\r\n process.exit(code);\r\n};\r\n\r\nlet exiting = false;\r\n\r\n/** Replace the exit implementation (for test injection). */\r\nexport function setExitFn(fn: (code: number) => never): void {\r\n exitFn = fn;\r\n exiting = false;\r\n}\r\n\r\n/** Exit the process with the given code. Tests can override via setExitFn. */\r\nexport function exit(code: number = 0): never {\r\n exiting = true;\r\n exitFn(code);\r\n}\r\n\r\n/** True when exit() has been called. Used by outer catch handlers to avoid double-exiting. */\r\nexport function isExiting(): boolean {\r\n return exiting;\r\n}\r\n","import { resolve } from 'path';\r\nimport { loadConfig } from '../config.js';\r\nimport { getPackageVersion } from '../version-info.js';\r\nimport { collectAgentDiagnostics } from '../agents/diagnostics.js';\r\nimport { withBuiltInAgents } from '../agents/profiles.js';\r\nimport { discoverAgents } from '../subagent-discovery.js';\r\nimport { resolveBookHome } from '../book-home.js';\r\nimport type { HookEntry } from '../settings.js';\r\nimport type { AgentConfig } from '../types/runtime.js';\r\n\r\n/** Characters every supported shell passes through without quoting. */\r\nconst SHELL_SAFE_BARE = /^[A-Za-z0-9_@%+=:,./\\\\-]+$/;\r\n\r\n/**\r\n * Render one argument for a command the user will paste into their own shell.\r\n *\r\n * It has to survive both a POSIX shell and `cmd.exe`, where single quotes are\r\n * literal — the reason the old `book config set … '<json>'` suggestion reached\r\n * validation as a string on Windows and failed. Double quotes are the one form\r\n * both accept, so anything needing quotes gets those; a value carrying a\r\n * character neither can quote verbatim gets no one-liner at all.\r\n */\r\nfunction shellArgument(value: string): string | null {\r\n if (SHELL_SAFE_BARE.test(value)) return value;\r\n if (/[\"`$\\n\\r]/.test(value) || value.endsWith('\\\\')) return null;\r\n return `\"${value}\"`;\r\n}\r\n\r\n/**\r\n * A `book trust …` command targeting the workspace doctor actually diagnosed.\r\n *\r\n * `book trust` defaults to `process.cwd()`, so a suggestion printed by\r\n * `book doctor --workspace <repo>` run from elsewhere would otherwise record\r\n * the decision in the wrong project. Returns null when the path cannot be\r\n * quoted safely; the caller then tells the user where to run it instead.\r\n */\r\nfunction trustCommandLine(workspace: string, rest: string): string | null {\r\n if (resolve(workspace) === resolve(process.cwd())) return `book trust ${rest}`;\r\n const quoted = shellArgument(workspace);\r\n return quoted === null ? null : `book trust ${rest} --workspace ${quoted}`;\r\n}\r\n\r\n/** One \"here is how to grant it\" line, or a fallback when the path defeats quoting. */\r\nfunction approvalHint(label: string, workspace: string, rest: string): string {\r\n const command = trustCommandLine(workspace, rest);\r\n return command === null\r\n ? `${label} book trust ${rest} (run it from ${workspace})`\r\n : `${label} ${command}`;\r\n}\r\n\r\nfunction formatRelativeTime(timestamp: number, now = Date.now()): string {\r\n const elapsedMs = Math.max(0, now - timestamp);\r\n const minutes = Math.floor(elapsedMs / 60_000);\r\n if (minutes < 1) return 'just now';\r\n if (minutes < 60) return `${minutes}m ago`;\r\n const hours = Math.floor(minutes / 60);\r\n if (hours < 24) return `${hours}h ago`;\r\n const days = Math.floor(hours / 24);\r\n return `${days}d ago`;\r\n}\r\n\r\n/**\r\n * One line naming what will actually authenticate the next request.\r\n */\r\nfunction describeCredentials(config: AgentConfig): string {\r\n return config.apiKey\r\n ? 'API key resolved'\r\n : 'not resolved - set BOOK_API_KEY or set provider.<id>.apiKey in settings';\r\n}\r\n\r\n/**\r\n * A path that cannot exist, used to drop one layer from a probe resolution.\r\n *\r\n * `loadSettingsFile` returns null for a missing file, so redirecting a layer at\r\n * a name nothing can occupy is how a subset of the stack gets resolved without\r\n * touching the user's files.\r\n */\r\nconst ABSENT_LAYER = '\\0absent-settings-layer';\r\n\r\n/** The settings files doctor reads, in the order they are layered. */\r\nasync function settingsLayers(workspace: string): Promise<Array<[string, string]>> {\r\n const { join, resolve } = await import('path');\r\n const root = resolve(workspace);\r\n return [\r\n ['User', join(resolveBookHome(), 'settings.json')],\r\n ['Project', join(root, '.book', 'settings.json')],\r\n ['Local', join(root, '.book', 'settings.local.json')],\r\n ];\r\n}\r\n\r\n/**\r\n * Which layer a configuration failure first appears in.\r\n *\r\n * Some rejections name their own file: malformed JSON and schema violations both\r\n * carry a path. Resolving cumulative prefixes of the stack answers which layer\r\n * turned a working configuration into a broken one. Undefined means no prefix loads,\r\n * so the cause is outside the layers -- an environment variable, or a legacy `.bookrc.json`.\r\n */\r\nasync function attributeFailingLayer(workspace: string): Promise<string | undefined> {\r\n const layers = await settingsLayers(workspace);\r\n\r\n for (let included = 0; included <= layers.length; included++) {\r\n const [userSettingsPath, projectSettingsPath, localSettingsPath] = layers.map(\r\n ([, path], index) => (index < included ? path : ABSENT_LAYER),\r\n );\r\n try {\r\n loadConfig(workspace, {\r\n allowMissingApiKey: true,\r\n // A probe must not write: migrations are the real load's business.\r\n runMigrations: false,\r\n settingsPaths: { userSettingsPath, projectSettingsPath, localSettingsPath },\r\n });\r\n } catch {\r\n // included === 0 is the no-layer probe; failing there blames nothing.\r\n return included === 0 ? undefined : layers[included - 1][0];\r\n }\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Report a configuration that would not load at all.\r\n *\r\n * A missing credential is already handled by allowMissingApiKey, but every\r\n * other rejection - malformed JSON, a schema violation - used to escape\r\n * loadConfig as an unhandled stack trace. A broken settings file is precisely\r\n * what doctor exists to diagnose, so it is a finding to render, not a reason to die.\r\n */\r\nasync function reportUnloadableConfig(workspace: string, error: unknown): Promise<void> {\r\n const { existsSync } = await import('fs');\r\n const { resolve } = await import('path');\r\n\r\n console.log('Book Doctor');\r\n console.log('===========');\r\n console.log();\r\n console.log('Version:', getPackageVersion());\r\n console.log('Node:', process.version);\r\n console.log('Platform:', process.platform, process.arch);\r\n console.log('Workspace:', resolve(workspace));\r\n console.log();\r\n console.log('Configuration: FAILED TO LOAD');\r\n console.log(' ' + (error instanceof Error ? error.message : String(error)));\r\n console.log();\r\n console.log(' No other check can run until the configuration loads.');\r\n\r\n const culprit = await attributeFailingLayer(workspace);\r\n console.log(' Settings layers, in the order they are applied:');\r\n for (const [label, path] of await settingsLayers(workspace)) {\r\n const marker = existsSync(path) ? '[x]' : '[ ]';\r\n const blame = label === culprit ? ' <- the failure appears with this layer' : '';\r\n console.log(' ' + marker + ' ' + label + ': ' + path + blame);\r\n }\r\n console.log();\r\n if (culprit) {\r\n console.log(` The ${culprit} layer is where the configuration stops loading.`);\r\n } else {\r\n console.log(' No single layer accounts for it: check the environment and .bookrc.json.');\r\n }\r\n console.log(' Run `book doctor --no-settings` to report the rest with every layer skipped.');\r\n}\r\n\r\nexport async function runDoctorCommand(\r\n workspace: string,\r\n options: { noSettings?: boolean } = {},\r\n): Promise<void> {\r\n // Doctor must diagnose a broken environment, so it cannot require a working one:\r\n // a missing credential is a finding to report, not a reason to abort, and\r\n // neither is a settings file that fails to load.\r\n let config: ReturnType<typeof loadConfig>;\r\n try {\r\n config = loadConfig(workspace, {\r\n // --no-settings is the way past a layer doctor cannot otherwise get around;\r\n // migrations would rewrite settings this run has been told to ignore.\r\n noSettings: options.noSettings,\r\n runMigrations: !options.noSettings,\r\n allowMissingApiKey: true,\r\n });\r\n } catch (error) {\r\n await reportUnloadableConfig(workspace, error);\r\n return;\r\n }\r\n const settings = config.settings;\r\n\r\n console.log('Book Doctor');\r\n console.log('===========');\r\n console.log();\r\n console.log('Version:', getPackageVersion());\r\n console.log('Node:', process.version);\r\n console.log('Platform:', process.platform, process.arch);\r\n console.log('Workspace:', config.workspace);\r\n console.log('Model:', config.model, '(' + config.baseUrl + ')');\r\n // Printed before Credentials on purpose: an unresolved provider prefix makes\r\n // the credential line read as a missing key, which is the wrong hunt.\r\n if (config.modelProviderWarning) console.log(' ⚠ ' + config.modelProviderWarning);\r\n console.log('Credentials:', describeCredentials(config));\r\n // Configuration for a feature that no longer exists is invisible otherwise:\r\n // validation discards unknown blocks silently, so a user whose subscription\r\n // login stopped working has nothing to read. The orphaned credential file\r\n // matters most — it holds a refresh token nothing revokes.\r\n const {\r\n collectRemovedSettingNotices,\r\n collectRemovedEnvNotices,\r\n removedAuthStoreNotice,\r\n readSettingsDocumentForNotices,\r\n } = await import('../settings-removed.js');\r\n const { settingsLayerPaths } = await import('../settings-loader.js');\r\n const { join: joinPath } = await import('path');\r\n const { existsSync: fileExists } = await import('fs');\r\n const removedNotices = [\r\n ...settingsLayerPaths(workspace, undefined, {}).flatMap((path) =>\r\n collectRemovedSettingNotices(readSettingsDocumentForNotices(path)).map(\r\n (notice) => `${notice.key} in ${path}: ${notice.message}`,\r\n ),\r\n ),\r\n ...collectRemovedEnvNotices(process.env).map(\r\n (notice) => `${notice.key} is set: ${notice.message}`,\r\n ),\r\n ];\r\n const authStorePath = joinPath(resolveBookHome(), 'auth.json');\r\n if (fileExists(authStorePath)) removedNotices.push(removedAuthStoreNotice(authStorePath));\r\n if (removedNotices.length > 0) {\r\n console.log();\r\n console.log('Removed features still configured on this machine:');\r\n for (const notice of removedNotices) console.log(` [!] ${notice}`);\r\n }\r\n console.log();\r\n\r\n // Settings layers.\r\n console.log('Settings layers:');\r\n const { existsSync } = await import('fs');\r\n const { join } = await import('path');\r\n for (const [label, path] of await settingsLayers(config.workspace)) {\r\n const marker = options.noSettings ? '[-]' : existsSync(path) ? '[x]' : '[ ]';\r\n console.log(' ' + marker + ' ' + label + ': ' + path);\r\n }\r\n // Everything below is resolved from defaults in this mode. Saying so once\r\n // stops the report reading as a description of the user's configuration.\r\n if (options.noSettings) {\r\n console.log(' (--no-settings: every layer skipped, defaults reported below)');\r\n }\r\n console.log();\r\n\r\n // Permissions.\r\n const perms = settings.permissions;\r\n console.log('Permissions:');\r\n console.log(' Allow rules: ' + perms.allow.length);\r\n console.log(' Ask rules: ' + perms.ask.length);\r\n console.log(' Deny rules: ' + perms.deny.length);\r\n\r\n // Allow rules the repository declared are withheld until the user decides on\r\n // them, so doctor is where an unexplained \"my project rule does nothing\" is\r\n // meant to be answered.\r\n const { loadSettingsFile } = await import('../settings-loader.js');\r\n const { partitionProjectAllowRules } = await import('../permission-approvals.js');\r\n const projectSettings = loadSettingsFile(join(config.workspace, '.book', 'settings.json'));\r\n const projectAllow = partitionProjectAllowRules(\r\n projectSettings?.permissions?.allow ?? [],\r\n perms.projectAllowRules,\r\n );\r\n if (\r\n projectAllow.approved.length + projectAllow.pending.length + projectAllow.rejected.length >\r\n 0\r\n ) {\r\n console.log(' Project-declared allow rules (require approval):');\r\n for (const rule of projectAllow.approved) console.log(' [x] ' + rule);\r\n for (const rule of projectAllow.rejected) console.log(' [-] ' + rule + ' (rejected)');\r\n for (const rule of projectAllow.pending) console.log(' [!] ' + rule + ' (not in effect)');\r\n if (projectAllow.pending.length > 0) {\r\n console.log(approvalHint(' Approve one:', config.workspace, 'rule <rule>'));\r\n console.log(\r\n approvalHint(' Approve all pending:', config.workspace, 'rule --all-pending') +\r\n ' (add --reject to refuse)',\r\n );\r\n }\r\n }\r\n\r\n console.log();\r\n\r\n // A command body that substitutes shell runs it outside the permission\r\n // system, so a repository-declared one is withheld until the user decides.\r\n // Its own section: these are not permission rules, and printing them inside\r\n // the permissions block reads as if they were a rule category.\r\n const { discoverCommands } = await import('../commands/loader.js');\r\n const { partitionProjectCommands, describeProjectCommandShell, displayableCommandName } =\r\n await import('../command-approvals.js');\r\n const gatedCommands = partitionProjectCommands(discoverCommands(config.workspace), settings);\r\n if (\r\n gatedCommands.approved.length + gatedCommands.pending.length + gatedCommands.rejected.length >\r\n 0\r\n ) {\r\n console.log('Project commands that run shell (require approval):');\r\n for (const command of gatedCommands.approved)\r\n console.log(' [x] /' + displayableCommandName(command.name));\r\n for (const command of gatedCommands.rejected)\r\n console.log(' [-] /' + displayableCommandName(command.name) + ' (rejected)');\r\n // A withheld command is listed with the shell it would run, the way a\r\n // withheld hook is listed with its command, matcher, and environment:\r\n // the decision is about that shell, so a name alone cannot inform it.\r\n for (const command of gatedCommands.pending) {\r\n console.log(' [!] /' + displayableCommandName(command.name) + ' (refused until approved)');\r\n for (const line of describeProjectCommandShell(command)) console.log(' ' + line);\r\n }\r\n if (gatedCommands.pending.length > 0) {\r\n console.log(approvalHint(' Approve one:', config.workspace, 'command <name>'));\r\n console.log(\r\n approvalHint(' Approve all pending:', config.workspace, 'command --all-pending') +\r\n ' (add --reject to refuse)',\r\n );\r\n }\r\n console.log();\r\n }\r\n\r\n // Hooks.\r\n const hooks = settings.hooks;\r\n // `hooks.projectEntries` records trust decisions, not hook entries.\r\n const hookLists = Object.entries(hooks).filter((pair): pair is [string, HookEntry[]] =>\r\n Array.isArray(pair[1]),\r\n );\r\n let hookTotal = 0;\r\n for (const [, entries] of hookLists) hookTotal += entries.length;\r\n console.log('Hooks:');\r\n for (const [event, entries] of hookLists) {\r\n if (entries.length > 0) console.log(' ' + event + ': ' + entries.length);\r\n }\r\n if (hookTotal === 0) console.log(' (none)');\r\n\r\n // Hook entries a repository declared are withheld until the user decides on\r\n // them, so doctor is where an unexplained \"my project hook does nothing\" is\r\n // meant to be answered.\r\n const { collectDeclaredHooks, describeDeclaredHook, partitionProjectHooks } =\r\n await import('../hook-approvals.js');\r\n const declaredProjectHooks = collectDeclaredHooks(projectSettings);\r\n if (declaredProjectHooks.length > 0) {\r\n const hookPartition = partitionProjectHooks(\r\n declaredProjectHooks,\r\n settings.hooks.projectEntries,\r\n );\r\n console.log(' Project-declared hooks (require approval):');\r\n // Approval is keyed by a fingerprint covering event, matcher, command and\r\n // env, so all four are disclosed. A hook rendered as its command alone hides\r\n // exactly the fields behaviour can be smuggled in: `npm test` carrying\r\n // `NODE_OPTIONS=--require ./payload.js` reads as harmless and is not.\r\n const groups = [\r\n { mark: '[x]', suffix: '', hooks: hookPartition.approved },\r\n { mark: '[-]', suffix: ' (rejected)', hooks: hookPartition.rejected },\r\n { mark: '[!]', suffix: ' (not in effect)', hooks: hookPartition.pending },\r\n ];\r\n for (const group of groups) {\r\n for (const hook of group.hooks) {\r\n const described = describeDeclaredHook(hook);\r\n console.log(' ' + group.mark + ' ' + described.headline + group.suffix);\r\n for (const detail of described.details) console.log(' ' + detail);\r\n }\r\n }\r\n if (hookPartition.pending.length > 0) {\r\n console.log(approvalHint(' Approve one:', config.workspace, 'hook <fingerprint>'));\r\n console.log(\r\n approvalHint(' Approve all pending:', config.workspace, 'hook --all-pending') +\r\n ' (add --reject to refuse)',\r\n );\r\n }\r\n }\r\n console.log();\r\n\r\n // MCP.\r\n const { formatMcpServerCommand, resolveMcpServerList } = await import('../mcp-config.js');\r\n const { evaluateMcpServerApproval } = await import('../mcp-approvals.js');\r\n const mcpServers = resolveMcpServerList(config.workspace);\r\n console.log('MCP Servers:');\r\n for (const server of mcpServers) {\r\n const trust =\r\n server.source === 'user' ? 'user' : `project: ${evaluateMcpServerApproval(settings, server)}`;\r\n console.log(' ' + server.name + ': ' + formatMcpServerCommand(server.config) + ` [${trust}]`);\r\n }\r\n if (mcpServers.length === 0) console.log(' (none)');\r\n console.log();\r\n\r\n // Sandbox.\r\n const { createSandbox, sandboxPolicySummary } = await import('../sandbox.js');\r\n const { hasAdjudicationPolicy } = await import('../permissions.js');\r\n const sandbox = createSandbox(settings.sandbox);\r\n const policy = sandboxPolicySummary(settings.sandbox, {\r\n sandboxActive: sandbox !== null,\r\n adjudicationConfigured: hasAdjudicationPolicy(settings),\r\n });\r\n console.log('Sandbox:');\r\n console.log(' Enabled: ' + settings.sandbox.enabled);\r\n console.log(' Available: ' + (sandbox !== null));\r\n if (sandbox) console.log(' Enforcing: ' + sandbox.describe());\r\n console.log(' Excluded commands: ' + settings.sandbox.excludedCommands.length);\r\n console.log(' Unsandboxed commands: ' + policy.unsandboxedCommands);\r\n console.log(' Auto-allow Bash: ' + policy.autoAllowBash);\r\n console.log();\r\n\r\n // Shell: the program every Bash command is handed to, and why it was chosen.\r\n const { describeShell, resolveShell } = await import('../shell-selection.js');\r\n const shell = config.shell ?? resolveShell({ requested: settings.shell });\r\n console.log('Shell:');\r\n console.log(' Bash tool runs: ' + describeShell(shell));\r\n console.log(' Selected by: ' + shell.source);\r\n if (shell.warning) console.log(` [!] ${shell.warning}`);\r\n console.log();\r\n\r\n // Managed agents.\r\n console.log('Managed agents:');\r\n const agentDiagnostics = collectAgentDiagnostics(\r\n config,\r\n withBuiltInAgents(discoverAgents(config.workspace)),\r\n );\r\n if (agentDiagnostics.length === 0) {\r\n console.log(' [x] Profiles and overrides look valid');\r\n } else {\r\n for (const diagnostic of agentDiagnostics) {\r\n console.log(` [!] ${diagnostic.message}`);\r\n }\r\n }\r\n for (const directory of [\r\n join(config.workspace, '.claude', 'agents'),\r\n join(config.workspace, '.agents', 'agents'),\r\n ]) {\r\n if (existsSync(directory)) {\r\n console.log(\r\n ` [!] Third-party definitions found at ${directory}; preview them with /agents import ${directory}.`,\r\n );\r\n }\r\n }\r\n console.log();\r\n\r\n // Learned context windows.\r\n const { createModelWindowStore } = await import('../model-window-store.js');\r\n const windowStore = createModelWindowStore();\r\n const allLearned = windowStore.all();\r\n const learnedModels = Object.keys(allLearned);\r\n console.log('Learned context windows:');\r\n if (learnedModels.length === 0) {\r\n console.log(' (none)');\r\n } else {\r\n for (const modelName of learnedModels) {\r\n const entry = windowStore.getEntry(modelName) ?? allLearned[modelName];\r\n console.log(\r\n ` ${modelName}: ${entry.contextWindow.toLocaleString()} tokens (${formatRelativeTime(entry.learnedAt)})`,\r\n );\r\n }\r\n }\r\n console.log();\r\n\r\n // Environment.\r\n console.log('Environment:');\r\n for (const key of ['BOOK_API_KEY', 'BOOK_BASE_URL', 'BOOK_MODEL', 'BOOK_WORKSPACE']) {\r\n const val = process.env[key];\r\n if (key === 'BOOK_API_KEY' && val) {\r\n console.log(' ' + key + ': *** (set)');\r\n } else {\r\n console.log(' ' + key + ': ' + (val || '(not set)'));\r\n }\r\n }\r\n}\r\n","import type { AgentConfig } from '../types/runtime.js';\r\nimport { canonicalToolName } from '../tools/aliases.js';\r\nimport type { ManagedAgentDef } from './profiles.js';\r\n\r\nexport interface AgentDiagnostic {\r\n code:\r\n | 'duplicate-profile'\r\n | 'invalid-model'\r\n | 'literal-inherit'\r\n | 'missing-profile'\r\n | 'readonly-mutation'\r\n | 'reserved-profile'\r\n | 'unknown-tool';\r\n message: string;\r\n}\r\n\r\nconst MUTATION_TOOLS = new Set([\r\n 'ApplyPatch',\r\n 'Write',\r\n 'Edit',\r\n 'MultiEdit',\r\n 'NotebookEdit',\r\n 'Bash',\r\n 'Check',\r\n]);\r\n\r\nfunction validateModel(\r\n profile: string,\r\n model: string | undefined,\r\n config: AgentConfig,\r\n): AgentDiagnostic | undefined {\r\n if (!model || model === 'inherit') return undefined;\r\n const slash = model.indexOf('/');\r\n if (slash === 0 || slash === model.length - 1) {\r\n return {\r\n code: 'invalid-model',\r\n message: `${profile} uses invalid model \"${model}\"; expected a model or provider/model reference.`,\r\n };\r\n }\r\n if (slash > 0) {\r\n const providerId = model.slice(0, slash);\r\n const modelId = model.slice(slash + 1);\r\n const provider = config.settings.provider[providerId];\r\n if (provider && Object.keys(provider.models).length > 0 && !provider.models[modelId]) {\r\n return {\r\n code: 'invalid-model',\r\n message: `${profile} references ${model}, which is not in provider ${providerId}'s model catalog.`,\r\n };\r\n }\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function collectAgentDiagnostics(\r\n config: AgentConfig,\r\n profiles: ManagedAgentDef[],\r\n): AgentDiagnostic[] {\r\n const diagnostics: AgentDiagnostic[] = [];\r\n const counts = new Map<string, number>();\r\n for (const profile of profiles) counts.set(profile.name, (counts.get(profile.name) ?? 0) + 1);\r\n for (const [name, count] of counts) {\r\n if (count > 1) {\r\n diagnostics.push({\r\n code: 'duplicate-profile',\r\n message: `${name} is defined ${count} times; keep one profile definition per name.`,\r\n });\r\n }\r\n }\r\n\r\n const profileNames = new Set(profiles.map((profile) => profile.name));\r\n for (const [name, override] of Object.entries(config.settings.agents.profiles)) {\r\n if (!profileNames.has(name)) {\r\n diagnostics.push({\r\n code: 'missing-profile',\r\n message: `agents.profiles.${name} has settings but no matching agent definition.`,\r\n });\r\n }\r\n const modelDiagnostic = validateModel(name, override.model, config);\r\n if (modelDiagnostic) diagnostics.push(modelDiagnostic);\r\n }\r\n\r\n for (const profile of profiles) {\r\n if (profile.suppressedOverride) {\r\n diagnostics.push({\r\n code: 'reserved-profile',\r\n message: `${profile.name} is a reserved built-in agent, so the ${profile.suppressedOverride} definition of the same name is ignored. Rename it, or tune model/effort through agents.profiles.${profile.name}.`,\r\n });\r\n }\r\n for (const tool of profile.unknownTools ?? []) {\r\n diagnostics.push({\r\n code: 'unknown-tool',\r\n message: `${profile.name} declares unsupported tool ${tool}; import or edit the definition.`,\r\n });\r\n }\r\n if (profile.isolation === 'workspace-readonly') {\r\n const mutations = profile.allowedTools.filter((tool) =>\r\n MUTATION_TOOLS.has(canonicalToolName(tool.split('(')[0].trim())),\r\n );\r\n if (mutations.length > 0) {\r\n diagnostics.push({\r\n code: 'readonly-mutation',\r\n message: `${profile.name} is read-only but declares mutation tools: ${mutations.join(', ')}. They will be hard-filtered.`,\r\n });\r\n }\r\n }\r\n if (!config.settings.agents.profiles[profile.name]?.model) {\r\n const modelDiagnostic = validateModel(profile.name, profile.model, config);\r\n if (modelDiagnostic) diagnostics.push(modelDiagnostic);\r\n }\r\n }\r\n return diagnostics;\r\n}\r\n","import { resolveSettings } from '../settings-loader.js';\r\nimport {\r\n aggregateToolUse,\r\n formatToolStatsReport,\r\n pruneToolUseRecords,\r\n readToolUseRecords,\r\n} from '../tool-telemetry.js';\r\n\r\nexport interface ToolStatsCommandOptions {\r\n workspace: string;\r\n /** Emit the raw aggregate as JSON instead of a text report. */\r\n json?: boolean;\r\n /** Only include records from the last N days (overrides the retention window). */\r\n since?: string;\r\n /** Include every record regardless of the retention window. */\r\n all?: boolean;\r\n /** Drop records older than the window from disk before reporting. */\r\n prune?: boolean;\r\n}\r\n\r\nconst DAY_MS = 86_400_000;\r\n\r\n/**\r\n * `book tool-stats` — read the persistent tool-use telemetry log and report\r\n * calls, failure rates, durations, retries, and a per-model breakdown.\r\n */\r\nexport async function runToolStatsCommand(options: ToolStatsCommandOptions): Promise<void> {\r\n const settings = resolveSettings(options.workspace);\r\n const retentionDays = settings.observability.toolTelemetryRetentionDays;\r\n\r\n let windowDays: number | undefined;\r\n if (options.all) {\r\n windowDays = undefined;\r\n } else if (options.since !== undefined) {\r\n const parsed = Number(options.since);\r\n // A non-finite --since falls back to the configured window; 0 is honored as \"today only\".\r\n windowDays = Number.isFinite(parsed) ? Math.max(0, parsed) : retentionDays;\r\n } else {\r\n windowDays = retentionDays;\r\n }\r\n const cutoffTs = windowDays === undefined ? 0 : Date.now() - windowDays * DAY_MS;\r\n\r\n if (options.prune) {\r\n const result = await pruneToolUseRecords(cutoffTs);\r\n console.error(\r\n `Pruned ${result.dropped} record${result.dropped === 1 ? '' : 's'} older than ${windowDays ?? 0} days (${result.kept} kept).`,\r\n );\r\n }\r\n\r\n const all = await readToolUseRecords();\r\n const records = all.filter((record) => (record.ts ?? 0) >= cutoffTs);\r\n const aggregate = aggregateToolUse(records);\r\n\r\n if (options.json) {\r\n console.log(JSON.stringify(aggregate, null, 2));\r\n return;\r\n }\r\n\r\n console.log(formatToolStatsReport(aggregate));\r\n if (windowDays !== undefined && aggregate.totalCalls > 0) {\r\n console.log(\r\n `\\n(Window: last ${windowDays} days. Use --all for full history, --since <days> to change.)`,\r\n );\r\n }\r\n}\r\n","import { exit } from './exit.js';\r\nimport { getNestedValue } from './utils.js';\r\nimport { redactSettingValue, redactSettingsForDisplay } from '../settings-redaction.js';\r\nimport { DEFAULT_SETTINGS, type ResolvedSettings } from '../settings.js';\r\nimport { formatSettingsDiagnostics, SettingsRepository } from '../settings-repository.js';\r\nimport { resolveSettings } from '../settings-loader.js';\r\nimport { settingsScopeLabel, type SettingsScope } from '../settings-scope.js';\r\nimport { applySettingWrite, describeSettingShadow, readScopeDocument } from '../settings-write.js';\r\n\r\nexport interface ConfigCommandSettingsOptions {\r\n settingsOverridePath?: string;\r\n noSettings?: boolean;\r\n /**\r\n * Which layer to act on. Writes default to `user`, so a setting follows the\r\n * person rather than the directory they happened to run the command in.\r\n * Reads default to the resolved merge of every layer; a scope narrows them to\r\n * that one file, which is how a user finds the stray value overriding them.\r\n */\r\n scope?: SettingsScope;\r\n}\r\n\r\nexport async function runConfigCommand(\r\n workspace: string,\r\n action: string | undefined,\r\n key: string | undefined,\r\n value: string | undefined,\r\n settingsOptions: ConfigCommandSettingsOptions = {},\r\n): Promise<void> {\r\n // *Calling* this is deferred because it throws on a malformed layer, and the\r\n // paths that do not need it are exactly the ones a user reaches for when a\r\n // layer *is* malformed: a scoped read to find the broken file, and a write to\r\n // replace the bad value. Resolving eagerly made `config` the one tool that\r\n // stopped working precisely when the config was wrong. The import itself is\r\n // static — `settings-write.js` pulls the loader in regardless, so a dynamic\r\n // one deferred nothing while reading as though it did.\r\n const resolveMergedSettings = (): ResolvedSettings =>\r\n settingsOptions.noSettings\r\n ? structuredClone(DEFAULT_SETTINGS)\r\n : resolveSettings(workspace, settingsOptions.settingsOverridePath);\r\n\r\n // A scope narrows a read to one file. Without it a read reports the merge,\r\n // which is the right default but cannot answer \"why is this not what I set\" —\r\n // for that the user needs to see the layer the value actually came from.\r\n const scopeRead = settingsOptions.scope\r\n ? readScopeDocument(settingsOptions.scope, workspace)\r\n : undefined;\r\n\r\n if (!action || action === 'list') {\r\n if (scopeRead) {\r\n console.log(`${settingsScopeLabel(scopeRead.scope)} settings (${scopeRead.path}):`);\r\n if (scopeRead.status === 'unreadable') {\r\n console.error(`Could not read it: ${scopeRead.error ?? 'unknown error'}`);\r\n exit(1);\r\n }\r\n console.log(\r\n scopeRead.status === 'present'\r\n ? JSON.stringify(redactSettingsForDisplay(scopeRead.document), null, 2)\r\n : 'No settings file at this scope yet.',\r\n );\r\n return;\r\n }\r\n console.log('Resolved settings:');\r\n console.log(JSON.stringify(redactSettingsForDisplay(resolveMergedSettings()), null, 2));\r\n return;\r\n }\r\n\r\n if (action === 'get') {\r\n if (!key) {\r\n console.error('Usage: book config get <key>');\r\n exit(1);\r\n }\r\n if (scopeRead?.status === 'unreadable') {\r\n console.error(\r\n `Could not read ${settingsScopeLabel(scopeRead.scope)} settings (${scopeRead.path}): ` +\r\n `${scopeRead.error ?? 'unknown error'}`,\r\n );\r\n exit(1);\r\n }\r\n const source = scopeRead\r\n ? scopeRead.document\r\n : (resolveMergedSettings() as unknown as Record<string, unknown>);\r\n const val = getNestedValue(source, key);\r\n if (val === undefined) {\r\n console.log(\r\n scopeRead\r\n ? `Key ${key} is not set in ${settingsScopeLabel(scopeRead.scope)} settings (${scopeRead.path}).`\r\n : 'Key ' + key + ' is not set (no value).',\r\n );\r\n } else {\r\n console.log(JSON.stringify(redactSettingValue(key, val), null, 2));\r\n }\r\n return;\r\n }\r\n\r\n if (action === 'set') {\r\n if (!key || value === undefined) {\r\n console.error('Usage: book config set <key> <value>');\r\n exit(1);\r\n }\r\n let parsedValue: unknown;\r\n try {\r\n parsedValue = JSON.parse(value);\r\n } catch {\r\n parsedValue = value;\r\n }\r\n\r\n const scope = settingsOptions.scope ?? 'user';\r\n const result = applySettingWrite({\r\n workspace,\r\n key,\r\n value: parsedValue,\r\n scope,\r\n settingsOverridePath: settingsOptions.settingsOverridePath,\r\n noSettings: settingsOptions.noSettings,\r\n });\r\n if (!result.ok) {\r\n console.error(result.error);\r\n exit(1);\r\n return;\r\n }\r\n console.log(\r\n 'Set ' +\r\n key +\r\n ' = ' +\r\n JSON.stringify(redactSettingValue(key, result.value)) +\r\n ' in ' +\r\n settingsScopeLabel(result.scope) +\r\n ' settings (' +\r\n result.path +\r\n ')',\r\n );\r\n // A user-global write is the one that silently loses: the local layer is\r\n // resolved last, so a value left there from before this command defaulted\r\n // to `user` keeps winning. Say so rather than letting the write look inert.\r\n for (const shadow of result.shadowedBy) {\r\n console.warn(`⚠ ${describeSettingShadow(shadow, key)}`);\r\n }\r\n return;\r\n }\r\n\r\n if (action === 'unset') {\r\n if (!key) {\r\n console.error('Usage: book config unset <key>');\r\n exit(1);\r\n }\r\n // Unset needs no scope default of its own beyond `set`'s: the reason to\r\n // reach for it is almost always a stray value in a layer that outranks the\r\n // global one, and that layer has to be named explicitly anyway.\r\n const scope = settingsOptions.scope ?? 'user';\r\n const layer = readScopeDocument(scope, workspace);\r\n if (layer.status === 'unreadable') {\r\n console.error(\r\n `Could not read ${settingsScopeLabel(scope)} settings (${layer.path}): ` +\r\n `${layer.error ?? 'unknown error'}`,\r\n );\r\n exit(1);\r\n }\r\n if (layer.status === 'absent' || getNestedValue(layer.document, key) === undefined) {\r\n console.log(\r\n `${key} is not set in ${settingsScopeLabel(scope)} settings (${layer.path}); nothing to remove.`,\r\n );\r\n return;\r\n }\r\n const result = new SettingsRepository(layer.path).remove([key]);\r\n if (!result.ok) {\r\n console.error(formatSettingsDiagnostics(result.diagnostics));\r\n exit(1);\r\n }\r\n console.log(`Removed ${key} from ${settingsScopeLabel(scope)} settings (${result.path})`);\r\n return;\r\n }\r\n\r\n console.error(\r\n 'Unknown action: ' + action + '. Use: get <key>, set <key> <value>, unset <key>, or list',\r\n );\r\n exit(1);\r\n}\r\n","/**\r\n * `book trust` — record a decision about repository-declared configuration.\r\n *\r\n * The gated input is a hook entry, a `permissions.allow` rule, or a project\r\n * command whose body substitutes shell; until a decision exists, the resolver\r\n * withholds it. Doctor reports what is withheld and prints the command that\r\n * grants it, so this is the non-interactive half of that flow.\r\n *\r\n * Commands are keyed by name rather than by fingerprint. A hook or a rule is\r\n * anonymous — a fingerprint is the only handle it has — but a command already\r\n * has one the user typed, and asking them to paste a digest to approve\r\n * `/deploy` would be ceremony without a gain. The fingerprint still decides\r\n * *validity*: it is recorded with the choice and re-checked on every\r\n * invocation, so editing what the body runs re-asks under the same name.\r\n *\r\n * It replaces a printed `book config set hooks.projectEntries '<json>'`\r\n * one-liner, which was wrong in three ways: `config set` *replaces* the value\r\n * at a path, so pasting a map of newly-pending entries silently discarded every\r\n * earlier approve/reject; the suggestion omitted `--workspace`, so running it\r\n * from elsewhere wrote decisions into the wrong project; and its single-quoted\r\n * JSON does not survive `cmd.exe`, where quotes are literal and the argument\r\n * reaches validation as a string. Decisions here are recorded one at a time\r\n * through the per-key persist helpers, and a fingerprint is bare hex, so\r\n * nothing needs quoting.\r\n */\r\nimport { join } from 'path';\r\nimport {\r\n describeProjectCommandShell,\r\n displayableCommandName,\r\n partitionProjectCommands,\r\n persistProjectCommandChoice,\r\n projectCommandFingerprint,\r\n} from '../command-approvals.js';\r\nimport { discoverCommands } from '../commands/loader.js';\r\nimport {\r\n collectDeclaredHooks,\r\n describeDeclaredHook,\r\n hookFingerprint,\r\n partitionProjectHooks,\r\n persistProjectHookChoice,\r\n} from '../hook-approvals.js';\r\nimport {\r\n partitionProjectAllowRules,\r\n persistProjectAllowRuleChoice,\r\n} from '../permission-approvals.js';\r\nimport { loadSettingsFile, resolveSettings } from '../settings-loader.js';\r\nimport type { SlashCommand } from '../types/commands.js';\r\nimport { exit } from './exit.js';\r\n\r\nexport type TrustKind = 'hook' | 'rule' | 'command';\r\n\r\nexport interface TrustCommandOptions {\r\n workspace: string;\r\n /** Record a refusal instead of an approval. */\r\n reject?: boolean;\r\n /** Apply the decision to everything currently withheld. */\r\n allPending?: boolean;\r\n}\r\n\r\nfunction fail(message: string): never {\r\n console.error(message);\r\n return exit(1);\r\n}\r\n\r\nexport async function runTrustCommand(\r\n kind: TrustKind,\r\n target: string | undefined,\r\n options: TrustCommandOptions,\r\n): Promise<void> {\r\n const workspace = options.workspace;\r\n const choice = options.reject ? 'rejected' : 'approved';\r\n const verb = options.reject ? 'Rejected' : 'Approved';\r\n\r\n if (options.allPending && target !== undefined) {\r\n fail(`book trust ${kind}: pass either a target or --all-pending, not both`);\r\n }\r\n if (!options.allPending && target === undefined) {\r\n fail(\r\n `book trust ${kind}: name what to trust, or pass --all-pending. Run \\`book doctor\\` to list what is withheld.`,\r\n );\r\n }\r\n\r\n let settings;\r\n try {\r\n settings = resolveSettings(workspace);\r\n } catch (error) {\r\n return fail(\r\n `book trust ${kind}: cannot read settings for ${workspace}: ${error instanceof Error ? error.message : String(error)}`,\r\n );\r\n }\r\n\r\n // Only the checked-in layer is gated, so only its declarations are decidable.\r\n const projectSettings = loadSettingsFile(join(workspace, '.book', 'settings.json'));\r\n\r\n // A command decision carries the fingerprint of the shell it was made\r\n // against, so the body cannot change under an approval already on file.\r\n const decisions: Array<{ key: string; label: string; fingerprint?: string }> = [];\r\n\r\n if (kind === 'command') {\r\n // Commands are discovered from disk, not declared in settings: the gated\r\n // artefact is the `.book/commands/*.md` body itself.\r\n const partition = partitionProjectCommands(discoverCommands(workspace), settings);\r\n const push = (command: SlashCommand) => {\r\n // Approving is approving the shell, so the shell is what gets shown —\r\n // never just the name. The single-command path reaches here from a\r\n // refusal that already listed it; `--all-pending` has no such prior, and\r\n // a bulk grant against a list of names is approval without reading.\r\n if (!options.reject) {\r\n console.log(`/${displayableCommandName(command.name)} runs:`);\r\n for (const line of describeProjectCommandShell(command)) console.log(` ${line}`);\r\n }\r\n decisions.push({\r\n key: command.name,\r\n label: `/${displayableCommandName(command.name)}`,\r\n fingerprint: projectCommandFingerprint(command.body),\r\n });\r\n };\r\n\r\n if (options.allPending) {\r\n if (partition.pending.length === 0) {\r\n console.log(`No project commands are awaiting a decision in ${workspace}.`);\r\n return;\r\n }\r\n for (const command of partition.pending) push(command);\r\n } else {\r\n const name = target!.replace(/^\\//, '');\r\n const decidable = [...partition.pending, ...partition.approved, ...partition.rejected];\r\n const command = decidable.find((candidate) => candidate.name === name);\r\n if (!command) {\r\n // Either the command does not exist, or it substitutes no shell and so\r\n // has nothing to decide. Both mean this decision would change nothing.\r\n const known = partition.pending\r\n .map((pending) => ` /${displayableCommandName(pending.name)}`)\r\n .join('\\n');\r\n return fail(\r\n `book trust command: ${workspace} has no project command \"${name}\" that runs shell.` +\r\n (known ? `\\nAwaiting a decision:\\n${known}` : '\\nNothing is awaiting a decision.'),\r\n );\r\n }\r\n push(command);\r\n }\r\n } else if (kind === 'hook') {\r\n const declared = collectDeclaredHooks(projectSettings);\r\n const byFingerprint = new Map(\r\n declared.map((hook) => [hookFingerprint(hook.event, hook.entry), hook]),\r\n );\r\n const partition = partitionProjectHooks(declared, settings.hooks.projectEntries);\r\n\r\n if (options.allPending) {\r\n if (partition.pending.length === 0) {\r\n console.log(`No project-declared hooks are awaiting a decision in ${workspace}.`);\r\n return;\r\n }\r\n for (const hook of partition.pending) {\r\n const fingerprint = hookFingerprint(hook.event, hook.entry);\r\n decisions.push({ key: fingerprint, label: describeDeclaredHook(hook).headline });\r\n }\r\n } else {\r\n const hook = byFingerprint.get(target!);\r\n if (!hook) {\r\n // A typo would otherwise record a decision that matches no hook and\r\n // silently changes nothing.\r\n const known = partition.pending\r\n .map(\r\n (pending) =>\r\n ` ${hookFingerprint(pending.event, pending.entry)} ${describeDeclaredHook(pending).headline}`,\r\n )\r\n .join('\\n');\r\n return fail(\r\n `book trust hook: no project-declared hook in ${workspace} has fingerprint \"${target}\".` +\r\n (known ? `\\nAwaiting a decision:\\n${known}` : '\\nNothing is awaiting a decision.'),\r\n );\r\n }\r\n decisions.push({ key: target!, label: describeDeclaredHook(hook).headline });\r\n }\r\n } else {\r\n const declared = projectSettings?.permissions?.allow ?? [];\r\n const partition = partitionProjectAllowRules(declared, settings.permissions.projectAllowRules);\r\n\r\n if (options.allPending) {\r\n if (partition.pending.length === 0) {\r\n console.log(`No project-declared allow rules are awaiting a decision in ${workspace}.`);\r\n return;\r\n }\r\n for (const rule of partition.pending) decisions.push({ key: rule, label: rule });\r\n } else {\r\n if (!declared.includes(target!)) {\r\n const known = partition.pending.map((rule) => ` ${rule}`).join('\\n');\r\n return fail(\r\n `book trust rule: ${workspace} declares no project allow rule \"${target}\".` +\r\n (known ? `\\nAwaiting a decision:\\n${known}` : '\\nNothing is awaiting a decision.'),\r\n );\r\n }\r\n decisions.push({ key: target!, label: target! });\r\n }\r\n }\r\n\r\n const failures: string[] = [];\r\n for (const decision of decisions) {\r\n const result =\r\n kind === 'command'\r\n ? persistProjectCommandChoice(workspace, decision.key, decision.fingerprint!, choice)\r\n : kind === 'hook'\r\n ? persistProjectHookChoice(workspace, decision.key, choice)\r\n : persistProjectAllowRuleChoice(workspace, decision.key, choice);\r\n if (result.ok) console.log(`${verb} ${decision.label}`);\r\n else failures.push(`${decision.label}: ${result.error ?? 'unknown error'}`);\r\n }\r\n\r\n if (failures.length > 0) {\r\n fail(\r\n `Failed to record ${failures.length} decision(s):\\n${failures.map((f) => ` ${f}`).join('\\n')}`,\r\n );\r\n }\r\n}\r\n","import { render } from 'ink';\r\nimport { createElement } from 'react';\r\nimport { freezeAgentConfig, loadConfig } from '../config.js';\r\nimport { runHeadless } from '../headless.js';\r\nimport { createDefaultRegistry } from '../tools/registry.js';\r\nimport { SessionStore } from '../session/store.js';\r\nimport { connectMcpServers, disconnectMcpServers } from '../mcp.js';\r\nimport { McpSessionHost } from '../mcp-host.js';\r\nimport { mcpServersToRecord, partitionMcpServersByApproval } from '../mcp-approvals.js';\r\nimport { resolveMcpServerList } from '../mcp-config.js';\r\nimport { collectWithheldProjectNotices } from '../project-approval-notices.js';\r\nimport { exit, isExiting } from './exit.js';\r\nimport { parseNumericFlag } from './utils.js';\r\nimport { parseEffortLevel } from '../commands/effort.js';\r\nimport { join } from 'path';\r\nimport type { AgentConfig } from '../types/runtime.js';\r\nimport type { RewindSnapshotStoreInterface } from '../types/sessions.js';\r\nimport type { HeadlessResult } from '../types/public-sdk.js';\r\nimport { resolveSessionBootstrap } from '../session/resolve.js';\r\nimport {\r\n createRewindSnapshotStore,\r\n createUnavailableRewindSnapshotStore,\r\n} from '../rewind/snapshot-store.js';\r\nimport { createEphemeralRewindEnvironment } from '../rewind/environment.js';\r\nimport {\r\n cleanupDebugLogs,\r\n DEFAULT_LOCAL_DATA_RETENTION_DAYS,\r\n getDebugLogPath,\r\n} from '../debug-log.js';\r\nimport { installInkScrollRenderer } from './ink-scroll-renderer.js';\r\nimport { installFrameCapture } from './frame-buffer.js';\r\nimport { isInkIncrementalRendererPatched } from './ink-patch.js';\r\nimport { resolveTuiRendererMode } from './tui-renderer-mode.js';\r\nimport { resolvePermissionMode } from '../permission-mode.js';\r\nimport { spawn } from 'node:child_process';\r\nimport { resolveBookHome } from '../book-home.js';\r\n\r\nconst SESSION_ROOT = join(resolveBookHome(), 'sessions');\r\nconst ENTER_ALT_SCREEN = '\\x1b[?1049h';\r\nconst EXIT_ALT_SCREEN = '\\x1b[?1049l';\r\n/**\r\n * Every mouse-reporting mode a terminal may have on, not just the ones Book\r\n * sets. Clear stale modes before enabling the narrow mode Book needs, and\r\n * clear them all again on exit so a crashed session cannot leak reports into\r\n * the next shell prompt.\r\n */\r\nconst DISABLE_MOUSE_REPORTING =\r\n '\\x1b[?1000l' + '\\x1b[?1002l' + '\\x1b[?1003l' + '\\x1b[?1006l' + '\\x1b[?1015l';\r\nconst ENABLE_BUTTON_EVENT_TRACKING = '\\x1b[?1002h';\r\nconst ENABLE_SGR_MOUSE = '\\x1b[?1006h';\r\n/**\r\n * Alternate scroll translates the wheel into cursor keys while the alternate\r\n * screen is up. Book handles SGR wheel reports itself, so cursor-key emulation\r\n * must stay off for the session and is handed back on exit.\r\n */\r\nconst DISABLE_ALTERNATE_SCROLL = '\\x1b[?1007l';\r\nconst RESTORE_ALTERNATE_SCROLL = '\\x1b[?1007h';\r\nconst WSL_TERMINAL_BRIDGE_SCRIPT = `\r\nfor process in /proc/[0-9]*; do\r\n [ -r \"$process/environ\" ] || continue\r\n /usr/bin/grep -Fzqx \"WT_SESSION=$2\" \"$process/environ\" 2>/dev/null || continue\r\n target=$(/usr/bin/readlink \"$process/fd/1\" 2>/dev/null) || continue\r\n case \"$target\" in\r\n /dev/pts/*)\r\n /usr/bin/printf '%s' \"$1\" > \"$process/fd/1\"\r\n exit $?\r\n ;;\r\n esac\r\ndone\r\nexit 1\r\n`.trim();\r\n\r\nexport function shouldBridgeWslTerminal(\r\n platform = process.platform,\r\n env: NodeJS.ProcessEnv = process.env,\r\n): boolean {\r\n const sharedVariables = (env.WSLENV ?? '').split(':').map((entry) => entry.split('/')[0]);\r\n return platform === 'win32' && Boolean(env.WT_SESSION) && sharedVariables.includes('WT_SESSION');\r\n}\r\n\r\nfunction writeTerminalControl(stdout: Pick<NodeJS.WriteStream, 'write'>, sequence: string): void {\r\n stdout.write(sequence);\r\n if (stdout !== process.stdout || !shouldBridgeWslTerminal()) return;\r\n\r\n // A Windows process launched from WSL writes through an inner ConPTY. Find\r\n // the WSL proxy for this terminal session and write modes to its real PTY.\r\n try {\r\n const bridge = spawn(\r\n 'wsl.exe',\r\n [\r\n '-e',\r\n 'sh',\r\n '-c',\r\n WSL_TERMINAL_BRIDGE_SCRIPT,\r\n 'book-terminal-bridge',\r\n sequence,\r\n process.env.WT_SESSION!,\r\n ],\r\n {\r\n detached: true,\r\n stdio: 'ignore',\r\n windowsHide: true,\r\n },\r\n );\r\n bridge.on('error', () => {});\r\n bridge.unref();\r\n } catch {\r\n // Terminal restoration remains best effort when the WSL bridge is unavailable.\r\n }\r\n}\r\n\r\nfunction collectSnapshotReferences(store: SessionStore, cwd: string): Set<string> {\r\n return store.listSnapshotReferences(cwd);\r\n}\r\n\r\nexport function enterInteractiveScreen(\r\n stdout: Pick<NodeJS.WriteStream, 'isTTY' | 'write'> = process.stdout,\r\n /** Injectable so the non-TTY bridge path is testable off win32. */\r\n bridgeWslTerminal: boolean = shouldBridgeWslTerminal(),\r\n): () => void {\r\n if (!stdout.isTTY && !bridgeWslTerminal) return () => {};\r\n\r\n let restored = false;\r\n const restore = () => {\r\n if (restored) return;\r\n restored = true;\r\n writeTerminalControl(\r\n stdout,\r\n DISABLE_MOUSE_REPORTING + RESTORE_ALTERNATE_SCROLL + EXIT_ALT_SCREEN,\r\n );\r\n process.off('exit', restore);\r\n };\r\n\r\n writeTerminalControl(\r\n stdout,\r\n ENTER_ALT_SCREEN +\r\n DISABLE_MOUSE_REPORTING +\r\n DISABLE_ALTERNATE_SCROLL +\r\n ENABLE_BUTTON_EVENT_TRACKING +\r\n ENABLE_SGR_MOUSE,\r\n );\r\n process.once('exit', restore);\r\n return restore;\r\n}\r\n\r\nexport async function runMainAction(options: Record<string, unknown>): Promise<void> {\r\n try {\r\n const requestedWorkspace = options.workspace as string | undefined;\r\n // Validated again here rather than trusted from commander: the option parser\r\n // covers the CLI, this covers every other caller of runMainAction.\r\n const effortOverride = options.effort\r\n ? parseEffortLevel(String(options.effort), '--effort')\r\n : undefined;\r\n const config = loadConfig(requestedWorkspace, {\r\n settingsOverridePath: options.settings as string | undefined,\r\n noSettings: options.settings === false,\r\n runMigrations: options.settings !== false,\r\n modelOverride: options.model as string | undefined,\r\n effortOverride,\r\n allowMissingApiKey: options.print === undefined && !options.scrollback,\r\n }) as AgentConfig;\r\n // Stderr, so it cannot corrupt --output-format json on stdout.\r\n if (config.modelProviderWarning) console.warn('⚠ ' + config.modelProviderWarning);\r\n const interactiveMaxTurns = parseNumericFlag(options.maxTurns, '--max-turns', {\r\n integer: true,\r\n });\r\n if (interactiveMaxTurns !== undefined) config.maxTurns = interactiveMaxTurns;\r\n if (options.agents) {\r\n const agentsMode = String(options.agents);\r\n if (!['adaptive', 'manual', 'off'].includes(agentsMode)) {\r\n throw new Error('--agents must be adaptive, manual, or off');\r\n }\r\n config.settings.agents.mode = agentsMode as 'adaptive' | 'manual' | 'off';\r\n }\r\n if (options.provider) {\r\n const VALID_PROVIDERS = new Set(['anthropic', 'openai', 'auto']);\r\n const raw = String(options.provider).trim().toLowerCase();\r\n if (VALID_PROVIDERS.has(raw)) {\r\n config.provider = raw as AgentConfig['provider'];\r\n }\r\n }\r\n freezeAgentConfig(config);\r\n cleanupDebugLogs(DEFAULT_LOCAL_DATA_RETENTION_DAYS, getDebugLogPath());\r\n\r\n // Headless / print mode.\r\n if (options.print !== undefined) {\r\n // Connect approved MCP servers and merge their tools into the registry.\r\n // Project-declared servers need a prior interactive approval; there is\r\n // no prompt to give one here.\r\n // Repository-declared allow rules and hooks are withheld until the user\r\n // decides on them; a non-interactive host cannot ask, so it reports and\r\n // continues.\r\n for (const notice of collectWithheldProjectNotices({\r\n workspace: config.workspace,\r\n settings: config.settings,\r\n settingsEnabled: options.settings !== false,\r\n })) {\r\n console.warn(notice);\r\n }\r\n const declaredMcpServers = resolveMcpServerList(config.workspace);\r\n const mcpPartition = partitionMcpServersByApproval(declaredMcpServers, config.settings);\r\n for (const server of mcpPartition.pending) {\r\n console.warn(\r\n `⚠ Skipping MCP server \"${server.name}\" (${server.path}): project-declared servers require one-time approval. Approve it in an interactive session first.`,\r\n );\r\n }\r\n const mcp = await connectMcpServers(config.workspace, {\r\n servers: mcpServersToRecord(mcpPartition.allowed),\r\n });\r\n let result: HeadlessResult | undefined;\r\n try {\r\n const registry = createDefaultRegistry({ agents: config.settings.agents.mode !== 'off' });\r\n if (mcp.tools.length > 0) {\r\n registry.registerAll(mcp.tools);\r\n }\r\n\r\n const mode = resolvePermissionMode(config.settings, options.permissionMode);\r\n\r\n const sessionStore = (options.sessionPersistence as boolean)\r\n ? new SessionStore(SESSION_ROOT)\r\n : undefined;\r\n const bootstrap = resolveSessionBootstrap(sessionStore, {\r\n cwd: config.workspace,\r\n resume: options.resume as string | undefined,\r\n continue: options.continue as boolean | undefined,\r\n sessionId: options.sessionId as string | undefined,\r\n sessionName: options.name as string | undefined,\r\n forkSession: options.forkSession as boolean | undefined,\r\n });\r\n sessionStore?.cleanup(DEFAULT_LOCAL_DATA_RETENTION_DAYS, new Set([bootstrap.sessionId]));\r\n\r\n result = await runHeadless(config, registry, {\r\n prompt: typeof options.print === 'string' ? (options.print as string) : undefined,\r\n inputFormat: options.inputFormat as 'text' | 'stream-json',\r\n outputFormat: options.outputFormat as 'text' | 'json' | 'stream-json',\r\n history: bootstrap.history,\r\n transcript: bootstrap.transcript,\r\n compactBoundaries: bootstrap.compactBoundaries,\r\n plan: bootstrap.plan,\r\n carriedUsage: bootstrap.carriedUsage,\r\n carriedModels: bootstrap.carriedModels,\r\n mode,\r\n signal: options.signal as AbortSignal | undefined,\r\n maxTurns: parseNumericFlag(options.maxTurns, '--max-turns', { integer: true }),\r\n maxBudgetUsd: parseNumericFlag(options.maxBudgetUsd, '--max-budget-usd'),\r\n verbose: options.verbose as boolean | undefined,\r\n jsonSchema: options.jsonSchema ? JSON.parse(options.jsonSchema as string) : undefined,\r\n sessionStore,\r\n sessionId: bootstrap.sessionId,\r\n sessionName: bootstrap.sessionName,\r\n forkSession: false,\r\n sessionCreated: bootstrap.created,\r\n persistSession: options.sessionPersistence as boolean | undefined,\r\n includeHookEvents: options.includeHookEvents as boolean | undefined,\r\n includePartialMessages: options.includePartialMessages as boolean | undefined,\r\n promptSuggestions: options.promptSuggestions as boolean | undefined,\r\n });\r\n } finally {\r\n await disconnectMcpServers(mcp.connections);\r\n }\r\n if (result?.outcome.status === 'failed') {\r\n exit(1);\r\n }\r\n return;\r\n }\r\n\r\n // Interactive TUI mode.\r\n const mode = resolvePermissionMode(config.settings, options.permissionMode);\r\n if (options.scrollback) {\r\n const { runScrollbackSession } = await import('./scrollback.js');\r\n await runScrollbackSession(config, { mode });\r\n return;\r\n }\r\n\r\n const sessionStore = (options.sessionPersistence as boolean)\r\n ? new SessionStore(SESSION_ROOT)\r\n : undefined;\r\n const ephemeralRewind = sessionStore\r\n ? undefined\r\n : createEphemeralRewindEnvironment(config.workspace);\r\n const timelineStore = sessionStore ?? ephemeralRewind!.timelineStore;\r\n let snapshotStore: RewindSnapshotStoreInterface = sessionStore\r\n ? createRewindSnapshotStore(config.workspace)\r\n : ephemeralRewind!.snapshotStore;\r\n if (sessionStore) {\r\n try {\r\n snapshotStore.cleanup(collectSnapshotReferences(sessionStore, config.workspace), 30);\r\n } catch (error) {\r\n snapshotStore = createUnavailableRewindSnapshotStore(\r\n `Code rewind unavailable: snapshot cleanup failed (${error instanceof Error ? error.message : String(error)}).`,\r\n );\r\n }\r\n }\r\n const bootstrap = resolveSessionBootstrap(sessionStore, {\r\n cwd: config.workspace,\r\n resume: options.resume as string | undefined,\r\n continue: options.continue as boolean | undefined,\r\n sessionId: options.sessionId as string | undefined,\r\n sessionName: options.name as string | undefined,\r\n forkSession: options.forkSession as boolean | undefined,\r\n });\r\n sessionStore?.cleanup(DEFAULT_LOCAL_DATA_RETENTION_DAYS, new Set([bootstrap.sessionId]));\r\n if (!sessionStore) {\r\n timelineStore.create({\r\n id: bootstrap.sessionId,\r\n cwd: config.workspace,\r\n name: bootstrap.sessionName,\r\n });\r\n }\r\n\r\n const [{ App }, { loadInteractiveAssets }] = await Promise.all([\r\n import('../tui/app.js'),\r\n import('../tui/interactive-assets.js'),\r\n ]);\r\n const interactiveAssets = loadInteractiveAssets(config);\r\n // Session MCP owner: user-global and previously approved project servers\r\n // connect in the background; unapproved project servers surface as a\r\n // one-time trust prompt inside the TUI.\r\n const mcpHost = new McpSessionHost(config.workspace, config.settings);\r\n mcpHost.start();\r\n let app: ReturnType<typeof render> | undefined;\r\n const redrawViewport = () => {\r\n app?.clear();\r\n process.stdout.write('\\x1b[H\\x1b[2J');\r\n };\r\n const restoreScreen = config.accessibility.screenReader\r\n ? () => {}\r\n : enterInteractiveScreen(process.stdout);\r\n try {\r\n const rendererMode = resolveTuiRendererMode(process.env.BOOK_TUI_RENDERER, {\r\n isTTY: process.stdout.isTTY === true,\r\n screenReader: config.accessibility.screenReader,\r\n incrementalRendererPatched: isInkIncrementalRendererPatched(),\r\n platform: process.platform,\r\n });\r\n await installInkScrollRenderer(rendererMode === 'experimental-scroll');\r\n await installFrameCapture();\r\n app = render(\r\n createElement(App, {\r\n config,\r\n permissionMode: mode,\r\n interactiveAssets,\r\n redrawViewport,\r\n mcp: mcpHost,\r\n session: { ...bootstrap, store: sessionStore, timelineStore, snapshotStore },\r\n }),\r\n {\r\n exitOnCtrlC: false,\r\n isScreenReaderEnabled: config.accessibility.screenReader,\r\n incrementalRendering: rendererMode !== 'safe',\r\n maxFps: 60,\r\n },\r\n );\r\n await app.waitUntilExit();\r\n } finally {\r\n app?.cleanup();\r\n restoreScreen();\r\n await mcpHost.dispose();\r\n ephemeralRewind?.dispose();\r\n }\r\n } catch (e) {\r\n if (isExiting()) throw e;\r\n console.error(e instanceof Error ? e.message : String(e));\r\n exit(1);\r\n }\r\n}\r\n","/**\r\n * Session-scoped MCP owner for interactive hosts.\r\n *\r\n * Resolves declared servers, enforces the project-server approval boundary,\r\n * connects approved servers in the background, and exposes a subscribe/snapshot\r\n * surface plus live tool definitions for per-send registry assembly. All\r\n * diagnostics route through the debug log — never the console — so Ink output\r\n * stays intact.\r\n */\r\nimport type { ChildProcess } from 'child_process';\r\nimport {\r\n buildMcpToolDefinitions,\r\n connectMcpServers,\r\n disconnectMcpServers,\r\n type McpConnection,\r\n} from './mcp.js';\r\nimport {\r\n formatMcpServerCommand,\r\n resolveMcpServerList,\r\n type McpServerSource,\r\n type ResolvedMcpServer,\r\n} from './mcp-config.js';\r\nimport {\r\n evaluateMcpServerApproval,\r\n mcpServerFingerprint,\r\n persistMcpProjectServerChoice,\r\n} from './mcp-approvals.js';\r\nimport { createDebugLogger } from './debug-log.js';\r\nimport type { McpSettings } from './settings.js';\r\nimport type { ElicitationHandler, ToolDefinition } from './types/tools.js';\r\n\r\nconst log = createDebugLogger('mcp');\r\n\r\nexport type McpServerStatus =\r\n | 'pending-approval'\r\n | 'deferred'\r\n | 'rejected'\r\n | 'connecting'\r\n | 'connected'\r\n | 'disconnected'\r\n | 'failed';\r\n\r\nexport interface McpHostServerSnapshot {\r\n name: string;\r\n source: McpServerSource;\r\n path: string;\r\n /** Full non-secret connection target the user is trusting. */\r\n target: string;\r\n envKeys: string[];\r\n headerKeys: string[];\r\n fingerprint: string;\r\n status: McpServerStatus;\r\n /** True when a recorded decision exists but the config changed since. */\r\n configChangedSinceApproval: boolean;\r\n toolCount?: number;\r\n error?: string;\r\n}\r\n\r\nexport type McpHostEvent =\r\n | { id: number; type: 'connected'; server: string; toolCount: number }\r\n | { id: number; type: 'disconnected'; server: string }\r\n | { id: number; type: 'failed'; server: string; error: string }\r\n | { id: number; type: 'tools-changed'; server: string; toolCount: number };\r\n\r\ntype McpHostEventInput<T = McpHostEvent> = T extends McpHostEvent ? Omit<T, 'id'> : never;\r\n\r\nexport interface McpHostSnapshot {\r\n servers: McpHostServerSnapshot[];\r\n /** Project servers awaiting a user decision, in declaration order. */\r\n pendingApprovals: McpHostServerSnapshot[];\r\n /** Bounded event feed with monotonic IDs; hosts track the last consumed ID. */\r\n events: McpHostEvent[];\r\n}\r\n\r\nexport interface McpSessionHostOptions {\r\n home?: string;\r\n initializationTimeoutMs?: number;\r\n requestTimeoutMs?: number;\r\n /** Injectable for tests; defaults to the settings.local.json writer. */\r\n persistChoice?: typeof persistMcpProjectServerChoice;\r\n /** Lifecycle observer for spawned server processes. */\r\n onProcessSpawn?: (name: string, process: ChildProcess) => void;\r\n /** Injectable connector used by lifecycle tests. */\r\n connectServers?: typeof connectMcpServers;\r\n}\r\n\r\nconst MAX_EVENTS = 50;\r\n\r\ninterface HostServerState {\r\n server: ResolvedMcpServer;\r\n fingerprint: string;\r\n status: McpServerStatus;\r\n configChangedSinceApproval: boolean;\r\n toolCount?: number;\r\n error?: string;\r\n}\r\n\r\ninterface McpApprovalSettings {\r\n mcp?: Partial<McpSettings>;\r\n}\r\n\r\nexport class McpSessionHost {\r\n private readonly states = new Map<string, HostServerState>();\r\n private readonly connections: McpConnection[] = [];\r\n private readonly listeners = new Set<() => void>();\r\n private readonly events: McpHostEvent[] = [];\r\n private readonly abortController = new AbortController();\r\n private readonly persistChoice: typeof persistMcpProjectServerChoice;\r\n private elicitationHandler?: ElicitationHandler;\r\n private nextEventId = 1;\r\n private snapshot: McpHostSnapshot = { servers: [], pendingApprovals: [], events: [] };\r\n private started = false;\r\n private disposed = false;\r\n\r\n constructor(\r\n private readonly workspace: string,\r\n private readonly settings: McpApprovalSettings,\r\n private readonly options: McpSessionHostOptions = {},\r\n ) {\r\n this.persistChoice = options.persistChoice ?? persistMcpProjectServerChoice;\r\n }\r\n\r\n /** Resolve declared servers and begin connecting every already-trusted one. */\r\n start(): void {\r\n if (this.started || this.disposed) return;\r\n this.started = true;\r\n const servers = resolveMcpServerList(this.workspace, {\r\n home: this.options.home,\r\n onDiagnostic: (diagnostic) => log.debug(diagnostic.message),\r\n });\r\n for (const server of servers) {\r\n const approval = evaluateMcpServerApproval(this.settings, server);\r\n const recorded = this.settings.mcp?.projectServers?.[server.name];\r\n const fingerprint = mcpServerFingerprint(server.config);\r\n this.states.set(server.name, {\r\n server,\r\n fingerprint,\r\n status:\r\n approval === 'approved'\r\n ? 'connecting'\r\n : approval === 'rejected'\r\n ? 'rejected'\r\n : 'pending-approval',\r\n configChangedSinceApproval:\r\n approval === 'unknown' && recorded !== undefined && recorded.fingerprint !== fingerprint,\r\n });\r\n }\r\n this.rebuildSnapshot();\r\n for (const state of this.states.values()) {\r\n if (state.status === 'connecting') void this.connect(state);\r\n }\r\n }\r\n\r\n /** Persist approval for a pending project server and connect it. */\r\n approve(name: string): { ok: boolean; error?: string } {\r\n const state = this.states.get(name);\r\n if (!state || state.status !== 'pending-approval') {\r\n return { ok: false, error: `No pending approval for MCP server \"${name}\".` };\r\n }\r\n const persisted = this.persistChoice(this.workspace, name, state.fingerprint, 'approved');\r\n if (!persisted.ok) return persisted;\r\n state.status = 'connecting';\r\n state.configChangedSinceApproval = false;\r\n this.rebuildSnapshot();\r\n void this.connect(state);\r\n return { ok: true };\r\n }\r\n\r\n /** Persist rejection for a pending project server. */\r\n reject(name: string): { ok: boolean; error?: string } {\r\n const state = this.states.get(name);\r\n if (!state || state.status !== 'pending-approval') {\r\n return { ok: false, error: `No pending approval for MCP server \"${name}\".` };\r\n }\r\n const persisted = this.persistChoice(this.workspace, name, state.fingerprint, 'rejected');\r\n if (!persisted.ok) return persisted;\r\n state.status = 'rejected';\r\n this.rebuildSnapshot();\r\n return { ok: true };\r\n }\r\n\r\n /** Leave a pending server undecided for this session (re-prompts next session). */\r\n defer(name: string): void {\r\n const state = this.states.get(name);\r\n if (!state || state.status !== 'pending-approval') return;\r\n state.status = 'deferred';\r\n this.rebuildSnapshot();\r\n }\r\n\r\n /** Live tool definitions; hosts call this per send so list changes surface. */\r\n getToolDefinitions(): ToolDefinition[] {\r\n return buildMcpToolDefinitions(this.connections, this.options.requestTimeoutMs);\r\n }\r\n\r\n getSnapshot(): McpHostSnapshot {\r\n return this.snapshot;\r\n }\r\n\r\n subscribe(listener: () => void): () => void {\r\n this.listeners.add(listener);\r\n return () => this.listeners.delete(listener);\r\n }\r\n\r\n /** Install the host prompt used to answer server elicitation requests. */\r\n setElicitationHandler(handler: ElicitationHandler | undefined): void {\r\n this.elicitationHandler = handler;\r\n }\r\n\r\n async dispose(): Promise<void> {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n this.abortController.abort(new Error('MCP host disposed'));\r\n await disconnectMcpServers(this.connections);\r\n this.listeners.clear();\r\n }\r\n\r\n private async connect(state: HostServerState): Promise<void> {\r\n const { name } = state.server;\r\n try {\r\n const result = await (this.options.connectServers ?? connectMcpServers)(this.workspace, {\r\n servers: { [name]: state.server.config },\r\n home: this.options.home,\r\n signal: this.abortController.signal,\r\n initializationTimeoutMs: this.options.initializationTimeoutMs,\r\n requestTimeoutMs: this.options.requestTimeoutMs,\r\n onProcessSpawn: this.options.onProcessSpawn,\r\n onDiagnostic: (diagnostic) => log.debug(diagnostic.message),\r\n onToolListChanged: (serverName) => this.handleToolListChanged(serverName),\r\n onConnectionClosed: (serverName) => this.handleConnectionClosed(serverName),\r\n // Stable indirection: servers connect in the background before the UI\r\n // can install its prompt, so the capability is declared up front and\r\n // the handler is resolved per request.\r\n onElicit: (request, context) =>\r\n this.elicitationHandler\r\n ? this.elicitationHandler(request, context)\r\n : Promise.resolve({ action: 'decline' as const }),\r\n });\r\n const connection = result.connections[0];\r\n if (this.disposed) {\r\n if (connection) await disconnectMcpServers([connection]);\r\n return;\r\n }\r\n if (!connection) {\r\n state.status = 'failed';\r\n state.error = 'connection failed (see debug log)';\r\n this.pushEvent({ type: 'failed', server: name, error: state.error });\r\n return;\r\n }\r\n if (connection.closed) {\r\n state.status = 'failed';\r\n state.error = 'connection closed during startup';\r\n this.pushEvent({ type: 'failed', server: name, error: state.error });\r\n return;\r\n }\r\n this.connections.push(connection);\r\n state.status = 'connected';\r\n state.toolCount = connection.tools.length;\r\n state.error = undefined;\r\n this.pushEvent({ type: 'connected', server: name, toolCount: connection.tools.length });\r\n } catch (error) {\r\n state.status = 'failed';\r\n state.error = error instanceof Error ? error.message : String(error);\r\n log.debug(`MCP host connect error for \"${name}\": ${state.error}`);\r\n this.pushEvent({ type: 'failed', server: name, error: state.error });\r\n }\r\n }\r\n\r\n private handleToolListChanged(serverName: string): void {\r\n const state = this.states.get(serverName);\r\n const connection = this.connections.find((conn) => conn.name === serverName);\r\n if (!state || !connection) return;\r\n state.toolCount = connection.tools.length;\r\n this.pushEvent({ type: 'tools-changed', server: serverName, toolCount: state.toolCount });\r\n }\r\n\r\n private handleConnectionClosed(serverName: string): void {\r\n if (this.disposed) return;\r\n const state = this.states.get(serverName);\r\n if (!state || state.status !== 'connected') return;\r\n state.status = 'disconnected';\r\n state.error = 'connection closed';\r\n state.toolCount = 0;\r\n this.pushEvent({ type: 'disconnected', server: serverName });\r\n }\r\n\r\n private pushEvent(event: McpHostEventInput): void {\r\n this.events.push({ ...event, id: this.nextEventId++ } as McpHostEvent);\r\n if (this.events.length > MAX_EVENTS) this.events.splice(0, this.events.length - MAX_EVENTS);\r\n this.rebuildSnapshot();\r\n }\r\n\r\n private rebuildSnapshot(): void {\r\n const servers = [...this.states.values()].map((state) => ({\r\n name: state.server.name,\r\n source: state.server.source,\r\n path: state.server.path,\r\n target: formatMcpServerCommand(state.server.config),\r\n envKeys: Object.keys(state.server.config.env ?? {}).sort(),\r\n headerKeys: Object.keys(state.server.config.headers ?? {}).sort(),\r\n fingerprint: state.fingerprint,\r\n status: state.status,\r\n configChangedSinceApproval: state.configChangedSinceApproval,\r\n toolCount: state.toolCount,\r\n error: state.error,\r\n }));\r\n this.snapshot = {\r\n servers,\r\n pendingApprovals: servers.filter((server) => server.status === 'pending-approval'),\r\n events: [...this.events],\r\n };\r\n for (const listener of this.listeners) listener();\r\n }\r\n}\r\n","import {\r\n chmodSync,\r\n existsSync,\r\n lstatSync,\r\n mkdirSync,\r\n readFileSync,\r\n readdirSync,\r\n readlinkSync,\r\n renameSync,\r\n rmSync,\r\n symlinkSync,\r\n unlinkSync,\r\n writeFileSync,\r\n} from 'fs';\r\nimport { lstat, mkdir, readFile, readdir, readlink, rename, rm, writeFile } from 'fs/promises';\r\nimport { createHash, randomUUID } from 'crypto';\r\nimport { dirname, isAbsolute, join, relative, resolve, sep } from 'path';\r\nimport ignore from 'ignore';\r\nimport type {\r\n RewindRestoreResult,\r\n RewindSnapshotCaptureResult,\r\n RewindSnapshotEntry,\r\n RewindSnapshotManifest,\r\n RewindSnapshotStoreInterface,\r\n} from '../types/sessions.js';\r\nimport { resolveBookHome } from '../book-home.js';\r\n\r\nexport const REWIND_MAX_ENTRIES = 20_000;\r\nexport const REWIND_MAX_FILE_BYTES = 16 * 1024 * 1024;\r\nexport const REWIND_MAX_LOGICAL_BYTES = 256 * 1024 * 1024;\r\n\r\nexport interface RewindSnapshotLimits {\r\n maxEntries: number;\r\n maxFileBytes: number;\r\n maxLogicalBytes: number;\r\n}\r\n\r\nconst DEFAULT_IGNORE_PATTERNS = [\r\n '.book/',\r\n 'node_modules/',\r\n '.pnpm-store/',\r\n '.npm/',\r\n '.yarn/',\r\n '.venv/',\r\n 'venv/',\r\n 'env/',\r\n 'dist/',\r\n 'build/',\r\n 'target/',\r\n '.next/',\r\n '.cache/',\r\n '.turbo/',\r\n '.parcel-cache/',\r\n '.gradle/',\r\n 'coverage/',\r\n '__pycache__/',\r\n '.pytest_cache/',\r\n '.mypy_cache/',\r\n '.ruff_cache/',\r\n '.tox/',\r\n '*.pyc',\r\n];\r\n\r\nfunction sha256(value: Buffer | string): string {\r\n return createHash('sha256').update(value).digest('hex');\r\n}\r\n\r\nfunction pathExists(path: string): boolean {\r\n try {\r\n lstatSync(path);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nfunction normalizeWorkspace(workspace: string): string {\r\n const normalized = resolve(workspace);\r\n return process.platform === 'win32' ? normalized.toLowerCase() : normalized;\r\n}\r\n\r\nexport function rewindWorkspaceHash(workspace: string): string {\r\n return sha256(normalizeWorkspace(workspace));\r\n}\r\n\r\nexport function persistentRewindRoot(workspace: string): string {\r\n return join(resolveBookHome(), 'rewind', rewindWorkspaceHash(workspace));\r\n}\r\n\r\nclass UnavailableRewindSnapshotStore implements RewindSnapshotStoreInterface {\r\n constructor(private readonly reason: string) {}\r\n\r\n capture(): RewindSnapshotCaptureResult {\r\n return { ok: false, reason: this.reason };\r\n }\r\n\r\n async captureAsync(): Promise<RewindSnapshotCaptureResult> {\r\n return this.capture();\r\n }\r\n\r\n getCurrentGitHead(): string | undefined {\r\n return undefined;\r\n }\r\n\r\n getManifest(): RewindSnapshotManifest | undefined {\r\n return undefined;\r\n }\r\n\r\n getAvailability() {\r\n return { available: false, reason: this.reason };\r\n }\r\n\r\n restore(): RewindRestoreResult {\r\n return { ok: false, error: this.reason };\r\n }\r\n\r\n rollback(): { ok: false; error: string } {\r\n return { ok: false, error: this.reason };\r\n }\r\n\r\n discardManifest(): void {}\r\n\r\n cleanup() {\r\n return { manifests: 0, blobs: 0 };\r\n }\r\n}\r\n\r\nexport function createUnavailableRewindSnapshotStore(reason: string): RewindSnapshotStoreInterface {\r\n return new UnavailableRewindSnapshotStore(reason);\r\n}\r\n\r\nexport function createRewindSnapshotStore(\r\n workspace: string,\r\n root?: string,\r\n): RewindSnapshotStoreInterface {\r\n try {\r\n return new RewindSnapshotStore(workspace, root);\r\n } catch (error) {\r\n const detail = error instanceof Error ? error.message : String(error);\r\n return createUnavailableRewindSnapshotStore(\r\n `Code rewind unavailable: snapshot storage could not be initialized (${detail}).`,\r\n );\r\n }\r\n}\r\n\r\nfunction readCustomIgnorePatterns(workspace: string): string[] {\r\n const path = join(workspace, '.book', 'rewindignore');\r\n if (!existsSync(path)) return [];\r\n return readFileSync(path, 'utf-8')\r\n .split(/\\r?\\n/)\r\n .map((line) => line.trim())\r\n .filter((line) => line.length > 0 && !line.startsWith('#'));\r\n}\r\n\r\nasync function readCustomIgnorePatternsAsync(workspace: string): Promise<string[]> {\r\n const path = join(workspace, '.book', 'rewindignore');\r\n try {\r\n return (await readFile(path, 'utf-8'))\r\n .split(/\\r?\\n/)\r\n .map((line) => line.trim())\r\n .filter((line) => line.length > 0 && !line.startsWith('#'));\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\r\n throw error;\r\n }\r\n}\r\n\r\nfunction expandNegatedParents(patterns: string[]): string[] {\r\n const expanded: string[] = [];\r\n for (const pattern of patterns) {\r\n if (pattern.startsWith('!') && !pattern.slice(1).startsWith('*')) {\r\n const parts = pattern.slice(1).split('/').filter(Boolean);\r\n for (let index = 1; index < parts.length; index++) {\r\n expanded.push(`!${parts.slice(0, index).join('/')}/`);\r\n }\r\n }\r\n expanded.push(pattern);\r\n }\r\n return expanded;\r\n}\r\n\r\nfunction readOptionalText(path: string): string | undefined {\r\n try {\r\n return readFileSync(path, 'utf-8').trim();\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nfunction resolveGitDirectory(workspace: string): string | undefined {\r\n const dotGit = join(workspace, '.git');\r\n try {\r\n if (lstatSync(dotGit).isDirectory()) return dotGit;\r\n } catch {\r\n return undefined;\r\n }\r\n\r\n const match = /^gitdir:\\s*(.+)$/i.exec(readOptionalText(dotGit) ?? '');\r\n return match ? resolve(dirname(dotGit), match[1]) : undefined;\r\n}\r\n\r\nfunction resolveCommonGitDirectory(gitDirectory: string): string {\r\n const commonDirectory = readOptionalText(join(gitDirectory, 'commondir'));\r\n return commonDirectory ? resolve(gitDirectory, commonDirectory) : gitDirectory;\r\n}\r\n\r\nfunction parseGitHash(value: string | undefined): string | undefined {\r\n const hash = value?.trim();\r\n return hash && /^[0-9a-f]{40,64}$/i.test(hash) ? hash : undefined;\r\n}\r\n\r\nfunction readPackedRef(directory: string, ref: string): string | undefined {\r\n const packedRefs = readOptionalText(join(directory, 'packed-refs'));\r\n if (!packedRefs) return undefined;\r\n for (const line of packedRefs.split(/\\r?\\n/)) {\r\n if (!line || line.startsWith('#') || line.startsWith('^')) continue;\r\n const separator = line.indexOf(' ');\r\n if (separator > 0 && line.slice(separator + 1) === ref) {\r\n return parseGitHash(line.slice(0, separator));\r\n }\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction resolveGitRef(\r\n gitDirectory: string,\r\n commonDirectory: string,\r\n ref: string,\r\n depth = 0,\r\n): string | undefined {\r\n if (\r\n depth > 4 ||\r\n !ref.startsWith('refs/') ||\r\n ref.includes('..') ||\r\n ref.includes('\\\\') ||\r\n ref.includes('\\0')\r\n ) {\r\n return undefined;\r\n }\r\n\r\n for (const directory of new Set([gitDirectory, commonDirectory])) {\r\n const value = readOptionalText(join(directory, ...ref.split('/')));\r\n const hash = parseGitHash(value);\r\n if (hash) return hash;\r\n if (value?.startsWith('ref:')) {\r\n const resolved = resolveGitRef(\r\n gitDirectory,\r\n commonDirectory,\r\n value.slice('ref:'.length).trim(),\r\n depth + 1,\r\n );\r\n if (resolved) return resolved;\r\n }\r\n }\r\n\r\n return (\r\n readPackedRef(gitDirectory, ref) ??\r\n (commonDirectory === gitDirectory ? undefined : readPackedRef(commonDirectory, ref))\r\n );\r\n}\r\n\r\nfunction gitHead(workspace: string): string | undefined {\r\n const gitDirectory = resolveGitDirectory(workspace);\r\n if (!gitDirectory) return undefined;\r\n const head = readOptionalText(join(gitDirectory, 'HEAD'));\r\n const directHash = parseGitHash(head);\r\n if (directHash) return directHash;\r\n if (!head?.startsWith('ref:')) return undefined;\r\n return resolveGitRef(\r\n gitDirectory,\r\n resolveCommonGitDirectory(gitDirectory),\r\n head.slice('ref:'.length).trim(),\r\n );\r\n}\r\n\r\nasync function gitHeadAsync(workspace: string): Promise<string | undefined> {\r\n return gitHead(workspace);\r\n}\r\n\r\nfunction assertSafeRelativePath(path: string): void {\r\n if (!path || path.includes('\\0') || isAbsolute(path) || path.includes('\\\\')) {\r\n throw new Error(`Unsafe rewind path: ${JSON.stringify(path)}`);\r\n }\r\n const segments = path.split('/');\r\n if (segments.some((segment) => !segment || segment === '.' || segment === '..')) {\r\n throw new Error(`Unsafe rewind path: ${JSON.stringify(path)}`);\r\n }\r\n if (segments.includes('.git')) throw new Error('Rewind snapshots may not contain .git paths.');\r\n}\r\n\r\nfunction resolveEntryPath(workspace: string, path: string): string {\r\n assertSafeRelativePath(path);\r\n const target = resolve(workspace, ...path.split('/'));\r\n const rel = relative(workspace, target);\r\n if (rel.startsWith(`..${sep}`) || rel === '..' || isAbsolute(rel)) {\r\n throw new Error(`Rewind path escapes the workspace: ${path}`);\r\n }\r\n return target;\r\n}\r\n\r\ntype WalkedEntry = {\r\n path: string;\r\n absolutePath: string;\r\n kind: RewindSnapshotEntry['kind'];\r\n byteSize: number;\r\n mode: number;\r\n mtimeMs: number;\r\n};\r\n\r\ninterface CachedSnapshotEntry {\r\n kind: RewindSnapshotEntry['kind'];\r\n byteSize: number;\r\n mode: number;\r\n mtimeMs: number;\r\n snapshotEntry: RewindSnapshotEntry;\r\n}\r\n\r\nfunction walkIncludedEntries(\r\n workspace: string,\r\n patterns: string[],\r\n maxEntries = Number.POSITIVE_INFINITY,\r\n): WalkedEntry[] {\r\n const matcher = ignore().add(patterns);\r\n const hasNegations = patterns.some((pattern) => pattern.startsWith('!'));\r\n const entries: WalkedEntry[] = [];\r\n\r\n const visit = (directory: string, prefix: string) => {\r\n const children = readdirSync(directory, { withFileTypes: true }).sort((a, b) =>\r\n a.name.localeCompare(b.name),\r\n );\r\n for (const child of children) {\r\n if (child.name === '.git') continue;\r\n const path = prefix ? `${prefix}/${child.name}` : child.name;\r\n const absolutePath = join(directory, child.name);\r\n if (child.isDirectory()) {\r\n if (!matcher.ignores(`${path}/`) || hasNegations) visit(absolutePath, path);\r\n continue;\r\n }\r\n if (matcher.ignores(path)) continue;\r\n const stat = lstatSync(absolutePath);\r\n if (!stat.isFile() && !stat.isSymbolicLink()) continue;\r\n entries.push({\r\n path,\r\n absolutePath,\r\n kind: stat.isSymbolicLink() ? 'symlink' : 'file',\r\n byteSize: stat.isSymbolicLink() ? Buffer.byteLength(readlinkSync(absolutePath)) : stat.size,\r\n mode: stat.mode,\r\n mtimeMs: stat.mtimeMs,\r\n });\r\n if (entries.length > maxEntries) {\r\n throw new Error(`Code rewind unavailable: checkpoint exceeds ${maxEntries} entries.`);\r\n }\r\n }\r\n };\r\n\r\n visit(workspace, '');\r\n return entries;\r\n}\r\n\r\nasync function walkIncludedEntriesAsync(\r\n workspace: string,\r\n patterns: string[],\r\n maxEntries = Number.POSITIVE_INFINITY,\r\n): Promise<WalkedEntry[]> {\r\n const matcher = ignore().add(patterns);\r\n const hasNegations = patterns.some((pattern) => pattern.startsWith('!'));\r\n const entries: WalkedEntry[] = [];\r\n\r\n const visit = async (directory: string, prefix: string): Promise<void> => {\r\n const children = (await readdir(directory, { withFileTypes: true })).sort((a, b) =>\r\n a.name.localeCompare(b.name),\r\n );\r\n const files: Array<{ child: (typeof children)[number]; path: string; absolutePath: string }> =\r\n [];\r\n for (const child of children) {\r\n if (child.name === '.git') continue;\r\n const path = prefix ? `${prefix}/${child.name}` : child.name;\r\n const absolutePath = join(directory, child.name);\r\n if (child.isDirectory()) {\r\n if (!matcher.ignores(`${path}/`) || hasNegations) await visit(absolutePath, path);\r\n continue;\r\n }\r\n if (matcher.ignores(path)) continue;\r\n files.push({ child, path, absolutePath });\r\n }\r\n const stats = await Promise.all(files.map(({ absolutePath }) => lstat(absolutePath)));\r\n for (let index = 0; index < files.length; index++) {\r\n const { path, absolutePath } = files[index];\r\n const stat = stats[index];\r\n if (!stat.isFile() && !stat.isSymbolicLink()) continue;\r\n entries.push({\r\n path,\r\n absolutePath,\r\n kind: stat.isSymbolicLink() ? 'symlink' : 'file',\r\n byteSize: stat.isSymbolicLink()\r\n ? Buffer.byteLength(await readlink(absolutePath, { encoding: 'utf-8' }))\r\n : stat.size,\r\n mode: stat.mode,\r\n mtimeMs: stat.mtimeMs,\r\n });\r\n if (entries.length > maxEntries) {\r\n throw new Error(`Code rewind unavailable: checkpoint exceeds ${maxEntries} entries.`);\r\n }\r\n }\r\n };\r\n\r\n await visit(workspace, '');\r\n return entries;\r\n}\r\n\r\nfunction writeAtomic(path: string, contents: Buffer | string): void {\r\n mkdirSync(dirname(path), { recursive: true });\r\n const temporary = join(dirname(path), `.book-rewind-${randomUUID()}.tmp`);\r\n try {\r\n writeFileSync(temporary, contents);\r\n renameSync(temporary, path);\r\n } finally {\r\n if (pathExists(temporary)) unlinkSync(temporary);\r\n }\r\n}\r\n\r\nasync function writeAtomicAsync(path: string, contents: Buffer | string): Promise<void> {\r\n await mkdir(dirname(path), { recursive: true });\r\n const temporary = join(dirname(path), `.book-rewind-${randomUUID()}.tmp`);\r\n try {\r\n await writeFile(temporary, contents);\r\n await rename(temporary, path);\r\n } finally {\r\n await rm(temporary, { force: true });\r\n }\r\n}\r\n\r\nasync function pathExistsAsync(path: string): Promise<boolean> {\r\n try {\r\n await lstat(path);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport class RewindSnapshotStore implements RewindSnapshotStoreInterface {\r\n private readonly manifestsRoot: string;\r\n private readonly entrySetsRoot: string;\r\n private readonly blobsRoot: string;\r\n private readonly workspace: string;\r\n private readonly limits: RewindSnapshotLimits;\r\n private fileCache = new Map<string, CachedSnapshotEntry>();\r\n\r\n constructor(\r\n workspace: string,\r\n private readonly root = persistentRewindRoot(workspace),\r\n limits: Partial<RewindSnapshotLimits> = {},\r\n ) {\r\n this.workspace = resolve(workspace);\r\n this.limits = {\r\n maxEntries: limits.maxEntries ?? REWIND_MAX_ENTRIES,\r\n maxFileBytes: limits.maxFileBytes ?? REWIND_MAX_FILE_BYTES,\r\n maxLogicalBytes: limits.maxLogicalBytes ?? REWIND_MAX_LOGICAL_BYTES,\r\n };\r\n this.manifestsRoot = join(root, 'manifests');\r\n this.entrySetsRoot = join(root, 'entry-sets');\r\n this.blobsRoot = join(root, 'blobs');\r\n mkdirSync(this.manifestsRoot, { recursive: true });\r\n mkdirSync(this.entrySetsRoot, { recursive: true });\r\n mkdirSync(this.blobsRoot, { recursive: true });\r\n }\r\n\r\n capture(ignorePatterns?: string[]): RewindSnapshotCaptureResult {\r\n const head = gitHead(this.workspace);\r\n const patterns =\r\n ignorePatterns ??\r\n expandNegatedParents([\r\n ...DEFAULT_IGNORE_PATTERNS,\r\n ...readCustomIgnorePatterns(this.workspace),\r\n ]);\r\n try {\r\n const walked = walkIncludedEntries(this.workspace, patterns, this.limits.maxEntries);\r\n\r\n let logicalBytes = 0;\r\n const entries: RewindSnapshotEntry[] = [];\r\n const nextCache = new Map<string, CachedSnapshotEntry>();\r\n for (const entry of walked) {\r\n if (entry.byteSize > this.limits.maxFileBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\r\n );\r\n }\r\n const cached = this.fileCache.get(entry.path);\r\n if (\r\n cached &&\r\n cached.kind === entry.kind &&\r\n cached.byteSize === entry.byteSize &&\r\n cached.mode === entry.mode &&\r\n cached.mtimeMs === entry.mtimeMs\r\n ) {\r\n logicalBytes += cached.snapshotEntry.byteSize;\r\n if (logicalBytes > this.limits.maxLogicalBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\r\n );\r\n }\r\n entries.push(cached.snapshotEntry);\r\n nextCache.set(entry.path, cached);\r\n continue;\r\n }\r\n const contents =\r\n entry.kind === 'symlink'\r\n ? Buffer.from(readlinkSync(entry.absolutePath), 'utf-8')\r\n : readFileSync(entry.absolutePath);\r\n if (contents.byteLength > this.limits.maxFileBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\r\n );\r\n }\r\n logicalBytes += contents.byteLength;\r\n if (logicalBytes > this.limits.maxLogicalBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\r\n );\r\n }\r\n const blobHash = sha256(contents);\r\n const blobPath = join(this.blobsRoot, blobHash);\r\n if (!existsSync(blobPath)) writeAtomic(blobPath, contents);\r\n const snapshotEntry: RewindSnapshotEntry = {\r\n path: entry.path.replaceAll('\\\\', '/'),\r\n kind: entry.kind,\r\n blobHash,\r\n byteSize: contents.byteLength,\r\n mode: entry.mode,\r\n };\r\n entries.push(snapshotEntry);\r\n nextCache.set(entry.path, {\r\n kind: entry.kind,\r\n byteSize: entry.byteSize,\r\n mode: entry.mode,\r\n mtimeMs: entry.mtimeMs,\r\n snapshotEntry,\r\n });\r\n }\r\n\r\n const manifest: RewindSnapshotManifest = {\r\n version: 1,\r\n id: randomUUID(),\r\n workspace: normalizeWorkspace(this.workspace),\r\n createdAt: Date.now(),\r\n gitHead: head,\r\n ignorePatterns: patterns,\r\n entries,\r\n logicalBytes,\r\n };\r\n this.writeManifest(manifest);\r\n this.fileCache = nextCache;\r\n return { ok: true, manifest };\r\n } catch (error) {\r\n return {\r\n ok: false,\r\n reason: error instanceof Error ? error.message : String(error),\r\n gitHead: head,\r\n };\r\n }\r\n }\r\n\r\n async captureAsync(ignorePatterns?: string[]): Promise<RewindSnapshotCaptureResult> {\r\n let head: string | undefined;\r\n try {\r\n const [resolvedHead, customIgnorePatterns] = await Promise.all([\r\n gitHeadAsync(this.workspace),\r\n ignorePatterns ? Promise.resolve([]) : readCustomIgnorePatternsAsync(this.workspace),\r\n ]);\r\n head = resolvedHead;\r\n const patterns =\r\n ignorePatterns ??\r\n expandNegatedParents([...DEFAULT_IGNORE_PATTERNS, ...customIgnorePatterns]);\r\n const walked = await walkIncludedEntriesAsync(\r\n this.workspace,\r\n patterns,\r\n this.limits.maxEntries,\r\n );\r\n\r\n let logicalBytes = 0;\r\n const entries: RewindSnapshotEntry[] = [];\r\n const nextCache = new Map<string, CachedSnapshotEntry>();\r\n for (const entry of walked) {\r\n if (entry.byteSize > this.limits.maxFileBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\r\n );\r\n }\r\n const cached = this.fileCache.get(entry.path);\r\n if (\r\n cached &&\r\n cached.kind === entry.kind &&\r\n cached.byteSize === entry.byteSize &&\r\n cached.mode === entry.mode &&\r\n cached.mtimeMs === entry.mtimeMs\r\n ) {\r\n logicalBytes += cached.snapshotEntry.byteSize;\r\n if (logicalBytes > this.limits.maxLogicalBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\r\n );\r\n }\r\n entries.push(cached.snapshotEntry);\r\n nextCache.set(entry.path, cached);\r\n continue;\r\n }\r\n const contents =\r\n entry.kind === 'symlink'\r\n ? Buffer.from(await readlink(entry.absolutePath, { encoding: 'utf-8' }), 'utf-8')\r\n : await readFile(entry.absolutePath);\r\n if (contents.byteLength > this.limits.maxFileBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\r\n );\r\n }\r\n logicalBytes += contents.byteLength;\r\n if (logicalBytes > this.limits.maxLogicalBytes) {\r\n throw new Error(\r\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\r\n );\r\n }\r\n const blobHash = sha256(contents);\r\n const blobPath = join(this.blobsRoot, blobHash);\r\n if (!(await pathExistsAsync(blobPath))) await writeAtomicAsync(blobPath, contents);\r\n const snapshotEntry: RewindSnapshotEntry = {\r\n path: entry.path.replaceAll('\\\\', '/'),\r\n kind: entry.kind,\r\n blobHash,\r\n byteSize: contents.byteLength,\r\n mode: entry.mode,\r\n };\r\n entries.push(snapshotEntry);\r\n nextCache.set(entry.path, {\r\n kind: entry.kind,\r\n byteSize: entry.byteSize,\r\n mode: entry.mode,\r\n mtimeMs: entry.mtimeMs,\r\n snapshotEntry,\r\n });\r\n }\r\n\r\n const manifest: RewindSnapshotManifest = {\r\n version: 1,\r\n id: randomUUID(),\r\n workspace: normalizeWorkspace(this.workspace),\r\n createdAt: Date.now(),\r\n gitHead: head,\r\n ignorePatterns: patterns,\r\n entries,\r\n logicalBytes,\r\n };\r\n await this.writeManifestAsync(manifest);\r\n this.fileCache = nextCache;\r\n return { ok: true, manifest };\r\n } catch (error) {\r\n return {\r\n ok: false,\r\n reason: error instanceof Error ? error.message : String(error),\r\n gitHead: head,\r\n };\r\n }\r\n }\r\n\r\n getManifest(id: string): RewindSnapshotManifest | undefined {\r\n if (!/^[a-zA-Z0-9-]+$/.test(id)) return undefined;\r\n const path = join(this.manifestsRoot, `${id}.json`);\r\n if (!existsSync(path)) return undefined;\r\n try {\r\n const stored = JSON.parse(readFileSync(path, 'utf-8')) as RewindSnapshotManifest & {\r\n entrySetHash?: string;\r\n };\r\n let manifest: RewindSnapshotManifest = stored;\r\n if (!Array.isArray(stored.entries) && stored.entrySetHash) {\r\n if (!/^[a-f0-9]{64}$/.test(stored.entrySetHash)) return undefined;\r\n const entriesPath = join(this.entrySetsRoot, `${stored.entrySetHash}.json`);\r\n if (!existsSync(entriesPath)) return undefined;\r\n const serializedEntries = readFileSync(entriesPath, 'utf-8');\r\n if (sha256(serializedEntries) !== stored.entrySetHash) return undefined;\r\n manifest = {\r\n ...stored,\r\n entries: JSON.parse(serializedEntries) as RewindSnapshotEntry[],\r\n };\r\n }\r\n if (\r\n manifest.version !== 1 ||\r\n manifest.id !== id ||\r\n normalizeWorkspace(manifest.workspace) !== normalizeWorkspace(this.workspace) ||\r\n !Array.isArray(manifest.entries)\r\n ) {\r\n return undefined;\r\n }\r\n return manifest;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n getCurrentGitHead(): string | undefined {\r\n return gitHead(this.workspace);\r\n }\r\n\r\n getAvailability(id: string | undefined, expectedGitHead?: string) {\r\n if (!id) return { available: false, reason: 'No filesystem checkpoint was captured.' };\r\n if (!this.getManifest(id)) {\r\n return { available: false, reason: 'The filesystem checkpoint is missing or corrupt.' };\r\n }\r\n if (this.getCurrentGitHead() !== expectedGitHead) {\r\n return {\r\n available: false,\r\n reason: 'Git HEAD changed since this prompt; rewind never moves HEAD or the index.',\r\n };\r\n }\r\n return { available: true };\r\n }\r\n\r\n restore(id: string): RewindRestoreResult {\r\n const manifest = this.getManifest(id);\r\n if (!manifest) return { ok: false, error: 'The filesystem checkpoint is missing or corrupt.' };\r\n const availability = this.getAvailability(id, manifest.gitHead);\r\n if (!availability.available) return { ok: false, error: availability.reason ?? 'Unavailable.' };\r\n\r\n const safety = this.capture(manifest.ignorePatterns);\r\n if (!safety.ok) {\r\n return { ok: false, error: `Could not create a safety snapshot: ${safety.reason}` };\r\n }\r\n if (this.getCurrentGitHead() !== manifest.gitHead) {\r\n this.discardManifest(safety.manifest.id);\r\n return {\r\n ok: false,\r\n error: 'Git HEAD changed while preparing rewind; no files were restored.',\r\n };\r\n }\r\n\r\n try {\r\n this.applyManifest(manifest);\r\n return { ok: true, safetySnapshotId: safety.manifest.id };\r\n } catch (error) {\r\n const rollback = this.applyManifestSafely(safety.manifest);\r\n this.discardManifest(safety.manifest.id);\r\n return {\r\n ok: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n ...(rollback.ok ? {} : { rollbackError: rollback.error }),\r\n };\r\n }\r\n }\r\n\r\n rollback(safetySnapshotId: string): { ok: true } | { ok: false; error: string } {\r\n const manifest = this.getManifest(safetySnapshotId);\r\n if (!manifest) return { ok: false, error: 'The safety snapshot is missing or corrupt.' };\r\n const result = this.applyManifestSafely(manifest);\r\n if (result.ok) this.discardManifest(safetySnapshotId);\r\n return result;\r\n }\r\n\r\n discardManifest(id: string): void {\r\n if (!/^[a-zA-Z0-9-]+$/.test(id)) return;\r\n const path = join(this.manifestsRoot, `${id}.json`);\r\n if (existsSync(path)) unlinkSync(path);\r\n }\r\n\r\n private writeManifest(manifest: RewindSnapshotManifest): void {\r\n const entriesHash = sha256(JSON.stringify(manifest.entries));\r\n const entriesPath = join(this.entrySetsRoot, `${entriesHash}.json`);\r\n if (!existsSync(entriesPath)) writeAtomic(entriesPath, JSON.stringify(manifest.entries));\r\n const metadata = { ...manifest } as Partial<RewindSnapshotManifest> & {\r\n entrySetHash?: string;\r\n };\r\n delete metadata.entries;\r\n writeAtomic(\r\n join(this.manifestsRoot, `${manifest.id}.json`),\r\n JSON.stringify({ ...metadata, entrySetHash: entriesHash }),\r\n );\r\n }\r\n\r\n private async writeManifestAsync(manifest: RewindSnapshotManifest): Promise<void> {\r\n const entriesHash = sha256(JSON.stringify(manifest.entries));\r\n const entriesPath = join(this.entrySetsRoot, `${entriesHash}.json`);\r\n if (!(await pathExistsAsync(entriesPath))) {\r\n await writeAtomicAsync(entriesPath, JSON.stringify(manifest.entries));\r\n }\r\n const metadata = { ...manifest } as Partial<RewindSnapshotManifest> & {\r\n entrySetHash?: string;\r\n };\r\n delete metadata.entries;\r\n await writeAtomicAsync(\r\n join(this.manifestsRoot, `${manifest.id}.json`),\r\n JSON.stringify({ ...metadata, entrySetHash: entriesHash }),\r\n );\r\n }\r\n\r\n cleanup(referencedSnapshotIds: Set<string>, days: number) {\r\n const cutoff = Date.now() - days * 86_400_000;\r\n let manifests = 0;\r\n let blobs = 0;\r\n for (const file of readdirSync(this.manifestsRoot)) {\r\n if (!file.endsWith('.json')) continue;\r\n const id = file.slice(0, -5);\r\n const manifest = this.getManifest(id);\r\n if (referencedSnapshotIds.has(id)) continue;\r\n if (!manifest || manifest.createdAt < cutoff) {\r\n unlinkSync(join(this.manifestsRoot, file));\r\n manifests++;\r\n }\r\n }\r\n\r\n const referencedBlobs = new Set<string>();\r\n const referencedEntrySets = new Set<string>();\r\n for (const file of readdirSync(this.manifestsRoot)) {\r\n if (!file.endsWith('.json')) continue;\r\n const id = file.slice(0, -5);\r\n const manifest = this.getManifest(id);\r\n try {\r\n const stored = JSON.parse(readFileSync(join(this.manifestsRoot, file), 'utf-8')) as {\r\n entrySetHash?: string;\r\n };\r\n if (stored.entrySetHash) referencedEntrySets.add(stored.entrySetHash);\r\n } catch {\r\n // Corrupt manifests are removed or ignored above.\r\n }\r\n for (const entry of manifest?.entries ?? []) referencedBlobs.add(entry.blobHash);\r\n }\r\n for (const file of readdirSync(this.entrySetsRoot)) {\r\n if (!file.endsWith('.json') || referencedEntrySets.has(file.slice(0, -5))) continue;\r\n rmSync(join(this.entrySetsRoot, file), { force: true });\r\n }\r\n for (const file of readdirSync(this.blobsRoot)) {\r\n if (referencedBlobs.has(file)) continue;\r\n rmSync(join(this.blobsRoot, file), { force: true });\r\n blobs++;\r\n }\r\n return { manifests, blobs };\r\n }\r\n\r\n private applyManifestSafely(\r\n manifest: RewindSnapshotManifest,\r\n ): { ok: true } | { ok: false; error: string } {\r\n try {\r\n this.applyManifest(manifest);\r\n return { ok: true };\r\n } catch (error) {\r\n return { ok: false, error: error instanceof Error ? error.message : String(error) };\r\n }\r\n }\r\n\r\n private applyManifest(manifest: RewindSnapshotManifest): void {\r\n if (manifest.entries.length > this.limits.maxEntries) {\r\n throw new Error(`Rewind manifest exceeds ${this.limits.maxEntries} entries.`);\r\n }\r\n const targetPaths = new Set<string>();\r\n let logicalBytes = 0;\r\n for (const entry of manifest.entries) {\r\n resolveEntryPath(this.workspace, entry.path);\r\n if (!['file', 'symlink'].includes(entry.kind) || !Number.isInteger(entry.mode)) {\r\n throw new Error(`Invalid rewind entry for ${entry.path}.`);\r\n }\r\n if (targetPaths.has(entry.path)) throw new Error(`Duplicate rewind path: ${entry.path}.`);\r\n if (!/^[a-f0-9]{64}$/.test(entry.blobHash)) {\r\n throw new Error(`Invalid blob hash for ${entry.path}.`);\r\n }\r\n const blobPath = join(this.blobsRoot, entry.blobHash);\r\n if (!existsSync(blobPath)) throw new Error(`Missing rewind blob for ${entry.path}.`);\r\n const contents = readFileSync(blobPath);\r\n if (sha256(contents) !== entry.blobHash)\r\n throw new Error(`Corrupt rewind blob for ${entry.path}.`);\r\n if (\r\n contents.byteLength !== entry.byteSize ||\r\n contents.byteLength > this.limits.maxFileBytes\r\n ) {\r\n throw new Error(`Invalid rewind size for ${entry.path}.`);\r\n }\r\n logicalBytes += contents.byteLength;\r\n if (logicalBytes > this.limits.maxLogicalBytes) {\r\n throw new Error(`Rewind manifest exceeds ${this.limits.maxLogicalBytes} bytes.`);\r\n }\r\n targetPaths.add(entry.path);\r\n }\r\n\r\n const current = walkIncludedEntries(\r\n this.workspace,\r\n manifest.ignorePatterns,\r\n this.limits.maxEntries,\r\n );\r\n const removals = current\r\n .filter((entry) => !targetPaths.has(entry.path))\r\n .sort((a, b) => b.path.length - a.path.length);\r\n for (const entry of removals) unlinkSync(entry.absolutePath);\r\n\r\n for (const entry of manifest.entries) {\r\n const target = resolveEntryPath(this.workspace, entry.path);\r\n mkdirSync(dirname(target), { recursive: true });\r\n if (pathExists(target) && lstatSync(target).isDirectory()) {\r\n throw new Error(`Cannot restore ${entry.path} because a directory exists at that path.`);\r\n }\r\n const contents = readFileSync(join(this.blobsRoot, entry.blobHash));\r\n const temporary = join(dirname(target), `.book-rewind-${randomUUID()}.tmp`);\r\n try {\r\n if (entry.kind === 'symlink') {\r\n symlinkSync(contents.toString('utf-8'), temporary);\r\n } else {\r\n writeFileSync(temporary, contents, { mode: entry.mode });\r\n chmodSync(temporary, entry.mode);\r\n }\r\n renameSync(temporary, target);\r\n } finally {\r\n if (pathExists(temporary)) unlinkSync(temporary);\r\n }\r\n }\r\n }\r\n}\r\n","import { existsSync, mkdtempSync, rmSync } from 'fs';\r\nimport { tmpdir } from 'os';\r\nimport { join, resolve, sep } from 'path';\r\nimport { SessionStore } from '../session/store.js';\r\nimport type { RewindSnapshotStoreInterface } from '../types/sessions.js';\r\nimport { createRewindSnapshotStore } from './snapshot-store.js';\r\n\r\nexport interface EphemeralRewindEnvironment {\r\n root: string;\r\n timelineStore: SessionStore;\r\n snapshotStore: RewindSnapshotStoreInterface;\r\n dispose: () => void;\r\n}\r\n\r\nexport function createEphemeralRewindEnvironment(\r\n workspace: string,\r\n temporaryRoot = tmpdir(),\r\n): EphemeralRewindEnvironment {\r\n const resolvedTemporaryRoot = resolve(temporaryRoot);\r\n const root = mkdtempSync(join(resolvedTemporaryRoot, 'book-rewind-'));\r\n let disposed = false;\r\n const dispose = () => {\r\n if (disposed) return;\r\n disposed = true;\r\n const resolvedRoot = resolve(root);\r\n if (\r\n resolvedRoot.startsWith(`${resolvedTemporaryRoot}${sep}`) &&\r\n resolvedRoot.split(sep).at(-1)?.startsWith('book-rewind-') &&\r\n existsSync(resolvedRoot)\r\n ) {\r\n rmSync(resolvedRoot, { recursive: true, force: true });\r\n }\r\n process.off('exit', dispose);\r\n };\r\n process.once('exit', dispose);\r\n return {\r\n root,\r\n timelineStore: new SessionStore(join(root, 'sessions')),\r\n snapshotStore: createRewindSnapshotStore(workspace, join(root, 'snapshots')),\r\n dispose,\r\n };\r\n}\r\n","import { readFileSync } from 'node:fs';\r\nimport { createRequire } from 'node:module';\r\nimport { dirname, join } from 'node:path';\r\n\r\nconst INK_PATCH_MARKER = 'ansiEscapes.cursorUp(previousLines.length - 1)';\r\n\r\n/** Incremental rendering is safe only when the Ink trailing-newline patch is present. */\r\nexport function isInkIncrementalRendererPatched(): boolean {\r\n try {\r\n const require = createRequire(import.meta.url);\r\n const logUpdatePath = join(dirname(require.resolve('ink')), 'log-update.js');\r\n return readFileSync(logUpdatePath, 'utf8').includes(INK_PATCH_MARKER);\r\n } catch {\r\n return false;\r\n }\r\n}\r\n","export type TuiRendererMode = 'safe' | 'incremental' | 'experimental-scroll';\r\n\r\ninterface TuiRendererContext {\r\n isTTY?: boolean;\r\n screenReader?: boolean;\r\n incrementalRendererPatched?: boolean;\r\n platform?: NodeJS.Platform;\r\n}\r\n\r\nexport function resolveTuiRendererMode(\r\n value = process.env.BOOK_TUI_RENDERER,\r\n context: TuiRendererContext = {},\r\n): TuiRendererMode {\r\n if (context.isTTY === false || context.screenReader) return 'safe';\r\n if (context.incrementalRendererPatched === false) return 'safe';\r\n if (value === 'incremental') return 'incremental';\r\n if (value === 'experimental-scroll') return 'experimental-scroll';\r\n if (value === undefined) return context.platform === 'win32' ? 'safe' : 'incremental';\r\n return 'safe';\r\n}\r\n","import { existsSync, readFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { resolveBookHome } from '../book-home.js';\r\nimport { evaluateMcpServerApproval } from '../mcp-approvals.js';\r\nimport {\r\n formatMcpServerCommand,\r\n isValidMcpServerName,\r\n resolveMcpServerList,\r\n type McpServerConfig,\r\n type McpServerSource,\r\n type McpTransportType,\r\n} from '../mcp-config.js';\r\nimport { resolveSettings } from '../settings-loader.js';\r\nimport { writeFileAtomic } from '../settings-repository.js';\r\n\r\nexport type McpConfigScope = 'user' | 'project';\r\n\r\nexport interface McpCommandOptions {\r\n workspace: string;\r\n json?: boolean;\r\n /** System-home override used by tests, matching resolveMcpServerList's `home` option. */\r\n home?: string;\r\n}\r\n\r\nexport interface McpAddCommandOptions extends McpCommandOptions {\r\n scope?: McpConfigScope;\r\n transport?: McpTransportType;\r\n env?: string[];\r\n header?: string[];\r\n cwd?: string;\r\n force?: boolean;\r\n}\r\n\r\nexport interface McpRemoveCommandOptions extends McpCommandOptions {\r\n scope?: McpConfigScope;\r\n}\r\n\r\ninterface McpConfigDocument extends Record<string, unknown> {\r\n mcpServers?: Record<string, unknown>;\r\n}\r\n\r\ninterface McpCliServerRecord {\r\n name: string;\r\n source: McpServerSource;\r\n path: string;\r\n transport: McpTransportType;\r\n target: string;\r\n approval: 'user' | 'approved' | 'rejected' | 'unknown';\r\n envKeys: string[];\r\n headerKeys: string[];\r\n}\r\n\r\nfunction configPath(workspace: string, scope: McpConfigScope, home?: string): string {\r\n return scope === 'project'\r\n ? join(workspace, '.mcp.json')\r\n : home\r\n ? join(home, '.book', 'mcp.json')\r\n : join(resolveBookHome(), 'mcp.json');\r\n}\r\n\r\nfunction validScope(scope: string | undefined): McpConfigScope {\r\n const normalized = scope ?? 'user';\r\n if (normalized !== 'user' && normalized !== 'project') {\r\n throw new Error('MCP scope must be \"user\" or \"project\".');\r\n }\r\n return normalized;\r\n}\r\n\r\nfunction readConfigDocument(path: string): McpConfigDocument {\r\n if (!existsSync(path)) return {};\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(readFileSync(path, 'utf8'));\r\n } catch (error) {\r\n throw new Error(\r\n `Cannot update ${path}: ${error instanceof Error ? error.message : String(error)}`,\r\n );\r\n }\r\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\r\n throw new Error(`Cannot update ${path}: expected a JSON object.`);\r\n }\r\n const document = parsed as McpConfigDocument;\r\n if (\r\n document.mcpServers !== undefined &&\r\n (!document.mcpServers ||\r\n typeof document.mcpServers !== 'object' ||\r\n Array.isArray(document.mcpServers))\r\n ) {\r\n throw new Error(`Cannot update ${path}: mcpServers must be an object.`);\r\n }\r\n return document;\r\n}\r\n\r\nfunction parseEntries(kind: 'env' | 'header', entries: string[] = []): Record<string, string> {\r\n const parsed: Record<string, string> = {};\r\n for (const entry of entries) {\r\n const separator = entry.indexOf('=');\r\n if (separator <= 0) throw new Error(`Invalid --${kind} value \"${entry}\"; expected KEY=VALUE.`);\r\n const key = entry.slice(0, separator).trim();\r\n if (!key) throw new Error(`Invalid --${kind} value \"${entry}\"; the key is empty.`);\r\n parsed[key] = entry.slice(separator + 1);\r\n }\r\n return parsed;\r\n}\r\n\r\nfunction validateRemoteUrl(raw: string): string {\r\n let url: URL;\r\n try {\r\n url = new URL(raw);\r\n } catch {\r\n throw new Error('Remote MCP URL must be an absolute http:// or https:// URL.');\r\n }\r\n if (!['http:', 'https:'].includes(url.protocol)) {\r\n throw new Error('Remote MCP URL must use http:// or https://.');\r\n }\r\n if (url.username || url.password) throw new Error('Remote MCP URL must not contain credentials.');\r\n return raw;\r\n}\r\n\r\nfunction inferredTransport(target: string, requested?: McpTransportType): McpTransportType {\r\n if (requested) {\r\n if (!['stdio', 'http', 'sse'].includes(requested)) {\r\n throw new Error('MCP transport must be \"stdio\", \"http\", or \"sse\".');\r\n }\r\n return requested;\r\n }\r\n return /^https?:\\/\\//i.test(target) ? 'http' : 'stdio';\r\n}\r\n\r\nfunction createServerConfig(\r\n target: string,\r\n serverArgs: string[],\r\n options: McpAddCommandOptions,\r\n): McpServerConfig {\r\n const transport = inferredTransport(target, options.transport);\r\n if (transport === 'stdio') {\r\n if (!target.trim()) throw new Error('Stdio MCP command must not be empty.');\r\n if ((options.header?.length ?? 0) > 0) {\r\n throw new Error('--header is available only for HTTP/SSE servers.');\r\n }\r\n return {\r\n type: 'stdio',\r\n command: target,\r\n args: serverArgs,\r\n env: parseEntries('env', options.env),\r\n ...(options.cwd ? { cwd: options.cwd } : {}),\r\n };\r\n }\r\n if (serverArgs.length > 0)\r\n throw new Error('HTTP/SSE MCP servers do not accept command arguments.');\r\n if ((options.env?.length ?? 0) > 0 || options.cwd) {\r\n throw new Error('--env and --cwd are available only for stdio servers.');\r\n }\r\n return {\r\n type: transport,\r\n url: validateRemoteUrl(target),\r\n headers: parseEntries('header', options.header),\r\n };\r\n}\r\n\r\nfunction writeServer(\r\n workspace: string,\r\n scope: McpConfigScope,\r\n name: string,\r\n config: McpServerConfig,\r\n force: boolean,\r\n home?: string,\r\n): string {\r\n const path = configPath(workspace, scope, home);\r\n const document = readConfigDocument(path);\r\n const servers = { ...(document.mcpServers ?? {}) };\r\n if (Object.prototype.hasOwnProperty.call(servers, name) && !force) {\r\n throw new Error(`MCP server \"${name}\" already exists in ${path}; pass --force to replace it.`);\r\n }\r\n servers[name] = config;\r\n writeFileAtomic(path, JSON.stringify({ ...document, mcpServers: servers }, null, 2) + '\\n');\r\n return path;\r\n}\r\n\r\nfunction removeServer(\r\n workspace: string,\r\n scope: McpConfigScope,\r\n name: string,\r\n home?: string,\r\n): string {\r\n const path = configPath(workspace, scope, home);\r\n const document = readConfigDocument(path);\r\n const servers = { ...(document.mcpServers ?? {}) };\r\n if (!Object.prototype.hasOwnProperty.call(servers, name)) {\r\n throw new Error(`MCP server \"${name}\" is not declared in ${path}.`);\r\n }\r\n delete servers[name];\r\n writeFileAtomic(path, JSON.stringify({ ...document, mcpServers: servers }, null, 2) + '\\n');\r\n return path;\r\n}\r\n\r\nfunction serverRecords(workspace: string, home?: string): McpCliServerRecord[] {\r\n const settings = resolveSettings(workspace);\r\n return resolveMcpServerList(workspace, { home }).map((server) => ({\r\n name: server.name,\r\n source: server.source,\r\n path: server.path,\r\n transport: server.config.type ?? (server.config.url ? 'http' : 'stdio'),\r\n target: formatMcpServerCommand(server.config),\r\n approval: server.source === 'user' ? 'user' : evaluateMcpServerApproval(settings, server),\r\n envKeys: Object.keys(server.config.env ?? {}).sort(),\r\n headerKeys: Object.keys(server.config.headers ?? {}).sort(),\r\n }));\r\n}\r\n\r\nfunction printRecords(records: McpCliServerRecord[], json = false): void {\r\n if (json) {\r\n console.log(JSON.stringify(records, null, 2));\r\n return;\r\n }\r\n if (records.length === 0) {\r\n console.log('No MCP servers configured.');\r\n return;\r\n }\r\n for (const server of records) {\r\n console.log(\r\n `${server.name}: ${server.target} [${server.source}${server.source === 'project' ? `: ${server.approval}` : ''}]`,\r\n );\r\n if (server.envKeys.length > 0) console.log(` env: ${server.envKeys.join(', ')}`);\r\n if (server.headerKeys.length > 0) {\r\n console.log(` headers: ${server.headerKeys.join(', ')} (values hidden)`);\r\n }\r\n console.log(` config: ${server.path}`);\r\n }\r\n}\r\n\r\nexport function runMcpListCommand(options: McpCommandOptions): void {\r\n printRecords(serverRecords(options.workspace, options.home), options.json);\r\n}\r\n\r\nexport function runMcpGetCommand(name: string, options: McpCommandOptions): void {\r\n const server = serverRecords(options.workspace, options.home).find(\r\n (candidate) => candidate.name === name,\r\n );\r\n if (!server) throw new Error(`MCP server \"${name}\" is not configured.`);\r\n printRecords([server], options.json);\r\n}\r\n\r\nexport function runMcpAddCommand(\r\n name: string,\r\n target: string,\r\n serverArgs: string[],\r\n options: McpAddCommandOptions,\r\n): void {\r\n if (!isValidMcpServerName(name)) {\r\n throw new Error(\r\n 'MCP server names may contain letters, numbers, hyphens, or underscores, but not a double underscore.',\r\n );\r\n }\r\n const scope = validScope(options.scope);\r\n const config = createServerConfig(target, serverArgs, options);\r\n const path = writeServer(\r\n options.workspace,\r\n scope,\r\n name,\r\n config,\r\n options.force ?? false,\r\n options.home,\r\n );\r\n console.log(`Added MCP server \"${name}\" to ${path}.`);\r\n if (scope === 'project') {\r\n console.log('Project servers require one-time approval in an interactive Book session.');\r\n }\r\n}\r\n\r\nexport function runMcpRemoveCommand(name: string, options: McpRemoveCommandOptions): void {\r\n const scope = options.scope\r\n ? validScope(options.scope)\r\n : serverRecords(options.workspace, options.home).find((candidate) => candidate.name === name)\r\n ?.source;\r\n if (!scope) throw new Error(`MCP server \"${name}\" is not configured.`);\r\n const path = removeServer(options.workspace, scope, name, options.home);\r\n console.log(`Removed MCP server \"${name}\" from ${path}.`);\r\n}\r\n"],"mappings":"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","names":["join","resolve","existsSync","loadSettingsFile","partitionProjectAllowRules","discoverCommands","partitionProjectCommands","describeProjectCommandShell","displayableCommandName","collectDeclaredHooks","describeDeclaredHook","partitionProjectHooks","formatMcpServerCommand","resolveMcpServerList","evaluateMcpServerApproval","join","join","join","join","resolve","resolve","join","existsSync","rmSync","join","resolve","sep","resolve","join","sep","existsSync","rmSync","readFileSync","dirname","join","require","join","mode","sessionStore","bootstrap","existsSync","readFileSync","join","join","existsSync","readFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime-env.ts","../src/index.ts","../src/cli/status-cmd.ts","../src/cli/exit.ts","../src/agents/diagnostics.ts","../src/cli/doctor.ts","../src/cli/tool-stats.ts","../src/cli/provider-key-cmd.ts","../src/cli/config-cmd.ts","../src/cli/trust-cmd.ts","../src/mcp-host.ts","../src/cli/print-interrupt.ts","../src/cli/run.ts","../src/rewind/snapshot-store.ts","../src/rewind/environment.ts","../src/cli/ink-frame-throttle.ts","../src/cli/mcp.ts"],"sourcesContent":["/**\n * Default NODE_ENV to \"production\" before any dependency loads.\n *\n * React and react-reconciler pick their development or production build from\n * NODE_ENV at import time. A CLI normally runs with NODE_ENV unset, which\n * silently loads the development renderer — 2-3x slower per render pass.\n * This must be the first import of the CLI entry, and nothing the entry imports\n * statically may load React or Ink: a split bundle hoists every static import\n * above the entry's body, so React would be evaluated before this runs. The TUI\n * loads them with a dynamic import, and scripts/check-architecture.ts enforces\n * it. An explicitly set NODE_ENV always wins.\n *\n * A default Book invented is marked as one, so `buildChildEnv` can keep it off\n * every command Book starts (`child-env.ts`). Without the marker a child\n * inherits `NODE_ENV=production` from a user who set nothing, and `npm\n * install` in a project drops its devDependencies.\n */\nif (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'production';\n process.env.BOOK_DEFAULTED_NODE_ENV = '1';\n}\n\nexport {};\n","#!/usr/bin/env node\nimport './runtime-env.js';\nimport { InvalidArgumentError, program } from 'commander';\nimport { EFFORT_LEVELS, isEffortLevel } from './commands/effort.js';\nimport { runStatusCommand } from './cli/status-cmd.js';\nimport { exit } from './cli/exit.js';\nimport { runDoctorCommand } from './cli/doctor.js';\nimport { runToolStatsCommand } from './cli/tool-stats.js';\nimport { runConfigCommand } from './cli/config-cmd.js';\nimport { runTrustCommand } from './cli/trust-cmd.js';\nimport { runMainAction } from './cli/run.js';\nimport { resolvePrintPrompt } from './cli/utils.js';\nimport { getPackageVersion } from './version-info.js';\nimport { formatSettingsKeyHelp } from './settings-repository.js';\nimport {\n runMcpAddCommand,\n runMcpGetCommand,\n runMcpListCommand,\n runMcpRemoveCommand,\n} from './cli/mcp.js';\n\nfunction collectOption(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/**\n * Reject a bad effort level at parse time, where commander can name the option.\n * Reaching the provider with an unchecked level costs a round trip and returns\n * an opaque HTTP 400 for a mistake stated precisely here.\n */\nfunction parseEffortOption(value: string): string {\n const normalized = value.trim().toLowerCase();\n if (!isEffortLevel(normalized)) {\n throw new InvalidArgumentError(`Valid levels: ${EFFORT_LEVELS.join(', ')}.`);\n }\n return normalized;\n}\n\n/**\n * Resolve the workspace a subcommand should act on.\n *\n * The root and every subcommand declare -w/--workspace, and positional option\n * parsing hands each placement to a different command object: `book -w X sub`\n * is parsed by the root, `book sub -w X` by the subcommand, and neither can see\n * the other's value. Defaulting the subcommand option to process.cwd() made an\n * unset one indistinguishable from a deliberate `.`, so a root-side flag was\n * silently overridden and the command acted on the current directory while\n * reporting the flagged path. Leaving the subcommand option undefaulted lets an\n * unset one fall through to the root, which still carries the cwd default.\n */\nfunction resolveWorkspace(workspace: string | undefined): string {\n return workspace ?? (program.opts().workspace as string);\n}\n\nprogram\n .name('book')\n .description('AI coding agent with rich TUI')\n // Root and subcommands both declare -w/--workspace. Without positional\n // option parsing, commander 15 routes a -w that follows a subcommand to the\n // root command, leaving the subcommand on its process.cwd() default: every\n // `book <subcommand> --workspace <path>` silently acted on the wrong\n // directory, and `book config set` wrote settings into the current one.\n // The other placement is handled by resolveWorkspace(); positional parsing\n // also means a root option written after a subcommand name is an error, so\n // any root option a subcommand's action reads must be re-declared on it.\n .enablePositionalOptions()\n .version(getPackageVersion())\n // `--print [prompt]` takes the prompt as its own optional value, so a prompt\n // written after a later flag was a stray positional and commander rejected\n // it (#226). The positional is the print-mode prompt; the root action merges\n // the two placements and refuses both at once.\n .argument('[prompt]', 'Prompt for print mode; the same as the -p value, in either position')\n .option('-w, --workspace <path>', 'Workspace root directory', process.cwd())\n .option('-m, --model <model>', 'Model to use')\n .option(\n '-p, --print [prompt]',\n 'Print mode (non-interactive). Reads the prompt from the flag, the [prompt] argument, or stdin.',\n )\n .option('--output-format <format>', 'text | json | stream-json (print mode)', 'text')\n .option('--input-format <format>', 'text | stream-json (print mode)', 'text')\n .option('--max-turns <n>', 'Max agent turns (print mode; omit for unlimited)')\n .option('--max-budget-usd <amount>', 'Max USD spend (print mode)')\n .option(\n '--permission-mode <mode>',\n 'default | acceptEdits | plan | auto | dontAsk | bypassPermissions (overrides settings.defaultMode)',\n )\n .option('--verbose', 'Print mode: add each tool result to the progress lines on stderr')\n .option('-q, --quiet', 'Print mode: no progress lines on stderr')\n .option('--json-schema <schema>', 'Return validated JSON matching a JSON Schema (print mode)')\n .option('-r, --resume <id|name>', 'Resume a session by id or name')\n .option('-c, --continue', 'Resume the most recent session in this directory that has a message')\n .option('--session-id <uuid>', 'Use a specific session id')\n .option('-n, --name <name>', 'Set a display name for the session')\n .option('--no-session-persistence', 'Do not save the session to disk')\n .option('--fork-session', 'On resume, create a new session id instead of reusing')\n .option(\n '--session-driver <driver>',\n 'human or agent (default: agent under another agent harness); an agent-driven session saves only what it learned, never its instructions',\n )\n .option('--include-hook-events', 'Emit hook lifecycle events in stream-json output')\n .option('--include-partial-messages', 'Emit partial assistant text deltas in stream-json output')\n .option(\n '--include-result-messages',\n 'Include the full message history in the stream-json result event',\n )\n .option('--prompt-suggestions', 'Ask model for follow-up prompt suggestions after completion')\n .option('--agents <mode>', 'Managed agents: adaptive, manual, off')\n .option('--scrollback', 'Use terminal-native scrollback instead of the full-screen TUI')\n .option('--settings <path>', 'Path to an ad-hoc settings file (overrides all scopes)')\n .option('--no-settings', 'Skip all settings.json layers (use defaults + legacy .bookrc.json)')\n // No commander default: \"the user passed --effort\" has to stay observable, or\n // the flag cannot be told apart from the fallback and can never count as an\n // explicit choice. `high` is still the fallback, resolved in loadConfig after\n // BOOK_EFFORT, settings.effort, and model metadata have had their turn.\n .option(\n '--effort <level>',\n 'Thinking effort: low, medium, high, xhigh, max (default: high)',\n parseEffortOption,\n )\n .option('--provider <type>', 'Provider: anthropic, openai, auto (default: auto-detect)');\n\n// ---- book doctor ----\nprogram\n .command('doctor')\n .description('Diagnose configuration and environment')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n // Doctor exists for a configuration that does not work, so it needs the way\n // past one that will not even load. Positional option parsing means a root\n // option written after a subcommand is an error, so it is re-declared here.\n .option('--no-settings', 'Skip all settings.json layers (use defaults + legacy .bookrc.json)')\n .action(async (options: { workspace?: string; settings?: boolean }) => {\n await runDoctorCommand(resolveWorkspace(options.workspace), {\n noSettings: options.settings === false,\n });\n });\n\n// ---- book status ----\nprogram\n .command('status')\n .description('Report what a session is working on and what it has spent (no credentials needed)')\n .argument(\n '[session]',\n 'Session id or name (defaults to the most recent session in this workspace with a message or a run record)',\n )\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--json', 'Emit the status as JSON')\n .action((session: string | undefined, options: { workspace?: string; json?: boolean }) => {\n const code = runStatusCommand({\n session,\n workspace: resolveWorkspace(options.workspace),\n json: options.json,\n });\n if (code !== 0) exit(code);\n });\n\n// ---- book tool-stats ----\nprogram\n .command('tool-stats')\n .description(\n 'Inspect and measure tool use recorded across sessions (fail counts, rates, durations)',\n )\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--json', 'Emit the aggregate as JSON')\n .option('--since <days>', 'Only include records from the last N days')\n .option('--all', 'Include the full history, ignoring the retention window')\n .option('--prune', 'Drop records older than the window from disk before reporting')\n .action(\n async (options: {\n workspace?: string;\n json?: boolean;\n since?: string;\n all?: boolean;\n prune?: boolean;\n }) => {\n await runToolStatsCommand({ ...options, workspace: resolveWorkspace(options.workspace) });\n },\n );\n\n// ---- book mcp ----\nconst mcpCommand = program.command('mcp').description('Manage MCP server configurations');\n\nmcpCommand\n .command('list')\n .description('List resolved MCP servers without revealing secret values')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--json', 'Emit JSON')\n .action((options: { workspace?: string; json?: boolean }) =>\n runMcpListCommand({ ...options, workspace: resolveWorkspace(options.workspace) }),\n );\n\nmcpCommand\n .command('get')\n .description('Show one resolved MCP server without revealing secret values')\n .argument('<name>', 'Server name')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--json', 'Emit JSON')\n .action((name: string, options: { workspace?: string; json?: boolean }) =>\n runMcpGetCommand(name, { ...options, workspace: resolveWorkspace(options.workspace) }),\n );\n\nmcpCommand\n .command('add')\n .description('Add an MCP server (use -- before stdio arguments that start with a dash)')\n .argument('<name>', 'Server name')\n .argument('<command-or-url>', 'Stdio executable or HTTP/SSE URL')\n .argument('[server-args...]', 'Arguments for a stdio server')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--scope <scope>', 'user | project', 'user')\n .option('--transport <type>', 'stdio | http | sse')\n .option('-e, --env <KEY=VALUE>', 'Stdio environment entry (repeatable)', collectOption, [])\n .option('-H, --header <KEY=VALUE>', 'HTTP header (repeatable)', collectOption, [])\n .option('--cwd <path>', 'Working directory for a stdio server')\n .option('--force', 'Replace an existing same-scope server')\n .action(\n (\n name: string,\n target: string,\n serverArgs: string[],\n options: {\n workspace?: string;\n scope: 'user' | 'project';\n transport?: 'stdio' | 'http' | 'sse';\n env: string[];\n header: string[];\n cwd?: string;\n force?: boolean;\n },\n ) =>\n runMcpAddCommand(name, target, serverArgs, {\n ...options,\n workspace: resolveWorkspace(options.workspace),\n }),\n );\n\nmcpCommand\n .command('remove')\n .alias('rm')\n .description('Remove an MCP server from its effective scope')\n .argument('<name>', 'Server name')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--scope <scope>', 'user | project')\n .action((name: string, options: { workspace?: string; scope?: 'user' | 'project' }) =>\n runMcpRemoveCommand(name, { ...options, workspace: resolveWorkspace(options.workspace) }),\n );\n\n// ---- book trust ----\nconst trustCommand = program\n .command('trust')\n .description('Record decisions about configuration a repository declared');\n\ntrustCommand\n .command('hook')\n .description('Approve or reject a project-declared hook (see `book doctor`)')\n .argument('[fingerprint]', 'Hook fingerprint reported by `book doctor`')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--all-pending', 'Apply to every hook currently awaiting a decision')\n .option('--reject', 'Record a refusal instead of an approval')\n .action(\n async (\n fingerprint: string | undefined,\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\n ) => {\n await runTrustCommand('hook', fingerprint, {\n ...options,\n workspace: resolveWorkspace(options.workspace),\n });\n },\n );\n\ntrustCommand\n .command('command')\n .description('Approve or reject a project command that substitutes shell into its prompt')\n .argument('[name]', 'Command name, with or without the leading slash')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--all-pending', 'Apply to every command currently awaiting a decision')\n .option('--reject', 'Record a refusal instead of an approval')\n .action(\n async (\n name: string | undefined,\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\n ) => {\n await runTrustCommand('command', name, {\n ...options,\n workspace: resolveWorkspace(options.workspace),\n });\n },\n );\n\ntrustCommand\n .command('rule')\n .description('Approve or reject a project-declared permissions.allow rule')\n .argument('[rule]', 'Rule text exactly as the project declared it')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--all-pending', 'Apply to every rule currently awaiting a decision')\n .option('--reject', 'Record a refusal instead of an approval')\n .action(\n async (\n rule: string | undefined,\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\n ) => {\n await runTrustCommand('rule', rule, {\n ...options,\n workspace: resolveWorkspace(options.workspace),\n });\n },\n );\n\ntrustCommand\n .command('dir')\n .description('Approve or reject a project-declared additionalDirectories entry')\n .argument('[path]', 'The declared entry, or the real path `book doctor` reported for it')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--all-pending', 'Apply to every directory currently awaiting a decision')\n .option('--reject', 'Record a refusal instead of an approval')\n .action(\n async (\n path: string | undefined,\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\n ) => {\n await runTrustCommand('dir', path, {\n ...options,\n workspace: resolveWorkspace(options.workspace),\n });\n },\n );\n\ntrustCommand\n .command('provider')\n .description('Approve or reject a provider (origin and key) a repository declared')\n .argument(\n '[id]',\n 'Provider id, or .bookrc.json for a legacy baseUrl; omit to list what is pending',\n )\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n .option('--all-pending', 'Apply to every provider currently awaiting a decision')\n .option('--reject', 'Record a refusal instead of an approval')\n .action(\n async (\n id: string | undefined,\n options: { workspace?: string; allPending?: boolean; reject?: boolean },\n ) => {\n await runTrustCommand('provider', id, {\n ...options,\n workspace: resolveWorkspace(options.workspace),\n });\n },\n );\n\n// ---- book config ----\nprogram\n .command('config')\n .description('Read and write settings')\n .option('-w, --workspace <path>', 'Workspace root directory (defaults to the root -w, then cwd)')\n // Re-declared from the root because this action reads them: positional option\n // parsing rejects a root option written after the subcommand name, so without\n // these `book config get model --settings <path>` fails with \"unknown option\".\n // Declared in this order so commander leaves `settings` undefined when neither\n // flag is passed, letting an unset one fall through to the root's value.\n .option('--settings <path>', 'Path to an ad-hoc settings file (overrides all scopes)')\n .option('--no-settings', 'Skip all settings.json layers (use defaults + legacy .bookrc.json)')\n // Writes default to the user layer so a setting follows the person, not the\n // directory. The two workspace layers stay reachable, but have to be asked\n // for -- the shortest command is the one that stays consistent everywhere.\n .option('-g, --global', 'Act on user-global settings (<BOOK_HOME>/settings.json) [default]')\n .option('--project', 'Act on checked-in project settings (.book/settings.json)')\n .option('--local', 'Act on gitignored project-local settings (.book/settings.local.json)')\n // provider-key only. `--no-check` for an endpoint without a model-list API; `--force` for a\n // script that wants the key saved whatever the endpoint answers, as `mcp add --force` replaces.\n .option('--no-check', 'provider-key: save without testing the key against the endpoint')\n .option('--force', 'provider-key: save even when the endpoint rejects the key')\n .argument(\n '[action]',\n 'get <key>, set <key> <value>, unset <key>, list, or provider-key <id> (key read from stdin)',\n )\n .argument('[key]', 'Dot-separated key path (e.g. permissions.deny), or the provider id')\n .argument('[value]', 'Value to set (JSON-parsed)')\n .addHelpText('after', `\\n${formatSettingsKeyHelp()}`)\n .action(\n async (\n action: string | undefined,\n key: string | undefined,\n value: string | undefined,\n options: {\n workspace?: string;\n settings?: string | false;\n global?: boolean;\n project?: boolean;\n local?: boolean;\n check?: boolean;\n force?: boolean;\n },\n ) => {\n const rootSettings = program.opts().settings as string | false | undefined;\n const settings = options.settings ?? rootSettings;\n const selected = (\n [\n ['user', options.global],\n ['project', options.project],\n ['local', options.local],\n ] as const\n ).filter(([, on]) => on === true);\n if (selected.length > 1) {\n console.error(\n 'Pass at most one of --global, --project, --local. ' +\n 'Writes default to --global; reads without one report the resolved merge.',\n );\n exit(1);\n }\n await runConfigCommand(resolveWorkspace(options.workspace), action, key, value, {\n settingsOverridePath: typeof settings === 'string' ? settings : undefined,\n noSettings: settings === false,\n scope: selected[0]?.[0],\n providerKey: { check: options.check, force: options.force },\n });\n },\n );\n\n// ---- main (interactive / headless) ----\nprogram.action(async (prompt: string | undefined, options: Record<string, unknown>) => {\n // Resolved before the await: `program.parse()` does not await an async\n // action, so an error thrown past this point would surface as an unhandled\n // rejection with a stack trace instead of a usage error.\n const resolved = resolvePrintPrompt(options.print as string | boolean | undefined, prompt);\n if ('error' in resolved) program.error(`error: ${resolved.error}`);\n await runMainAction({ ...options, print: resolved.print });\n});\n\nprogram.parse();\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { SessionStore } from '../session/store.js';\nimport { resolveBookHome } from '../book-home.js';\nimport { estimateUsageCost } from '../pricing.js';\nimport { readRunStatus, runStatusPath, type RunStatusRecord } from '../run-status.js';\nimport type { LoadedSession, SessionMeta } from '../types/sessions.js';\nimport type { Message } from '../types/messages.js';\n\n/**\n * `book status` — what a long-running session is working on and what it has cost,\n * answerable without a provider credential.\n *\n * The question this exists for is asked at hour 180, often by a supervisor script\n * or by someone who has just walked back to the machine: *what was this asked to\n * do, how far has it got, and what has it spent?* Every input is already on disk.\n *\n * Credential-free by construction, and asserted so in\n * `src/cli/subcommands.contract.test.ts`: a run whose provider is misconfigured is\n * exactly when someone needs to read its state.\n *\n * The objective is read from the transcript rather than a summary because the\n * transcript is never rewritten by compaction — `SessionStore.load` truncates it\n * only for a rewind record — so the user's first words survive verbatim however\n * many generations have passed.\n *\n * The session JSONL answers \"what was this asked to do and what has it spent\".\n * What it cannot answer is *liveness*, which is the half a supervisor actually\n * needs mid-run: whether the process is alive, which turn it is on, what tool it\n * last called, and whether it finished cleanly or died. `src/run-status.ts` has\n * been writing exactly that to `<BOOK_HOME>/runs/<session-id>.json` at every turn\n * boundary, and nothing read it — a 20-minute print run that had done the work\n * correctly and one that died at turn 16 looked identical from outside, and the\n * only way to tell them apart was `jq` on a file with no documented reader. That\n * record is folded in here rather than into a new command: this is the surface\n * someone looks at, and it already runs without a credential.\n */\n\n/**\n * What the liveness record says about the process, once the pid is tested.\n *\n * `died` is the case the record exists for: no terminal outcome and no crash\n * note, and the process is gone. Silence and a clean finish are indistinguishable\n * without it, which is the whole complaint.\n */\nexport type RunLiveness = 'running' | 'completed' | 'crashed' | 'died';\n\nexport interface RunStatus {\n liveness: RunLiveness;\n pid: number;\n /** True when the pid answers a signal-0 probe right now. */\n processAlive: boolean;\n runId: string;\n turn: number;\n elapsedMs: number;\n /** When the record was last rewritten — a running record that is old is wedged. */\n updatedAt: number;\n lastTool?: string;\n currentTodo?: string;\n openTodos: number;\n costUsd: number | null;\n budgetUsd?: number;\n freeDiskBytes?: number;\n terminal?: { status: string; reason: string; message?: string };\n crash?: { message: string; at: number };\n}\n\n/**\n * Does this pid still answer? Signal 0 performs the permission and existence\n * checks without delivering anything. `EPERM` means it exists under another\n * user, which is still alive; only `ESRCH` means gone.\n */\nfunction isProcessAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nexport function buildRunStatus(record: RunStatusRecord): RunStatus {\n const processAlive = isProcessAlive(record.pid);\n const liveness: RunLiveness = record.terminal\n ? 'completed'\n : record.crash\n ? 'crashed'\n : processAlive\n ? 'running'\n : 'died';\n\n return {\n liveness,\n pid: record.pid,\n processAlive,\n runId: record.runId,\n turn: record.turn,\n elapsedMs: record.elapsedMs,\n updatedAt: record.updatedAt,\n lastTool: record.lastTool,\n currentTodo: record.currentTodo,\n openTodos: record.openTodos,\n costUsd: record.costUsd,\n budgetUsd: record.budgetUsd,\n freeDiskBytes: record.freeDiskBytes,\n terminal: record.terminal ? { ...record.terminal } : undefined,\n crash: record.crash ? { ...record.crash } : undefined,\n };\n}\n\nexport interface SessionStatus {\n sessionId: string;\n sessionName?: string;\n workspace: string;\n createdAt: number;\n updatedAt: number;\n /** Byte-exact text of the first user turn. */\n objective?: string;\n transcriptMessages: number;\n contextMessages: number;\n compactions: number;\n /** Newest checkpoint generation, or 0 when the session has never compacted. */\n generation: number;\n usage?: {\n promptTokens: number;\n completionTokens: number;\n cacheReadInputTokens: number;\n cacheCreationInputTokens: number;\n };\n costUsd: number | null;\n costModels: string[];\n plan?: {\n todos: Array<{ content: string; status: string }>;\n tasks: Array<{ id: string; subject: string; status: string; blockedBy: string[] }>;\n };\n /**\n * Absent when no run of this session ever wrote a liveness record, or when the 30-day\n * retention has removed it.\n */\n run?: RunStatus;\n}\n\nfunction firstUserTurn(transcript: readonly Message[]): string | undefined {\n for (const message of transcript) {\n if (message.role !== 'user') continue;\n // Skip host-authored turns: checkpoints, agent notifications, and the loop's\n // own continuation and work-state messages are not what anyone asked for.\n if (message.kind && message.kind !== 'conversation') continue;\n if (message.content.startsWith('[continuation]')) continue;\n if (message.content.startsWith('[work-state]')) continue;\n if (message.agentNotifications?.length) continue;\n return message.content;\n }\n return undefined;\n}\n\nexport function buildSessionStatus(\n meta: SessionMeta,\n loaded: LoadedSession,\n runRecord?: RunStatusRecord,\n): SessionStatus {\n const usage = loaded.carriedUsage;\n const models = loaded.carriedModels ?? [];\n // Price at the most expensive model involved: the records do not attribute\n // tokens per model, so an upper bound is the honest reading.\n let costUsd: number | null = models.length > 0 && usage ? 0 : null;\n if (usage) {\n for (const model of models) {\n const quote = estimateUsageCost(\n model,\n {\n promptTokens: usage.promptTokens,\n completionTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n cacheReadInputTokens: usage.cacheReadInputTokens,\n cacheCreationInputTokens: usage.cacheCreationInputTokens,\n },\n 'pool',\n );\n if (quote.status !== 'known') {\n costUsd = null;\n break;\n }\n costUsd = Math.max(costUsd ?? 0, quote.costUsd);\n }\n }\n\n return {\n sessionId: meta.id,\n sessionName: meta.name,\n workspace: meta.cwd,\n createdAt: meta.createdAt,\n updatedAt: meta.updatedAt,\n objective: firstUserTurn(loaded.transcript),\n transcriptMessages: loaded.transcript.length,\n contextMessages: loaded.contextHistory.length,\n compactions: loaded.compactBoundaries.length,\n generation: loaded.compactBoundaries.at(-1)?.generation ?? 0,\n usage: usage\n ? {\n promptTokens: usage.promptTokens,\n completionTokens: usage.completionTokens,\n cacheReadInputTokens: usage.cacheReadInputTokens ?? 0,\n cacheCreationInputTokens: usage.cacheCreationInputTokens ?? 0,\n }\n : undefined,\n costUsd,\n costModels: models,\n plan: loaded.plan\n ? {\n todos: (loaded.plan.todos ?? []).map((todo) => ({\n content: todo.content,\n status: todo.status,\n })),\n tasks: (loaded.plan.tasks ?? []).map((task) => ({\n id: task.id,\n subject: task.subject,\n status: task.status,\n blockedBy: task.blockedBy,\n })),\n }\n : undefined,\n run: runRecord ? buildRunStatus(runRecord) : undefined,\n };\n}\n\nfunction truncate(text: string, max: number): string {\n const single = text.replace(/\\s+/g, ' ').trim();\n return single.length <= max ? single : `${single.slice(0, max - 1)}…`;\n}\n\nfunction since(timestamp: number, now: number): string {\n const minutes = Math.max(0, Math.round((now - timestamp) / 60_000));\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.round(minutes / 60);\n return hours < 48 ? `${hours}h ago` : `${Math.round(hours / 24)}d ago`;\n}\n\nfunction duration(ms: number): string {\n const seconds = Math.max(0, Math.round(ms / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ${seconds % 60}s`;\n return `${Math.floor(minutes / 60)}h ${minutes % 60}m`;\n}\n\nfunction gibibytes(bytes: number): string {\n return `${(bytes / 1024 ** 3).toFixed(1)} GiB`;\n}\n\n/**\n * The liveness half of the report.\n *\n * Led by the one fact the session JSONL cannot supply — whether the process is\n * still there — because that is the question being asked when someone runs this\n * mid-run. A `running` record whose last write is old is the wedged case, and is\n * called out rather than left for the reader to compute from two timestamps.\n */\nfunction renderRunStatus(run: RunStatus, now: number): string[] {\n const lines: string[] = [];\n const headline: Record<RunLiveness, string> = {\n running: `running (pid ${run.pid})`,\n completed: `finished — ${run.terminal?.status ?? 'unknown'} (${run.terminal?.reason ?? 'no reason recorded'})`,\n crashed: 'crashed without a terminal outcome',\n died: `no longer running, and recorded no outcome (pid ${run.pid} is gone)`,\n };\n lines.push(`Run: ${headline[run.liveness]}`);\n\n if (run.terminal?.message) lines.push(` ${run.terminal.message}`);\n if (run.crash) lines.push(` ${run.crash.message}`);\n\n lines.push(` turn ${run.turn} • elapsed ${duration(run.elapsedMs)}`);\n lines.push(` last update: ${since(run.updatedAt, now)}`);\n // Wall clock, and it has to be: `updatedAt` comes from the run's status file,\n // written by another process. This is why the line hedges — \"may be wedged\" —\n // rather than asserting. A wall-clock correction between the writer's stamp and\n // this read can produce the warning on a healthy run, and the cost of that is\n // one cautious sentence, which is the right trade for a diagnostic.\n if (run.liveness === 'running' && now - run.updatedAt > STALE_RUN_MS) {\n lines.push(\n ` ⚠ the process is alive but has not written a turn boundary in ${duration(now - run.updatedAt)} —` +\n ' it may be wedged on a long tool call or a permission prompt.',\n );\n }\n if (run.lastTool) lines.push(` last tool: ${run.lastTool}`);\n if (run.currentTodo) lines.push(` in progress: ${truncate(run.currentTodo, 120)}`);\n if (run.openTodos > 0) lines.push(` open todos: ${run.openTodos}`);\n\n if (run.costUsd !== null) {\n lines.push(\n ` spend: ~$${run.costUsd.toFixed(4)}` +\n (run.budgetUsd !== undefined ? ` of $${run.budgetUsd.toFixed(2)} budget` : ''),\n );\n }\n if (run.freeDiskBytes !== undefined) lines.push(` free disk: ${gibibytes(run.freeDiskBytes)}`);\n\n return lines;\n}\n\n/** How long a live process may go without a turn boundary before it is worth naming. */\nconst STALE_RUN_MS = 15 * 60_000;\n\nexport function renderSessionStatus(status: SessionStatus, now = Date.now()): string {\n const lines: string[] = [];\n lines.push(`Session: ${status.sessionName ?? status.sessionId}`);\n if (status.sessionName) lines.push(` id: ${status.sessionId}`);\n lines.push(` workspace: ${status.workspace}`);\n lines.push(` last activity: ${since(status.updatedAt, now)}`);\n lines.push('');\n\n // Before the objective: someone running this mid-run wants liveness first, and\n // someone reading it afterwards wants to know how the run ended before they\n // read what it was for.\n if (status.run) {\n lines.push(...renderRunStatus(status.run, now));\n lines.push('');\n }\n lines.push(\n status.objective\n ? `Objective: ${truncate(status.objective, 300)}`\n : 'Objective: (no user turn recorded)',\n );\n lines.push('');\n lines.push(\n `History: ${status.transcriptMessages} messages, ${status.contextMessages} in context` +\n (status.compactions > 0\n ? ` • ${status.compactions} compaction${status.compactions === 1 ? '' : 's'} (generation ${status.generation})`\n : ' • never compacted'),\n );\n\n if (status.usage) {\n const { promptTokens, completionTokens, cacheReadInputTokens, cacheCreationInputTokens } =\n status.usage;\n lines.push(\n `Tokens: prompt ${promptTokens.toLocaleString()} • completion ${completionTokens.toLocaleString()} • cache read ${cacheReadInputTokens.toLocaleString()} • cache write ${cacheCreationInputTokens.toLocaleString()}`,\n );\n lines.push(\n status.costUsd !== null\n ? `Spend: ~$${status.costUsd.toFixed(4)} (upper bound across ${status.costModels.join(', ') || 'unknown model'})`\n : 'Spend: (pricing unknown for at least one model used)',\n );\n } else {\n lines.push('Tokens: (none recorded — this session predates usage records, or never ran)');\n }\n\n if (status.plan) {\n const open = status.plan.todos.filter((todo) => todo.status !== 'completed');\n const openTasks = status.plan.tasks.filter(\n (task) => task.status !== 'completed' && task.status !== 'deleted',\n );\n lines.push('');\n lines.push(`Plan: ${open.length} open todo(s), ${openTasks.length} open task(s)`);\n for (const todo of open.slice(0, 10)) lines.push(` [${todo.status}] ${todo.content}`);\n for (const task of openTasks.slice(0, 10)) {\n const blockers = task.blockedBy.length ? ` (blocked by ${task.blockedBy.join(', ')})` : '';\n lines.push(` [${task.status}] ${task.subject}${blockers}`);\n }\n } else {\n lines.push('');\n lines.push('Plan: (none persisted)');\n }\n\n return lines.join('\\n');\n}\n\nexport interface StatusCommandOptions {\n session?: string;\n workspace: string;\n json?: boolean;\n /** Injectable so the contract test can run without touching a real BOOK_HOME. */\n store?: SessionStore;\n /** Where `runs/<session-id>.json` lives; injectable for the same reason. */\n home?: string;\n stdout?: { write: (text: string) => unknown };\n}\n\nexport function runStatusCommand(options: StatusCommandOptions): number {\n const stdout = options.stdout ?? process.stdout;\n const home = options.home ?? resolveBookHome();\n const store = options.store ?? new SessionStore(join(home, 'sessions'));\n\n const meta = options.session\n ? (store.findById(options.session) ?? store.findByName(options.session))\n : // A print run of host-performed commands records no message, only a run record (#428).\n store.mostRecentInCwd(\n options.workspace,\n (candidate) => candidate.messageCount > 0 || existsSync(runStatusPath(candidate.id, home)),\n );\n\n if (!meta) {\n stdout.write(\n options.session\n ? `No session found matching \"${options.session}\".\\n`\n : `No session has run in ${options.workspace} yet.\\n`,\n );\n return 1;\n }\n\n const status = buildSessionStatus(meta, store.load(meta.id), readRunStatus(meta.id, home));\n stdout.write(\n options.json ? `${JSON.stringify(status, null, 2)}\\n` : `${renderSessionStatus(status)}\\n`,\n );\n return 0;\n}\n","/**\n * Test-injectable process.exit() abstraction.\n *\n * All CLI modules should use `exit()` instead of `process.exit()` so that\n * tests can capture exit codes without actually terminating the process.\n */\n\nlet exitFn: (code: number) => never = (code: number): never => {\n process.exit(code);\n};\n\nlet exiting = false;\n\n/** Replace the exit implementation (for test injection). */\nexport function setExitFn(fn: (code: number) => never): void {\n exitFn = fn;\n exiting = false;\n}\n\n/** Exit the process with the given code. Tests can override via setExitFn. */\nexport function exit(code: number = 0): never {\n exiting = true;\n exitFn(code);\n}\n\n/** True when exit() has been called. Used by outer catch handlers to avoid double-exiting. */\nexport function isExiting(): boolean {\n return exiting;\n}\n\nlet exitCodeFn: (code: number) => void = (code: number): void => {\n process.exitCode = code;\n};\n\n/** Replace how a deferred exit code is recorded (for test injection). */\nexport function setExitCodeFn(fn: (code: number) => void): void {\n exitCodeFn = fn;\n}\n\n/**\n * Fail the process without ending it: record `code`, and let Node exit once its\n * last handle closes. Print mode ends a failed run this way. On Windows, `exit()`\n * straight after a pooled HTTP request aborts inside libuv\n * (`Assertion failed: !(handle->flags & UV_HANDLE_CLOSING)`), and the process\n * exits 127 instead of 1 (#243).\n */\nexport function setExitCode(code: number): void {\n exitCodeFn(code);\n}\n","import type { AgentConfig } from '../types/runtime.js';\nimport { canonicalToolName } from '../tools/aliases.js';\nimport type { ManagedAgentDef } from './profiles.js';\n\nexport interface AgentDiagnostic {\n code:\n | 'duplicate-profile'\n | 'invalid-model'\n | 'literal-inherit'\n | 'missing-profile'\n | 'readonly-mutation'\n | 'reserved-profile'\n | 'unknown-tool';\n message: string;\n}\n\nconst MUTATION_TOOLS = new Set([\n 'ApplyPatch',\n 'Write',\n 'Edit',\n 'MultiEdit',\n 'NotebookEdit',\n 'Bash',\n 'Check',\n]);\n\nfunction validateModel(\n profile: string,\n model: string | undefined,\n config: AgentConfig,\n): AgentDiagnostic | undefined {\n if (!model || model === 'inherit') return undefined;\n const slash = model.indexOf('/');\n if (slash === 0 || slash === model.length - 1) {\n return {\n code: 'invalid-model',\n message: `${profile} uses invalid model \"${model}\"; expected a model or provider/model reference.`,\n };\n }\n if (slash > 0) {\n const providerId = model.slice(0, slash);\n const modelId = model.slice(slash + 1);\n const provider = config.settings.provider[providerId];\n if (provider && Object.keys(provider.models).length > 0 && !provider.models[modelId]) {\n return {\n code: 'invalid-model',\n message: `${profile} references ${model}, which is not in provider ${providerId}'s model catalog.`,\n };\n }\n }\n return undefined;\n}\n\nexport function collectAgentDiagnostics(\n config: AgentConfig,\n profiles: ManagedAgentDef[],\n): AgentDiagnostic[] {\n const diagnostics: AgentDiagnostic[] = [];\n const counts = new Map<string, number>();\n for (const profile of profiles) counts.set(profile.name, (counts.get(profile.name) ?? 0) + 1);\n for (const [name, count] of counts) {\n if (count > 1) {\n diagnostics.push({\n code: 'duplicate-profile',\n message: `${name} is defined ${count} times; keep one profile definition per name.`,\n });\n }\n }\n\n const profileNames = new Set(profiles.map((profile) => profile.name));\n for (const [name, override] of Object.entries(config.settings.agents.profiles)) {\n if (!profileNames.has(name)) {\n diagnostics.push({\n code: 'missing-profile',\n message: `agents.profiles.${name} has settings but no matching agent definition.`,\n });\n }\n const modelDiagnostic = validateModel(name, override.model, config);\n if (modelDiagnostic) diagnostics.push(modelDiagnostic);\n }\n\n for (const profile of profiles) {\n if (profile.suppressedOverride) {\n diagnostics.push({\n code: 'reserved-profile',\n message: `${profile.name} is a reserved built-in agent, so the ${profile.suppressedOverride} definition of the same name is ignored. Rename it, or tune model/effort through agents.profiles.${profile.name}.`,\n });\n }\n for (const tool of profile.unknownTools ?? []) {\n diagnostics.push({\n code: 'unknown-tool',\n message: `${profile.name} declares unsupported tool ${tool}; import or edit the definition.`,\n });\n }\n if (profile.isolation === 'workspace-readonly') {\n const mutations = profile.allowedTools.filter((tool) =>\n MUTATION_TOOLS.has(canonicalToolName(tool.split('(')[0].trim())),\n );\n if (mutations.length > 0) {\n diagnostics.push({\n code: 'readonly-mutation',\n message: `${profile.name} is read-only but declares mutation tools: ${mutations.join(', ')}. They will be hard-filtered.`,\n });\n }\n }\n if (!config.settings.agents.profiles[profile.name]?.model) {\n const modelDiagnostic = validateModel(profile.name, profile.model, config);\n if (modelDiagnostic) diagnostics.push(modelDiagnostic);\n }\n }\n return diagnostics;\n}\n","import { loadConfig } from '../config.js';\nimport { renderUntrustedText } from '../hook-approvals.js';\nimport { providerTrustCommand, trustCommandText } from '../trust-command.js';\nimport { getPackageVersion } from '../version-info.js';\nimport { collectAgentDiagnostics } from '../agents/diagnostics.js';\nimport { withBuiltInAgents } from '../agents/profiles.js';\nimport { discoverAgents } from '../subagent-discovery.js';\nimport { resolveBookHome } from '../book-home.js';\nimport type { HookEntry } from '../settings.js';\nimport type { AgentConfig } from '../types/runtime.js';\n\n/**\n * How much a settings layer named by `settingsLayers` is trusted, in the terms\n * `workspaceLayerThatEnabledSandbox` uses. The label is what `settingsLayers`\n * prints; an unrecognised one falls back to `local`, the least-trusted\n * workspace position there is, so a renamed label cannot quietly promote a file\n * to the trusted baseline the activation question is measured against.\n */\nconst WORKSPACE_LAYER_TRUST: Record<string, 'trusted' | 'repository' | 'local'> = {\n User: 'trusted',\n Project: 'repository',\n Local: 'local',\n};\n\n/**\n * One \"here is how to grant it\" line, naming the workspace doctor actually diagnosed (see\n * `trustCommandText`), or a fallback when the path defeats quoting.\n */\nfunction approvalHint(label: string, workspace: string, rest: string): string {\n const { command, note } = trustCommandText(workspace, rest);\n return `${label} ${command}${note}`;\n}\n\nfunction formatRelativeTime(timestamp: number, now = Date.now()): string {\n const elapsedMs = Math.max(0, now - timestamp);\n const minutes = Math.floor(elapsedMs / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n\n/**\n * One line naming what will actually authenticate the next request.\n */\nfunction describeCredentials(config: AgentConfig): string {\n return config.apiKey\n ? 'API key resolved'\n : 'not resolved - set BOOK_API_KEY or set provider.<id>.apiKey in settings';\n}\n\n/**\n * A path that cannot exist, used to drop one layer from a probe resolution.\n *\n * `loadSettingsFile` returns null for a missing file, so redirecting a layer at\n * a name nothing can occupy is how a subset of the stack gets resolved without\n * touching the user's files.\n */\nconst ABSENT_LAYER = '\\0absent-settings-layer';\n\n/** The settings files doctor reads, in the order they are layered. */\nasync function settingsLayers(workspace: string): Promise<Array<[string, string]>> {\n const { join, resolve } = await import('path');\n const root = resolve(workspace);\n return [\n ['User', join(resolveBookHome(), 'settings.json')],\n ['Project', join(root, '.book', 'settings.json')],\n ['Local', join(root, '.book', 'settings.local.json')],\n ];\n}\n\n/**\n * Which layer a configuration failure first appears in.\n *\n * Some rejections name their own file: malformed JSON and schema violations both\n * carry a path. Resolving cumulative prefixes of the stack answers which layer\n * turned a working configuration into a broken one. Undefined means no prefix loads,\n * so the cause is outside the layers -- an environment variable, or a legacy `.bookrc.json`.\n */\nasync function attributeFailingLayer(workspace: string): Promise<string | undefined> {\n const layers = await settingsLayers(workspace);\n\n for (let included = 0; included <= layers.length; included++) {\n const [userSettingsPath, projectSettingsPath, localSettingsPath] = layers.map(\n ([, path], index) => (index < included ? path : ABSENT_LAYER),\n );\n try {\n loadConfig(workspace, {\n allowMissingApiKey: true,\n // A probe must not write: migrations are the real load's business.\n runMigrations: false,\n settingsPaths: { userSettingsPath, projectSettingsPath, localSettingsPath },\n });\n } catch {\n // included === 0 is the no-layer probe; failing there blames nothing.\n return included === 0 ? undefined : layers[included - 1][0];\n }\n }\n return undefined;\n}\n\n/**\n * Report a configuration that would not load at all.\n *\n * A missing credential is already handled by allowMissingApiKey, but every\n * other rejection - malformed JSON, a schema violation - used to escape\n * loadConfig as an unhandled stack trace. A broken settings file is precisely\n * what doctor exists to diagnose, so it is a finding to render, not a reason to die.\n */\nasync function reportUnloadableConfig(workspace: string, error: unknown): Promise<void> {\n const { existsSync } = await import('fs');\n const { resolve } = await import('path');\n\n console.log('Book Doctor');\n console.log('===========');\n console.log();\n console.log('Version:', getPackageVersion());\n console.log('Node:', process.version);\n console.log('Platform:', process.platform, process.arch);\n console.log('Workspace:', resolve(workspace));\n console.log();\n console.log('Configuration: FAILED TO LOAD');\n console.log(' ' + (error instanceof Error ? error.message : String(error)));\n console.log();\n console.log(' No other check can run until the configuration loads.');\n\n const culprit = await attributeFailingLayer(workspace);\n console.log(' Settings layers, in the order they are applied:');\n for (const [label, path] of await settingsLayers(workspace)) {\n const marker = existsSync(path) ? '[x]' : '[ ]';\n const blame = label === culprit ? ' <- the failure appears with this layer' : '';\n console.log(' ' + marker + ' ' + label + ': ' + path + blame);\n }\n console.log();\n if (culprit) {\n console.log(` The ${culprit} layer is where the configuration stops loading.`);\n } else {\n console.log(' No single layer accounts for it: check the environment and .bookrc.json.');\n }\n console.log(' Run `book doctor --no-settings` to report the rest with every layer skipped.');\n}\n\nexport async function runDoctorCommand(\n workspace: string,\n options: { noSettings?: boolean } = {},\n): Promise<void> {\n // Doctor must diagnose a broken environment, so it cannot require a working one:\n // a missing credential is a finding to report, not a reason to abort, and\n // neither is a settings file that fails to load.\n let config: ReturnType<typeof loadConfig>;\n try {\n config = loadConfig(workspace, {\n // --no-settings is the way past a layer doctor cannot otherwise get around;\n // migrations would rewrite settings this run has been told to ignore.\n noSettings: options.noSettings,\n runMigrations: !options.noSettings,\n allowMissingApiKey: true,\n });\n } catch (error) {\n await reportUnloadableConfig(workspace, error);\n return;\n }\n const settings = config.settings;\n\n console.log('Book Doctor');\n console.log('===========');\n console.log();\n console.log('Version:', getPackageVersion());\n console.log('Node:', process.version);\n console.log('Platform:', process.platform, process.arch);\n console.log('Workspace:', config.workspace);\n console.log('Model:', config.model, '(' + config.baseUrl + ')');\n // Printed before Credentials on purpose: an unresolved provider prefix makes\n // the credential line read as a missing key, which is the wrong hunt.\n if (config.modelProviderWarning) console.log(' ⚠ ' + config.modelProviderWarning);\n console.log('Credentials:', describeCredentials(config));\n // Configuration for a feature that no longer exists is invisible otherwise:\n // validation discards unknown blocks silently, so a user whose subscription\n // login stopped working has nothing to read. The orphaned credential file\n // matters most — it holds a refresh token nothing revokes.\n const {\n collectRemovedSettingNotices,\n collectRemovedEnvNotices,\n removedAuthStoreNotice,\n readSettingsDocumentForNotices,\n } = await import('../settings-removed.js');\n const { settingsLayerPaths } = await import('../settings-loader.js');\n const { join: joinPath } = await import('path');\n const { existsSync: fileExists } = await import('fs');\n const removedNotices = [\n ...settingsLayerPaths(workspace, undefined, {}).flatMap((path) =>\n collectRemovedSettingNotices(readSettingsDocumentForNotices(path)).map(\n (notice) => `${notice.key} in ${path}: ${notice.message}`,\n ),\n ),\n ...collectRemovedEnvNotices(process.env).map(\n (notice) => `${notice.key} is set: ${notice.message}`,\n ),\n ];\n const authStorePath = joinPath(resolveBookHome(), 'auth.json');\n if (fileExists(authStorePath)) removedNotices.push(removedAuthStoreNotice(authStorePath));\n if (removedNotices.length > 0) {\n console.log();\n console.log('Removed features still configured on this machine:');\n for (const notice of removedNotices) console.log(` [!] ${notice}`);\n }\n console.log();\n\n // Settings layers.\n console.log('Settings layers:');\n const { existsSync } = await import('fs');\n const { join } = await import('path');\n const { isUserSettingsFile } = await import('../settings-loader.js');\n for (const [label, path] of await settingsLayers(config.workspace)) {\n const marker = options.noSettings ? '[-]' : existsSync(path) ? '[x]' : '[ ]';\n // At `$HOME` the project file is the user file, and the loader reads it once (#429).\n const note =\n label === 'Project' && isUserSettingsFile(path) ? ' (the User file; read once, as User)' : '';\n console.log(' ' + marker + ' ' + label + ': ' + path + note);\n }\n // Everything below is resolved from defaults in this mode. Saying so once\n // stops the report reading as a description of the user's configuration.\n if (options.noSettings) {\n console.log(' (--no-settings: every layer skipped, defaults reported below)');\n }\n console.log();\n\n // Permissions.\n const perms = settings.permissions;\n console.log('Permissions:');\n console.log(' Allow rules: ' + perms.allow.length);\n console.log(' Ask rules: ' + perms.ask.length);\n console.log(' Deny rules: ' + perms.deny.length);\n\n // Allow rules the repository declared are withheld until the user decides on\n // them, so doctor is where an unexplained \"my project rule does nothing\" is\n // meant to be answered.\n const { loadSettingsFile } = await import('../settings-loader.js');\n const { partitionProjectAllowRules } = await import('../permission-approvals.js');\n const projectPath = join(config.workspace, '.book', 'settings.json');\n const projectSettings = isUserSettingsFile(projectPath) ? null : loadSettingsFile(projectPath);\n const projectAllow = partitionProjectAllowRules(\n projectSettings?.permissions?.allow ?? [],\n perms.projectAllowRules,\n );\n if (\n projectAllow.approved.length + projectAllow.pending.length + projectAllow.rejected.length >\n 0\n ) {\n console.log(' Project-declared allow rules (require approval):');\n for (const rule of projectAllow.approved) console.log(' [x] ' + rule);\n for (const rule of projectAllow.rejected) console.log(' [-] ' + rule + ' (rejected)');\n for (const rule of projectAllow.pending) console.log(' [!] ' + rule + ' (not in effect)');\n if (projectAllow.pending.length > 0) {\n console.log(approvalHint(' Approve one:', config.workspace, 'rule <rule>'));\n console.log(\n approvalHint(' Approve all pending:', config.workspace, 'rule --all-pending') +\n ' (add --reject to refuse)',\n );\n }\n }\n\n // A declared `additionalDirectories` entry widens the roots Read, Glob and Grep may cross, so\n // a checked-in one is withheld the same way a project allow rule is. The line shows the real\n // path next to the declared text: the decision is keyed by, and granted over, where the path\n // really goes, because the text is the repository's to write and a link can point anywhere.\n //\n // A rejected entry is not listed. It is not in effect, nothing is awaiting a decision, and\n // there is no command to print — re-reporting it on every run would be noise that trains the\n // reader to skim past the `[!]` lines that do matter.\n const { collectDeclaredDirectories, partitionProjectDirectories, resolveAdditionalRoots } =\n await import('../additional-roots.js');\n const projectDirectories = partitionProjectDirectories(\n collectDeclaredDirectories(config.workspace, projectSettings?.additionalDirectories ?? []),\n settings.projectDirectories,\n );\n const honoredAdditionalRoots = resolveAdditionalRoots(\n config.workspace,\n settings.additionalDirectories,\n );\n if (honoredAdditionalRoots.length > 0 || projectDirectories.pending.length > 0) {\n console.log('Additional directories (Read, Glob and Grep may reach these):');\n for (const root of honoredAdditionalRoots) console.log(' [x] ' + root);\n for (const directory of projectDirectories.pending) {\n console.log(\n ' [!] ' +\n directory.realPath +\n ' (not in effect; declared as ' +\n directory.declared +\n ')',\n );\n }\n if (projectDirectories.pending.length > 0) {\n console.log(approvalHint(' Approve one:', config.workspace, 'dir <path>'));\n console.log(\n approvalHint(' Approve all pending:', config.workspace, 'dir --all-pending') +\n ' (add --reject to refuse)',\n );\n }\n }\n\n console.log();\n\n // A command body that substitutes shell runs it outside the permission\n // system, so a repository-declared one is withheld until the user decides.\n // Its own section: these are not permission rules, and printing them inside\n // the permissions block reads as if they were a rule category.\n const { discoverCommands } = await import('../commands/loader.js');\n const { partitionProjectCommands, describeProjectCommandShell, displayableCommandName } =\n await import('../command-approvals.js');\n const gatedCommands = partitionProjectCommands(discoverCommands(config.workspace), settings);\n if (\n gatedCommands.approved.length + gatedCommands.pending.length + gatedCommands.rejected.length >\n 0\n ) {\n console.log('Project commands that run shell (require approval):');\n for (const command of gatedCommands.approved)\n console.log(' [x] /' + displayableCommandName(command.name));\n for (const command of gatedCommands.rejected)\n console.log(' [-] /' + displayableCommandName(command.name) + ' (rejected)');\n // A withheld command is listed with the shell it would run, the way a\n // withheld hook is listed with its command, matcher, and environment:\n // the decision is about that shell, so a name alone cannot inform it.\n for (const command of gatedCommands.pending) {\n console.log(' [!] /' + displayableCommandName(command.name) + ' (refused until approved)');\n for (const line of describeProjectCommandShell(command)) console.log(' ' + line);\n }\n if (gatedCommands.pending.length > 0) {\n console.log(approvalHint(' Approve one:', config.workspace, 'command <name>'));\n console.log(\n approvalHint(' Approve all pending:', config.workspace, 'command --all-pending') +\n ' (add --reject to refuse)',\n );\n }\n console.log();\n }\n\n // A provider names where a request goes and which credential rides along, so one only the\n // workspace declares is withheld until the user decides on that exact declaration (#418).\n // Listed in every state. The origin is the parsed protocol, host and port, in full; a key\n // reference is shown as the variable it names or the normalised file it opens, never resolved,\n // and a literal is not echoed at all. Every command printed is quoted for the user's shell.\n const providerGate = config.workspaceProviderGate;\n if (providerGate) {\n const {\n describeDroppedOverride,\n describeLegacyBaseUrl,\n describeReservedProvider,\n describeUnaffectedSelection,\n describeWithheldSelection,\n describeWorkspaceProvider,\n } = await import('../provider-approvals.js');\n const STATE_MARKS = {\n approved: { mark: '[x]', suffix: '' },\n rejected: { mark: '[-]', suffix: ' (rejected)' },\n pending: { mark: '[!]', suffix: ' (not in effect)' },\n } as const;\n const providerGroups = (['approved', 'rejected', 'pending'] as const).map((state) => ({\n ...STATE_MARKS[state],\n state,\n entries: providerGate.partition[state],\n }));\n const legacy = providerGate.legacyBaseUrl;\n const anyPending = providerGate.partition.pending.length > 0 || legacy?.state === 'pending';\n if (providerGate.declared.length > 0 || legacy) {\n console.log('Workspace-declared providers (require approval):');\n for (const group of providerGroups) {\n for (const entry of group.entries) {\n const routed =\n group.state === 'pending'\n ? providerGate.unaffectedSelections.filter((s) => s.providerId === entry.id)\n : [];\n const [first, ...rest] = describeWorkspaceProvider(entry, config.workspace, routed);\n console.log(` ${group.mark} ${first}${group.suffix}`);\n for (const line of rest) console.log(` ${line}`);\n console.log(` declared in: ${entry.layers.join(', ')}`);\n }\n }\n for (const entry of providerGate.partition.reserved) {\n console.log(` [!] ${describeReservedProvider(entry)}`);\n }\n if (legacy) {\n const { mark, suffix } = STATE_MARKS[legacy.state];\n const [first, ...rest] = describeLegacyBaseUrl(legacy.baseUrl, {\n providers: settings.provider,\n workspace: config.workspace,\n });\n console.log(` ${mark} ${first}${suffix}`);\n for (const line of rest) console.log(` ${line}`);\n }\n for (const entry of providerGate.partition.pending) {\n // The command is on a line of its own: the id is repository-authored, and a line copied\n // whole must not carry it into the shell beside the command.\n const { command, note } = providerTrustCommand(config.workspace, entry.id);\n console.log(` Approve ${renderUntrustedText(entry.id, 64)}:`);\n console.log(` ${command}${note}`);\n }\n if (legacy?.state === 'pending') {\n console.log(\n approvalHint(' Approve the legacy baseUrl:', config.workspace, 'provider .bookrc.json'),\n );\n }\n if (anyPending) {\n console.log(\n approvalHint(' Approve all pending:', config.workspace, 'provider --all-pending') +\n ' (add --reject to refuse)',\n );\n }\n console.log();\n }\n if (providerGate.droppedOverrides.length > 0) {\n console.log('Workspace overrides of your providers (dropped):');\n for (const dropped of providerGate.droppedOverrides) {\n console.log(` [!] ${describeDroppedOverride(dropped)}`);\n }\n console.log();\n }\n if (providerGate.withheldSelections.length > 0) {\n console.log('Withheld model selections:');\n for (const selection of providerGate.withheldSelections) {\n console.log(` [!] ${describeWithheldSelection(selection)}`);\n }\n console.log();\n }\n if (providerGate.unaffectedSelections.length > 0) {\n console.log('Your model selections that share a prefix with a withheld provider:');\n for (const selection of providerGate.unaffectedSelections) {\n console.log(` [x] ${describeUnaffectedSelection(selection)}`);\n }\n console.log();\n }\n }\n\n // Hooks.\n const hooks = settings.hooks;\n // `hooks.projectEntries` records trust decisions, not hook entries.\n const hookLists = Object.entries(hooks).filter((pair): pair is [string, HookEntry[]] =>\n Array.isArray(pair[1]),\n );\n let hookTotal = 0;\n for (const [, entries] of hookLists) hookTotal += entries.length;\n console.log('Hooks:');\n for (const [event, entries] of hookLists) {\n if (entries.length > 0) console.log(' ' + event + ': ' + entries.length);\n }\n if (hookTotal === 0) console.log(' (none)');\n\n // Hook entries a repository declared are withheld until the user decides on\n // them, so doctor is where an unexplained \"my project hook does nothing\" is\n // meant to be answered.\n const { collectDeclaredHooks, describeDeclaredHook, partitionProjectHooks } =\n await import('../hook-approvals.js');\n const declaredProjectHooks = collectDeclaredHooks(projectSettings);\n if (declaredProjectHooks.length > 0) {\n const hookPartition = partitionProjectHooks(\n declaredProjectHooks,\n settings.hooks.projectEntries,\n );\n console.log(' Project-declared hooks (require approval):');\n // Approval is keyed by a fingerprint covering event, matcher, command and\n // env, so all four are disclosed. A hook rendered as its command alone hides\n // exactly the fields behaviour can be smuggled in: `npm test` carrying\n // `NODE_OPTIONS=--require ./payload.js` reads as harmless and is not.\n const groups = [\n { mark: '[x]', suffix: '', hooks: hookPartition.approved },\n { mark: '[-]', suffix: ' (rejected)', hooks: hookPartition.rejected },\n { mark: '[!]', suffix: ' (not in effect)', hooks: hookPartition.pending },\n ];\n for (const group of groups) {\n for (const hook of group.hooks) {\n const described = describeDeclaredHook(hook);\n console.log(' ' + group.mark + ' ' + described.headline + group.suffix);\n for (const detail of described.details) console.log(' ' + detail);\n }\n }\n if (hookPartition.pending.length > 0) {\n console.log(approvalHint(' Approve one:', config.workspace, 'hook <fingerprint>'));\n console.log(\n approvalHint(' Approve all pending:', config.workspace, 'hook --all-pending') +\n ' (add --reject to refuse)',\n );\n }\n }\n console.log();\n\n // MCP.\n const { formatMcpServerCommand, resolveMcpServerList } = await import('../mcp-config.js');\n const { evaluateMcpServerApproval } = await import('../mcp-approvals.js');\n const mcpServers = resolveMcpServerList(config.workspace);\n console.log('MCP Servers:');\n for (const server of mcpServers) {\n const trust =\n server.source === 'user' ? 'user' : `project: ${evaluateMcpServerApproval(settings, server)}`;\n console.log(' ' + server.name + ': ' + formatMcpServerCommand(server.config) + ` [${trust}]`);\n }\n if (mcpServers.length === 0) console.log(' (none)');\n console.log();\n\n // Sandbox.\n const { createSandbox, sandboxPolicySummary } = await import('../sandbox.js');\n const { hasAdjudicationPolicy } = await import('../permissions.js');\n const sandbox = createSandbox(settings.sandbox);\n const policy = sandboxPolicySummary(settings.sandbox, {\n sandboxActive: sandbox !== null,\n adjudicationConfigured: hasAdjudicationPolicy(settings),\n });\n console.log('Sandbox:');\n console.log(' Enabled: ' + settings.sandbox.enabled);\n console.log(' Available: ' + (sandbox !== null));\n if (sandbox) console.log(' Enforcing: ' + sandbox.describe());\n console.log(' Excluded commands: ' + settings.sandbox.excludedCommands.length);\n console.log(' Unsandboxed commands: ' + policy.unsandboxedCommands);\n console.log(' Auto-allow Bash: ' + policy.autoAllowBash);\n console.log(' Git directories: ' + policy.gitDirectories);\n // The loader drops every `sandbox.*` key a workspace layer supplied in order\n // to *loosen* the policy (#373), and a silently dropped key is\n // indistinguishable from a setting that does nothing. The list is computed\n // from the raw layer files by the same function the loader applies, so what\n // is reported here is exactly what was dropped.\n //\n // The layers come from `settingsLayers`, which is the one place that knows how\n // the paths are resolved — this section used to rebuild the two workspace ones\n // by hand, and printed the workspace-relative name rather than the file it\n // read, so a report about a file the user could not find was the whole output.\n if (!options.noSettings) {\n const {\n formatIgnoredWorkspaceSandboxKey,\n ignoredWorkspaceSandboxKeys,\n loadSettingsFile,\n workspaceLayerThatEnabledSandbox,\n } = await import('../settings-loader.js');\n const layers = (await settingsLayers(config.workspace)).map(([label, path]) => ({\n label,\n path,\n document: label === 'Project' && isUserSettingsFile(path) ? null : loadSettingsFile(path),\n }));\n // The user-global layer is read here even though nothing about it is\n // reported: it is the baseline for what a workspace layer turned *on*, and\n // a repository repeating `enabled: true` after the user already set it\n // changed nothing, which is not a decision to attribute to that repository.\n const activation = workspaceLayerThatEnabledSandbox(\n layers.map((layer) => ({\n path: layer.path,\n trust: WORKSPACE_LAYER_TRUST[layer.label] ?? 'local',\n document: layer.document,\n })),\n );\n for (const { label, path, document } of layers) {\n // The user-global layer is where these values are read from, so a key it\n // writes is never ignored and there is nothing to report for it.\n if (label === 'User') continue;\n for (const entry of ignoredWorkspaceSandboxKeys(document ?? {})) {\n console.log(\n ` Ignored from ${path}: ${formatIgnoredWorkspaceSandboxKey(entry)} — workspace settings may only tighten the sandbox; set it in ~/.book/settings.json or pass --settings`,\n );\n }\n // The one *honoured* sandbox key that still changes something else.\n // `enabled` is the only key a workspace layer may set, and the loader pairs\n // it with `autoAllowBashIfSandboxed: false` so the repository cannot\n // pre-approve the commands that follow its own sandbox. That is a policy\n // change with no symptom of its own, which is what the block above exists\n // to make visible — reported for the layer that actually flipped the key\n // on, and only for that one.\n if (path === activation) {\n console.log(\n ` From ${path}: sandbox.enabled=true — a workspace file turned the sandbox on, so ` +\n `sandbox.autoAllowBashIfSandboxed=false with it; set autoAllowBashIfSandboxed in ` +\n `~/.book/settings.json to have it back.`,\n );\n }\n }\n }\n console.log();\n\n // Shell: the program every Bash command is handed to, and why it was chosen.\n const { describeShell, resolveShell } = await import('../shell-selection.js');\n const shell = config.shell ?? resolveShell({ requested: settings.shell });\n console.log('Shell:');\n console.log(' Bash tool runs: ' + describeShell(shell));\n console.log(' Selected by: ' + shell.source);\n // The MSYS-runtime flag decides whether `'` is read as on Linux under a Windows bash or sh (#566).\n if (process.platform === 'win32' && (shell.kind === 'bash' || shell.kind === 'sh')) {\n console.log(' msys: ' + (shell.msys ? 'yes' : 'no'));\n }\n if (shell.warning) console.log(` [!] ${shell.warning}`);\n console.log();\n\n // Managed agents.\n console.log('Managed agents:');\n const agentDiagnostics = collectAgentDiagnostics(\n config,\n withBuiltInAgents(discoverAgents(config.workspace)),\n );\n if (agentDiagnostics.length === 0) {\n console.log(' [x] Profiles and overrides look valid');\n } else {\n for (const diagnostic of agentDiagnostics) {\n console.log(` [!] ${diagnostic.message}`);\n }\n }\n for (const directory of [\n join(config.workspace, '.claude', 'agents'),\n join(config.workspace, '.agents', 'agents'),\n ]) {\n if (existsSync(directory)) {\n console.log(\n ` [!] Third-party definitions found at ${directory}; preview them with /agents import ${directory}.`,\n );\n }\n }\n console.log();\n\n // Learned context windows.\n const { createModelWindowStore } = await import('../model-window-store.js');\n const windowStore = createModelWindowStore();\n const allLearned = windowStore.all();\n const learnedModels = Object.keys(allLearned);\n console.log('Learned context windows:');\n if (learnedModels.length === 0) {\n console.log(' (none)');\n } else {\n for (const modelName of learnedModels) {\n const entry = windowStore.getEntry(modelName) ?? allLearned[modelName];\n console.log(\n ` ${modelName}: ${entry.contextWindow.toLocaleString()} tokens (${formatRelativeTime(entry.learnedAt)})`,\n );\n }\n }\n console.log();\n\n // Memory.\n const {\n DEFAULT_MAX_INDEX_LINES,\n MAX_INDEX_BYTES,\n findLegacyMemoryBackup,\n getMemoryHealth,\n legacyBackupNotice,\n loadMemoryContext,\n } = await import('../memory-store.js');\n // Loaded first so a directory keyed the old way is moved (and migrated) before it is counted,\n // as at session start.\n const memoryContext = loadMemoryContext(config.workspace);\n const memoryHealth = getMemoryHealth(memoryContext);\n const memoryBackup = findLegacyMemoryBackup(memoryContext.dir);\n const lastWrite = memoryHealth.lastWrite ? memoryHealth.lastWrite.toISOString() : 'never';\n console.log('Memory:');\n console.log(' Memories: ' + memoryHealth.fileCount);\n if (memoryHealth.legacySupersededCount > 0) {\n console.log(\n ` Legacy superseded: ${memoryHealth.legacySupersededCount} (retired by the old save tool; they load like any other)`,\n );\n }\n console.log(` Index lines: ${memoryHealth.indexLineCount} / ${DEFAULT_MAX_INDEX_LINES}`);\n console.log(\n ` Index bytes: ${memoryHealth.indexByteCount.toLocaleString('en-US')} / ${MAX_INDEX_BYTES.toLocaleString('en-US')}`,\n );\n if (memoryHealth.wasLineTruncated || memoryHealth.wasByteTruncated) {\n const limits = [\n memoryHealth.wasLineTruncated ? `${DEFAULT_MAX_INDEX_LINES} lines` : '',\n memoryHealth.wasByteTruncated ? `${MAX_INDEX_BYTES.toLocaleString('en-US')} bytes` : '',\n ].filter(Boolean);\n console.log(\n ` Index cut: MEMORY.md is over the ${limits.join(' and ')} limit; a session loads only part of it. Consolidate it.`,\n );\n }\n console.log(' Last write: ' + lastWrite);\n if (memoryBackup) console.log(' ' + legacyBackupNotice(memoryBackup));\n console.log();\n\n // Environment.\n console.log('Environment:');\n for (const key of ['BOOK_API_KEY', 'BOOK_BASE_URL', 'BOOK_MODEL', 'BOOK_WORKSPACE']) {\n const val = process.env[key];\n if (key === 'BOOK_API_KEY' && val) {\n console.log(' ' + key + ': *** (set)');\n } else {\n console.log(' ' + key + ': ' + (val || '(not set)'));\n }\n }\n}\n","import { resolveSettings } from '../settings-loader.js';\nimport {\n aggregateToolUse,\n formatToolStatsReport,\n pruneToolUseRecords,\n readToolUseRecords,\n} from '../tool-telemetry.js';\n\nexport interface ToolStatsCommandOptions {\n workspace: string;\n /** Emit the raw aggregate as JSON instead of a text report. */\n json?: boolean;\n /** Only include records from the last N days (overrides the retention window). */\n since?: string;\n /** Include every record regardless of the retention window. */\n all?: boolean;\n /** Drop records older than the window from disk before reporting. */\n prune?: boolean;\n}\n\nconst DAY_MS = 86_400_000;\n\n/**\n * `book tool-stats` — read the persistent tool-use telemetry log and report\n * calls, failure rates, durations, retries, and a per-model breakdown.\n */\nexport async function runToolStatsCommand(options: ToolStatsCommandOptions): Promise<void> {\n const settings = resolveSettings(options.workspace);\n const retentionDays = settings.observability.toolTelemetryRetentionDays;\n\n let windowDays: number | undefined;\n if (options.all) {\n windowDays = undefined;\n } else if (options.since !== undefined) {\n const parsed = Number(options.since);\n // A non-finite --since falls back to the configured window; 0 is honored as \"today only\".\n windowDays = Number.isFinite(parsed) ? Math.max(0, parsed) : retentionDays;\n } else {\n windowDays = retentionDays;\n }\n const cutoffTs = windowDays === undefined ? 0 : Date.now() - windowDays * DAY_MS;\n\n if (options.prune) {\n const result = await pruneToolUseRecords(cutoffTs);\n console.error(\n `Pruned ${result.dropped} record${result.dropped === 1 ? '' : 's'} older than ${windowDays ?? 0} days (${result.kept} kept).`,\n );\n }\n\n const all = await readToolUseRecords();\n const records = all.filter((record) => (record.ts ?? 0) >= cutoffTs);\n const aggregate = aggregateToolUse(records);\n\n if (options.json) {\n console.log(JSON.stringify(aggregate, null, 2));\n return;\n }\n\n console.log(formatToolStatsReport(aggregate));\n if (windowDays !== undefined && aggregate.totalCalls > 0) {\n console.log(\n `\\n(Window: last ${windowDays} days. Use --all for full history, --since <days> to change.)`,\n );\n }\n}\n","/**\n * `book config provider-key <id>`: replace the API key of a provider in the user file (#592).\n *\n * The key is read from stdin, hidden on a terminal and piped otherwise, and never from the command\n * line, where it would land in shell history and the process table. Like every `config`\n * subcommand it runs without a working credential: replacing a dead key is the reason it exists.\n */\nimport { createInterface } from 'readline';\nimport { Writable } from 'stream';\nimport { exit } from './exit.js';\nimport {\n checkProviderKey,\n providerKeyTarget,\n validateApiKey,\n writeProviderKey,\n type ProviderKeyCheckOptions,\n} from '../provider-key.js';\nimport { DEFAULT_SETTINGS } from '../settings.js';\nimport { settingsScopeLabel, type SettingsScope } from '../settings-scope.js';\n\n/** stdin, or a stand-in for it in tests. */\nexport interface ProviderKeyInput extends NodeJS.ReadableStream {\n isTTY?: boolean;\n setRawMode?: (mode: boolean) => unknown;\n}\n\nexport interface ProviderKeyCommandOptions {\n /** False for `--no-check`: save without asking the endpoint. */\n check?: boolean;\n /** `--force`: save even when the check fails. */\n force?: boolean;\n /** `-g` / `--project` / `--local`. Only the user layer holds providers this edits. */\n scope?: SettingsScope;\n /** `--settings <path>` or `--no-settings` was passed: refused, since neither changes the target. */\n ignoresSettingsFlags?: boolean;\n stdin?: ProviderKeyInput;\n /** Where prompts go; stdout stays for the result. */\n stderr?: NodeJS.WritableStream;\n discover?: ProviderKeyCheckOptions['discover'];\n}\n\nconst USAGE = 'Usage: book config provider-key <provider-id> (the key is read from stdin)';\n\n/** Far above any real key; a stream past it is not one, and is not read to the end. */\nconst MAX_PIPED_BYTES = 64 * 1024;\n\n/**\n * Read a piped stdin, dropping the one line ending `echo` adds. Undefined when the input runs past\n * {@link MAX_PIPED_BYTES}.\n */\nasync function readPiped(input: ProviderKeyInput): Promise<string | undefined> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of input) {\n const buffer = typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer);\n size += buffer.length;\n if (size > MAX_PIPED_BYTES) return undefined;\n chunks.push(buffer);\n }\n return Buffer.concat(chunks)\n .toString('utf-8')\n .replace(/\\r?\\n$/, '');\n}\n\n/** One line from a terminal; undefined on Ctrl+C or Ctrl+D. `hidden` echoes nothing. */\nasync function readTerminalLine(\n input: ProviderKeyInput,\n stderr: NodeJS.WritableStream,\n prompt: string,\n hidden: boolean,\n): Promise<string | undefined> {\n stderr.write(prompt);\n const output = hidden\n ? new Writable({\n write(_chunk, _encoding, done) {\n done();\n },\n })\n : stderr;\n const rl = createInterface({ input, output, terminal: true });\n try {\n return await new Promise<string | undefined>((resolve) => {\n rl.once('line', resolve);\n rl.once('SIGINT', () => resolve(undefined));\n rl.once('close', () => resolve(undefined));\n });\n } finally {\n rl.close();\n if (hidden) stderr.write('\\n');\n }\n}\n\ntype FailureChoice = 'save' | 'retry' | 'edit' | 'cancel';\n\nasync function askAfterFailure(\n input: ProviderKeyInput,\n stderr: NodeJS.WritableStream,\n): Promise<FailureChoice> {\n const answer = await readTerminalLine(\n input,\n stderr,\n '[s] save anyway [r] retry [e] enter a different key [c] cancel: ',\n false,\n );\n switch (answer?.trim().toLowerCase()) {\n case 's':\n return 'save';\n case 'r':\n return 'retry';\n case 'e':\n return 'edit';\n default:\n return 'cancel';\n }\n}\n\nexport async function runProviderKeyCommand(\n workspace: string,\n providerId: string | undefined,\n extra: string | undefined,\n options: ProviderKeyCommandOptions = {},\n): Promise<void> {\n const stdin = options.stdin ?? (process.stdin as ProviderKeyInput);\n const stderr = options.stderr ?? process.stderr;\n if (extra !== undefined) {\n // Never echoed: it is most likely the key itself.\n console.error(\n 'provider-key reads the key from stdin, never from an argument; nothing was saved. ' +\n 'A key typed on the command line is in your shell history: consider rotating it.',\n );\n console.error(USAGE);\n return exit(1);\n }\n if (!providerId) {\n console.error(USAGE);\n return exit(1);\n }\n if (options.ignoresSettingsFlags) {\n console.error(\n 'provider-key edits your user settings (<BOOK_HOME>/settings.json) whatever the settings ' +\n 'layers in use; --settings and --no-settings do not apply to it.',\n );\n return exit(1);\n }\n if (options.scope && options.scope !== 'user') {\n console.error(\n `provider-key changes providers in your user settings only, not ${settingsScopeLabel(options.scope)} settings.`,\n );\n return exit(1);\n }\n\n const target = providerKeyTarget(workspace, providerId);\n if (target.kind === 'unreadable') {\n console.error(`Could not read user settings (${target.path}): ${target.error}`);\n return exit(1);\n }\n if (target.kind === 'workspace-only') {\n console.error(\n `Provider \"${providerId}\" is declared by this repository (${target.declaredIn}), not your ` +\n `user settings (${target.path}). provider-key changes only providers you configured.`,\n );\n return exit(1);\n }\n if (target.kind === 'unknown') {\n console.error(\n // The id is not repeated: one that names no provider is as likely to be a key typed in\n // its place, and the command promises never to echo a key.\n `No provider with that id in user settings (${target.path}). ` +\n (target.configured.length > 0\n ? `Configured: ${target.configured.join(', ')}.`\n : 'No providers are configured there yet; add one with /providers in the TUI.'),\n );\n return exit(1);\n }\n\n const interactive = stdin.isTTY === true;\n const readKey = async (): Promise<string> => {\n const raw = interactive\n ? await readTerminalLine(stdin, stderr, `API key for ${providerId}: `, true)\n : await readPiped(stdin);\n if (raw === undefined) {\n console.error(\n interactive\n ? 'Cancelled; nothing was saved.'\n : `The input is longer than ${MAX_PIPED_BYTES} bytes, which no API key is; nothing was saved.`,\n );\n return exit(1);\n }\n try {\n return validateApiKey(raw);\n } catch (caught) {\n console.error(caught instanceof Error ? caught.message : 'Invalid API key.');\n return exit(1);\n }\n };\n\n let apiKey = await readKey();\n let tested = false;\n while (options.check !== false) {\n const result = await checkProviderKey({\n provider: target.provider,\n apiKey,\n workspace,\n retry: DEFAULT_SETTINGS.retry,\n discover: options.discover,\n });\n if (result.ok) {\n tested = true;\n break;\n }\n console.error(`The key check failed: ${result.error}`);\n if (options.force) {\n console.warn('Saving anyway (--force).');\n break;\n }\n if (!interactive) {\n console.error(\n 'Nothing was saved. Pass --force to save anyway, or --no-check to skip the check.',\n );\n return exit(1);\n }\n const choice = await askAfterFailure(stdin, stderr);\n if (choice === 'save') break;\n if (choice === 'cancel') {\n console.error('Cancelled; nothing was saved.');\n return exit(1);\n }\n if (choice === 'edit') apiKey = await readKey();\n }\n\n const written = writeProviderKey(workspace, providerId, apiKey);\n if (!written.ok) {\n console.error(written.error);\n return exit(1);\n }\n console.log(\n `Updated the API key of provider \"${providerId}\" in user settings (${written.path})` +\n (tested ? '; the endpoint accepted it.' : '.'),\n );\n if (written.localCleared) {\n console.log(\n `Removed the connection keys of the same-named entry in ${written.localCleared}, which ` +\n 'would otherwise look like they override it.',\n );\n }\n if (written.localError) {\n console.warn(`⚠ Could not clean up the local entry: ${written.localError}`);\n }\n}\n","import { exit } from './exit.js';\nimport { getNestedValue } from './utils.js';\nimport { redactSettingValue, redactSettingsForDisplay } from '../settings-redaction.js';\nimport { DEFAULT_SETTINGS, type ResolvedSettings } from '../settings.js';\nimport { formatSettingsDiagnostics, SettingsRepository } from '../settings-repository.js';\nimport {\n resolveSettings,\n applySettingsEnvOverrides,\n startupAnimationEnvNote,\n} from '../settings-loader.js';\nimport { settingsScopeLabel, type SettingsScope } from '../settings-scope.js';\nimport { applySettingWrite, describeSettingShadow, readScopeDocument } from '../settings-write.js';\nimport { runProviderKeyCommand, type ProviderKeyCommandOptions } from './provider-key-cmd.js';\n\nexport interface ConfigCommandSettingsOptions {\n settingsOverridePath?: string;\n noSettings?: boolean;\n /**\n * Which layer to act on. Writes default to `user`, so a setting follows the\n * person rather than the directory they happened to run the command in.\n * Reads default to the resolved merge of every layer; a scope narrows them to\n * that one file, which is how a user finds the stray value overriding them.\n */\n scope?: SettingsScope;\n /** `provider-key` only: `--no-check`, `--force`, and the streams tests stand in for. */\n providerKey?: ProviderKeyCommandOptions;\n}\n\nexport async function runConfigCommand(\n workspace: string,\n action: string | undefined,\n key: string | undefined,\n value: string | undefined,\n settingsOptions: ConfigCommandSettingsOptions = {},\n): Promise<void> {\n // *Calling* this is deferred because it throws on a malformed layer, and the\n // paths that do not need it are exactly the ones a user reaches for when a\n // layer *is* malformed: a scoped read to find the broken file, and a write to\n // replace the bad value. Resolving eagerly made `config` the one tool that\n // stopped working precisely when the config was wrong. The import itself is\n // static — `settings-write.js` pulls the loader in regardless, so a dynamic\n // one deferred nothing while reading as though it did.\n //\n // What it returns is the *effective* settings, environment included: a read\n // that reported the file's value while Book acts on `BOOK_STARTUP_ANIMATION`\n // would answer a question about a setting that is not in force.\n const resolveMergedSettings = (): ResolvedSettings =>\n applySettingsEnvOverrides(\n settingsOptions.noSettings\n ? structuredClone(DEFAULT_SETTINGS)\n : resolveSettings(workspace, settingsOptions.settingsOverridePath),\n );\n\n if (action === 'provider-key') {\n await runProviderKeyCommand(workspace, key, value, {\n ...settingsOptions.providerKey,\n scope: settingsOptions.scope,\n ignoresSettingsFlags: Boolean(\n settingsOptions.settingsOverridePath || settingsOptions.noSettings,\n ),\n });\n return;\n }\n if (settingsOptions.providerKey?.force || settingsOptions.providerKey?.check === false) {\n console.error('--force and --no-check apply to provider-key only.');\n exit(1);\n }\n\n // A scope narrows a read to one file. Without it a read reports the merge,\n // which is the right default but cannot answer \"why is this not what I set\" —\n // for that the user needs to see the layer the value actually came from.\n const scopeRead = settingsOptions.scope\n ? readScopeDocument(settingsOptions.scope, workspace)\n : undefined;\n\n if (!action || action === 'list') {\n if (scopeRead) {\n console.log(`${settingsScopeLabel(scopeRead.scope)} settings (${scopeRead.path}):`);\n if (scopeRead.status === 'unreadable') {\n console.error(`Could not read it: ${scopeRead.error ?? 'unknown error'}`);\n exit(1);\n }\n console.log(\n scopeRead.status === 'present'\n ? JSON.stringify(redactSettingsForDisplay(scopeRead.document), null, 2)\n : 'No settings file at this scope yet.',\n );\n return;\n }\n console.log('Resolved settings:');\n console.log(JSON.stringify(redactSettingsForDisplay(resolveMergedSettings()), null, 2));\n // The dump can show a value the file does not hold, so it has to say so\n // rather than let the reader go looking for a line that is not there.\n const listNote = startupAnimationEnvNote();\n if (listNote) console.log(`⚠ ${listNote}`);\n return;\n }\n\n if (action === 'get') {\n if (!key) {\n console.error('Usage: book config get <key>');\n exit(1);\n }\n if (scopeRead?.status === 'unreadable') {\n console.error(\n `Could not read ${settingsScopeLabel(scopeRead.scope)} settings (${scopeRead.path}): ` +\n `${scopeRead.error ?? 'unknown error'}`,\n );\n exit(1);\n }\n const source = scopeRead\n ? scopeRead.document\n : (resolveMergedSettings() as unknown as Record<string, unknown>);\n const val = getNestedValue(source, key);\n if (val === undefined) {\n console.log(\n scopeRead\n ? `Key ${key} is not set in ${settingsScopeLabel(scopeRead.scope)} settings (${scopeRead.path}).`\n : 'Key ' + key + ' is not set (no value).',\n );\n } else {\n console.log(JSON.stringify(redactSettingValue(key, val), null, 2));\n // Only for the key the environment decides: on any other key the note\n // would be noise about a setting the reader did not ask about.\n if (!scopeRead && key === 'ui.startupAnimation') {\n const note = startupAnimationEnvNote();\n if (note) console.log(`⚠ ${note}`);\n }\n }\n return;\n }\n\n if (action === 'set') {\n if (!key || value === undefined) {\n console.error('Usage: book config set <key> <value>');\n exit(1);\n }\n let parsedValue: unknown;\n try {\n parsedValue = JSON.parse(value);\n } catch {\n parsedValue = value;\n }\n\n const scope = settingsOptions.scope ?? 'user';\n const result = applySettingWrite({\n workspace,\n key,\n value: parsedValue,\n scope,\n settingsOverridePath: settingsOptions.settingsOverridePath,\n noSettings: settingsOptions.noSettings,\n });\n if (!result.ok) {\n console.error(result.error);\n exit(1);\n return;\n }\n console.log(\n 'Set ' +\n key +\n ' = ' +\n JSON.stringify(redactSettingValue(key, result.value)) +\n ' in ' +\n settingsScopeLabel(result.scope) +\n ' settings (' +\n result.path +\n ')',\n );\n // A user-global write is the one that silently loses: the local layer is\n // resolved last, so a value left there from before this command defaulted\n // to `user` keeps winning. Say so rather than letting the write look inert.\n for (const shadow of result.shadowedBy) {\n console.warn(`⚠ ${describeSettingShadow(shadow, key)}`);\n }\n return;\n }\n\n if (action === 'unset') {\n if (!key) {\n console.error('Usage: book config unset <key>');\n exit(1);\n }\n // Unset needs no scope default of its own beyond `set`'s: the reason to\n // reach for it is almost always a stray value in a layer that outranks the\n // global one, and that layer has to be named explicitly anyway.\n const scope = settingsOptions.scope ?? 'user';\n const layer = readScopeDocument(scope, workspace, { forWrite: true });\n if (layer.status === 'unreadable') {\n console.error(\n `Could not read ${settingsScopeLabel(scope)} settings (${layer.path}): ` +\n `${layer.error ?? 'unknown error'}`,\n );\n exit(1);\n }\n if (layer.status === 'absent' || getNestedValue(layer.document, key) === undefined) {\n console.log(\n `${key} is not set in ${settingsScopeLabel(scope)} settings (${layer.path}); nothing to remove.`,\n );\n return;\n }\n const result = new SettingsRepository(layer.path).remove([key]);\n if (!result.ok) {\n console.error(formatSettingsDiagnostics(result.diagnostics));\n exit(1);\n }\n console.log(`Removed ${key} from ${settingsScopeLabel(scope)} settings (${result.path})`);\n return;\n }\n\n console.error(\n 'Unknown action: ' +\n action +\n '. Use: get <key>, set <key> <value>, unset <key>, list, or provider-key <id>',\n );\n exit(1);\n}\n","/**\n * `book trust` — record a decision about repository-declared configuration.\n *\n * The gated input is a hook entry, a `permissions.allow` rule, a project\n * command whose body substitutes shell, a directory, or a provider only the\n * workspace declares (its origin and key reference; #418); until a decision\n * exists, the resolver withholds it. Doctor reports what is withheld and prints the command that\n * grants it, so this is the non-interactive half of that flow.\n *\n * Commands are keyed by name rather than by fingerprint. A hook or a rule is\n * anonymous — a fingerprint is the only handle it has — but a command already\n * has one the user typed, and asking them to paste a digest to approve\n * `/deploy` would be ceremony without a gain. The fingerprint still decides\n * *validity*: it is recorded with the choice and re-checked on every\n * invocation, so editing what the body runs re-asks under the same name.\n *\n * It replaces a printed `book config set hooks.projectEntries '<json>'`\n * one-liner, which was wrong in three ways: `config set` *replaces* the value\n * at a path, so pasting a map of newly-pending entries silently discarded every\n * earlier approve/reject; the suggestion omitted `--workspace`, so running it\n * from elsewhere wrote decisions into the wrong project; and its single-quoted\n * JSON does not survive `cmd.exe`, where quotes are literal and the argument\n * reaches validation as a string. Decisions here are recorded one at a time\n * through the per-key persist helpers, and a fingerprint is bare hex, so\n * nothing needs quoting.\n */\nimport { join } from 'path';\nimport {\n describeProjectCommandShell,\n displayableCommandName,\n partitionProjectCommands,\n persistProjectCommandChoice,\n projectCommandFingerprint,\n} from '../command-approvals.js';\nimport { discoverCommands } from '../commands/loader.js';\nimport {\n collectDeclaredHooks,\n describeDeclaredHook,\n hookFingerprint,\n partitionProjectHooks,\n persistProjectHookChoice,\n renderUntrustedText,\n} from '../hook-approvals.js';\nimport {\n collectDeclaredDirectories,\n partitionProjectDirectories,\n persistProjectDirectoryChoice,\n realPathOfDirectory,\n type DeclaredDirectory,\n} from '../additional-roots.js';\nimport {\n partitionProjectAllowRules,\n persistProjectAllowRuleChoice,\n} from '../permission-approvals.js';\nimport { readLegacyBaseUrl } from '../legacy-config.js';\nimport {\n describeLegacyBaseUrl,\n describeReservedProvider,\n describeWorkspaceProvider,\n environmentModelSelections,\n evaluateLegacyBaseUrl,\n LEGACY_BASE_URL_ID,\n legacyBaseUrlFingerprint,\n persistWorkspaceProviderChoice,\n withEnvironmentSelections,\n type WorkspaceProviderState,\n} from '../provider-approvals.js';\nimport { providerTrustCommand, trustCommandText } from '../trust-command.js';\nimport {\n isUserSettingsFile,\n loadSettingsFile,\n resolveSettingsWithProviderGate,\n} from '../settings-loader.js';\nimport type { SlashCommand } from '../types/commands.js';\nimport { exit } from './exit.js';\n\nexport type TrustKind = 'hook' | 'rule' | 'command' | 'dir' | 'provider';\n\nexport interface TrustCommandOptions {\n workspace: string;\n /** Record a refusal instead of an approval. */\n reject?: boolean;\n /** Apply the decision to everything currently withheld. */\n allPending?: boolean;\n}\n\nfunction fail(message: string): never {\n console.error(message);\n return exit(1);\n}\n\nexport async function runTrustCommand(\n kind: TrustKind,\n target: string | undefined,\n options: TrustCommandOptions,\n): Promise<void> {\n const workspace = options.workspace;\n const choice = options.reject ? 'rejected' : 'approved';\n const verb = options.reject ? 'Rejected' : 'Approved';\n\n if (options.allPending && target !== undefined) {\n fail(`book trust ${kind}: pass either a target or --all-pending, not both`);\n }\n // `provider` with neither is the listing: what is awaiting a decision, and the command for it.\n const listsProviders = kind === 'provider' && !options.allPending && target === undefined;\n if (!options.allPending && target === undefined && !listsProviders) {\n fail(\n `book trust ${kind}: name what to trust, or pass --all-pending. Run \\`book doctor\\` to list what is withheld.`,\n );\n }\n\n let settings;\n let providerGate;\n try {\n ({ settings, providerGate } = resolveSettingsWithProviderGate(workspace));\n } catch (error) {\n return fail(\n `book trust ${kind}: cannot read settings for ${workspace}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n // Only the checked-in layer is gated, so only its declarations are decidable. At `$HOME`\n // that path is the user's own file, which is trusted and has nothing to decide (#429).\n const projectPath = join(workspace, '.book', 'settings.json');\n const projectSettings = isUserSettingsFile(projectPath) ? null : loadSettingsFile(projectPath);\n\n // A command decision carries the fingerprint of the shell it was made\n // against, so the body cannot change under an approval already on file.\n const decisions: Array<{ key: string; label: string; fingerprint?: string }> = [];\n // Directories carry their real path as the key (see `additional-roots.ts`), so they get their\n // own list rather than borrowing the `{key, label}` shape whose key is a fingerprint.\n const directoryDecisions: DeclaredDirectory[] = [];\n\n if (kind === 'command') {\n // Commands are discovered from disk, not declared in settings: the gated\n // artefact is the `.book/commands/*.md` body itself.\n const partition = partitionProjectCommands(discoverCommands(workspace), settings);\n const push = (command: SlashCommand) => {\n // Approving is approving the shell, so the shell is what gets shown —\n // never just the name. The single-command path reaches here from a\n // refusal that already listed it; `--all-pending` has no such prior, and\n // a bulk grant against a list of names is approval without reading.\n if (!options.reject) {\n console.log(`/${displayableCommandName(command.name)} runs:`);\n for (const line of describeProjectCommandShell(command)) console.log(` ${line}`);\n }\n decisions.push({\n key: command.name,\n label: `/${displayableCommandName(command.name)}`,\n fingerprint: projectCommandFingerprint(command.body),\n });\n };\n\n if (options.allPending) {\n if (partition.pending.length === 0) {\n console.log(`No project commands are awaiting a decision in ${workspace}.`);\n return;\n }\n for (const command of partition.pending) push(command);\n } else {\n const name = target!.replace(/^\\//, '');\n const decidable = [...partition.pending, ...partition.approved, ...partition.rejected];\n const command = decidable.find((candidate) => candidate.name === name);\n if (!command) {\n // Either the command does not exist, or it substitutes no shell and so\n // has nothing to decide. Both mean this decision would change nothing.\n const known = partition.pending\n .map((pending) => ` /${displayableCommandName(pending.name)}`)\n .join('\\n');\n return fail(\n `book trust command: ${workspace} has no project command \"${name}\" that runs shell.` +\n (known ? `\\nAwaiting a decision:\\n${known}` : '\\nNothing is awaiting a decision.'),\n );\n }\n push(command);\n }\n } else if (kind === 'hook') {\n const declared = collectDeclaredHooks(projectSettings);\n const byFingerprint = new Map(\n declared.map((hook) => [hookFingerprint(hook.event, hook.entry), hook]),\n );\n const partition = partitionProjectHooks(declared, settings.hooks.projectEntries);\n\n if (options.allPending) {\n if (partition.pending.length === 0) {\n console.log(`No project-declared hooks are awaiting a decision in ${workspace}.`);\n return;\n }\n for (const hook of partition.pending) {\n const fingerprint = hookFingerprint(hook.event, hook.entry);\n decisions.push({ key: fingerprint, label: describeDeclaredHook(hook).headline });\n }\n } else {\n const hook = byFingerprint.get(target!);\n if (!hook) {\n // A typo would otherwise record a decision that matches no hook and\n // silently changes nothing.\n const known = partition.pending\n .map(\n (pending) =>\n ` ${hookFingerprint(pending.event, pending.entry)} ${describeDeclaredHook(pending).headline}`,\n )\n .join('\\n');\n return fail(\n `book trust hook: no project-declared hook in ${workspace} has fingerprint \"${target}\".` +\n (known ? `\\nAwaiting a decision:\\n${known}` : '\\nNothing is awaiting a decision.'),\n );\n }\n decisions.push({ key: target!, label: describeDeclaredHook(hook).headline });\n }\n } else if (kind === 'dir') {\n // A directory is keyed by where it *really* is, not by the text the repository wrote, so the\n // target the user typed is resolved the same way the resolver resolves it and then matched\n // against the real paths: `./shared`, `shared` and the absolute path are one entry. Matching\n // the declared text too means a symlink repointed since approval can no longer be decided\n // under its old name. A path that no longer exists is a different matter: `collectDeclaredDirectories`\n // drops it, so it is simply not offered here — there is nothing left to decide about.\n const declared = collectDeclaredDirectories(\n workspace,\n projectSettings?.additionalDirectories ?? [],\n );\n const partition = partitionProjectDirectories(declared, settings.projectDirectories);\n const targetRealPath = realPathOfDirectory(workspace, target ?? '');\n const entry = declared.find(\n (candidate) => candidate.realPath === targetRealPath || candidate.declared === target,\n );\n\n if (options.allPending) {\n if (partition.pending.length === 0) {\n console.log(`No project-declared directories are awaiting a decision in ${workspace}.`);\n return;\n }\n for (const pending of partition.pending) {\n console.log(`${pending.declared} is really:`);\n console.log(` ${pending.realPath}`);\n directoryDecisions.push(pending);\n }\n } else if (!entry) {\n const known = partition.pending.map((pending) => ` ${pending.realPath}`).join('\\n');\n return fail(\n `book trust dir: ${workspace} declares no project additionalDirectories entry at \"${target}\".` +\n (known ? `\\nAwaiting a decision:\\n${known}` : '\\nNothing is awaiting a decision.'),\n );\n } else {\n if (!options.reject) {\n console.log(`${entry.declared} is really:`);\n console.log(` ${entry.realPath}`);\n }\n directoryDecisions.push(entry);\n }\n } else if (kind === 'provider') {\n // Providers only the workspace declares, plus the legacy `.bookrc.json` `baseUrl` under its\n // own id. A provider a trusted layer defines has nothing to decide: its origin and key are\n // the user's, and a workspace layer's override of them is dropped whatever is recorded here.\n interface ProviderCandidate {\n id: string;\n fingerprint: string;\n state: WorkspaceProviderState;\n /** What approving it would do, first line then detail. */\n lines: string[];\n }\n // The user's own selections that share a prefix with a withheld provider: approving the\n // provider routes them to its origin, so the listing names them.\n const unaffected = withEnvironmentSelections(\n providerGate.unaffectedSelections,\n environmentModelSelections(undefined),\n new Set(providerGate.withheld),\n );\n const candidates: ProviderCandidate[] = (['approved', 'pending', 'rejected'] as const).flatMap(\n (state) =>\n providerGate.partition[state].map((entry) => ({\n id: entry.id,\n fingerprint: entry.fingerprint,\n state,\n lines: describeWorkspaceProvider(\n entry,\n workspace,\n unaffected.filter((selection) => selection.providerId === entry.id),\n ),\n })),\n );\n // Parsed by the loader's own parser, so the fingerprint is the one the loader checks.\n const legacyBaseUrl = readLegacyBaseUrl(workspace);\n if (legacyBaseUrl !== undefined) {\n candidates.push({\n id: LEGACY_BASE_URL_ID,\n fingerprint: legacyBaseUrlFingerprint(legacyBaseUrl),\n state: evaluateLegacyBaseUrl(settings.workspaceProviders, legacyBaseUrl),\n lines: describeLegacyBaseUrl(legacyBaseUrl, { providers: settings.provider, workspace }),\n });\n }\n const pending = candidates.filter((candidate) => candidate.state === 'pending');\n const printCandidate = (candidate: ProviderCandidate, prefix: string) => {\n const [first, ...rest] = candidate.lines;\n console.log(`${prefix}${first}`);\n for (const line of rest) console.log(` ${line}`);\n };\n const push = (candidate: ProviderCandidate) => {\n // Approving sends the user's requests, and the key a reference names, to the origin shown,\n // so that is what gets shown before the decision is recorded.\n if (!options.reject) printCandidate(candidate, ' ');\n decisions.push({\n key: candidate.id,\n label: candidate.id,\n fingerprint: candidate.fingerprint,\n });\n };\n // A provider named like the legacy decision's key can never be approved (see the partition),\n // so it is reported rather than offered.\n const reserved = providerGate.partition.reserved.map(\n (entry) => ` [!] ${describeReservedProvider(entry)}`,\n );\n\n if (listsProviders) {\n for (const line of reserved) console.log(line);\n if (pending.length === 0) {\n console.log(`No workspace-declared providers are awaiting a decision in ${workspace}.`);\n return;\n }\n console.log(`Workspace-declared providers awaiting a decision in ${workspace}:`);\n for (const candidate of pending) printCandidate(candidate, ' [!] ');\n // The id is repository-authored: it is quoted for the shell, or left off the line when it\n // cannot be quoted, so a copied command cannot run what a hostile id spells.\n for (const candidate of pending) {\n const { command, note } = providerTrustCommand(workspace, candidate.id);\n console.log(`Approve ${renderUntrustedText(candidate.id, 64)}:`);\n console.log(` ${command}${note}`);\n }\n const all = trustCommandText(workspace, 'provider --all-pending');\n console.log(`Approve all: ${all.command}${all.note} (add --reject to refuse)`);\n return;\n }\n if (options.allPending) {\n if (pending.length === 0) {\n console.log(`No workspace-declared providers are awaiting a decision in ${workspace}.`);\n return;\n }\n for (const candidate of pending) push(candidate);\n } else {\n const candidate = candidates.find((known) => known.id === target);\n if (!candidate) {\n // A typo would otherwise record a decision that matches no provider.\n const known = candidates\n .map((entry) => ` ${renderUntrustedText(entry.id, 64)} (${entry.state})`)\n .join('\\n');\n return fail(\n `book trust provider: ${workspace} declares no provider \"${target}\" that can be decided.` +\n (known ? `\\nDeclared by the workspace:\\n${known}` : '\\nNothing is declared.') +\n (reserved.length > 0 ? `\\n${reserved.join('\\n')}` : ''),\n );\n }\n push(candidate);\n }\n } else {\n const declared = projectSettings?.permissions?.allow ?? [];\n const partition = partitionProjectAllowRules(declared, settings.permissions.projectAllowRules);\n\n if (options.allPending) {\n if (partition.pending.length === 0) {\n console.log(`No project-declared allow rules are awaiting a decision in ${workspace}.`);\n return;\n }\n for (const rule of partition.pending) decisions.push({ key: rule, label: rule });\n } else {\n if (!declared.includes(target!)) {\n const known = partition.pending.map((rule) => ` ${rule}`).join('\\n');\n return fail(\n `book trust rule: ${workspace} declares no project allow rule \"${target}\".` +\n (known ? `\\nAwaiting a decision:\\n${known}` : '\\nNothing is awaiting a decision.'),\n );\n }\n decisions.push({ key: target!, label: target! });\n }\n }\n\n const failures: string[] = [];\n for (const directory of directoryDecisions) {\n const result = persistProjectDirectoryChoice(workspace, directory.realPath, choice);\n if (result.ok) console.log(`${verb} ${directory.realPath}`);\n else failures.push(`${directory.realPath}: ${result.error ?? 'unknown error'}`);\n }\n for (const decision of decisions) {\n const result =\n kind === 'command'\n ? persistProjectCommandChoice(workspace, decision.key, decision.fingerprint!, choice)\n : kind === 'provider'\n ? persistWorkspaceProviderChoice(workspace, decision.key, decision.fingerprint!, choice)\n : kind === 'hook'\n ? persistProjectHookChoice(workspace, decision.key, choice)\n : persistProjectAllowRuleChoice(workspace, decision.key, choice);\n if (result.ok) console.log(`${verb} ${decision.label}`);\n else failures.push(`${decision.label}: ${result.error ?? 'unknown error'}`);\n }\n\n if (failures.length > 0) {\n fail(\n `Failed to record ${failures.length} decision(s):\\n${failures.map((f) => ` ${f}`).join('\\n')}`,\n );\n }\n}\n","/**\n * Session-scoped MCP owner for interactive hosts.\n *\n * Resolves declared servers, enforces the project-server approval boundary,\n * connects approved servers in the background, and exposes a subscribe/snapshot\n * surface plus live tool definitions for per-send registry assembly. All\n * diagnostics route through the debug log — never the console — so Ink output\n * stays intact.\n */\nimport type { ChildProcess } from 'child_process';\nimport {\n buildMcpToolDefinitions,\n connectMcpServers,\n disconnectMcpServers,\n type McpConnection,\n} from './mcp.js';\nimport {\n formatMcpServerCommand,\n resolveMcpServerList,\n type McpServerSource,\n type ResolvedMcpServer,\n} from './mcp-config.js';\nimport {\n evaluateMcpServerApproval,\n mcpServerFingerprint,\n persistMcpProjectServerChoice,\n} from './mcp-approvals.js';\nimport { createDebugLogger } from './debug-log.js';\nimport type { McpSettings } from './settings.js';\nimport type { ElicitationHandler, ToolDefinition } from './types/tools.js';\n\nconst log = createDebugLogger('mcp');\n\nexport type McpServerStatus =\n | 'pending-approval'\n | 'deferred'\n | 'rejected'\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'failed';\n\nexport interface McpHostServerSnapshot {\n name: string;\n source: McpServerSource;\n path: string;\n /** Full non-secret connection target the user is trusting. */\n target: string;\n envKeys: string[];\n headerKeys: string[];\n fingerprint: string;\n status: McpServerStatus;\n /** True when a recorded decision exists but the config changed since. */\n configChangedSinceApproval: boolean;\n toolCount?: number;\n error?: string;\n}\n\nexport type McpHostEvent =\n | { id: number; type: 'connected'; server: string; toolCount: number }\n | { id: number; type: 'disconnected'; server: string }\n | { id: number; type: 'failed'; server: string; error: string }\n | { id: number; type: 'tools-changed'; server: string; toolCount: number };\n\ntype McpHostEventInput<T = McpHostEvent> = T extends McpHostEvent ? Omit<T, 'id'> : never;\n\nexport interface McpHostSnapshot {\n servers: McpHostServerSnapshot[];\n /** Project servers awaiting a user decision, in declaration order. */\n pendingApprovals: McpHostServerSnapshot[];\n /** Bounded event feed with monotonic IDs; hosts track the last consumed ID. */\n events: McpHostEvent[];\n}\n\nexport interface McpSessionHostOptions {\n home?: string;\n initializationTimeoutMs?: number;\n requestTimeoutMs?: number;\n /** Injectable for tests; defaults to the settings.local.json writer. */\n persistChoice?: typeof persistMcpProjectServerChoice;\n /** Lifecycle observer for spawned server processes. */\n onProcessSpawn?: (name: string, process: ChildProcess) => void;\n /** Injectable connector used by lifecycle tests. */\n connectServers?: typeof connectMcpServers;\n}\n\nconst MAX_EVENTS = 50;\n\ninterface HostServerState {\n server: ResolvedMcpServer;\n fingerprint: string;\n status: McpServerStatus;\n configChangedSinceApproval: boolean;\n toolCount?: number;\n error?: string;\n}\n\ninterface McpApprovalSettings {\n mcp?: Partial<McpSettings>;\n}\n\nexport class McpSessionHost {\n private readonly states = new Map<string, HostServerState>();\n private readonly connections: McpConnection[] = [];\n private readonly listeners = new Set<() => void>();\n private readonly events: McpHostEvent[] = [];\n private readonly abortController = new AbortController();\n private readonly persistChoice: typeof persistMcpProjectServerChoice;\n private elicitationHandler?: ElicitationHandler;\n private nextEventId = 1;\n private snapshot: McpHostSnapshot = { servers: [], pendingApprovals: [], events: [] };\n private started = false;\n private disposed = false;\n\n constructor(\n private readonly workspace: string,\n private readonly settings: McpApprovalSettings,\n private readonly options: McpSessionHostOptions = {},\n ) {\n this.persistChoice = options.persistChoice ?? persistMcpProjectServerChoice;\n }\n\n /** Resolve declared servers and begin connecting every already-trusted one. */\n start(): void {\n if (this.started || this.disposed) return;\n this.started = true;\n const servers = resolveMcpServerList(this.workspace, {\n home: this.options.home,\n onDiagnostic: (diagnostic) => log.debug(diagnostic.message),\n });\n for (const server of servers) {\n const approval = evaluateMcpServerApproval(this.settings, server);\n const recorded = this.settings.mcp?.projectServers?.[server.name];\n const fingerprint = mcpServerFingerprint(server.config);\n this.states.set(server.name, {\n server,\n fingerprint,\n status:\n approval === 'approved'\n ? 'connecting'\n : approval === 'rejected'\n ? 'rejected'\n : 'pending-approval',\n configChangedSinceApproval:\n approval === 'unknown' && recorded !== undefined && recorded.fingerprint !== fingerprint,\n });\n }\n this.rebuildSnapshot();\n for (const state of this.states.values()) {\n if (state.status === 'connecting') void this.connect(state);\n }\n }\n\n /** Persist approval for a pending project server and connect it. */\n approve(name: string): { ok: boolean; error?: string } {\n const state = this.states.get(name);\n if (!state || state.status !== 'pending-approval') {\n return { ok: false, error: `No pending approval for MCP server \"${name}\".` };\n }\n const persisted = this.persistChoice(this.workspace, name, state.fingerprint, 'approved');\n if (!persisted.ok) return persisted;\n state.status = 'connecting';\n state.configChangedSinceApproval = false;\n this.rebuildSnapshot();\n void this.connect(state);\n return { ok: true };\n }\n\n /** Persist rejection for a pending project server. */\n reject(name: string): { ok: boolean; error?: string } {\n const state = this.states.get(name);\n if (!state || state.status !== 'pending-approval') {\n return { ok: false, error: `No pending approval for MCP server \"${name}\".` };\n }\n const persisted = this.persistChoice(this.workspace, name, state.fingerprint, 'rejected');\n if (!persisted.ok) return persisted;\n state.status = 'rejected';\n this.rebuildSnapshot();\n return { ok: true };\n }\n\n /** Leave a pending server undecided for this session (re-prompts next session). */\n defer(name: string): void {\n const state = this.states.get(name);\n if (!state || state.status !== 'pending-approval') return;\n state.status = 'deferred';\n this.rebuildSnapshot();\n }\n\n /** Live tool definitions; hosts call this per send so list changes surface. */\n getToolDefinitions(): ToolDefinition[] {\n return buildMcpToolDefinitions(this.connections, this.options.requestTimeoutMs);\n }\n\n getSnapshot(): McpHostSnapshot {\n return this.snapshot;\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /** Install the host prompt used to answer server elicitation requests. */\n setElicitationHandler(handler: ElicitationHandler | undefined): void {\n this.elicitationHandler = handler;\n }\n\n async dispose(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n this.abortController.abort(new Error('MCP host disposed'));\n await disconnectMcpServers(this.connections);\n this.listeners.clear();\n }\n\n private async connect(state: HostServerState): Promise<void> {\n const { name } = state.server;\n try {\n const result = await (this.options.connectServers ?? connectMcpServers)(this.workspace, {\n servers: { [name]: state.server.config },\n home: this.options.home,\n signal: this.abortController.signal,\n initializationTimeoutMs: this.options.initializationTimeoutMs,\n requestTimeoutMs: this.options.requestTimeoutMs,\n onProcessSpawn: this.options.onProcessSpawn,\n onDiagnostic: (diagnostic) => log.debug(diagnostic.message),\n onToolListChanged: (serverName) => this.handleToolListChanged(serverName),\n onConnectionClosed: (serverName) => this.handleConnectionClosed(serverName),\n // Stable indirection: servers connect in the background before the UI\n // can install its prompt, so the capability is declared up front and\n // the handler is resolved per request.\n onElicit: (request, context) =>\n this.elicitationHandler\n ? this.elicitationHandler(request, context)\n : Promise.resolve({ action: 'decline' as const }),\n });\n const connection = result.connections[0];\n if (this.disposed) {\n if (connection) await disconnectMcpServers([connection]);\n return;\n }\n if (!connection) {\n state.status = 'failed';\n state.error = 'connection failed (see debug log)';\n this.pushEvent({ type: 'failed', server: name, error: state.error });\n return;\n }\n if (connection.closed) {\n state.status = 'failed';\n state.error = 'connection closed during startup';\n this.pushEvent({ type: 'failed', server: name, error: state.error });\n return;\n }\n this.connections.push(connection);\n state.status = 'connected';\n state.toolCount = connection.tools.length;\n state.error = undefined;\n this.pushEvent({ type: 'connected', server: name, toolCount: connection.tools.length });\n } catch (error) {\n state.status = 'failed';\n state.error = error instanceof Error ? error.message : String(error);\n log.debug(`MCP host connect error for \"${name}\": ${state.error}`);\n this.pushEvent({ type: 'failed', server: name, error: state.error });\n }\n }\n\n private handleToolListChanged(serverName: string): void {\n const state = this.states.get(serverName);\n const connection = this.connections.find((conn) => conn.name === serverName);\n if (!state || !connection) return;\n state.toolCount = connection.tools.length;\n this.pushEvent({ type: 'tools-changed', server: serverName, toolCount: state.toolCount });\n }\n\n private handleConnectionClosed(serverName: string): void {\n if (this.disposed) return;\n const state = this.states.get(serverName);\n if (!state || state.status !== 'connected') return;\n state.status = 'disconnected';\n state.error = 'connection closed';\n state.toolCount = 0;\n this.pushEvent({ type: 'disconnected', server: serverName });\n }\n\n private pushEvent(event: McpHostEventInput): void {\n this.events.push({ ...event, id: this.nextEventId++ } as McpHostEvent);\n if (this.events.length > MAX_EVENTS) this.events.splice(0, this.events.length - MAX_EVENTS);\n this.rebuildSnapshot();\n }\n\n private rebuildSnapshot(): void {\n const servers = [...this.states.values()].map((state) => ({\n name: state.server.name,\n source: state.server.source,\n path: state.server.path,\n target: formatMcpServerCommand(state.server.config),\n envKeys: Object.keys(state.server.config.env ?? {}).sort(),\n headerKeys: Object.keys(state.server.config.headers ?? {}).sort(),\n fingerprint: state.fingerprint,\n status: state.status,\n configChangedSinceApproval: state.configChangedSinceApproval,\n toolCount: state.toolCount,\n error: state.error,\n }));\n this.snapshot = {\n servers,\n pendingApprovals: servers.filter((server) => server.status === 'pending-approval'),\n events: [...this.events],\n };\n for (const listener of this.listeners) listener();\n }\n}\n","import { exit } from './exit.js';\nimport type { AgentTerminalOutcome } from '../types/terminal.js';\n\ntype InterruptSignal = 'SIGINT' | 'SIGTERM';\n\nexport interface PrintInterrupt {\n /** Aborts on the first SIGINT or SIGTERM, with a `user_cancelled` reason. */\n signal: AbortSignal;\n /** The signal that cancelled the run, if one did. */\n interruptedBy(): InterruptSignal | undefined;\n /** Remove the listeners. */\n dispose(): void;\n}\n\n/**\n * Make Ctrl+C cancel a print run instead of killing it: the run is given the same\n * abort a cancelled stream gets, so it still runs SessionEnd hooks, and a second\n * Ctrl+C leaves at once rather than waiting on them (#248).\n */\nexport function installPrintInterrupt(\n options: {\n stderr?: { write(text: string): unknown };\n onSecondSignal?: (signal: InterruptSignal) => void;\n } = {},\n): PrintInterrupt {\n const controller = new AbortController();\n let interrupted: InterruptSignal | undefined;\n const onSignal = (signal: InterruptSignal): void => {\n if (interrupted) {\n (\n options.onSecondSignal ??\n ((second: InterruptSignal) => exit(second === 'SIGINT' ? 130 : 143))\n )(signal);\n return;\n }\n interrupted = signal;\n (options.stderr ?? process.stderr).write(\n '\\nCancelling: running SessionEnd hooks. Press Ctrl+C again to exit now.\\n',\n );\n // An Error, so a native `signal.throwIfAborted()` rethrows something a user\n // can read, that still carries the `bookTerminalReason` `classifyAbortReason`\n // reads so the run reports `cancelled` rather than a bare `caller_cancelled`.\n controller.abort(\n Object.assign(new Error(`Cancelled by ${signal}`), { bookTerminalReason: 'user_cancelled' }),\n );\n };\n const onSigint = (): void => onSignal('SIGINT');\n const onSigterm = (): void => onSignal('SIGTERM');\n process.on('SIGINT', onSigint);\n process.on('SIGTERM', onSigterm);\n return {\n signal: controller.signal,\n interruptedBy: () => interrupted,\n dispose: () => {\n process.off('SIGINT', onSigint);\n process.off('SIGTERM', onSigterm);\n },\n };\n}\n\n/**\n * The exit code a print run leaves behind: 130 or 143 when a signal interrupted it\n * (what a shell reports for a process a signal ended); otherwise whatever the run's\n * own outcome says, even if the signal aborted after it, so a reader that goes away\n * once a failed run has reported cannot turn it green; 1 for a run that threw; and\n * 0 for a run that was merely cancelled, wherever the abort landed, in the stream or\n * inside a tool — cancelling is not failing (#248).\n */\nexport function printExitCode(run: {\n outcome?: AgentTerminalOutcome;\n aborted: boolean;\n interruptedBy?: InterruptSignal;\n}): number {\n if (run.interruptedBy) return run.interruptedBy === 'SIGINT' ? 130 : 143;\n if (run.outcome) return run.outcome.status === 'failed' ? 1 : 0;\n return run.aborted ? 0 : 1;\n}\n","import type { Instance } from 'ink';\nimport { freezeAgentConfig, loadConfig } from '../config.js';\nimport { runHeadless } from '../headless.js';\nimport { createDefaultRegistry } from '../tools/registry.js';\nimport { SessionStore } from '../session/store.js';\nimport { connectMcpServers, disconnectMcpServers } from '../mcp.js';\nimport { McpSessionHost } from '../mcp-host.js';\nimport { mcpServersToRecord, partitionMcpServersByApproval } from '../mcp-approvals.js';\nimport { resolveMcpServerList } from '../mcp-config.js';\nimport {\n collectSkippedProjectFileNotices,\n collectWithheldProjectNotices,\n collectWithheldProviderNotices,\n} from '../project-approval-notices.js';\nimport { isExiting, setExitCode } from './exit.js';\nimport { installPrintInterrupt, printExitCode, type PrintInterrupt } from './print-interrupt.js';\nimport { parseNumericFlag } from './utils.js';\nimport { parseEffortLevel } from '../commands/effort.js';\nimport { join } from 'path';\nimport type { AgentConfig } from '../types/runtime.js';\nimport type { RewindSnapshotStoreInterface } from '../types/sessions.js';\nimport type { HeadlessResult } from '../types/public-sdk.js';\nimport {\n discardUntouchedSessions,\n resolveSessionBootstrap,\n type SessionBootstrap,\n} from '../session/resolve.js';\nimport { parseSessionDriver, resolveSessionDriver } from '../session-driver.js';\nimport {\n createRewindSnapshotStore,\n createUnavailableRewindSnapshotStore,\n} from '../rewind/snapshot-store.js';\nimport { createEphemeralRewindEnvironment } from '../rewind/environment.js';\nimport {\n cleanupDebugLogs,\n createDebugLogger,\n DEFAULT_LOCAL_DATA_RETENTION_DAYS,\n getDebugLogPath,\n} from '../debug-log.js';\nimport { installInkScrollRenderer } from './ink-scroll-renderer.js';\nimport { installFrameCapture } from './frame-buffer.js';\nimport { hasInkTrailingNewlineFix, loadInkFlushSync } from './ink-renderer.js';\nimport { installInkFrameThrottle } from './ink-frame-throttle.js';\nimport { installInkOutputCache } from './ink-output-cache.js';\nimport { installInkRenderCull } from './ink-render-cull.js';\nimport { installInkFrameClip } from './ink-frame-clip.js';\nimport { isCiEnvironment, resolveInkMaxFps, resolveTuiRendererMode } from './tui-renderer-mode.js';\nimport { resolvePermissionMode } from '../permission-mode.js';\nimport { spawn } from 'node:child_process';\nimport { buildChildEnv } from '../child-env.js';\nimport { resolveBookHome } from '../book-home.js';\nimport { isReaderGoneError } from '../reader-gone.js';\nimport { cleanupRunStatus } from '../run-status.js';\n\n/** Read at each use, so a BOOK_HOME set after this module loads is honoured. */\nfunction sessionRoot(): string {\n return join(resolveBookHome(), 'sessions');\n}\nconst ENTER_ALT_SCREEN = '\\x1b[?1049h';\nconst EXIT_ALT_SCREEN = '\\x1b[?1049l';\n/**\n * Every mouse-reporting mode a terminal may have on, not just the ones Book\n * sets. Clear stale modes before enabling the narrow mode Book needs, and\n * clear them all again on exit so a crashed session cannot leak reports into\n * the next shell prompt.\n */\nconst DISABLE_MOUSE_REPORTING =\n '\\x1b[?1000l' + '\\x1b[?1002l' + '\\x1b[?1003l' + '\\x1b[?1006l' + '\\x1b[?1015l';\nconst ENABLE_BUTTON_EVENT_TRACKING = '\\x1b[?1002h';\nconst ENABLE_SGR_MOUSE = '\\x1b[?1006h';\n/**\n * Alternate scroll translates the wheel into cursor keys while the alternate\n * screen is up. Book handles SGR wheel reports itself, so cursor-key emulation\n * must stay off for the session and is handed back on exit.\n */\nconst DISABLE_ALTERNATE_SCROLL = '\\x1b[?1007l';\nconst RESTORE_ALTERNATE_SCROLL = '\\x1b[?1007h';\nconst WSL_TERMINAL_BRIDGE_SCRIPT = `\nfor process in /proc/[0-9]*; do\n [ -r \"$process/environ\" ] || continue\n /usr/bin/grep -Fzqx \"WT_SESSION=$2\" \"$process/environ\" 2>/dev/null || continue\n target=$(/usr/bin/readlink \"$process/fd/1\" 2>/dev/null) || continue\n case \"$target\" in\n /dev/pts/*)\n /usr/bin/printf '%s' \"$1\" > \"$process/fd/1\"\n exit $?\n ;;\n esac\ndone\nexit 1\n`.trim();\n\nexport function shouldBridgeWslTerminal(\n platform = process.platform,\n env: NodeJS.ProcessEnv = process.env,\n): boolean {\n const sharedVariables = (env.WSLENV ?? '').split(':').map((entry) => entry.split('/')[0]);\n return platform === 'win32' && Boolean(env.WT_SESSION) && sharedVariables.includes('WT_SESSION');\n}\n\nfunction writeTerminalControl(stdout: Pick<NodeJS.WriteStream, 'write'>, sequence: string): void {\n stdout.write(sequence);\n if (stdout !== process.stdout || !shouldBridgeWslTerminal()) return;\n\n // A Windows process launched from WSL writes through an inner ConPTY. Find\n // the WSL proxy for this terminal session and write modes to its real PTY.\n try {\n const bridge = spawn(\n 'wsl.exe',\n [\n '-e',\n 'sh',\n '-c',\n WSL_TERMINAL_BRIDGE_SCRIPT,\n 'book-terminal-bridge',\n sequence,\n process.env.WT_SESSION!,\n ],\n {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n env: buildChildEnv(),\n },\n );\n bridge.on('error', () => {});\n bridge.unref();\n } catch {\n // Terminal restoration remains best effort when the WSL bridge is unavailable.\n }\n}\n\nfunction collectSnapshotReferences(store: SessionStore, cwd: string): Set<string> {\n return store.listSnapshotReferences(cwd);\n}\n\n/**\n * A print run's `error` handler for `process.stdout` and `process.stderr`.\n *\n * A closed reader is not a failure to report: the run is over for whoever was\n * reading, so the handler cancels it and returns. Every code a closed far end\n * arrives with is recognised, not just EPIPE — the run is already cancelled\n * through the failing write's own callback by the time the stream's `error`\n * event lands, so rethrowing a second code for the same fault would turn one\n * closed reader into an uncaught exception: exit 1, and no SessionEnd.\n *\n * Anything else is a real failure of the process's own output, and is thrown\n * rather than reported as a reader that left.\n */\nexport function printPipeErrorHandler(\n stream: 'stdout' | 'stderr',\n printFormat: 'text' | 'json' | 'stream-json',\n readerGone: AbortController,\n): (error: NodeJS.ErrnoException) => void {\n return (error: NodeJS.ErrnoException) => {\n if (!isReaderGoneError(error)) throw error;\n if (stream === 'stdout' && printFormat === 'stream-json') readerGone.abort();\n };\n}\n\nexport function enterInteractiveScreen(\n stdout: Pick<NodeJS.WriteStream, 'isTTY' | 'write'> = process.stdout,\n /** Injectable so the non-TTY bridge path is testable off win32. */\n bridgeWslTerminal: boolean = shouldBridgeWslTerminal(),\n): () => void {\n if (!stdout.isTTY && !bridgeWslTerminal) return () => {};\n\n let restored = false;\n const restore = () => {\n if (restored) return;\n restored = true;\n writeTerminalControl(\n stdout,\n DISABLE_MOUSE_REPORTING + RESTORE_ALTERNATE_SCROLL + EXIT_ALT_SCREEN,\n );\n process.off('exit', restore);\n };\n\n writeTerminalControl(\n stdout,\n ENTER_ALT_SCREEN +\n DISABLE_MOUSE_REPORTING +\n DISABLE_ALTERNATE_SCROLL +\n ENABLE_BUTTON_EVENT_TRACKING +\n ENABLE_SGR_MOUSE,\n );\n process.once('exit', restore);\n return restore;\n}\n\nexport async function runMainAction(options: Record<string, unknown>): Promise<void> {\n // Declared before the `try` so the print branch's `catch` can still read them:\n // a run cancelled or interrupted before it returned has no `result` to read.\n let printInterrupt: PrintInterrupt | undefined;\n let printSignal: AbortSignal | undefined;\n // The session this launch opened, for the `finally` below: a launch that ends before its\n // first prompt, however it ends, must not leave an empty session behind (#444).\n let launched: { store: SessionStore | undefined; bootstrap: SessionBootstrap } | undefined;\n // The sessions the TUI's `/new` and `/clear` created: each is as much this process's as the\n // launch's own session, and goes the same way when nothing was ever recorded in it (#507).\n const createdSessions = new Set<string>();\n try {\n const requestedWorkspace = options.workspace as string | undefined;\n // Validated again here rather than trusted from commander: the option parser\n // covers the CLI, this covers every other caller of runMainAction.\n const effortOverride = options.effort\n ? parseEffortLevel(String(options.effort), '--effort')\n : undefined;\n // Before loadConfig, which may run settings migrations: a rejected flag leaves nothing behind.\n const explicitDriver =\n options.sessionDriver === undefined\n ? undefined\n : parseSessionDriver(String(options.sessionDriver));\n if (options.sessionDriver !== undefined && !explicitDriver) {\n throw new Error('--session-driver must be human or agent');\n }\n const config = loadConfig(requestedWorkspace, {\n settingsOverridePath: options.settings as string | undefined,\n noSettings: options.settings === false,\n runMigrations: options.settings !== false,\n modelOverride: options.model as string | undefined,\n effortOverride,\n allowMissingApiKey: options.print === undefined && !options.scrollback,\n }) as AgentConfig;\n // Stderr, so it cannot corrupt --output-format json on stdout.\n if (config.modelProviderWarning) console.warn('⚠ ' + config.modelProviderWarning);\n // Print mode reports these with the other withheld declarations below. The interactive modes\n // have no prompt for a provider, and one the workspace declared that is not in effect would\n // otherwise be silent: the model it names just never appears. The full-screen TUI clears the\n // screen on its first render, so it shows them itself (`startupNotices`) rather than have\n // them written here; only the scrollback mode, which keeps the terminal's history, prints.\n const providerNotices =\n options.print === undefined && config.workspaceProviderGate\n ? collectWithheldProviderNotices(config.workspaceProviderGate, config.workspace)\n : [];\n // Project instruction files, REVIEW.md and command files that link out of the repository are\n // not loaded (#539, #543). Not tied to `--no-settings`: they are read whatever the settings\n // layers are.\n const instructionNotices = collectSkippedProjectFileNotices(config.workspace);\n if (options.scrollback) {\n for (const notice of [...providerNotices, ...instructionNotices]) console.warn(notice);\n }\n const interactiveMaxTurns = parseNumericFlag(options.maxTurns, '--max-turns', {\n integer: true,\n });\n if (interactiveMaxTurns !== undefined) config.maxTurns = interactiveMaxTurns;\n if (options.agents) {\n const agentsMode = String(options.agents);\n if (!['adaptive', 'manual', 'off'].includes(agentsMode)) {\n throw new Error('--agents must be adaptive, manual, or off');\n }\n config.settings.agents.mode = agentsMode as 'adaptive' | 'manual' | 'off';\n }\n if (options.provider) {\n const VALID_PROVIDERS = new Set(['anthropic', 'openai', 'auto']);\n const raw = String(options.provider).trim().toLowerCase();\n if (VALID_PROVIDERS.has(raw)) {\n config.provider = raw as AgentConfig['provider'];\n }\n }\n // Who drives this process decides whether the model may write memory (src/session-driver.ts).\n const sessionDriver = resolveSessionDriver({ explicit: explicitDriver, env: process.env });\n config.sessionDriver = sessionDriver.driver;\n createDebugLogger('memory').info('session driver', { ...sessionDriver });\n freezeAgentConfig(config);\n cleanupDebugLogs(DEFAULT_LOCAL_DATA_RETENTION_DAYS, getDebugLogPath());\n cleanupRunStatus(DEFAULT_LOCAL_DATA_RETENTION_DAYS);\n\n // Headless / print mode.\n if (options.print !== undefined) {\n // Connect approved MCP servers and merge their tools into the registry.\n // Project-declared servers need a prior interactive approval; there is\n // no prompt to give one here.\n // Repository-declared allow rules and hooks are withheld until the user\n // decides on them; a non-interactive host cannot ask, so it reports and\n // continues.\n for (const notice of [\n ...collectWithheldProjectNotices({\n workspace: config.workspace,\n settings: config.settings,\n settingsEnabled: options.settings !== false,\n providerGate: config.workspaceProviderGate,\n }),\n ...instructionNotices,\n ]) {\n console.warn(notice);\n }\n const declaredMcpServers = resolveMcpServerList(config.workspace);\n const mcpPartition = partitionMcpServersByApproval(declaredMcpServers, config.settings);\n for (const server of mcpPartition.pending) {\n console.warn(\n `⚠ Skipping MCP server \"${server.name}\" (${server.path}): project-declared servers require one-time approval. Approve it in an interactive session first.`,\n );\n }\n const mcp = await connectMcpServers(config.workspace, {\n servers: mcpServersToRecord(mcpPartition.allowed),\n });\n let result: HeadlessResult | undefined;\n try {\n const registry = createDefaultRegistry({ agents: config.settings.agents.mode !== 'off' });\n if (mcp.tools.length > 0) {\n registry.registerAll(mcp.tools);\n }\n\n const mode = resolvePermissionMode(config.settings, options.permissionMode);\n\n const sessionStore = (options.sessionPersistence as boolean)\n ? new SessionStore(sessionRoot())\n : undefined;\n const bootstrap = resolveSessionBootstrap(sessionStore, {\n cwd: config.workspace,\n resume: options.resume as string | undefined,\n continue: options.continue as boolean | undefined,\n sessionId: options.sessionId as string | undefined,\n sessionName: options.name as string | undefined,\n forkSession: options.forkSession as boolean | undefined,\n driver: config.sessionDriver,\n });\n launched = { store: sessionStore, bootstrap };\n sessionStore?.cleanup(DEFAULT_LOCAL_DATA_RETENTION_DAYS, new Set([bootstrap.sessionId]));\n\n // Once a reader is gone, stderr and a `text` or `json` answer (written once, at the end)\n // are best-effort: `book -p … 2>&1 | head` must not crash the run with an unhandled EPIPE,\n // which also skipped its SessionEnd hooks. `stream-json` writes stdout for the whole run,\n // so a closed stdout there means the host has gone: abort the run rather than keep\n // editing files for no one. A SIGINT or SIGTERM cancels the run the same way, so\n // SessionEnd runs with reason `aborted`, and a second signal exits at once.\n const printFormat = options.outputFormat as 'text' | 'json' | 'stream-json';\n const readerGone = new AbortController();\n printInterrupt = installPrintInterrupt();\n const callerSignal = options.signal as AbortSignal | undefined;\n printSignal = AbortSignal.any(\n [callerSignal, readerGone.signal, printInterrupt.signal].filter(\n (signal): signal is AbortSignal => signal !== undefined,\n ),\n );\n process.stderr.on('error', printPipeErrorHandler('stderr', printFormat, readerGone));\n process.stdout.on('error', printPipeErrorHandler('stdout', printFormat, readerGone));\n result = await runHeadless(config, registry, {\n prompt: typeof options.print === 'string' ? (options.print as string) : undefined,\n inputFormat: options.inputFormat as 'text' | 'stream-json',\n outputFormat: options.outputFormat as 'text' | 'json' | 'stream-json',\n history: bootstrap.history,\n transcript: bootstrap.transcript,\n compactBoundaries: bootstrap.compactBoundaries,\n plan: bootstrap.plan,\n goal: bootstrap.goal,\n carriedUsage: bootstrap.carriedUsage,\n carriedModels: bootstrap.carriedModels,\n mode,\n signal: printSignal,\n maxTurns: parseNumericFlag(options.maxTurns, '--max-turns', { integer: true }),\n maxBudgetUsd: parseNumericFlag(options.maxBudgetUsd, '--max-budget-usd'),\n verbose: options.verbose as boolean | undefined,\n quiet: options.quiet as boolean | undefined,\n jsonSchema: options.jsonSchema ? JSON.parse(options.jsonSchema as string) : undefined,\n sessionStore,\n sessionId: bootstrap.sessionId,\n sessionName: bootstrap.sessionName,\n forkSession: false,\n sessionCreated: bootstrap.created,\n persistSession: options.sessionPersistence as boolean | undefined,\n includeHookEvents: options.includeHookEvents as boolean | undefined,\n includePartialMessages: options.includePartialMessages as boolean | undefined,\n includeResultMessages: options.includeResultMessages as boolean | undefined,\n promptSuggestions: options.promptSuggestions as boolean | undefined,\n });\n } finally {\n // The run has settled: its SIGINT/SIGTERM handlers go now, not after the\n // MCP disconnect. Waiting on a shutting-down server can take seconds, and\n // a second Ctrl+C in that window must still exit at once.\n printInterrupt?.dispose();\n await disconnectMcpServers(mcp.connections);\n }\n // Not `exit(1)`: a failed run returns like a successful one and only marks the exit\n // code, so Node exits once the provider's pooled sockets have closed. Exiting while\n // they are still closing aborts inside libuv on Windows, with exit code 127 (#243).\n const code = printExitCode({\n outcome: result?.outcome,\n aborted: printSignal?.aborted === true,\n interruptedBy: printInterrupt?.interruptedBy(),\n });\n if (code !== 0) setExitCode(code);\n return;\n }\n\n // Interactive TUI mode.\n const mode = resolvePermissionMode(config.settings, options.permissionMode);\n if (options.scrollback) {\n const { runScrollbackSession } = await import('./scrollback.js');\n await runScrollbackSession(config, { mode });\n return;\n }\n\n const sessionStore = (options.sessionPersistence as boolean)\n ? new SessionStore(sessionRoot())\n : undefined;\n const ephemeralRewind = sessionStore\n ? undefined\n : createEphemeralRewindEnvironment(config.workspace);\n const timelineStore = sessionStore ?? ephemeralRewind!.timelineStore;\n let snapshotStore: RewindSnapshotStoreInterface = sessionStore\n ? createRewindSnapshotStore(config.workspace)\n : ephemeralRewind!.snapshotStore;\n if (sessionStore) {\n try {\n snapshotStore.cleanup(collectSnapshotReferences(sessionStore, config.workspace), 30);\n } catch (error) {\n snapshotStore = createUnavailableRewindSnapshotStore(\n `Code rewind unavailable: snapshot cleanup failed (${error instanceof Error ? error.message : String(error)}).`,\n );\n }\n }\n const bootstrap = resolveSessionBootstrap(sessionStore, {\n cwd: config.workspace,\n resume: options.resume as string | undefined,\n continue: options.continue as boolean | undefined,\n sessionId: options.sessionId as string | undefined,\n sessionName: options.name as string | undefined,\n forkSession: options.forkSession as boolean | undefined,\n driver: config.sessionDriver,\n });\n launched = { store: sessionStore, bootstrap };\n sessionStore?.cleanup(DEFAULT_LOCAL_DATA_RETENTION_DAYS, new Set([bootstrap.sessionId]));\n if (!sessionStore) {\n timelineStore.create({\n id: bootstrap.sessionId,\n cwd: config.workspace,\n name: bootstrap.sessionName,\n driver: config.sessionDriver,\n });\n }\n\n // Ink and React load here, not at the top of the file: the CLI is a split bundle that hoists\n // every static import of the entry above its body, so a static import would evaluate React\n // before runtime-env.ts sets NODE_ENV and ship its development build. The architecture check\n // rejects a static React or Ink import the CLI entry can reach.\n const [{ App }, { loadInteractiveAssets }, { render }, { createElement }] = await Promise.all([\n import('../tui/app.js'),\n import('../tui/interactive-assets.js'),\n import('ink'),\n import('react'),\n ]);\n const interactiveAssets = loadInteractiveAssets(config);\n // Session MCP owner: user-global and previously approved project servers\n // connect in the background; unapproved project servers surface as a\n // one-time trust prompt inside the TUI.\n const mcpHost = new McpSessionHost(config.workspace, config.settings);\n mcpHost.start();\n let app: Instance | undefined;\n // App runs this inside Ink's suspendTerminal(), which erases Ink's frame before it and repaints\n // the whole frame after it, so this only wipes whatever else is on the screen.\n const redrawViewport = () => {\n process.stdout.write('\\x1b[H\\x1b[2J');\n };\n const restoreScreen = config.accessibility.screenReader\n ? () => {}\n : enterInteractiveScreen(process.stdout);\n try {\n const rendererMode = resolveTuiRendererMode(process.env.BOOK_TUI_RENDERER, {\n isTTY: process.stdout.isTTY === true,\n screenReader: config.accessibility.screenReader,\n incrementalRendererFixed: hasInkTrailingNewlineFix(),\n platform: process.platform,\n });\n await installInkScrollRenderer(rendererMode === 'experimental-scroll');\n await installFrameCapture();\n // Ink rebuilds every row of every frame from scratch, with fresh caches per frame, which is\n // where a scroll through a long session stalls. This shares them across frames.\n await installInkOutputCache();\n // Ink's walk draws every mounted transcript row, even the ones the viewport cannot see.\n await installInkRenderCull();\n await installInkFrameClip();\n // Lets a resize commit the new size before Ink's own `resized()` draws (#538).\n const flushSync = await loadInkFlushSync();\n app = render(\n createElement(App, {\n config,\n permissionMode: mode,\n interactiveAssets,\n redrawViewport,\n flushSync,\n mcp: mcpHost,\n session: {\n ...bootstrap,\n store: sessionStore,\n timelineStore,\n snapshotStore,\n createdSessions,\n },\n startupNotices: [...providerNotices, ...instructionNotices],\n }),\n {\n exitOnCtrlC: false,\n isScreenReaderEnabled: config.accessibility.screenReader,\n incrementalRendering: rendererMode !== 'safe',\n maxFps: resolveInkMaxFps(process.platform),\n // Ink 7 also turns live frames off for a non-TTY stdout, which the WSL bridge uses.\n interactive: !isCiEnvironment(),\n },\n );\n // Ink's throttle restarts its window on every commit, so a steady stream of commits drew at\n // about half `maxFps`; this one times each draw from the last.\n await installInkFrameThrottle(process.stdout);\n await app.waitUntilExit();\n } finally {\n app?.cleanup();\n restoreScreen();\n await mcpHost.dispose();\n ephemeralRewind?.dispose();\n }\n } catch (e) {\n if (isExiting()) throw e;\n console.error(e instanceof Error ? e.message : String(e));\n // A thrown print failure gets the same treatment as a returned one (#243): mark\n // the exit code and let Node exit once its handles close.\n if (options.print !== undefined) {\n printInterrupt?.dispose();\n const code = printExitCode({\n aborted: printSignal?.aborted === true,\n interruptedBy: printInterrupt?.interruptedBy(),\n });\n if (code !== 0) setExitCode(code);\n return;\n }\n // The TUI marks the exit code the same way (#268): `exit()` while a pooled provider\n // socket is still closing aborts inside libuv on Windows, with exit code 127, and the\n // reason it exited at once — Ink holding stdin — no longer holds; its `finally` has\n // unmounted Ink and restored the screen by now.\n setExitCode(1);\n } finally {\n // After every SessionEnd hook the launch ran (the print run and the TUI both await theirs),\n // so a record a hook wrote keeps the session. Never throws.\n if (launched) discardUntouchedSessions(launched.store, launched.bootstrap, createdSessions);\n }\n}\n","import {\n chmodSync,\n existsSync,\n lstatSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n readlinkSync,\n renameSync,\n rmSync,\n symlinkSync,\n unlinkSync,\n writeFileSync,\n} from 'fs';\nimport { lstat, mkdir, readFile, readdir, readlink, rename, rm, writeFile } from 'fs/promises';\nimport { createHash, randomUUID } from 'crypto';\nimport { dirname, isAbsolute, join, relative, resolve, sep } from 'path';\nimport ignore from 'ignore';\nimport type {\n RewindRestoreResult,\n RewindSnapshotCaptureResult,\n RewindSnapshotEntry,\n RewindSnapshotManifest,\n RewindSnapshotStoreInterface,\n} from '../types/sessions.js';\nimport { resolveBookHome } from '../book-home.js';\nimport { pathExists as pathExistsAsync } from '../fs-utils.js';\nimport { createUncGuard, reachesUncPath, type UncGuard } from '../unc-path.js';\n\nexport const REWIND_MAX_ENTRIES = 20_000;\nexport const REWIND_MAX_FILE_BYTES = 16 * 1024 * 1024;\nexport const REWIND_MAX_LOGICAL_BYTES = 256 * 1024 * 1024;\n\nexport interface RewindSnapshotLimits {\n maxEntries: number;\n maxFileBytes: number;\n maxLogicalBytes: number;\n}\n\nconst DEFAULT_IGNORE_PATTERNS = [\n '.book/',\n 'node_modules/',\n '.pnpm-store/',\n '.npm/',\n '.yarn/',\n '.venv/',\n 'venv/',\n 'env/',\n 'dist/',\n 'build/',\n 'target/',\n '.next/',\n '.cache/',\n '.turbo/',\n '.parcel-cache/',\n '.gradle/',\n 'coverage/',\n '__pycache__/',\n '.pytest_cache/',\n '.mypy_cache/',\n '.ruff_cache/',\n '.tox/',\n '*.pyc',\n];\n\nfunction sha256(value: Buffer | string): string {\n return createHash('sha256').update(value).digest('hex');\n}\n\nfunction pathExists(path: string): boolean {\n try {\n lstatSync(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction normalizeWorkspace(workspace: string): string {\n const normalized = resolve(workspace);\n return process.platform === 'win32' ? normalized.toLowerCase() : normalized;\n}\n\nexport function rewindWorkspaceHash(workspace: string): string {\n return sha256(normalizeWorkspace(workspace));\n}\n\nexport function persistentRewindRoot(workspace: string): string {\n return join(resolveBookHome(), 'rewind', rewindWorkspaceHash(workspace));\n}\n\nclass UnavailableRewindSnapshotStore implements RewindSnapshotStoreInterface {\n constructor(private readonly reason: string) {}\n\n capture(): RewindSnapshotCaptureResult {\n return { ok: false, reason: this.reason };\n }\n\n async captureAsync(): Promise<RewindSnapshotCaptureResult> {\n return this.capture();\n }\n\n getCurrentGitHead(): string | undefined {\n return undefined;\n }\n\n getManifest(): RewindSnapshotManifest | undefined {\n return undefined;\n }\n\n getAvailability() {\n return { available: false, reason: this.reason };\n }\n\n restore(): RewindRestoreResult {\n return { ok: false, error: this.reason };\n }\n\n rollback(): { ok: false; error: string } {\n return { ok: false, error: this.reason };\n }\n\n discardManifest(): void {}\n\n cleanup() {\n return { manifests: 0, blobs: 0 };\n }\n}\n\nexport function createUnavailableRewindSnapshotStore(reason: string): RewindSnapshotStoreInterface {\n return new UnavailableRewindSnapshotStore(reason);\n}\n\nexport function createRewindSnapshotStore(\n workspace: string,\n root?: string,\n): RewindSnapshotStoreInterface {\n try {\n return new RewindSnapshotStore(workspace, root);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n return createUnavailableRewindSnapshotStore(\n `Code rewind unavailable: snapshot storage could not be initialized (${detail}).`,\n );\n }\n}\n\nfunction readCustomIgnorePatterns(workspace: string): string[] {\n const path = join(workspace, '.book', 'rewindignore');\n // On a network (UNC) path it is not opened (#579): it counts as absent.\n if (reachesUncPath(path) || !existsSync(path)) return [];\n return readFileSync(path, 'utf-8')\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith('#'));\n}\n\nasync function readCustomIgnorePatternsAsync(workspace: string): Promise<string[]> {\n const path = join(workspace, '.book', 'rewindignore');\n if (reachesUncPath(path)) return [];\n try {\n return (await readFile(path, 'utf-8'))\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith('#'));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw error;\n }\n}\n\nfunction expandNegatedParents(patterns: string[]): string[] {\n const expanded: string[] = [];\n for (const pattern of patterns) {\n if (pattern.startsWith('!') && !pattern.slice(1).startsWith('*')) {\n const parts = pattern.slice(1).split('/').filter(Boolean);\n for (let index = 1; index < parts.length; index++) {\n expanded.push(`!${parts.slice(0, index).join('/')}/`);\n }\n }\n expanded.push(pattern);\n }\n return expanded;\n}\n\n/**\n * A git file's text, trimmed; undefined when it cannot be read, and, unopened, when it is, or\n * reaches through a link, a UNC location on Windows (`reachesUnc`, #579): a checkout controls\n * these files and the pointers between them.\n */\nfunction readOptionalText(path: string, reachesUnc: UncGuard): string | undefined {\n if (reachesUnc(path)) return undefined;\n try {\n return readFileSync(path, 'utf-8').trim();\n } catch {\n return undefined;\n }\n}\n\nfunction resolveGitDirectory(workspace: string, reachesUnc: UncGuard): string | undefined {\n const dotGit = join(workspace, '.git');\n if (reachesUnc(dotGit)) return undefined;\n try {\n if (lstatSync(dotGit).isDirectory()) return dotGit;\n } catch {\n return undefined;\n }\n\n const match = /^gitdir:\\s*(.+)$/i.exec(readOptionalText(dotGit, reachesUnc) ?? '');\n if (!match) return undefined;\n const gitDirectory = resolve(dirname(dotGit), match[1]);\n return reachesUnc(gitDirectory) ? undefined : gitDirectory;\n}\n\nfunction resolveCommonGitDirectory(gitDirectory: string, reachesUnc: UncGuard): string {\n const commonDirectory = readOptionalText(join(gitDirectory, 'commondir'), reachesUnc);\n if (!commonDirectory) return gitDirectory;\n const common = resolve(gitDirectory, commonDirectory);\n return reachesUnc(common) ? gitDirectory : common;\n}\n\nfunction parseGitHash(value: string | undefined): string | undefined {\n const hash = value?.trim();\n return hash && /^[0-9a-f]{40,64}$/i.test(hash) ? hash : undefined;\n}\n\nfunction readPackedRef(directory: string, ref: string, reachesUnc: UncGuard): string | undefined {\n const packedRefs = readOptionalText(join(directory, 'packed-refs'), reachesUnc);\n if (!packedRefs) return undefined;\n for (const line of packedRefs.split(/\\r?\\n/)) {\n if (!line || line.startsWith('#') || line.startsWith('^')) continue;\n const separator = line.indexOf(' ');\n if (separator > 0 && line.slice(separator + 1) === ref) {\n return parseGitHash(line.slice(0, separator));\n }\n }\n return undefined;\n}\n\nfunction resolveGitRef(\n gitDirectory: string,\n commonDirectory: string,\n ref: string,\n reachesUnc: UncGuard,\n depth = 0,\n): string | undefined {\n if (\n depth > 4 ||\n !ref.startsWith('refs/') ||\n ref.includes('..') ||\n ref.includes('\\\\') ||\n ref.includes('\\0')\n ) {\n return undefined;\n }\n\n for (const directory of new Set([gitDirectory, commonDirectory])) {\n const value = readOptionalText(join(directory, ...ref.split('/')), reachesUnc);\n const hash = parseGitHash(value);\n if (hash) return hash;\n if (value?.startsWith('ref:')) {\n const resolved = resolveGitRef(\n gitDirectory,\n commonDirectory,\n value.slice('ref:'.length).trim(),\n reachesUnc,\n depth + 1,\n );\n if (resolved) return resolved;\n }\n }\n\n return (\n readPackedRef(gitDirectory, ref, reachesUnc) ??\n (commonDirectory === gitDirectory ? undefined : readPackedRef(commonDirectory, ref, reachesUnc))\n );\n}\n\nfunction gitHead(workspace: string): string | undefined {\n // One guard for the whole lookup: the pointers it follows share their prefixes.\n const reachesUnc = createUncGuard();\n const gitDirectory = resolveGitDirectory(workspace, reachesUnc);\n if (!gitDirectory) return undefined;\n const head = readOptionalText(join(gitDirectory, 'HEAD'), reachesUnc);\n const directHash = parseGitHash(head);\n if (directHash) return directHash;\n if (!head?.startsWith('ref:')) return undefined;\n return resolveGitRef(\n gitDirectory,\n resolveCommonGitDirectory(gitDirectory, reachesUnc),\n head.slice('ref:'.length).trim(),\n reachesUnc,\n );\n}\n\nasync function gitHeadAsync(workspace: string): Promise<string | undefined> {\n return gitHead(workspace);\n}\n\nfunction assertSafeRelativePath(path: string): void {\n if (!path || path.includes('\\0') || isAbsolute(path) || path.includes('\\\\')) {\n throw new Error(`Unsafe rewind path: ${JSON.stringify(path)}`);\n }\n const segments = path.split('/');\n if (segments.some((segment) => !segment || segment === '.' || segment === '..')) {\n throw new Error(`Unsafe rewind path: ${JSON.stringify(path)}`);\n }\n if (segments.includes('.git')) throw new Error('Rewind snapshots may not contain .git paths.');\n}\n\nfunction resolveEntryPath(workspace: string, path: string): string {\n assertSafeRelativePath(path);\n const target = resolve(workspace, ...path.split('/'));\n const rel = relative(workspace, target);\n if (rel.startsWith(`..${sep}`) || rel === '..' || isAbsolute(rel)) {\n throw new Error(`Rewind path escapes the workspace: ${path}`);\n }\n return target;\n}\n\ntype WalkedEntry = {\n path: string;\n absolutePath: string;\n kind: RewindSnapshotEntry['kind'];\n byteSize: number;\n mode: number;\n mtimeMs: number;\n};\n\ninterface CachedSnapshotEntry {\n kind: RewindSnapshotEntry['kind'];\n byteSize: number;\n mode: number;\n mtimeMs: number;\n snapshotEntry: RewindSnapshotEntry;\n}\n\nfunction walkIncludedEntries(\n workspace: string,\n patterns: string[],\n maxEntries = Number.POSITIVE_INFINITY,\n): WalkedEntry[] {\n const matcher = ignore().add(patterns);\n const hasNegations = patterns.some((pattern) => pattern.startsWith('!'));\n const entries: WalkedEntry[] = [];\n\n const visit = (directory: string, prefix: string) => {\n const children = readdirSync(directory, { withFileTypes: true }).sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n for (const child of children) {\n if (child.name === '.git') continue;\n const path = prefix ? `${prefix}/${child.name}` : child.name;\n const absolutePath = join(directory, child.name);\n if (child.isDirectory()) {\n if (!matcher.ignores(`${path}/`) || hasNegations) visit(absolutePath, path);\n continue;\n }\n if (matcher.ignores(path)) continue;\n const stat = lstatSync(absolutePath);\n if (!stat.isFile() && !stat.isSymbolicLink()) continue;\n entries.push({\n path,\n absolutePath,\n kind: stat.isSymbolicLink() ? 'symlink' : 'file',\n byteSize: stat.isSymbolicLink() ? Buffer.byteLength(readlinkSync(absolutePath)) : stat.size,\n mode: stat.mode,\n mtimeMs: stat.mtimeMs,\n });\n if (entries.length > maxEntries) {\n throw new Error(`Code rewind unavailable: checkpoint exceeds ${maxEntries} entries.`);\n }\n }\n };\n\n visit(workspace, '');\n return entries;\n}\n\nasync function walkIncludedEntriesAsync(\n workspace: string,\n patterns: string[],\n maxEntries = Number.POSITIVE_INFINITY,\n): Promise<WalkedEntry[]> {\n const matcher = ignore().add(patterns);\n const hasNegations = patterns.some((pattern) => pattern.startsWith('!'));\n const entries: WalkedEntry[] = [];\n\n const visit = async (directory: string, prefix: string): Promise<void> => {\n const children = (await readdir(directory, { withFileTypes: true })).sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n const files: Array<{ child: (typeof children)[number]; path: string; absolutePath: string }> =\n [];\n for (const child of children) {\n if (child.name === '.git') continue;\n const path = prefix ? `${prefix}/${child.name}` : child.name;\n const absolutePath = join(directory, child.name);\n if (child.isDirectory()) {\n if (!matcher.ignores(`${path}/`) || hasNegations) await visit(absolutePath, path);\n continue;\n }\n if (matcher.ignores(path)) continue;\n files.push({ child, path, absolutePath });\n }\n const stats = await Promise.all(files.map(({ absolutePath }) => lstat(absolutePath)));\n for (let index = 0; index < files.length; index++) {\n const { path, absolutePath } = files[index];\n const stat = stats[index];\n if (!stat.isFile() && !stat.isSymbolicLink()) continue;\n entries.push({\n path,\n absolutePath,\n kind: stat.isSymbolicLink() ? 'symlink' : 'file',\n byteSize: stat.isSymbolicLink()\n ? Buffer.byteLength(await readlink(absolutePath, { encoding: 'utf-8' }))\n : stat.size,\n mode: stat.mode,\n mtimeMs: stat.mtimeMs,\n });\n if (entries.length > maxEntries) {\n throw new Error(`Code rewind unavailable: checkpoint exceeds ${maxEntries} entries.`);\n }\n }\n };\n\n await visit(workspace, '');\n return entries;\n}\n\nfunction writeAtomic(path: string, contents: Buffer | string): void {\n mkdirSync(dirname(path), { recursive: true });\n const temporary = join(dirname(path), `.book-rewind-${randomUUID()}.tmp`);\n try {\n writeFileSync(temporary, contents);\n renameSync(temporary, path);\n } finally {\n if (pathExists(temporary)) unlinkSync(temporary);\n }\n}\n\nasync function writeAtomicAsync(path: string, contents: Buffer | string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const temporary = join(dirname(path), `.book-rewind-${randomUUID()}.tmp`);\n try {\n await writeFile(temporary, contents);\n await rename(temporary, path);\n } finally {\n await rm(temporary, { force: true });\n }\n}\n\nexport class RewindSnapshotStore implements RewindSnapshotStoreInterface {\n private readonly manifestsRoot: string;\n private readonly entrySetsRoot: string;\n private readonly blobsRoot: string;\n private readonly workspace: string;\n private readonly limits: RewindSnapshotLimits;\n private fileCache = new Map<string, CachedSnapshotEntry>();\n\n constructor(\n workspace: string,\n private readonly root = persistentRewindRoot(workspace),\n limits: Partial<RewindSnapshotLimits> = {},\n ) {\n this.workspace = resolve(workspace);\n this.limits = {\n maxEntries: limits.maxEntries ?? REWIND_MAX_ENTRIES,\n maxFileBytes: limits.maxFileBytes ?? REWIND_MAX_FILE_BYTES,\n maxLogicalBytes: limits.maxLogicalBytes ?? REWIND_MAX_LOGICAL_BYTES,\n };\n this.manifestsRoot = join(root, 'manifests');\n this.entrySetsRoot = join(root, 'entry-sets');\n this.blobsRoot = join(root, 'blobs');\n mkdirSync(this.manifestsRoot, { recursive: true });\n mkdirSync(this.entrySetsRoot, { recursive: true });\n mkdirSync(this.blobsRoot, { recursive: true });\n }\n\n capture(ignorePatterns?: string[]): RewindSnapshotCaptureResult {\n const head = gitHead(this.workspace);\n const patterns =\n ignorePatterns ??\n expandNegatedParents([\n ...DEFAULT_IGNORE_PATTERNS,\n ...readCustomIgnorePatterns(this.workspace),\n ]);\n try {\n const walked = walkIncludedEntries(this.workspace, patterns, this.limits.maxEntries);\n\n let logicalBytes = 0;\n const entries: RewindSnapshotEntry[] = [];\n const nextCache = new Map<string, CachedSnapshotEntry>();\n for (const entry of walked) {\n if (entry.byteSize > this.limits.maxFileBytes) {\n throw new Error(\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\n );\n }\n const cached = this.fileCache.get(entry.path);\n if (\n cached &&\n cached.kind === entry.kind &&\n cached.byteSize === entry.byteSize &&\n cached.mode === entry.mode &&\n cached.mtimeMs === entry.mtimeMs\n ) {\n logicalBytes += cached.snapshotEntry.byteSize;\n if (logicalBytes > this.limits.maxLogicalBytes) {\n throw new Error(\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\n );\n }\n entries.push(cached.snapshotEntry);\n nextCache.set(entry.path, cached);\n continue;\n }\n const contents =\n entry.kind === 'symlink'\n ? Buffer.from(readlinkSync(entry.absolutePath), 'utf-8')\n : readFileSync(entry.absolutePath);\n if (contents.byteLength > this.limits.maxFileBytes) {\n throw new Error(\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\n );\n }\n logicalBytes += contents.byteLength;\n if (logicalBytes > this.limits.maxLogicalBytes) {\n throw new Error(\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\n );\n }\n const blobHash = sha256(contents);\n const blobPath = join(this.blobsRoot, blobHash);\n if (!existsSync(blobPath)) writeAtomic(blobPath, contents);\n const snapshotEntry: RewindSnapshotEntry = {\n path: entry.path.replaceAll('\\\\', '/'),\n kind: entry.kind,\n blobHash,\n byteSize: contents.byteLength,\n mode: entry.mode,\n };\n entries.push(snapshotEntry);\n nextCache.set(entry.path, {\n kind: entry.kind,\n byteSize: entry.byteSize,\n mode: entry.mode,\n mtimeMs: entry.mtimeMs,\n snapshotEntry,\n });\n }\n\n const manifest: RewindSnapshotManifest = {\n version: 1,\n id: randomUUID(),\n workspace: normalizeWorkspace(this.workspace),\n createdAt: Date.now(),\n gitHead: head,\n ignorePatterns: patterns,\n entries,\n logicalBytes,\n };\n this.writeManifest(manifest);\n this.fileCache = nextCache;\n return { ok: true, manifest };\n } catch (error) {\n return {\n ok: false,\n reason: error instanceof Error ? error.message : String(error),\n gitHead: head,\n };\n }\n }\n\n async captureAsync(ignorePatterns?: string[]): Promise<RewindSnapshotCaptureResult> {\n let head: string | undefined;\n try {\n const [resolvedHead, customIgnorePatterns] = await Promise.all([\n gitHeadAsync(this.workspace),\n ignorePatterns ? Promise.resolve([]) : readCustomIgnorePatternsAsync(this.workspace),\n ]);\n head = resolvedHead;\n const patterns =\n ignorePatterns ??\n expandNegatedParents([...DEFAULT_IGNORE_PATTERNS, ...customIgnorePatterns]);\n const walked = await walkIncludedEntriesAsync(\n this.workspace,\n patterns,\n this.limits.maxEntries,\n );\n\n let logicalBytes = 0;\n const entries: RewindSnapshotEntry[] = [];\n const nextCache = new Map<string, CachedSnapshotEntry>();\n for (const entry of walked) {\n if (entry.byteSize > this.limits.maxFileBytes) {\n throw new Error(\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\n );\n }\n const cached = this.fileCache.get(entry.path);\n if (\n cached &&\n cached.kind === entry.kind &&\n cached.byteSize === entry.byteSize &&\n cached.mode === entry.mode &&\n cached.mtimeMs === entry.mtimeMs\n ) {\n logicalBytes += cached.snapshotEntry.byteSize;\n if (logicalBytes > this.limits.maxLogicalBytes) {\n throw new Error(\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\n );\n }\n entries.push(cached.snapshotEntry);\n nextCache.set(entry.path, cached);\n continue;\n }\n const contents =\n entry.kind === 'symlink'\n ? Buffer.from(await readlink(entry.absolutePath, { encoding: 'utf-8' }), 'utf-8')\n : await readFile(entry.absolutePath);\n if (contents.byteLength > this.limits.maxFileBytes) {\n throw new Error(\n `Code rewind unavailable: ${entry.path} exceeds the ${this.limits.maxFileBytes}-byte per-file limit.`,\n );\n }\n logicalBytes += contents.byteLength;\n if (logicalBytes > this.limits.maxLogicalBytes) {\n throw new Error(\n `Code rewind unavailable: checkpoint exceeds ${this.limits.maxLogicalBytes} bytes of file content.`,\n );\n }\n const blobHash = sha256(contents);\n const blobPath = join(this.blobsRoot, blobHash);\n if (!(await pathExistsAsync(blobPath))) await writeAtomicAsync(blobPath, contents);\n const snapshotEntry: RewindSnapshotEntry = {\n path: entry.path.replaceAll('\\\\', '/'),\n kind: entry.kind,\n blobHash,\n byteSize: contents.byteLength,\n mode: entry.mode,\n };\n entries.push(snapshotEntry);\n nextCache.set(entry.path, {\n kind: entry.kind,\n byteSize: entry.byteSize,\n mode: entry.mode,\n mtimeMs: entry.mtimeMs,\n snapshotEntry,\n });\n }\n\n const manifest: RewindSnapshotManifest = {\n version: 1,\n id: randomUUID(),\n workspace: normalizeWorkspace(this.workspace),\n createdAt: Date.now(),\n gitHead: head,\n ignorePatterns: patterns,\n entries,\n logicalBytes,\n };\n await this.writeManifestAsync(manifest);\n this.fileCache = nextCache;\n return { ok: true, manifest };\n } catch (error) {\n return {\n ok: false,\n reason: error instanceof Error ? error.message : String(error),\n gitHead: head,\n };\n }\n }\n\n getManifest(id: string): RewindSnapshotManifest | undefined {\n if (!/^[a-zA-Z0-9-]+$/.test(id)) return undefined;\n const path = join(this.manifestsRoot, `${id}.json`);\n if (!existsSync(path)) return undefined;\n try {\n const stored = JSON.parse(readFileSync(path, 'utf-8')) as RewindSnapshotManifest & {\n entrySetHash?: string;\n };\n let manifest: RewindSnapshotManifest = stored;\n if (!Array.isArray(stored.entries) && stored.entrySetHash) {\n if (!/^[a-f0-9]{64}$/.test(stored.entrySetHash)) return undefined;\n const entriesPath = join(this.entrySetsRoot, `${stored.entrySetHash}.json`);\n if (!existsSync(entriesPath)) return undefined;\n const serializedEntries = readFileSync(entriesPath, 'utf-8');\n if (sha256(serializedEntries) !== stored.entrySetHash) return undefined;\n manifest = {\n ...stored,\n entries: JSON.parse(serializedEntries) as RewindSnapshotEntry[],\n };\n }\n if (\n manifest.version !== 1 ||\n manifest.id !== id ||\n normalizeWorkspace(manifest.workspace) !== normalizeWorkspace(this.workspace) ||\n !Array.isArray(manifest.entries)\n ) {\n return undefined;\n }\n return manifest;\n } catch {\n return undefined;\n }\n }\n\n getCurrentGitHead(): string | undefined {\n return gitHead(this.workspace);\n }\n\n getAvailability(id: string | undefined, expectedGitHead?: string) {\n if (!id) return { available: false, reason: 'No filesystem checkpoint was captured.' };\n if (!this.getManifest(id)) {\n return { available: false, reason: 'The filesystem checkpoint is missing or corrupt.' };\n }\n if (this.getCurrentGitHead() !== expectedGitHead) {\n return {\n available: false,\n reason: 'Git HEAD changed since this prompt; rewind never moves HEAD or the index.',\n };\n }\n return { available: true };\n }\n\n restore(id: string): RewindRestoreResult {\n const manifest = this.getManifest(id);\n if (!manifest) return { ok: false, error: 'The filesystem checkpoint is missing or corrupt.' };\n const availability = this.getAvailability(id, manifest.gitHead);\n if (!availability.available) return { ok: false, error: availability.reason ?? 'Unavailable.' };\n\n const safety = this.capture(manifest.ignorePatterns);\n if (!safety.ok) {\n return { ok: false, error: `Could not create a safety snapshot: ${safety.reason}` };\n }\n if (this.getCurrentGitHead() !== manifest.gitHead) {\n this.discardManifest(safety.manifest.id);\n return {\n ok: false,\n error: 'Git HEAD changed while preparing rewind; no files were restored.',\n };\n }\n\n try {\n this.applyManifest(manifest);\n return { ok: true, safetySnapshotId: safety.manifest.id };\n } catch (error) {\n const rollback = this.applyManifestSafely(safety.manifest);\n this.discardManifest(safety.manifest.id);\n return {\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n ...(rollback.ok ? {} : { rollbackError: rollback.error }),\n };\n }\n }\n\n rollback(safetySnapshotId: string): { ok: true } | { ok: false; error: string } {\n const manifest = this.getManifest(safetySnapshotId);\n if (!manifest) return { ok: false, error: 'The safety snapshot is missing or corrupt.' };\n const result = this.applyManifestSafely(manifest);\n if (result.ok) this.discardManifest(safetySnapshotId);\n return result;\n }\n\n discardManifest(id: string): void {\n if (!/^[a-zA-Z0-9-]+$/.test(id)) return;\n const path = join(this.manifestsRoot, `${id}.json`);\n if (existsSync(path)) unlinkSync(path);\n }\n\n private writeManifest(manifest: RewindSnapshotManifest): void {\n const entriesHash = sha256(JSON.stringify(manifest.entries));\n const entriesPath = join(this.entrySetsRoot, `${entriesHash}.json`);\n if (!existsSync(entriesPath)) writeAtomic(entriesPath, JSON.stringify(manifest.entries));\n const metadata = { ...manifest } as Partial<RewindSnapshotManifest> & {\n entrySetHash?: string;\n };\n delete metadata.entries;\n writeAtomic(\n join(this.manifestsRoot, `${manifest.id}.json`),\n JSON.stringify({ ...metadata, entrySetHash: entriesHash }),\n );\n }\n\n private async writeManifestAsync(manifest: RewindSnapshotManifest): Promise<void> {\n const entriesHash = sha256(JSON.stringify(manifest.entries));\n const entriesPath = join(this.entrySetsRoot, `${entriesHash}.json`);\n if (!(await pathExistsAsync(entriesPath))) {\n await writeAtomicAsync(entriesPath, JSON.stringify(manifest.entries));\n }\n const metadata = { ...manifest } as Partial<RewindSnapshotManifest> & {\n entrySetHash?: string;\n };\n delete metadata.entries;\n await writeAtomicAsync(\n join(this.manifestsRoot, `${manifest.id}.json`),\n JSON.stringify({ ...metadata, entrySetHash: entriesHash }),\n );\n }\n\n cleanup(referencedSnapshotIds: Set<string>, days: number) {\n const cutoff = Date.now() - days * 86_400_000;\n let manifests = 0;\n let blobs = 0;\n for (const file of readdirSync(this.manifestsRoot)) {\n if (!file.endsWith('.json')) continue;\n const id = file.slice(0, -5);\n const manifest = this.getManifest(id);\n if (referencedSnapshotIds.has(id)) continue;\n if (!manifest || manifest.createdAt < cutoff) {\n unlinkSync(join(this.manifestsRoot, file));\n manifests++;\n }\n }\n\n const referencedBlobs = new Set<string>();\n const referencedEntrySets = new Set<string>();\n for (const file of readdirSync(this.manifestsRoot)) {\n if (!file.endsWith('.json')) continue;\n const id = file.slice(0, -5);\n const manifest = this.getManifest(id);\n try {\n const stored = JSON.parse(readFileSync(join(this.manifestsRoot, file), 'utf-8')) as {\n entrySetHash?: string;\n };\n if (stored.entrySetHash) referencedEntrySets.add(stored.entrySetHash);\n } catch {\n // Corrupt manifests are removed or ignored above.\n }\n for (const entry of manifest?.entries ?? []) referencedBlobs.add(entry.blobHash);\n }\n for (const file of readdirSync(this.entrySetsRoot)) {\n if (!file.endsWith('.json') || referencedEntrySets.has(file.slice(0, -5))) continue;\n rmSync(join(this.entrySetsRoot, file), { force: true });\n }\n for (const file of readdirSync(this.blobsRoot)) {\n if (referencedBlobs.has(file)) continue;\n rmSync(join(this.blobsRoot, file), { force: true });\n blobs++;\n }\n return { manifests, blobs };\n }\n\n private applyManifestSafely(\n manifest: RewindSnapshotManifest,\n ): { ok: true } | { ok: false; error: string } {\n try {\n this.applyManifest(manifest);\n return { ok: true };\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n private applyManifest(manifest: RewindSnapshotManifest): void {\n if (manifest.entries.length > this.limits.maxEntries) {\n throw new Error(`Rewind manifest exceeds ${this.limits.maxEntries} entries.`);\n }\n const targetPaths = new Set<string>();\n let logicalBytes = 0;\n for (const entry of manifest.entries) {\n resolveEntryPath(this.workspace, entry.path);\n if (!['file', 'symlink'].includes(entry.kind) || !Number.isInteger(entry.mode)) {\n throw new Error(`Invalid rewind entry for ${entry.path}.`);\n }\n if (targetPaths.has(entry.path)) throw new Error(`Duplicate rewind path: ${entry.path}.`);\n if (!/^[a-f0-9]{64}$/.test(entry.blobHash)) {\n throw new Error(`Invalid blob hash for ${entry.path}.`);\n }\n const blobPath = join(this.blobsRoot, entry.blobHash);\n if (!existsSync(blobPath)) throw new Error(`Missing rewind blob for ${entry.path}.`);\n const contents = readFileSync(blobPath);\n if (sha256(contents) !== entry.blobHash)\n throw new Error(`Corrupt rewind blob for ${entry.path}.`);\n if (\n contents.byteLength !== entry.byteSize ||\n contents.byteLength > this.limits.maxFileBytes\n ) {\n throw new Error(`Invalid rewind size for ${entry.path}.`);\n }\n logicalBytes += contents.byteLength;\n if (logicalBytes > this.limits.maxLogicalBytes) {\n throw new Error(`Rewind manifest exceeds ${this.limits.maxLogicalBytes} bytes.`);\n }\n targetPaths.add(entry.path);\n }\n\n const current = walkIncludedEntries(\n this.workspace,\n manifest.ignorePatterns,\n this.limits.maxEntries,\n );\n const removals = current\n .filter((entry) => !targetPaths.has(entry.path))\n .sort((a, b) => b.path.length - a.path.length);\n for (const entry of removals) unlinkSync(entry.absolutePath);\n\n for (const entry of manifest.entries) {\n const target = resolveEntryPath(this.workspace, entry.path);\n mkdirSync(dirname(target), { recursive: true });\n if (pathExists(target) && lstatSync(target).isDirectory()) {\n throw new Error(`Cannot restore ${entry.path} because a directory exists at that path.`);\n }\n const contents = readFileSync(join(this.blobsRoot, entry.blobHash));\n const temporary = join(dirname(target), `.book-rewind-${randomUUID()}.tmp`);\n try {\n if (entry.kind === 'symlink') {\n symlinkSync(contents.toString('utf-8'), temporary);\n } else {\n writeFileSync(temporary, contents, { mode: entry.mode });\n chmodSync(temporary, entry.mode);\n }\n renameSync(temporary, target);\n } finally {\n if (pathExists(temporary)) unlinkSync(temporary);\n }\n }\n }\n}\n","import { existsSync, mkdtempSync, rmSync } from 'fs';\nimport { tmpdir } from 'os';\nimport { join, resolve, sep } from 'path';\nimport { SessionStore } from '../session/store.js';\nimport type { RewindSnapshotStoreInterface } from '../types/sessions.js';\nimport { createRewindSnapshotStore } from './snapshot-store.js';\n\nexport interface EphemeralRewindEnvironment {\n root: string;\n timelineStore: SessionStore;\n snapshotStore: RewindSnapshotStoreInterface;\n dispose: () => void;\n}\n\nexport function createEphemeralRewindEnvironment(\n workspace: string,\n temporaryRoot = tmpdir(),\n): EphemeralRewindEnvironment {\n const resolvedTemporaryRoot = resolve(temporaryRoot);\n const root = mkdtempSync(join(resolvedTemporaryRoot, 'book-rewind-'));\n let disposed = false;\n const dispose = () => {\n if (disposed) return;\n disposed = true;\n const resolvedRoot = resolve(root);\n if (\n resolvedRoot.startsWith(`${resolvedTemporaryRoot}${sep}`) &&\n resolvedRoot.split(sep).at(-1)?.startsWith('book-rewind-') &&\n existsSync(resolvedRoot)\n ) {\n rmSync(resolvedRoot, { recursive: true, force: true });\n }\n process.off('exit', dispose);\n };\n process.once('exit', dispose);\n return {\n root,\n timelineStore: new SessionStore(join(root, 'sessions')),\n snapshotStore: createRewindSnapshotStore(workspace, join(root, 'snapshots')),\n dispose,\n };\n}\n","import { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { inkBuildDir } from './ink-renderer.js';\n\n/** A render throttle Ink can settle: `flush` draws a pending frame now, `cancel` drops it. */\nexport interface FrameThrottle {\n (): void;\n flush: () => void;\n cancel: () => void;\n}\n\n/**\n * Draws at most once per `intervalMs`: at once when the last draw is that long ago, otherwise once,\n * at the last draw plus the interval, however many commits arrive meanwhile.\n *\n * Ink's own throttle (es-toolkit's `throttle`) is a debounce whose trailing timer restarts on every\n * call. Under a steady stream of commits — a wheel glide, a measured row, a streamed token — each\n * commit inside the window pushes the draw a whole window later, so a 14 ms cap drew every 25–31 ms\n * in a real session. Timing the trailing draw from the last draw keeps the cap honest.\n */\nexport function createFrameThrottle(\n draw: () => void,\n intervalMs: number,\n now: () => number = () => performance.now(),\n): FrameThrottle {\n let lastDrawAt = Number.NEGATIVE_INFINITY;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const fire = () => {\n timer = null;\n lastDrawAt = now();\n draw();\n };\n const throttled = (() => {\n // A draw is already due, and it will show this commit too.\n if (timer !== null) return;\n const wait = lastDrawAt + intervalMs - now();\n if (wait <= 0) fire();\n else timer = setTimeout(fire, wait);\n }) as FrameThrottle;\n throttled.flush = () => {\n if (timer === null) return;\n clearTimeout(timer);\n fire();\n };\n throttled.cancel = () => {\n if (timer === null) return;\n clearTimeout(timer);\n timer = null;\n };\n return throttled;\n}\n\n/** The fields of Ink's private `Ink` instance the replacement touches. */\ninterface ThrottledInk {\n onRender: () => void;\n renderThrottleMs: number;\n hasPendingThrottledRender: boolean;\n throttledOnRender: { flush: () => void; cancel: () => void };\n rootNode: { onRender: () => void };\n}\n\nfunction isThrottledInk(ink: unknown): ink is ThrottledInk {\n if (typeof ink !== 'object' || ink === null) return false;\n const candidate = ink as Partial<ThrottledInk>;\n return (\n typeof candidate.onRender === 'function' &&\n typeof candidate.renderThrottleMs === 'number' &&\n candidate.renderThrottleMs > 0 &&\n typeof candidate.throttledOnRender?.flush === 'function' &&\n typeof candidate.throttledOnRender.cancel === 'function' &&\n typeof candidate.rootNode?.onRender === 'function'\n );\n}\n\n/**\n * Replace the render throttle of the Ink instance drawing to `stdout` with `createFrameThrottle`, at\n * the interval Ink derived from `maxFps`. Returns false, leaving Ink's own throttle in place, when\n * no throttled instance draws there (debug and screen-reader rendering are unthrottled) or Ink's\n * private layout has changed; `ink-renderer.contract.test.ts` fails in that case, so an Ink upgrade\n * cannot drop the replacement unnoticed.\n */\nexport async function installInkFrameThrottle(stdout: NodeJS.WriteStream): Promise<boolean> {\n try {\n const module = (await import(pathToFileURL(join(inkBuildDir(), 'instances.js')).href)) as {\n default: { get: (stream: NodeJS.WriteStream) => unknown };\n };\n const ink = module.default.get(stdout);\n if (!isThrottledInk(ink)) return false;\n // Draw anything Ink's throttle was holding before it is dropped.\n ink.throttledOnRender.flush();\n const throttle = createFrameThrottle(() => ink.onRender(), ink.renderThrottleMs);\n // Ink settles `throttledOnRender` on unmount and when waiting for a render to flush.\n ink.throttledOnRender = throttle;\n ink.rootNode.onRender = () => {\n ink.hasPendingThrottledRender = true;\n throttle();\n };\n return true;\n } catch {\n return false;\n }\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { resolveBookHome } from '../book-home.js';\nimport { evaluateMcpServerApproval } from '../mcp-approvals.js';\nimport {\n formatMcpServerCommand,\n isValidMcpServerName,\n resolveMcpServerList,\n type McpServerConfig,\n type McpServerSource,\n type McpTransportType,\n} from '../mcp-config.js';\nimport { resolveSettings } from '../settings-loader.js';\nimport { writeFileAtomic } from '../settings-repository.js';\nimport { projectFileWriteRefusal } from '../workspace-files.js';\n\nexport type McpConfigScope = 'user' | 'project';\n\nexport interface McpCommandOptions {\n workspace: string;\n json?: boolean;\n /** System-home override used by tests, matching resolveMcpServerList's `home` option. */\n home?: string;\n}\n\nexport interface McpAddCommandOptions extends McpCommandOptions {\n scope?: McpConfigScope;\n transport?: McpTransportType;\n env?: string[];\n header?: string[];\n cwd?: string;\n force?: boolean;\n}\n\nexport interface McpRemoveCommandOptions extends McpCommandOptions {\n scope?: McpConfigScope;\n}\n\ninterface McpConfigDocument extends Record<string, unknown> {\n mcpServers?: Record<string, unknown>;\n}\n\ninterface McpCliServerRecord {\n name: string;\n source: McpServerSource;\n path: string;\n transport: McpTransportType;\n target: string;\n approval: 'user' | 'approved' | 'rejected' | 'unknown';\n envKeys: string[];\n headerKeys: string[];\n}\n\nfunction configPath(workspace: string, scope: McpConfigScope, home?: string): string {\n return scope === 'project'\n ? join(workspace, '.mcp.json')\n : home\n ? join(home, '.book', 'mcp.json')\n : join(resolveBookHome(), 'mcp.json');\n}\n\nfunction validScope(scope: string | undefined): McpConfigScope {\n const normalized = scope ?? 'user';\n if (normalized !== 'user' && normalized !== 'project') {\n throw new Error('MCP scope must be \"user\" or \"project\".');\n }\n return normalized;\n}\n\n/** The document a write to `path` starts from. */\nfunction readConfigDocument(path: string): McpConfigDocument {\n const refusal = projectFileWriteRefusal(path);\n if (refusal) throw new Error(`Cannot update ${path}: ${refusal}.`);\n if (!existsSync(path)) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(path, 'utf8'));\n } catch (error) {\n throw new Error(\n `Cannot update ${path}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`Cannot update ${path}: expected a JSON object.`);\n }\n const document = parsed as McpConfigDocument;\n if (\n document.mcpServers !== undefined &&\n (!document.mcpServers ||\n typeof document.mcpServers !== 'object' ||\n Array.isArray(document.mcpServers))\n ) {\n throw new Error(`Cannot update ${path}: mcpServers must be an object.`);\n }\n return document;\n}\n\nfunction parseEntries(kind: 'env' | 'header', entries: string[] = []): Record<string, string> {\n const parsed: Record<string, string> = {};\n for (const entry of entries) {\n const separator = entry.indexOf('=');\n if (separator <= 0) throw new Error(`Invalid --${kind} value \"${entry}\"; expected KEY=VALUE.`);\n const key = entry.slice(0, separator).trim();\n if (!key) throw new Error(`Invalid --${kind} value \"${entry}\"; the key is empty.`);\n parsed[key] = entry.slice(separator + 1);\n }\n return parsed;\n}\n\nfunction validateRemoteUrl(raw: string): string {\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new Error('Remote MCP URL must be an absolute http:// or https:// URL.');\n }\n if (!['http:', 'https:'].includes(url.protocol)) {\n throw new Error('Remote MCP URL must use http:// or https://.');\n }\n if (url.username || url.password) throw new Error('Remote MCP URL must not contain credentials.');\n return raw;\n}\n\nfunction inferredTransport(target: string, requested?: McpTransportType): McpTransportType {\n if (requested) {\n if (!['stdio', 'http', 'sse'].includes(requested)) {\n throw new Error('MCP transport must be \"stdio\", \"http\", or \"sse\".');\n }\n return requested;\n }\n return /^https?:\\/\\//i.test(target) ? 'http' : 'stdio';\n}\n\nfunction createServerConfig(\n target: string,\n serverArgs: string[],\n options: McpAddCommandOptions,\n): McpServerConfig {\n const transport = inferredTransport(target, options.transport);\n if (transport === 'stdio') {\n if (!target.trim()) throw new Error('Stdio MCP command must not be empty.');\n if ((options.header?.length ?? 0) > 0) {\n throw new Error('--header is available only for HTTP/SSE servers.');\n }\n return {\n type: 'stdio',\n command: target,\n args: serverArgs,\n env: parseEntries('env', options.env),\n ...(options.cwd ? { cwd: options.cwd } : {}),\n };\n }\n if (serverArgs.length > 0)\n throw new Error('HTTP/SSE MCP servers do not accept command arguments.');\n if ((options.env?.length ?? 0) > 0 || options.cwd) {\n throw new Error('--env and --cwd are available only for stdio servers.');\n }\n return {\n type: transport,\n url: validateRemoteUrl(target),\n headers: parseEntries('header', options.header),\n };\n}\n\nfunction writeServer(\n workspace: string,\n scope: McpConfigScope,\n name: string,\n config: McpServerConfig,\n force: boolean,\n home?: string,\n): string {\n const path = configPath(workspace, scope, home);\n const document = readConfigDocument(path);\n const servers = { ...(document.mcpServers ?? {}) };\n if (Object.prototype.hasOwnProperty.call(servers, name) && !force) {\n throw new Error(`MCP server \"${name}\" already exists in ${path}; pass --force to replace it.`);\n }\n servers[name] = config;\n writeFileAtomic(path, JSON.stringify({ ...document, mcpServers: servers }, null, 2) + '\\n');\n return path;\n}\n\nfunction removeServer(\n workspace: string,\n scope: McpConfigScope,\n name: string,\n home?: string,\n): string {\n const path = configPath(workspace, scope, home);\n const document = readConfigDocument(path);\n const servers = { ...(document.mcpServers ?? {}) };\n if (!Object.prototype.hasOwnProperty.call(servers, name)) {\n throw new Error(`MCP server \"${name}\" is not declared in ${path}.`);\n }\n delete servers[name];\n writeFileAtomic(path, JSON.stringify({ ...document, mcpServers: servers }, null, 2) + '\\n');\n return path;\n}\n\nfunction serverRecords(workspace: string, home?: string): McpCliServerRecord[] {\n const settings = resolveSettings(workspace);\n return resolveMcpServerList(workspace, { home }).map((server) => ({\n name: server.name,\n source: server.source,\n path: server.path,\n transport: server.config.type ?? (server.config.url ? 'http' : 'stdio'),\n target: formatMcpServerCommand(server.config),\n approval: server.source === 'user' ? 'user' : evaluateMcpServerApproval(settings, server),\n envKeys: Object.keys(server.config.env ?? {}).sort(),\n headerKeys: Object.keys(server.config.headers ?? {}).sort(),\n }));\n}\n\nfunction printRecords(records: McpCliServerRecord[], json = false): void {\n if (json) {\n console.log(JSON.stringify(records, null, 2));\n return;\n }\n if (records.length === 0) {\n console.log('No MCP servers configured.');\n return;\n }\n for (const server of records) {\n console.log(\n `${server.name}: ${server.target} [${server.source}${server.source === 'project' ? `: ${server.approval}` : ''}]`,\n );\n if (server.envKeys.length > 0) console.log(` env: ${server.envKeys.join(', ')}`);\n if (server.headerKeys.length > 0) {\n console.log(` headers: ${server.headerKeys.join(', ')} (values hidden)`);\n }\n console.log(` config: ${server.path}`);\n }\n}\n\nexport function runMcpListCommand(options: McpCommandOptions): void {\n printRecords(serverRecords(options.workspace, options.home), options.json);\n}\n\nexport function runMcpGetCommand(name: string, options: McpCommandOptions): void {\n const server = serverRecords(options.workspace, options.home).find(\n (candidate) => candidate.name === name,\n );\n if (!server) throw new Error(`MCP server \"${name}\" is not configured.`);\n printRecords([server], options.json);\n}\n\nexport function runMcpAddCommand(\n name: string,\n target: string,\n serverArgs: string[],\n options: McpAddCommandOptions,\n): void {\n if (!isValidMcpServerName(name)) {\n throw new Error(\n 'MCP server names may contain letters, numbers, hyphens, or underscores, but not a double underscore.',\n );\n }\n const scope = validScope(options.scope);\n const config = createServerConfig(target, serverArgs, options);\n const path = writeServer(\n options.workspace,\n scope,\n name,\n config,\n options.force ?? false,\n options.home,\n );\n console.log(`Added MCP server \"${name}\" to ${path}.`);\n if (scope === 'project') {\n console.log('Project servers require one-time approval in an interactive Book session.');\n }\n}\n\nexport function runMcpRemoveCommand(name: string, options: McpRemoveCommandOptions): void {\n const scope = options.scope\n ? validScope(options.scope)\n : serverRecords(options.workspace, options.home).find((candidate) => candidate.name === name)\n ?.source;\n if (!scope) throw new Error(`MCP server \"${name}\" is not configured.`);\n const path = removeServer(options.workspace, scope, name, options.home);\n console.log(`Removed MCP server \"${name}\" from ${path}.`);\n}\n"],"mappings":"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","names":["join","resolve","existsSync","isUserSettingsFile","loadSettingsFile","partitionProjectAllowRules","collectDeclaredDirectories","partitionProjectDirectories","discoverCommands","partitionProjectCommands","describeProjectCommandShell","displayableCommandName","describeLegacyBaseUrl","describeReservedProvider","describeWorkspaceProvider","collectDeclaredHooks","describeDeclaredHook","partitionProjectHooks","formatMcpServerCommand","resolveMcpServerList","evaluateMcpServerApproval","resolve","join","join","join","existsSync","join","pathExists","join","existsSync","existsSync","rmSync","join","resolve","sep","resolve","join","sep","existsSync","rmSync","join","join","join","mode","sessionStore","bootstrap","existsSync","readFileSync","join","join","existsSync","readFileSync"]}
|