@letrquan/book 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +2504 -0
  2. package/LICENSE +123 -0
  3. package/README.md +1383 -0
  4. package/dist/app-MOXXWEOY.js +18945 -0
  5. package/dist/app-MOXXWEOY.js.map +1 -0
  6. package/dist/chunk-24AXE6SP.js +12 -0
  7. package/dist/chunk-24AXE6SP.js.map +1 -0
  8. package/dist/chunk-3U5IBM24.js +213 -0
  9. package/dist/chunk-3U5IBM24.js.map +1 -0
  10. package/dist/chunk-574C6MQR.js +743 -0
  11. package/dist/chunk-574C6MQR.js.map +1 -0
  12. package/dist/chunk-5GDZ22YP.js +449 -0
  13. package/dist/chunk-5GDZ22YP.js.map +1 -0
  14. package/dist/chunk-5KLVH3PY.js +167 -0
  15. package/dist/chunk-5KLVH3PY.js.map +1 -0
  16. package/dist/chunk-5RDRAO4B.js +92 -0
  17. package/dist/chunk-5RDRAO4B.js.map +1 -0
  18. package/dist/chunk-7N4J557C.js +10 -0
  19. package/dist/chunk-7N4J557C.js.map +1 -0
  20. package/dist/chunk-A7JLBK2Y.js +3506 -0
  21. package/dist/chunk-A7JLBK2Y.js.map +1 -0
  22. package/dist/chunk-ANSJPYGI.js +84 -0
  23. package/dist/chunk-ANSJPYGI.js.map +1 -0
  24. package/dist/chunk-BTZZUCLI.js +264 -0
  25. package/dist/chunk-BTZZUCLI.js.map +1 -0
  26. package/dist/chunk-C7D4NJ2D.js +217 -0
  27. package/dist/chunk-C7D4NJ2D.js.map +1 -0
  28. package/dist/chunk-CAGOB2N4.js +208 -0
  29. package/dist/chunk-CAGOB2N4.js.map +1 -0
  30. package/dist/chunk-DGMQEI6Y.js +98 -0
  31. package/dist/chunk-DGMQEI6Y.js.map +1 -0
  32. package/dist/chunk-E75IPST5.js +289 -0
  33. package/dist/chunk-E75IPST5.js.map +1 -0
  34. package/dist/chunk-EYGD6X2T.js +180 -0
  35. package/dist/chunk-EYGD6X2T.js.map +1 -0
  36. package/dist/chunk-GTVB4HEM.js +765 -0
  37. package/dist/chunk-GTVB4HEM.js.map +1 -0
  38. package/dist/chunk-J7MIZ5CA.js +1907 -0
  39. package/dist/chunk-J7MIZ5CA.js.map +1 -0
  40. package/dist/chunk-KWHQ2XXL.js +626 -0
  41. package/dist/chunk-KWHQ2XXL.js.map +1 -0
  42. package/dist/chunk-L6LK2QIQ.js +657 -0
  43. package/dist/chunk-L6LK2QIQ.js.map +1 -0
  44. package/dist/chunk-MAQXCUR4.js +1007 -0
  45. package/dist/chunk-MAQXCUR4.js.map +1 -0
  46. package/dist/chunk-S4XL7HOM.js +402 -0
  47. package/dist/chunk-S4XL7HOM.js.map +1 -0
  48. package/dist/chunk-URLQAXTR.js +60 -0
  49. package/dist/chunk-URLQAXTR.js.map +1 -0
  50. package/dist/chunk-V4BOYR52.js +3504 -0
  51. package/dist/chunk-V4BOYR52.js.map +1 -0
  52. package/dist/chunk-VZQXX3WW.js +210 -0
  53. package/dist/chunk-VZQXX3WW.js.map +1 -0
  54. package/dist/chunk-WKBO5R4O.js +34 -0
  55. package/dist/chunk-WKBO5R4O.js.map +1 -0
  56. package/dist/chunk-XIFFTATU.js +15753 -0
  57. package/dist/chunk-XIFFTATU.js.map +1 -0
  58. package/dist/command-approvals-6Y57VCWZ.js +28 -0
  59. package/dist/command-approvals-6Y57VCWZ.js.map +1 -0
  60. package/dist/context-ZC5IFEAX.js +25 -0
  61. package/dist/context-ZC5IFEAX.js.map +1 -0
  62. package/dist/hook-approvals-CTUFKEJT.js +22 -0
  63. package/dist/hook-approvals-CTUFKEJT.js.map +1 -0
  64. package/dist/index.d.ts +1 -0
  65. package/dist/index.js +2582 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/interactive-assets-CCAAWVKH.js +31 -0
  68. package/dist/interactive-assets-CCAAWVKH.js.map +1 -0
  69. package/dist/job-runner.d.ts +2 -0
  70. package/dist/job-runner.js +235 -0
  71. package/dist/job-runner.js.map +1 -0
  72. package/dist/loader-4IDS2RIE.js +15 -0
  73. package/dist/loader-4IDS2RIE.js.map +1 -0
  74. package/dist/mcp-approvals-WNPH65BK.js +18 -0
  75. package/dist/mcp-approvals-WNPH65BK.js.map +1 -0
  76. package/dist/mcp-config-YIJIES2C.js +16 -0
  77. package/dist/mcp-config-YIJIES2C.js.map +1 -0
  78. package/dist/model-window-store-YFVNXCIP.js +27 -0
  79. package/dist/model-window-store-YFVNXCIP.js.map +1 -0
  80. package/dist/openai-compatible-RHZUBHV6.js +10 -0
  81. package/dist/openai-compatible-RHZUBHV6.js.map +1 -0
  82. package/dist/permission-approvals-76PVREFD.js +14 -0
  83. package/dist/permission-approvals-76PVREFD.js.map +1 -0
  84. package/dist/permissions-CHCKTFQQ.js +28 -0
  85. package/dist/permissions-CHCKTFQQ.js.map +1 -0
  86. package/dist/sandbox-CNVAQDA7.js +23 -0
  87. package/dist/sandbox-CNVAQDA7.js.map +1 -0
  88. package/dist/scrollback-LUKLIBVI.js +136 -0
  89. package/dist/scrollback-LUKLIBVI.js.map +1 -0
  90. package/dist/sdk.d.ts +4574 -0
  91. package/dist/sdk.js +665 -0
  92. package/dist/sdk.js.map +1 -0
  93. package/dist/settings-loader-M2QP5TX2.js +21 -0
  94. package/dist/settings-loader-M2QP5TX2.js.map +1 -0
  95. package/dist/settings-removed-JWWPT4WA.js +19 -0
  96. package/dist/settings-removed-JWWPT4WA.js.map +1 -0
  97. package/dist/shell-selection-V6QAYXPX.js +17 -0
  98. package/dist/shell-selection-V6QAYXPX.js.map +1 -0
  99. package/package.json +143 -0
  100. package/patches/ink+6.8.0.patch +13 -0
  101. package/scripts/apply-ink-patch.mjs +29 -0
  102. package/scripts/ink-patch.mjs +59 -0
  103. package/scripts/verify-ink-patch.mjs +11 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/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"]}
@@ -0,0 +1,31 @@
1
+ import {
2
+ listCustomThemes,
3
+ resolveTheme
4
+ } from "./chunk-L6LK2QIQ.js";
5
+ import {
6
+ discoverSkills
7
+ } from "./chunk-KWHQ2XXL.js";
8
+ import {
9
+ discoverCommands
10
+ } from "./chunk-E75IPST5.js";
11
+ import "./chunk-5KLVH3PY.js";
12
+ import "./chunk-DGMQEI6Y.js";
13
+ import "./chunk-574C6MQR.js";
14
+ import "./chunk-24AXE6SP.js";
15
+
16
+ // src/tui/interactive-assets.ts
17
+ function loadInteractiveAssets(config) {
18
+ return {
19
+ commands: discoverCommands(config.workspace),
20
+ skills: discoverSkills(config.workspace, config.settings.skills.overrides, {
21
+ executionOverrides: config.settings.skills.execution,
22
+ enabled: config.settings.skills.enabled
23
+ }),
24
+ customThemes: listCustomThemes(config.workspace),
25
+ initialTheme: resolveTheme(config.workspace, config.settings.theme ?? "apple")
26
+ };
27
+ }
28
+ export {
29
+ loadInteractiveAssets
30
+ };
31
+ //# sourceMappingURL=interactive-assets-CCAAWVKH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tui/interactive-assets.ts"],"sourcesContent":["import { discoverCommands } from '../commands/loader.js';\r\nimport { discoverSkills, type Skill } from '../skills.js';\r\nimport type { SlashCommand } from '../types/commands.js';\r\nimport type { AgentConfig } from '../types/runtime.js';\r\nimport { listCustomThemes, resolveTheme, type ResolvedTheme } from './theme.js';\r\n\r\nexport interface InteractiveAssets {\r\n commands: SlashCommand[];\r\n skills: Skill[];\r\n customThemes: string[];\r\n initialTheme: ResolvedTheme | null;\r\n}\r\n\r\n/** Load filesystem-backed UI metadata before React begins rendering. */\r\nexport function loadInteractiveAssets(\r\n config: Pick<AgentConfig, 'workspace' | 'settings'>,\r\n): InteractiveAssets {\r\n return {\r\n commands: discoverCommands(config.workspace),\r\n skills: discoverSkills(config.workspace, config.settings.skills.overrides, {\r\n executionOverrides: config.settings.skills.execution,\r\n enabled: config.settings.skills.enabled,\r\n }),\r\n customThemes: listCustomThemes(config.workspace),\r\n initialTheme: resolveTheme(config.workspace, config.settings.theme ?? 'apple'),\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;AAcO,SAAS,sBACd,QACmB;AACnB,SAAO;AAAA,IACL,UAAU,iBAAiB,OAAO,SAAS;AAAA,IAC3C,QAAQ,eAAe,OAAO,WAAW,OAAO,SAAS,OAAO,WAAW;AAAA,MACzE,oBAAoB,OAAO,SAAS,OAAO;AAAA,MAC3C,SAAS,OAAO,SAAS,OAAO;AAAA,IAClC,CAAC;AAAA,IACD,cAAc,iBAAiB,OAAO,SAAS;AAAA,IAC/C,cAAc,aAAa,OAAO,WAAW,OAAO,SAAS,SAAS,OAAO;AAAA,EAC/E;AACF;","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }