pi-agent-zh 17.1.8

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 (1519) hide show
  1. package/CHANGELOG.md +14459 -0
  2. package/README.md +35 -0
  3. package/dist/CHANGELOG-vt8ene9g.md +14459 -0
  4. package/dist/cli.js +22079 -0
  5. package/dist/template-dys3vk5b.js +1671 -0
  6. package/dist/template-f8wx9vfn.css +1355 -0
  7. package/dist/template-qat058wr.html +55 -0
  8. package/dist/tool-views.generated-jdfmzwmn.js +35 -0
  9. package/examples/README.md +21 -0
  10. package/examples/custom-tools/README.md +104 -0
  11. package/examples/custom-tools/hello/index.ts +20 -0
  12. package/examples/extensions/README.md +142 -0
  13. package/examples/extensions/api-demo.ts +79 -0
  14. package/examples/extensions/chalk-logger.ts +25 -0
  15. package/examples/extensions/hello.ts +31 -0
  16. package/examples/extensions/pirate.ts +43 -0
  17. package/examples/extensions/plan-mode.ts +549 -0
  18. package/examples/extensions/reload-runtime.ts +38 -0
  19. package/examples/extensions/thinking-note.ts +13 -0
  20. package/examples/extensions/tools.ts +145 -0
  21. package/examples/extensions/with-deps/index.ts +36 -0
  22. package/examples/extensions/with-deps/package-lock.json +31 -0
  23. package/examples/extensions/with-deps/package.json +17 -0
  24. package/examples/hooks/README.md +56 -0
  25. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  26. package/examples/hooks/confirm-destructive.ts +58 -0
  27. package/examples/hooks/custom-compaction.ts +115 -0
  28. package/examples/hooks/dirty-repo-guard.ts +51 -0
  29. package/examples/hooks/file-trigger.ts +40 -0
  30. package/examples/hooks/git-checkpoint.ts +52 -0
  31. package/examples/hooks/handoff.ts +149 -0
  32. package/examples/hooks/permission-gate.ts +33 -0
  33. package/examples/hooks/protected-paths.ts +29 -0
  34. package/examples/hooks/qna.ts +118 -0
  35. package/examples/hooks/status-line.ts +39 -0
  36. package/examples/sdk/01-minimal.ts +21 -0
  37. package/examples/sdk/02-custom-model.ts +49 -0
  38. package/examples/sdk/03-custom-prompt.ts +46 -0
  39. package/examples/sdk/04-skills.ts +43 -0
  40. package/examples/sdk/06-extensions.ts +82 -0
  41. package/examples/sdk/06-hooks.ts +61 -0
  42. package/examples/sdk/07-context-files.ts +35 -0
  43. package/examples/sdk/08-prompt-templates.ts +41 -0
  44. package/examples/sdk/08-slash-commands.ts +46 -0
  45. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  46. package/examples/sdk/11-sessions.ts +47 -0
  47. package/examples/sdk/12-redis-sessions.ts +54 -0
  48. package/examples/sdk/13-sql-sessions.ts +61 -0
  49. package/examples/sdk/README.md +169 -0
  50. package/package.json +606 -0
  51. package/scripts/bench-guard.ts +71 -0
  52. package/scripts/bench-title-models.ts +332 -0
  53. package/scripts/build-binary.ts +117 -0
  54. package/scripts/bundle-dist.ts +133 -0
  55. package/scripts/compile-binary.ts +69 -0
  56. package/scripts/embed-mupdf-wasm.ts +67 -0
  57. package/scripts/format-prompts.ts +68 -0
  58. package/scripts/generate-aria-snapshot.ts +134 -0
  59. package/scripts/generate-docs-index.ts +58 -0
  60. package/scripts/generate-share-viewer.ts +34 -0
  61. package/scripts/legacy-pi-virtual-module.ts +195 -0
  62. package/scripts/measure-prompt-tokens.ts +63 -0
  63. package/scripts/omp +42 -0
  64. package/scripts/omp.ts +19 -0
  65. package/src/advisor/advise-tool.ts +216 -0
  66. package/src/advisor/config.ts +341 -0
  67. package/src/advisor/emission-guard.ts +172 -0
  68. package/src/advisor/index.ts +6 -0
  69. package/src/advisor/runtime.ts +1232 -0
  70. package/src/advisor/transcript-recorder.ts +159 -0
  71. package/src/advisor/watchdog.ts +135 -0
  72. package/src/async/index.ts +1 -0
  73. package/src/async/job-manager.ts +821 -0
  74. package/src/auto-thinking/classifier.ts +182 -0
  75. package/src/autolearn/controller.ts +152 -0
  76. package/src/autolearn/managed-skills.ts +255 -0
  77. package/src/autoresearch/command-resume.md +14 -0
  78. package/src/autoresearch/dashboard.ts +436 -0
  79. package/src/autoresearch/git.ts +331 -0
  80. package/src/autoresearch/helpers.ts +218 -0
  81. package/src/autoresearch/index.ts +541 -0
  82. package/src/autoresearch/prompt-setup.md +43 -0
  83. package/src/autoresearch/prompt.md +103 -0
  84. package/src/autoresearch/resume-message.md +10 -0
  85. package/src/autoresearch/state.ts +273 -0
  86. package/src/autoresearch/storage.ts +700 -0
  87. package/src/autoresearch/tools/init-experiment.ts +269 -0
  88. package/src/autoresearch/tools/log-experiment.ts +521 -0
  89. package/src/autoresearch/tools/run-experiment.ts +407 -0
  90. package/src/autoresearch/tools/update-notes.ts +109 -0
  91. package/src/autoresearch/types.ts +168 -0
  92. package/src/capability/context-file.ts +44 -0
  93. package/src/capability/extension-module.ts +34 -0
  94. package/src/capability/extension.ts +47 -0
  95. package/src/capability/fs.ts +117 -0
  96. package/src/capability/hook.ts +40 -0
  97. package/src/capability/index.ts +467 -0
  98. package/src/capability/instruction.ts +37 -0
  99. package/src/capability/mcp.ts +97 -0
  100. package/src/capability/prompt.ts +35 -0
  101. package/src/capability/rule-buckets.ts +66 -0
  102. package/src/capability/rule.ts +298 -0
  103. package/src/capability/settings.ts +34 -0
  104. package/src/capability/skill.ts +63 -0
  105. package/src/capability/slash-command.ts +40 -0
  106. package/src/capability/ssh.ts +41 -0
  107. package/src/capability/system-prompt.ts +34 -0
  108. package/src/capability/tool.ts +38 -0
  109. package/src/capability/types.ts +187 -0
  110. package/src/cleanse/agent.ts +226 -0
  111. package/src/cleanse/balance.ts +79 -0
  112. package/src/cleanse/checkers.ts +996 -0
  113. package/src/cleanse/index.ts +190 -0
  114. package/src/cleanse/loop.ts +51 -0
  115. package/src/cleanse/parsers.ts +726 -0
  116. package/src/cleanse/progress.ts +50 -0
  117. package/src/cleanse/prompts/assignment.md +47 -0
  118. package/src/cleanse/types.ts +72 -0
  119. package/src/cli/agents-cli.ts +138 -0
  120. package/src/cli/args.ts +420 -0
  121. package/src/cli/auth-broker-cli.ts +940 -0
  122. package/src/cli/auth-gateway-cli.ts +674 -0
  123. package/src/cli/bench-cli.ts +990 -0
  124. package/src/cli/classify-install-target.ts +76 -0
  125. package/src/cli/claude-trace-cli.ts +795 -0
  126. package/src/cli/commands/init-xdg.ts +27 -0
  127. package/src/cli/completion-gen.ts +550 -0
  128. package/src/cli/config-cli.ts +459 -0
  129. package/src/cli/dry-balance-cli.ts +864 -0
  130. package/src/cli/extension-flags.ts +48 -0
  131. package/src/cli/file-processor.ts +132 -0
  132. package/src/cli/flag-tables.ts +352 -0
  133. package/src/cli/gallery-cli.ts +272 -0
  134. package/src/cli/gallery-fixtures/agentic.ts +420 -0
  135. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  136. package/src/cli/gallery-fixtures/edit.ts +254 -0
  137. package/src/cli/gallery-fixtures/fs.ts +220 -0
  138. package/src/cli/gallery-fixtures/index.ts +40 -0
  139. package/src/cli/gallery-fixtures/interaction.ts +46 -0
  140. package/src/cli/gallery-fixtures/memory.ts +81 -0
  141. package/src/cli/gallery-fixtures/misc.ts +177 -0
  142. package/src/cli/gallery-fixtures/search.ts +135 -0
  143. package/src/cli/gallery-fixtures/shell.ts +241 -0
  144. package/src/cli/gallery-fixtures/types.ts +57 -0
  145. package/src/cli/gallery-fixtures/web.ts +158 -0
  146. package/src/cli/gallery-screenshot.ts +279 -0
  147. package/src/cli/gc-cli.ts +946 -0
  148. package/src/cli/grep-cli.ts +161 -0
  149. package/src/cli/grievances-cli.ts +256 -0
  150. package/src/cli/initial-message.ts +58 -0
  151. package/src/cli/models-cli.ts +388 -0
  152. package/src/cli/plugin-cli.ts +996 -0
  153. package/src/cli/profile-alias.ts +369 -0
  154. package/src/cli/profile-bootstrap.ts +233 -0
  155. package/src/cli/read-cli.ts +99 -0
  156. package/src/cli/session-picker.ts +93 -0
  157. package/src/cli/setup-cli.ts +320 -0
  158. package/src/cli/setup-model-picker.ts +43 -0
  159. package/src/cli/shell-cli.ts +176 -0
  160. package/src/cli/ssh-cli.ts +179 -0
  161. package/src/cli/startup-cwd.ts +58 -0
  162. package/src/cli/stats-cli.ts +229 -0
  163. package/src/cli/tiny-models-cli.ts +153 -0
  164. package/src/cli/ttsr-cli.ts +995 -0
  165. package/src/cli/update-cli.ts +1219 -0
  166. package/src/cli/usage-cli.ts +1084 -0
  167. package/src/cli/usage-error.ts +7 -0
  168. package/src/cli/web-search-cli.ts +144 -0
  169. package/src/cli/worktree-cli.ts +311 -0
  170. package/src/cli-commands.ts +166 -0
  171. package/src/cli.ts +407 -0
  172. package/src/collab/crypto.ts +63 -0
  173. package/src/collab/display-name.ts +13 -0
  174. package/src/collab/guest.ts +731 -0
  175. package/src/collab/host.ts +691 -0
  176. package/src/collab/protocol.ts +296 -0
  177. package/src/collab/relay-client.ts +282 -0
  178. package/src/collab/replication-shrink.ts +111 -0
  179. package/src/commands/acp.ts +33 -0
  180. package/src/commands/agents.ts +57 -0
  181. package/src/commands/auth-broker.ts +99 -0
  182. package/src/commands/auth-gateway.ts +69 -0
  183. package/src/commands/bench.ts +65 -0
  184. package/src/commands/cleanse.ts +45 -0
  185. package/src/commands/commit.ts +46 -0
  186. package/src/commands/complete.ts +66 -0
  187. package/src/commands/completions.ts +60 -0
  188. package/src/commands/config.ts +51 -0
  189. package/src/commands/dry-balance.ts +43 -0
  190. package/src/commands/gallery.ts +60 -0
  191. package/src/commands/gc.ts +46 -0
  192. package/src/commands/grep.ts +48 -0
  193. package/src/commands/grievances.ts +51 -0
  194. package/src/commands/install.ts +107 -0
  195. package/src/commands/join.ts +39 -0
  196. package/src/commands/launch.ts +212 -0
  197. package/src/commands/models.ts +60 -0
  198. package/src/commands/plugin.ts +78 -0
  199. package/src/commands/read.ts +38 -0
  200. package/src/commands/say.ts +145 -0
  201. package/src/commands/setup.ts +67 -0
  202. package/src/commands/shell.ts +29 -0
  203. package/src/commands/ssh.ts +60 -0
  204. package/src/commands/stats.ts +29 -0
  205. package/src/commands/tiny-models.ts +36 -0
  206. package/src/commands/token.ts +164 -0
  207. package/src/commands/ttsr.ts +125 -0
  208. package/src/commands/update.ts +33 -0
  209. package/src/commands/usage.ts +54 -0
  210. package/src/commands/web-search.ts +42 -0
  211. package/src/commands/worktree.ts +62 -0
  212. package/src/commit/agentic/agent.ts +322 -0
  213. package/src/commit/agentic/fallback.ts +96 -0
  214. package/src/commit/agentic/index.ts +382 -0
  215. package/src/commit/agentic/lock-files.ts +107 -0
  216. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  217. package/src/commit/agentic/prompts/session-user.md +25 -0
  218. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  219. package/src/commit/agentic/prompts/system.md +38 -0
  220. package/src/commit/agentic/state.ts +60 -0
  221. package/src/commit/agentic/tools/analyze-file.ts +148 -0
  222. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  223. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  224. package/src/commit/agentic/tools/git-overview.ts +62 -0
  225. package/src/commit/agentic/tools/index.ts +54 -0
  226. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  227. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  228. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  229. package/src/commit/agentic/tools/schemas.ts +11 -0
  230. package/src/commit/agentic/tools/split-commit.ts +241 -0
  231. package/src/commit/agentic/topo-sort.ts +44 -0
  232. package/src/commit/agentic/trivial.ts +51 -0
  233. package/src/commit/agentic/validation.ts +183 -0
  234. package/src/commit/analysis/conventional.ts +64 -0
  235. package/src/commit/analysis/index.ts +4 -0
  236. package/src/commit/analysis/scope.ts +242 -0
  237. package/src/commit/analysis/summary.ts +107 -0
  238. package/src/commit/analysis/validation.ts +66 -0
  239. package/src/commit/changelog/detect.ts +40 -0
  240. package/src/commit/changelog/generate.ts +101 -0
  241. package/src/commit/changelog/index.ts +234 -0
  242. package/src/commit/changelog/parse.ts +44 -0
  243. package/src/commit/cli.ts +85 -0
  244. package/src/commit/git/diff.ts +148 -0
  245. package/src/commit/index.ts +5 -0
  246. package/src/commit/map-reduce/index.ts +69 -0
  247. package/src/commit/map-reduce/map-phase.ts +193 -0
  248. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  249. package/src/commit/map-reduce/utils.ts +9 -0
  250. package/src/commit/message.ts +11 -0
  251. package/src/commit/model-selection.ts +95 -0
  252. package/src/commit/pipeline.ts +243 -0
  253. package/src/commit/prompts/analysis-system.md +148 -0
  254. package/src/commit/prompts/analysis-user.md +38 -0
  255. package/src/commit/prompts/changelog-system.md +50 -0
  256. package/src/commit/prompts/changelog-user.md +18 -0
  257. package/src/commit/prompts/file-observer-system.md +24 -0
  258. package/src/commit/prompts/file-observer-user.md +8 -0
  259. package/src/commit/prompts/reduce-system.md +50 -0
  260. package/src/commit/prompts/reduce-user.md +17 -0
  261. package/src/commit/prompts/summary-retry.md +3 -0
  262. package/src/commit/prompts/summary-system.md +38 -0
  263. package/src/commit/prompts/summary-user.md +13 -0
  264. package/src/commit/prompts/types-description.md +2 -0
  265. package/src/commit/shared-llm.ts +70 -0
  266. package/src/commit/types.ts +118 -0
  267. package/src/commit/utils/exclusions.ts +42 -0
  268. package/src/commit/utils.ts +58 -0
  269. package/src/config/api-key-resolver.ts +81 -0
  270. package/src/config/append-only-context-mode.ts +76 -0
  271. package/src/config/config-file.ts +347 -0
  272. package/src/config/file-lock.ts +164 -0
  273. package/src/config/inline-tool-descriptors-mode.ts +26 -0
  274. package/src/config/keybindings.ts +688 -0
  275. package/src/config/mcp-schema.json +247 -0
  276. package/src/config/model-discovery.ts +999 -0
  277. package/src/config/model-registry.ts +2725 -0
  278. package/src/config/model-resolver.ts +2068 -0
  279. package/src/config/model-roles.ts +113 -0
  280. package/src/config/models-config-schema-bundle.ts +313 -0
  281. package/src/config/models-config-schema.ts +14 -0
  282. package/src/config/models-config.ts +130 -0
  283. package/src/config/prompt-templates.ts +205 -0
  284. package/src/config/provider-globals.ts +25 -0
  285. package/src/config/resolve-config-value.ts +94 -0
  286. package/src/config/service-tier.ts +141 -0
  287. package/src/config/settings-schema.ts +5751 -0
  288. package/src/config/settings.ts +2369 -0
  289. package/src/config.ts +242 -0
  290. package/src/cursor.ts +513 -0
  291. package/src/dap/client.ts +1043 -0
  292. package/src/dap/config.ts +480 -0
  293. package/src/dap/defaults.json +212 -0
  294. package/src/dap/index.ts +4 -0
  295. package/src/dap/session.ts +1841 -0
  296. package/src/dap/types.ts +611 -0
  297. package/src/debug/index.ts +584 -0
  298. package/src/debug/log-formatting.ts +58 -0
  299. package/src/debug/log-viewer.ts +966 -0
  300. package/src/debug/profiler.ts +168 -0
  301. package/src/debug/protocol-probe.ts +267 -0
  302. package/src/debug/raw-sse-buffer.ts +421 -0
  303. package/src/debug/raw-sse.ts +312 -0
  304. package/src/debug/remote-debugger.ts +151 -0
  305. package/src/debug/report-bundle.ts +411 -0
  306. package/src/debug/system-info.ts +111 -0
  307. package/src/debug/terminal-info.ts +124 -0
  308. package/src/discovery/agents-md.ts +67 -0
  309. package/src/discovery/agents.ts +230 -0
  310. package/src/discovery/at-imports.ts +273 -0
  311. package/src/discovery/builtin-defaults.ts +39 -0
  312. package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
  313. package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
  314. package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
  315. package/src/discovery/builtin-rules/go-ioutil.md +37 -0
  316. package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
  317. package/src/discovery/builtin-rules/go-new-expr.md +44 -0
  318. package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
  319. package/src/discovery/builtin-rules/go-range-int.md +45 -0
  320. package/src/discovery/builtin-rules/index.ts +74 -0
  321. package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
  322. package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
  323. package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
  324. package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
  325. package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
  326. package/src/discovery/builtin-rules/rs-result-type.md +20 -0
  327. package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
  328. package/src/discovery/builtin-rules/ts-import-type.md +43 -0
  329. package/src/discovery/builtin-rules/ts-no-any.md +66 -0
  330. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
  331. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
  332. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  333. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  334. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  335. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  336. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  337. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -0
  338. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  339. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  340. package/src/discovery/builtin.ts +935 -0
  341. package/src/discovery/claude-plugins.ts +624 -0
  342. package/src/discovery/claude.ts +588 -0
  343. package/src/discovery/cline.ts +83 -0
  344. package/src/discovery/codex.ts +540 -0
  345. package/src/discovery/cursor.ts +220 -0
  346. package/src/discovery/gemini.ts +383 -0
  347. package/src/discovery/github.ts +337 -0
  348. package/src/discovery/helpers.ts +1159 -0
  349. package/src/discovery/index.ts +81 -0
  350. package/src/discovery/mcp-json.ts +172 -0
  351. package/src/discovery/omp-extension-roots.ts +213 -0
  352. package/src/discovery/omp-plugins.ts +387 -0
  353. package/src/discovery/opencode.ts +441 -0
  354. package/src/discovery/plugin-dir-roots.ts +28 -0
  355. package/src/discovery/ssh.ts +153 -0
  356. package/src/discovery/substitute-plugin-root.ts +77 -0
  357. package/src/discovery/vscode.ts +105 -0
  358. package/src/discovery/windsurf.ts +147 -0
  359. package/src/edit/apply-patch/index.ts +87 -0
  360. package/src/edit/apply-patch/parser.ts +174 -0
  361. package/src/edit/diff.ts +999 -0
  362. package/src/edit/file-snapshot-store.ts +148 -0
  363. package/src/edit/hashline/block-resolver.ts +33 -0
  364. package/src/edit/hashline/diff.ts +356 -0
  365. package/src/edit/hashline/execute.ts +280 -0
  366. package/src/edit/hashline/filesystem.ts +223 -0
  367. package/src/edit/hashline/index.ts +5 -0
  368. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  369. package/src/edit/hashline/params.ts +12 -0
  370. package/src/edit/index.ts +676 -0
  371. package/src/edit/modes/apply-patch.lark +19 -0
  372. package/src/edit/modes/apply-patch.ts +53 -0
  373. package/src/edit/modes/patch.ts +1958 -0
  374. package/src/edit/modes/replace.ts +1137 -0
  375. package/src/edit/normalize.ts +345 -0
  376. package/src/edit/notebook.ts +242 -0
  377. package/src/edit/read-file.ts +25 -0
  378. package/src/edit/renderer.ts +998 -0
  379. package/src/edit/snapshot-details.ts +77 -0
  380. package/src/edit/streaming.ts +698 -0
  381. package/src/eval/agent-bridge.ts +224 -0
  382. package/src/eval/backend-helpers.ts +48 -0
  383. package/src/eval/backend.ts +71 -0
  384. package/src/eval/bridge-timeout.ts +62 -0
  385. package/src/eval/budget-bridge.ts +48 -0
  386. package/src/eval/completion-bridge.ts +211 -0
  387. package/src/eval/concurrency-bridge.ts +34 -0
  388. package/src/eval/executor-base.ts +504 -0
  389. package/src/eval/idle-timeout.ts +91 -0
  390. package/src/eval/index.ts +6 -0
  391. package/src/eval/jl/executor.ts +540 -0
  392. package/src/eval/jl/index.ts +54 -0
  393. package/src/eval/jl/kernel.ts +236 -0
  394. package/src/eval/jl/prelude.jl +736 -0
  395. package/src/eval/jl/prelude.ts +3 -0
  396. package/src/eval/jl/runner.jl +666 -0
  397. package/src/eval/jl/runtime.ts +118 -0
  398. package/src/eval/js/context-manager.ts +701 -0
  399. package/src/eval/js/executor.ts +175 -0
  400. package/src/eval/js/index.ts +40 -0
  401. package/src/eval/js/process-entry.ts +31 -0
  402. package/src/eval/js/shared/helpers.ts +170 -0
  403. package/src/eval/js/shared/indirect-eval.ts +30 -0
  404. package/src/eval/js/shared/local-module-loader.ts +364 -0
  405. package/src/eval/js/shared/prelude.ts +2 -0
  406. package/src/eval/js/shared/prelude.txt +294 -0
  407. package/src/eval/js/shared/rewrite-imports.ts +550 -0
  408. package/src/eval/js/shared/runtime.ts +590 -0
  409. package/src/eval/js/shared/types.ts +18 -0
  410. package/src/eval/js/tool-bridge.ts +163 -0
  411. package/src/eval/js/worker-core.ts +380 -0
  412. package/src/eval/js/worker-entry.ts +37 -0
  413. package/src/eval/js/worker-protocol.ts +47 -0
  414. package/src/eval/kernel-base.ts +569 -0
  415. package/src/eval/py/display.ts +71 -0
  416. package/src/eval/py/executor.ts +603 -0
  417. package/src/eval/py/index.ts +57 -0
  418. package/src/eval/py/kernel.ts +234 -0
  419. package/src/eval/py/prelude.py +672 -0
  420. package/src/eval/py/prelude.ts +3 -0
  421. package/src/eval/py/runner.py +1388 -0
  422. package/src/eval/py/runtime.ts +276 -0
  423. package/src/eval/py/spawn-options.ts +139 -0
  424. package/src/eval/py/tool-bridge.ts +181 -0
  425. package/src/eval/rb/executor.ts +504 -0
  426. package/src/eval/rb/index.ts +54 -0
  427. package/src/eval/rb/kernel.ts +231 -0
  428. package/src/eval/rb/prelude.rb +552 -0
  429. package/src/eval/rb/prelude.ts +3 -0
  430. package/src/eval/rb/runner.rb +581 -0
  431. package/src/eval/rb/runtime.ts +132 -0
  432. package/src/eval/runtime-env.ts +104 -0
  433. package/src/eval/session-id.ts +8 -0
  434. package/src/eval/types.ts +48 -0
  435. package/src/exa/index.ts +2 -0
  436. package/src/exa/mcp-client.ts +370 -0
  437. package/src/exa/types.ts +69 -0
  438. package/src/exec/bash-executor.ts +627 -0
  439. package/src/exec/direnv.ts +145 -0
  440. package/src/exec/exec.ts +53 -0
  441. package/src/exec/non-interactive-env.ts +118 -0
  442. package/src/export/custom-share.ts +65 -0
  443. package/src/export/html/args.ts +20 -0
  444. package/src/export/html/index.ts +313 -0
  445. package/src/export/html/share-loader.js +102 -0
  446. package/src/export/html/template.css +1355 -0
  447. package/src/export/html/template.html +55 -0
  448. package/src/export/html/template.js +1671 -0
  449. package/src/export/html/tool-views.generated.js +35 -0
  450. package/src/export/html/vendor/highlight.min.js +1213 -0
  451. package/src/export/html/vendor/marked.min.js +6 -0
  452. package/src/export/html/web-palette.ts +126 -0
  453. package/src/export/share.ts +682 -0
  454. package/src/export/ttsr.ts +590 -0
  455. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  456. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  457. package/src/extensibility/custom-commands/index.ts +2 -0
  458. package/src/extensibility/custom-commands/loader.ts +242 -0
  459. package/src/extensibility/custom-commands/types.ts +119 -0
  460. package/src/extensibility/custom-tools/index.ts +7 -0
  461. package/src/extensibility/custom-tools/loader.ts +301 -0
  462. package/src/extensibility/custom-tools/types.ts +286 -0
  463. package/src/extensibility/custom-tools/wrapper.ts +50 -0
  464. package/src/extensibility/extensions/compact-handler.ts +40 -0
  465. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  466. package/src/extensibility/extensions/index.ts +16 -0
  467. package/src/extensibility/extensions/load-errors.ts +13 -0
  468. package/src/extensibility/extensions/loader.ts +624 -0
  469. package/src/extensibility/extensions/managed-timers.ts +83 -0
  470. package/src/extensibility/extensions/model-api.ts +39 -0
  471. package/src/extensibility/extensions/runner.ts +1209 -0
  472. package/src/extensibility/extensions/types.ts +1526 -0
  473. package/src/extensibility/extensions/wrapper.ts +377 -0
  474. package/src/extensibility/hooks/index.ts +6 -0
  475. package/src/extensibility/hooks/loader.ts +244 -0
  476. package/src/extensibility/hooks/runner.ts +425 -0
  477. package/src/extensibility/hooks/tool-wrapper.ts +124 -0
  478. package/src/extensibility/hooks/types.ts +612 -0
  479. package/src/extensibility/legacy-pi-ai-shim.ts +140 -0
  480. package/src/extensibility/legacy-pi-coding-agent-shim.ts +1384 -0
  481. package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
  482. package/src/extensibility/plugins/bun-git-cache.ts +91 -0
  483. package/src/extensibility/plugins/doctor.ts +65 -0
  484. package/src/extensibility/plugins/git-url.ts +367 -0
  485. package/src/extensibility/plugins/index.ts +9 -0
  486. package/src/extensibility/plugins/installer.ts +201 -0
  487. package/src/extensibility/plugins/legacy-pi-compat.ts +2532 -0
  488. package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
  489. package/src/extensibility/plugins/loader.ts +535 -0
  490. package/src/extensibility/plugins/manager.ts +1142 -0
  491. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  492. package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
  493. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  494. package/src/extensibility/plugins/marketplace/manager.ts +926 -0
  495. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  496. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  497. package/src/extensibility/plugins/marketplace/types.ts +192 -0
  498. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  499. package/src/extensibility/plugins/parser.ts +107 -0
  500. package/src/extensibility/plugins/runtime-config.ts +9 -0
  501. package/src/extensibility/plugins/types.ts +194 -0
  502. package/src/extensibility/session-handler-types.ts +21 -0
  503. package/src/extensibility/shared-events.ts +401 -0
  504. package/src/extensibility/skills.ts +511 -0
  505. package/src/extensibility/slash-commands.ts +131 -0
  506. package/src/extensibility/tool-event-input.ts +80 -0
  507. package/src/extensibility/tool-proxy.ts +28 -0
  508. package/src/extensibility/typebox.ts +958 -0
  509. package/src/extensibility/utils.ts +184 -0
  510. package/src/goals/index.ts +3 -0
  511. package/src/goals/runtime.ts +521 -0
  512. package/src/goals/state.ts +37 -0
  513. package/src/goals/tools/goal-tool.ts +251 -0
  514. package/src/hindsight/backend.ts +354 -0
  515. package/src/hindsight/bank.ts +156 -0
  516. package/src/hindsight/client.ts +680 -0
  517. package/src/hindsight/config.ts +193 -0
  518. package/src/hindsight/content.ts +266 -0
  519. package/src/hindsight/index.ts +8 -0
  520. package/src/hindsight/mental-models.ts +429 -0
  521. package/src/hindsight/seeds.json +32 -0
  522. package/src/hindsight/state.ts +550 -0
  523. package/src/hindsight/transcript.ts +71 -0
  524. package/src/index.ts +66 -0
  525. package/src/internal-urls/agent-protocol.ts +180 -0
  526. package/src/internal-urls/artifact-protocol.ts +151 -0
  527. package/src/internal-urls/docs-index.ts +102 -0
  528. package/src/internal-urls/filesystem-resource.ts +34 -0
  529. package/src/internal-urls/history-protocol.ts +198 -0
  530. package/src/internal-urls/index.ts +27 -0
  531. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  532. package/src/internal-urls/json-query.ts +126 -0
  533. package/src/internal-urls/local-protocol.ts +470 -0
  534. package/src/internal-urls/mcp-protocol.ts +165 -0
  535. package/src/internal-urls/memory-protocol.ts +347 -0
  536. package/src/internal-urls/omp-protocol.ts +94 -0
  537. package/src/internal-urls/parse.ts +103 -0
  538. package/src/internal-urls/registry-helpers.ts +132 -0
  539. package/src/internal-urls/router.ts +150 -0
  540. package/src/internal-urls/rule-protocol.ts +45 -0
  541. package/src/internal-urls/skill-protocol.ts +117 -0
  542. package/src/internal-urls/ssh-protocol.ts +368 -0
  543. package/src/internal-urls/types.ts +196 -0
  544. package/src/internal-urls/vault-protocol.ts +940 -0
  545. package/src/internal-urls/xd-protocol.ts +46 -0
  546. package/src/irc/bus.ts +380 -0
  547. package/src/jsonrpc/message-framing.ts +142 -0
  548. package/src/launch/broker.ts +1134 -0
  549. package/src/launch/client.ts +350 -0
  550. package/src/launch/paths.ts +17 -0
  551. package/src/launch/presence.ts +82 -0
  552. package/src/launch/protocol.ts +396 -0
  553. package/src/launch/spawn-options.ts +17 -0
  554. package/src/launch/terminal-output.ts +46 -0
  555. package/src/lib/xai-http.ts +150 -0
  556. package/src/live/attestation.ts +91 -0
  557. package/src/live/controller.ts +517 -0
  558. package/src/live/prompts/agent-final-message.md +3 -0
  559. package/src/live/prompts/live-instructions.md +23 -0
  560. package/src/live/protocol.ts +233 -0
  561. package/src/live/transport.ts +422 -0
  562. package/src/live/visualizer.ts +214 -0
  563. package/src/live/voices.ts +18 -0
  564. package/src/lsp/client.ts +1429 -0
  565. package/src/lsp/clients/biome-client.ts +263 -0
  566. package/src/lsp/clients/index.ts +50 -0
  567. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  568. package/src/lsp/clients/swiftlint-client.ts +120 -0
  569. package/src/lsp/config.ts +549 -0
  570. package/src/lsp/defaults.json +499 -0
  571. package/src/lsp/deferred-diagnostics.ts +66 -0
  572. package/src/lsp/diagnostics-ledger.ts +51 -0
  573. package/src/lsp/edits.ts +288 -0
  574. package/src/lsp/format-options.ts +119 -0
  575. package/src/lsp/index.ts +2766 -0
  576. package/src/lsp/lspmux.ts +233 -0
  577. package/src/lsp/render.ts +668 -0
  578. package/src/lsp/startup-events.ts +13 -0
  579. package/src/lsp/types.ts +453 -0
  580. package/src/lsp/utils.ts +718 -0
  581. package/src/main.ts +1647 -0
  582. package/src/markit/NOTICE +32 -0
  583. package/src/markit/converters/docx.ts +56 -0
  584. package/src/markit/converters/epub.ts +136 -0
  585. package/src/markit/converters/mammoth.d.ts +24 -0
  586. package/src/markit/converters/pdf/columns.ts +103 -0
  587. package/src/markit/converters/pdf/extract.ts +598 -0
  588. package/src/markit/converters/pdf/grid.ts +780 -0
  589. package/src/markit/converters/pdf/headers.ts +106 -0
  590. package/src/markit/converters/pdf/index.ts +146 -0
  591. package/src/markit/converters/pdf/render.ts +501 -0
  592. package/src/markit/converters/pdf/types.ts +84 -0
  593. package/src/markit/converters/pptx.ts +325 -0
  594. package/src/markit/converters/xlsx.ts +173 -0
  595. package/src/markit/index.ts +2 -0
  596. package/src/markit/registry.ts +59 -0
  597. package/src/markit/types.ts +35 -0
  598. package/src/mcp/client.ts +511 -0
  599. package/src/mcp/config-writer.ts +377 -0
  600. package/src/mcp/config.ts +381 -0
  601. package/src/mcp/index.ts +29 -0
  602. package/src/mcp/json-rpc.ts +122 -0
  603. package/src/mcp/loader.ts +125 -0
  604. package/src/mcp/manager.ts +1419 -0
  605. package/src/mcp/oauth-credentials.ts +104 -0
  606. package/src/mcp/oauth-discovery.ts +587 -0
  607. package/src/mcp/oauth-flow.ts +820 -0
  608. package/src/mcp/render.ts +214 -0
  609. package/src/mcp/smithery-auth.ts +108 -0
  610. package/src/mcp/smithery-connect.ts +154 -0
  611. package/src/mcp/smithery-registry.ts +500 -0
  612. package/src/mcp/startup-events.ts +116 -0
  613. package/src/mcp/timeout.ts +59 -0
  614. package/src/mcp/tool-bridge.ts +691 -0
  615. package/src/mcp/tool-cache.ts +117 -0
  616. package/src/mcp/transports/http.ts +523 -0
  617. package/src/mcp/transports/index.ts +7 -0
  618. package/src/mcp/transports/sse.ts +377 -0
  619. package/src/mcp/transports/stdio.ts +903 -0
  620. package/src/mcp/types.ts +437 -0
  621. package/src/memories/index.ts +1434 -0
  622. package/src/memories/storage.ts +578 -0
  623. package/src/memory-backend/index.ts +18 -0
  624. package/src/memory-backend/local-backend.ts +47 -0
  625. package/src/memory-backend/off-backend.ts +25 -0
  626. package/src/memory-backend/resolve.ts +25 -0
  627. package/src/memory-backend/runtime.ts +66 -0
  628. package/src/memory-backend/tool-names.ts +2 -0
  629. package/src/memory-backend/types.ts +166 -0
  630. package/src/mnemopi/backend.ts +629 -0
  631. package/src/mnemopi/config.ts +267 -0
  632. package/src/mnemopi/embed-client.ts +246 -0
  633. package/src/mnemopi/embed-protocol.ts +35 -0
  634. package/src/mnemopi/embed-worker.ts +114 -0
  635. package/src/mnemopi/index.ts +3 -0
  636. package/src/mnemopi/state.ts +906 -0
  637. package/src/modes/acp/acp-agent.ts +2577 -0
  638. package/src/modes/acp/acp-client-bridge.ts +154 -0
  639. package/src/modes/acp/acp-event-mapper.ts +1084 -0
  640. package/src/modes/acp/acp-mode.ts +48 -0
  641. package/src/modes/acp/index.ts +2 -0
  642. package/src/modes/acp/terminal-auth.ts +37 -0
  643. package/src/modes/components/advisor-config.ts +635 -0
  644. package/src/modes/components/advisor-message.ts +109 -0
  645. package/src/modes/components/agent-dashboard.ts +1252 -0
  646. package/src/modes/components/agent-hub.ts +648 -0
  647. package/src/modes/components/agent-transcript-viewer.ts +649 -0
  648. package/src/modes/components/ask-dialog.ts +975 -0
  649. package/src/modes/components/assistant-message.ts +972 -0
  650. package/src/modes/components/background-tan-message.ts +36 -0
  651. package/src/modes/components/bash-execution.ts +233 -0
  652. package/src/modes/components/bordered-loader.ts +41 -0
  653. package/src/modes/components/btw-panel.ts +124 -0
  654. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  655. package/src/modes/components/chat-block.ts +111 -0
  656. package/src/modes/components/chat-transcript-builder.ts +495 -0
  657. package/src/modes/components/collab-prompt-message.ts +32 -0
  658. package/src/modes/components/compaction-summary-message.ts +221 -0
  659. package/src/modes/components/copy-selector.ts +218 -0
  660. package/src/modes/components/countdown-timer.ts +75 -0
  661. package/src/modes/components/custom-editor.ts +1027 -0
  662. package/src/modes/components/custom-message.ts +70 -0
  663. package/src/modes/components/diff.ts +254 -0
  664. package/src/modes/components/dynamic-border.ts +37 -0
  665. package/src/modes/components/error-banner.ts +33 -0
  666. package/src/modes/components/eval-execution.ts +169 -0
  667. package/src/modes/components/execution-shared.ts +101 -0
  668. package/src/modes/components/extensions/extension-dashboard.ts +492 -0
  669. package/src/modes/components/extensions/extension-list.ts +507 -0
  670. package/src/modes/components/extensions/index.ts +9 -0
  671. package/src/modes/components/extensions/inspector-panel.ts +321 -0
  672. package/src/modes/components/extensions/state-manager.ts +648 -0
  673. package/src/modes/components/extensions/types.ts +186 -0
  674. package/src/modes/components/footer.ts +276 -0
  675. package/src/modes/components/history-search.ts +268 -0
  676. package/src/modes/components/hook-editor.ts +213 -0
  677. package/src/modes/components/hook-input.ts +87 -0
  678. package/src/modes/components/hook-message.ts +67 -0
  679. package/src/modes/components/hook-selector.ts +691 -0
  680. package/src/modes/components/index.ts +42 -0
  681. package/src/modes/components/keybinding-hints.ts +65 -0
  682. package/src/modes/components/late-diagnostics-message.ts +60 -0
  683. package/src/modes/components/login-dialog.ts +197 -0
  684. package/src/modes/components/logout-account-selector.ts +130 -0
  685. package/src/modes/components/mcp-add-wizard.ts +1413 -0
  686. package/src/modes/components/message-frame.ts +98 -0
  687. package/src/modes/components/model-browser.ts +872 -0
  688. package/src/modes/components/model-hub.ts +2011 -0
  689. package/src/modes/components/model-picker.ts +233 -0
  690. package/src/modes/components/move-overlay.ts +293 -0
  691. package/src/modes/components/oauth-selector.ts +474 -0
  692. package/src/modes/components/omfg-panel.ts +141 -0
  693. package/src/modes/components/overlay-box.ts +109 -0
  694. package/src/modes/components/pause-screen.ts +208 -0
  695. package/src/modes/components/plan-review-overlay.ts +1226 -0
  696. package/src/modes/components/plan-toc.ts +138 -0
  697. package/src/modes/components/plugin-selector.ts +100 -0
  698. package/src/modes/components/plugin-settings.ts +745 -0
  699. package/src/modes/components/queue-mode-selector.ts +61 -0
  700. package/src/modes/components/read-tool-group.ts +678 -0
  701. package/src/modes/components/reset-usage-selector.ts +161 -0
  702. package/src/modes/components/segment-track.ts +89 -0
  703. package/src/modes/components/select-list-mouse-routing.ts +35 -0
  704. package/src/modes/components/selector-helpers.ts +129 -0
  705. package/src/modes/components/session-account-selector.ts +62 -0
  706. package/src/modes/components/session-selector.ts +1019 -0
  707. package/src/modes/components/settings-defs.ts +267 -0
  708. package/src/modes/components/settings-selector.ts +1445 -0
  709. package/src/modes/components/show-images-selector.ts +50 -0
  710. package/src/modes/components/skill-message.ts +110 -0
  711. package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
  712. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  713. package/src/modes/components/status-line/component.ts +1516 -0
  714. package/src/modes/components/status-line/context-thresholds.ts +86 -0
  715. package/src/modes/components/status-line/git-utils.ts +42 -0
  716. package/src/modes/components/status-line/index.ts +5 -0
  717. package/src/modes/components/status-line/presets.ts +106 -0
  718. package/src/modes/components/status-line/segments.ts +710 -0
  719. package/src/modes/components/status-line/separators.ts +55 -0
  720. package/src/modes/components/status-line/types.ts +159 -0
  721. package/src/modes/components/theme-selector.ts +68 -0
  722. package/src/modes/components/thinking-selector.ts +57 -0
  723. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  724. package/src/modes/components/tips.txt +26 -0
  725. package/src/modes/components/todo-reminder.ts +43 -0
  726. package/src/modes/components/tool-execution.ts +1356 -0
  727. package/src/modes/components/transcript-container.ts +527 -0
  728. package/src/modes/components/tree-selector.ts +1008 -0
  729. package/src/modes/components/ttsr-notification.ts +123 -0
  730. package/src/modes/components/usage-row.ts +47 -0
  731. package/src/modes/components/user-message-selector.ts +227 -0
  732. package/src/modes/components/user-message.ts +167 -0
  733. package/src/modes/components/visual-truncate.ts +63 -0
  734. package/src/modes/components/welcome.ts +578 -0
  735. package/src/modes/controllers/btw-controller.ts +198 -0
  736. package/src/modes/controllers/command-controller-shared.ts +109 -0
  737. package/src/modes/controllers/command-controller.ts +1993 -0
  738. package/src/modes/controllers/event-controller.ts +1781 -0
  739. package/src/modes/controllers/extension-ui-controller.ts +1242 -0
  740. package/src/modes/controllers/input-controller.ts +2004 -0
  741. package/src/modes/controllers/live-command-controller.ts +260 -0
  742. package/src/modes/controllers/mcp-command-controller.ts +2403 -0
  743. package/src/modes/controllers/omfg-controller.ts +287 -0
  744. package/src/modes/controllers/omfg-rule.ts +647 -0
  745. package/src/modes/controllers/selector-controller.ts +1968 -0
  746. package/src/modes/controllers/session-focus-controller.ts +117 -0
  747. package/src/modes/controllers/ssh-command-controller.ts +385 -0
  748. package/src/modes/controllers/streaming-reveal.ts +399 -0
  749. package/src/modes/controllers/tan-command-controller.ts +229 -0
  750. package/src/modes/controllers/todo-command-controller.ts +487 -0
  751. package/src/modes/controllers/tool-args-reveal.ts +591 -0
  752. package/src/modes/data/emojis.json +1 -0
  753. package/src/modes/emoji-autocomplete.ts +285 -0
  754. package/src/modes/github-ref-autocomplete.ts +75 -0
  755. package/src/modes/gradient-highlight.ts +99 -0
  756. package/src/modes/image-references.ts +137 -0
  757. package/src/modes/index.ts +10 -0
  758. package/src/modes/interactive-mode.ts +4957 -0
  759. package/src/modes/internal-url-autocomplete.ts +158 -0
  760. package/src/modes/loop-limit.ts +192 -0
  761. package/src/modes/magic-keyword-boundary.ts +23 -0
  762. package/src/modes/magic-keywords.ts +42 -0
  763. package/src/modes/markdown-prose.ts +247 -0
  764. package/src/modes/oauth-manual-input.ts +69 -0
  765. package/src/modes/orchestrate.ts +43 -0
  766. package/src/modes/print-mode.ts +265 -0
  767. package/src/modes/prompt-action-autocomplete.ts +322 -0
  768. package/src/modes/queue-input.ts +132 -0
  769. package/src/modes/rpc/host-tools.ts +204 -0
  770. package/src/modes/rpc/host-uris.ts +235 -0
  771. package/src/modes/rpc/rpc-client.ts +1195 -0
  772. package/src/modes/rpc/rpc-frame.ts +316 -0
  773. package/src/modes/rpc/rpc-input.ts +38 -0
  774. package/src/modes/rpc/rpc-messages.ts +127 -0
  775. package/src/modes/rpc/rpc-mode.ts +1504 -0
  776. package/src/modes/rpc/rpc-subagents.ts +265 -0
  777. package/src/modes/rpc/rpc-types.ts +533 -0
  778. package/src/modes/running-subagent-badge.ts +13 -0
  779. package/src/modes/runtime-init.ts +144 -0
  780. package/src/modes/session-observer-registry.ts +218 -0
  781. package/src/modes/session-teardown.ts +82 -0
  782. package/src/modes/setup-version.ts +11 -0
  783. package/src/modes/setup-wizard/index.ts +103 -0
  784. package/src/modes/setup-wizard/lazy.ts +16 -0
  785. package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
  786. package/src/modes/setup-wizard/scenes/model.ts +132 -0
  787. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  788. package/src/modes/setup-wizard/scenes/providers.ts +105 -0
  789. package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
  790. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  791. package/src/modes/setup-wizard/scenes/theme.ts +330 -0
  792. package/src/modes/setup-wizard/scenes/types.ts +65 -0
  793. package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
  794. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  795. package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
  796. package/src/modes/shared.ts +49 -0
  797. package/src/modes/skill-command.ts +91 -0
  798. package/src/modes/theme/dark.json +95 -0
  799. package/src/modes/theme/defaults/alabaster.json +93 -0
  800. package/src/modes/theme/defaults/amethyst.json +96 -0
  801. package/src/modes/theme/defaults/anthracite.json +93 -0
  802. package/src/modes/theme/defaults/basalt.json +91 -0
  803. package/src/modes/theme/defaults/birch.json +95 -0
  804. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  805. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  806. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  807. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  808. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  809. package/src/modes/theme/defaults/dark-copper.json +95 -0
  810. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  811. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  812. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  813. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  814. package/src/modes/theme/defaults/dark-ember.json +95 -0
  815. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  816. package/src/modes/theme/defaults/dark-forest.json +96 -0
  817. package/src/modes/theme/defaults/dark-github.json +105 -0
  818. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  819. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  820. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  821. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  822. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  823. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  824. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  825. package/src/modes/theme/defaults/dark-nord.json +97 -0
  826. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  827. package/src/modes/theme/defaults/dark-one.json +100 -0
  828. package/src/modes/theme/defaults/dark-poimandres.json +143 -0
  829. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  830. package/src/modes/theme/defaults/dark-reef.json +91 -0
  831. package/src/modes/theme/defaults/dark-retro.json +92 -0
  832. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  833. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  834. package/src/modes/theme/defaults/dark-slate.json +95 -0
  835. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  836. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  837. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  838. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  839. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  840. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  841. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  842. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  843. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  844. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  845. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  846. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  847. package/src/modes/theme/defaults/graphite.json +92 -0
  848. package/src/modes/theme/defaults/index.ts +199 -0
  849. package/src/modes/theme/defaults/light-arctic.json +107 -0
  850. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  851. package/src/modes/theme/defaults/light-canyon.json +91 -0
  852. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  853. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  854. package/src/modes/theme/defaults/light-coral.json +95 -0
  855. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  856. package/src/modes/theme/defaults/light-dawn.json +90 -0
  857. package/src/modes/theme/defaults/light-dunes.json +91 -0
  858. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  859. package/src/modes/theme/defaults/light-forest.json +100 -0
  860. package/src/modes/theme/defaults/light-frost.json +95 -0
  861. package/src/modes/theme/defaults/light-github.json +115 -0
  862. package/src/modes/theme/defaults/light-glacier.json +91 -0
  863. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  864. package/src/modes/theme/defaults/light-haze.json +90 -0
  865. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  866. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  867. package/src/modes/theme/defaults/light-lavender.json +95 -0
  868. package/src/modes/theme/defaults/light-meadow.json +91 -0
  869. package/src/modes/theme/defaults/light-mint.json +95 -0
  870. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  871. package/src/modes/theme/defaults/light-ocean.json +99 -0
  872. package/src/modes/theme/defaults/light-one.json +99 -0
  873. package/src/modes/theme/defaults/light-opal.json +91 -0
  874. package/src/modes/theme/defaults/light-orchard.json +91 -0
  875. package/src/modes/theme/defaults/light-paper.json +95 -0
  876. package/src/modes/theme/defaults/light-poimandres.json +143 -0
  877. package/src/modes/theme/defaults/light-prism.json +90 -0
  878. package/src/modes/theme/defaults/light-retro.json +98 -0
  879. package/src/modes/theme/defaults/light-sand.json +95 -0
  880. package/src/modes/theme/defaults/light-savanna.json +91 -0
  881. package/src/modes/theme/defaults/light-solarized.json +102 -0
  882. package/src/modes/theme/defaults/light-soleil.json +90 -0
  883. package/src/modes/theme/defaults/light-sunset.json +99 -0
  884. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  885. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  886. package/src/modes/theme/defaults/light-wetland.json +91 -0
  887. package/src/modes/theme/defaults/light-zenith.json +89 -0
  888. package/src/modes/theme/defaults/limestone.json +94 -0
  889. package/src/modes/theme/defaults/mahogany.json +97 -0
  890. package/src/modes/theme/defaults/marble.json +93 -0
  891. package/src/modes/theme/defaults/obsidian.json +91 -0
  892. package/src/modes/theme/defaults/onyx.json +91 -0
  893. package/src/modes/theme/defaults/pearl.json +93 -0
  894. package/src/modes/theme/defaults/porcelain.json +91 -0
  895. package/src/modes/theme/defaults/quartz.json +96 -0
  896. package/src/modes/theme/defaults/sandstone.json +95 -0
  897. package/src/modes/theme/defaults/titanium.json +90 -0
  898. package/src/modes/theme/light.json +93 -0
  899. package/src/modes/theme/mermaid-cache.ts +92 -0
  900. package/src/modes/theme/shimmer.ts +305 -0
  901. package/src/modes/theme/theme-schema.json +463 -0
  902. package/src/modes/theme/theme.ts +3019 -0
  903. package/src/modes/turn-budget.ts +31 -0
  904. package/src/modes/types.ts +479 -0
  905. package/src/modes/ultrathink.ts +42 -0
  906. package/src/modes/utils/context-usage.ts +518 -0
  907. package/src/modes/utils/copy-targets.ts +378 -0
  908. package/src/modes/utils/hotkeys-markdown.ts +63 -0
  909. package/src/modes/utils/interactive-context-helpers.ts +30 -0
  910. package/src/modes/utils/keybinding-matchers.ts +86 -0
  911. package/src/modes/utils/tools-markdown.ts +31 -0
  912. package/src/modes/utils/transcript-render-helpers.ts +253 -0
  913. package/src/modes/utils/ui-helpers.ts +963 -0
  914. package/src/modes/warp-events.ts +232 -0
  915. package/src/modes/workflow.ts +49 -0
  916. package/src/plan-mode/approved-plan.ts +194 -0
  917. package/src/plan-mode/model-transition.ts +51 -0
  918. package/src/plan-mode/plan-files.ts +40 -0
  919. package/src/plan-mode/plan-handoff.ts +37 -0
  920. package/src/plan-mode/plan-protection.ts +31 -0
  921. package/src/plan-mode/state.ts +6 -0
  922. package/src/priority.json +60 -0
  923. package/src/prompts/advisor/active-repo-watchdog.md +6 -0
  924. package/src/prompts/advisor/advise-tool.md +3 -0
  925. package/src/prompts/advisor/context-files.md +8 -0
  926. package/src/prompts/advisor/system.md +98 -0
  927. package/src/prompts/agents/designer.md +74 -0
  928. package/src/prompts/agents/frontmatter.md +12 -0
  929. package/src/prompts/agents/init.md +33 -0
  930. package/src/prompts/agents/librarian.md +119 -0
  931. package/src/prompts/agents/reviewer.md +139 -0
  932. package/src/prompts/agents/scout.md +58 -0
  933. package/src/prompts/agents/task.md +17 -0
  934. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  935. package/src/prompts/bench/cache-prefix.md +3 -0
  936. package/src/prompts/bench/cache-suffix.md +1 -0
  937. package/src/prompts/bench.md +6 -0
  938. package/src/prompts/ci-green-request.md +36 -0
  939. package/src/prompts/dry-balance-bench.md +8 -0
  940. package/src/prompts/goals/goal-budget-limit.md +16 -0
  941. package/src/prompts/goals/goal-continuation.md +28 -0
  942. package/src/prompts/goals/goal-mode-active.md +23 -0
  943. package/src/prompts/goals/goal-mode-context.md +4 -0
  944. package/src/prompts/goals/goal-todo-context.md +12 -0
  945. package/src/prompts/goals/guided-goal-interview.md +43 -0
  946. package/src/prompts/memories/consolidation.md +30 -0
  947. package/src/prompts/memories/consolidation_system.md +4 -0
  948. package/src/prompts/memories/read-path.md +17 -0
  949. package/src/prompts/memories/stage_one_input.md +6 -0
  950. package/src/prompts/memories/stage_one_system.md +21 -0
  951. package/src/prompts/review-custom-request.md +21 -0
  952. package/src/prompts/review-headless-request.md +16 -0
  953. package/src/prompts/review-request.md +68 -0
  954. package/src/prompts/skills/autoload.md +8 -0
  955. package/src/prompts/skills/user-invocation.md +11 -0
  956. package/src/prompts/steering/parent-irc.md +5 -0
  957. package/src/prompts/steering/user-interjection.md +6 -0
  958. package/src/prompts/system/active-repo-context.md +4 -0
  959. package/src/prompts/system/agent-creation-architect.md +50 -0
  960. package/src/prompts/system/agent-creation-user.md +6 -0
  961. package/src/prompts/system/auto-continue.md +1 -0
  962. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  963. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  964. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  965. package/src/prompts/system/autolearn-guidance.md +7 -0
  966. package/src/prompts/system/autolearn-nudge-autocontinue.md +5 -0
  967. package/src/prompts/system/background-tan-dispatch.md +8 -0
  968. package/src/prompts/system/btw-user.md +8 -0
  969. package/src/prompts/system/commit-message-system.md +14 -0
  970. package/src/prompts/system/computer-safety.md +14 -0
  971. package/src/prompts/system/custom-system-prompt.md +64 -0
  972. package/src/prompts/system/eager-task.md +7 -0
  973. package/src/prompts/system/eager-todo.md +18 -0
  974. package/src/prompts/system/empty-stop-retry.md +4 -0
  975. package/src/prompts/system/gemini-tool-call-reminder.md +9 -0
  976. package/src/prompts/system/interrupted-thinking.md +7 -0
  977. package/src/prompts/system/irc-autoreply.md +6 -0
  978. package/src/prompts/system/irc-incoming.md +9 -0
  979. package/src/prompts/system/manual-continue.md +7 -0
  980. package/src/prompts/system/mcp-xdev-guidance.md +11 -0
  981. package/src/prompts/system/memory-consolidation-system.md +8 -0
  982. package/src/prompts/system/memory-extraction-system.md +26 -0
  983. package/src/prompts/system/mid-run-todo-nudge.md +3 -0
  984. package/src/prompts/system/omfg-user.md +50 -0
  985. package/src/prompts/system/orchestrate-notice.md +40 -0
  986. package/src/prompts/system/personalities/default.md +18 -0
  987. package/src/prompts/system/personalities/friendly.md +17 -0
  988. package/src/prompts/system/personalities/pragmatic.md +15 -0
  989. package/src/prompts/system/plan-mode-active.md +125 -0
  990. package/src/prompts/system/plan-mode-approved.md +22 -0
  991. package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
  992. package/src/prompts/system/plan-mode-reference.md +10 -0
  993. package/src/prompts/system/plan-mode-subagent.md +33 -0
  994. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  995. package/src/prompts/system/plan-yolo-handoff.md +5 -0
  996. package/src/prompts/system/prewalk-checklist.md +7 -0
  997. package/src/prompts/system/prewalk-continue.md +1 -0
  998. package/src/prompts/system/prewalk-plan.md +13 -0
  999. package/src/prompts/system/project-prompt.md +61 -0
  1000. package/src/prompts/system/recap-user.md +9 -0
  1001. package/src/prompts/system/resolve-device-reminder.md +3 -0
  1002. package/src/prompts/system/rewind-report.md +6 -0
  1003. package/src/prompts/system/side-channel-no-tools.md +3 -0
  1004. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  1005. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  1006. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  1007. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  1008. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  1009. package/src/prompts/system/speech-rewrite.md +15 -0
  1010. package/src/prompts/system/subagent-async-pending.md +6 -0
  1011. package/src/prompts/system/subagent-system-prompt.md +73 -0
  1012. package/src/prompts/system/subagent-user-prompt.md +3 -0
  1013. package/src/prompts/system/subagent-yield-reminder.md +23 -0
  1014. package/src/prompts/system/system-prompt.md +283 -0
  1015. package/src/prompts/system/tan-context-switch.md +17 -0
  1016. package/src/prompts/system/task-label.md +23 -0
  1017. package/src/prompts/system/thinking-loop-redirect.md +10 -0
  1018. package/src/prompts/system/title-marker-instruction.md +1 -0
  1019. package/src/prompts/system/title-system.md +16 -0
  1020. package/src/prompts/system/tool-call-loop-redirect.md +8 -0
  1021. package/src/prompts/system/ttsr-interrupt.md +7 -0
  1022. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  1023. package/src/prompts/system/ultrathink-notice.md +3 -0
  1024. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  1025. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  1026. package/src/prompts/system/vibe-mode-active.md +26 -0
  1027. package/src/prompts/system/web-search.md +25 -0
  1028. package/src/prompts/system/workflow-notice.md +112 -0
  1029. package/src/prompts/system/xdev-mount-notice.md +20 -0
  1030. package/src/prompts/tools/apply-patch.md +65 -0
  1031. package/src/prompts/tools/ask.md +22 -0
  1032. package/src/prompts/tools/ast-edit.md +11 -0
  1033. package/src/prompts/tools/ast-grep.md +19 -0
  1034. package/src/prompts/tools/async-result.md +8 -0
  1035. package/src/prompts/tools/bash.md +25 -0
  1036. package/src/prompts/tools/browser.md +28 -0
  1037. package/src/prompts/tools/checkpoint.md +15 -0
  1038. package/src/prompts/tools/computer.md +26 -0
  1039. package/src/prompts/tools/debug.md +3 -0
  1040. package/src/prompts/tools/eval.md +45 -0
  1041. package/src/prompts/tools/github.md +22 -0
  1042. package/src/prompts/tools/glob.md +15 -0
  1043. package/src/prompts/tools/goal.md +11 -0
  1044. package/src/prompts/tools/grep.md +12 -0
  1045. package/src/prompts/tools/hub.md +34 -0
  1046. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  1047. package/src/prompts/tools/image-attachment-describe.md +10 -0
  1048. package/src/prompts/tools/image-gen.md +7 -0
  1049. package/src/prompts/tools/inspect-image-system.md +20 -0
  1050. package/src/prompts/tools/inspect-image.md +22 -0
  1051. package/src/prompts/tools/learn.md +7 -0
  1052. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  1053. package/src/prompts/tools/lsp.md +19 -0
  1054. package/src/prompts/tools/manage-skill.md +9 -0
  1055. package/src/prompts/tools/memory-edit.md +12 -0
  1056. package/src/prompts/tools/patch.md +57 -0
  1057. package/src/prompts/tools/read.md +27 -0
  1058. package/src/prompts/tools/recall.md +7 -0
  1059. package/src/prompts/tools/reflect.md +5 -0
  1060. package/src/prompts/tools/replace.md +29 -0
  1061. package/src/prompts/tools/retain.md +6 -0
  1062. package/src/prompts/tools/rewind.md +14 -0
  1063. package/src/prompts/tools/task-async-contract.md +1 -0
  1064. package/src/prompts/tools/task-summary.md +20 -0
  1065. package/src/prompts/tools/task.md +83 -0
  1066. package/src/prompts/tools/todo.md +42 -0
  1067. package/src/prompts/tools/vibe-kill.md +3 -0
  1068. package/src/prompts/tools/vibe-list.md +3 -0
  1069. package/src/prompts/tools/vibe-send.md +9 -0
  1070. package/src/prompts/tools/vibe-spawn.md +10 -0
  1071. package/src/prompts/tools/vibe-turn-result.md +19 -0
  1072. package/src/prompts/tools/vibe-wait.md +8 -0
  1073. package/src/prompts/tools/web-search.md +8 -0
  1074. package/src/prompts/tools/write.md +14 -0
  1075. package/src/registry/agent-lifecycle.ts +455 -0
  1076. package/src/registry/agent-registry.ts +217 -0
  1077. package/src/registry/persisted-agents.ts +98 -0
  1078. package/src/sdk.ts +3553 -0
  1079. package/src/secrets/index.ts +246 -0
  1080. package/src/secrets/obfuscator.ts +2574 -0
  1081. package/src/secrets/regex.ts +21 -0
  1082. package/src/session/acp-permission-gate.ts +165 -0
  1083. package/src/session/agent-session-events.ts +66 -0
  1084. package/src/session/agent-session-types.ts +346 -0
  1085. package/src/session/agent-session.ts +8406 -0
  1086. package/src/session/agent-storage.ts +805 -0
  1087. package/src/session/artifacts.ts +154 -0
  1088. package/src/session/async-job-delivery.ts +82 -0
  1089. package/src/session/auth-broker-config.ts +92 -0
  1090. package/src/session/auth-storage.ts +25 -0
  1091. package/src/session/bash-runner.ts +326 -0
  1092. package/src/session/blob-store.ts +295 -0
  1093. package/src/session/checkpoint-entries.ts +81 -0
  1094. package/src/session/client-bridge.ts +85 -0
  1095. package/src/session/codex-auto-reset.ts +202 -0
  1096. package/src/session/compact-modes.ts +105 -0
  1097. package/src/session/eval-runner.ts +217 -0
  1098. package/src/session/exit-diagnostics.ts +310 -0
  1099. package/src/session/history-storage.ts +327 -0
  1100. package/src/session/indexed-session-storage.ts +544 -0
  1101. package/src/session/irc-bridge.ts +203 -0
  1102. package/src/session/messages.ts +1280 -0
  1103. package/src/session/model-controls.ts +750 -0
  1104. package/src/session/prewalk.ts +257 -0
  1105. package/src/session/provider-image-budget.ts +86 -0
  1106. package/src/session/queued-messages.ts +99 -0
  1107. package/src/session/redis-session-storage.ts +257 -0
  1108. package/src/session/retry-fallback-chains.ts +455 -0
  1109. package/src/session/role-models.ts +85 -0
  1110. package/src/session/session-advisors.ts +1754 -0
  1111. package/src/session/session-context.ts +554 -0
  1112. package/src/session/session-dump-format.ts +216 -0
  1113. package/src/session/session-entries.ts +260 -0
  1114. package/src/session/session-handoff.ts +308 -0
  1115. package/src/session/session-history-format.ts +459 -0
  1116. package/src/session/session-listing.ts +715 -0
  1117. package/src/session/session-loader.ts +280 -0
  1118. package/src/session/session-maintenance.ts +2983 -0
  1119. package/src/session/session-manager.ts +2557 -0
  1120. package/src/session/session-memory.ts +222 -0
  1121. package/src/session/session-metadata.ts +53 -0
  1122. package/src/session/session-migrations.ts +78 -0
  1123. package/src/session/session-paths.ts +222 -0
  1124. package/src/session/session-persistence.ts +293 -0
  1125. package/src/session/session-provider-boundary.ts +306 -0
  1126. package/src/session/session-stats.ts +293 -0
  1127. package/src/session/session-storage.ts +734 -0
  1128. package/src/session/session-title-slot.ts +141 -0
  1129. package/src/session/session-tools.ts +1226 -0
  1130. package/src/session/session-workspace.ts +53 -0
  1131. package/src/session/settings-stream-fn.ts +74 -0
  1132. package/src/session/shake-types.ts +43 -0
  1133. package/src/session/snapcompact-inline.ts +545 -0
  1134. package/src/session/snapcompact-savings-journal.ts +113 -0
  1135. package/src/session/sql-session-storage.ts +374 -0
  1136. package/src/session/stream-guards.ts +417 -0
  1137. package/src/session/streaming-output.ts +1459 -0
  1138. package/src/session/todo-tracker.ts +380 -0
  1139. package/src/session/tool-choice-queue.ts +305 -0
  1140. package/src/session/ttsr-coordinator.ts +496 -0
  1141. package/src/session/turn-persistence.ts +142 -0
  1142. package/src/session/turn-recovery.ts +1728 -0
  1143. package/src/session/unexpected-stop-classifier.ts +132 -0
  1144. package/src/session/yield-queue.ts +183 -0
  1145. package/src/slash-commands/acp-builtins.ts +70 -0
  1146. package/src/slash-commands/available-commands.ts +105 -0
  1147. package/src/slash-commands/builtin-registry.ts +2982 -0
  1148. package/src/slash-commands/helpers/active-oauth-account.ts +80 -0
  1149. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  1150. package/src/slash-commands/helpers/context-report.ts +66 -0
  1151. package/src/slash-commands/helpers/format.ts +46 -0
  1152. package/src/slash-commands/helpers/logout.ts +108 -0
  1153. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  1154. package/src/slash-commands/helpers/mcp.ts +533 -0
  1155. package/src/slash-commands/helpers/parse.ts +85 -0
  1156. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  1157. package/src/slash-commands/helpers/session-pin.ts +44 -0
  1158. package/src/slash-commands/helpers/ssh.ts +196 -0
  1159. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  1160. package/src/slash-commands/helpers/todo.ts +285 -0
  1161. package/src/slash-commands/helpers/usage-report.ts +198 -0
  1162. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1163. package/src/slash-commands/types.ts +139 -0
  1164. package/src/ssh/config-writer.ts +183 -0
  1165. package/src/ssh/connection-manager.ts +667 -0
  1166. package/src/ssh/file-transfer.ts +214 -0
  1167. package/src/ssh/sshfs-mount.ts +163 -0
  1168. package/src/ssh/utils.ts +51 -0
  1169. package/src/startup-splash.ts +19 -0
  1170. package/src/stt/asr-client.ts +401 -0
  1171. package/src/stt/asr-protocol.ts +65 -0
  1172. package/src/stt/asr-worker.ts +603 -0
  1173. package/src/stt/downloader.ts +142 -0
  1174. package/src/stt/endpointer.ts +259 -0
  1175. package/src/stt/index.ts +6 -0
  1176. package/src/stt/models.ts +150 -0
  1177. package/src/stt/sherpa-runtime.ts +71 -0
  1178. package/src/stt/stt-controller.ts +320 -0
  1179. package/src/stt/submit-trigger.ts +74 -0
  1180. package/src/subprocess/worker-client.ts +463 -0
  1181. package/src/subprocess/worker-runtime.ts +494 -0
  1182. package/src/system-prompt.ts +894 -0
  1183. package/src/task/agents.ts +168 -0
  1184. package/src/task/commands.ts +132 -0
  1185. package/src/task/discovery.ts +145 -0
  1186. package/src/task/executor.ts +3129 -0
  1187. package/src/task/index.ts +1519 -0
  1188. package/src/task/isolation-ownership.ts +106 -0
  1189. package/src/task/isolation-runner.ts +413 -0
  1190. package/src/task/label.ts +40 -0
  1191. package/src/task/name-generator.ts +1577 -0
  1192. package/src/task/omp-command.ts +26 -0
  1193. package/src/task/output-manager.ts +115 -0
  1194. package/src/task/parallel.ts +221 -0
  1195. package/src/task/persisted-revive.ts +141 -0
  1196. package/src/task/prewalk.ts +6 -0
  1197. package/src/task/prompt-policy.ts +8 -0
  1198. package/src/task/provider-concurrency.ts +100 -0
  1199. package/src/task/render.ts +1814 -0
  1200. package/src/task/renderer.ts +14 -0
  1201. package/src/task/repair-args.ts +118 -0
  1202. package/src/task/spawn-policy.ts +58 -0
  1203. package/src/task/structured-subagent.ts +649 -0
  1204. package/src/task/subprocess-tool-registry.ts +88 -0
  1205. package/src/task/types.ts +551 -0
  1206. package/src/task/worktree.ts +967 -0
  1207. package/src/task/yield-assembly.ts +198 -0
  1208. package/src/telemetry-export.ts +500 -0
  1209. package/src/thinking.ts +364 -0
  1210. package/src/tiny/device.ts +111 -0
  1211. package/src/tiny/dtype.ts +101 -0
  1212. package/src/tiny/message-preproc.ts +155 -0
  1213. package/src/tiny/models.ts +268 -0
  1214. package/src/tiny/text.ts +278 -0
  1215. package/src/tiny/title-client.ts +460 -0
  1216. package/src/tiny/title-protocol.ts +56 -0
  1217. package/src/tiny/worker.ts +354 -0
  1218. package/src/tools/acp-bridge.ts +81 -0
  1219. package/src/tools/approval.ts +245 -0
  1220. package/src/tools/ask.ts +1459 -0
  1221. package/src/tools/ast-edit.ts +718 -0
  1222. package/src/tools/ast-grep.ts +520 -0
  1223. package/src/tools/auto-generated-guard.ts +335 -0
  1224. package/src/tools/bash-interactive.ts +435 -0
  1225. package/src/tools/bash-interceptor.ts +67 -0
  1226. package/src/tools/bash-pty-selection.ts +14 -0
  1227. package/src/tools/bash-skill-urls.ts +335 -0
  1228. package/src/tools/bash.ts +1762 -0
  1229. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  1230. package/src/tools/browser/aria/aria-snapshot.ts +131 -0
  1231. package/src/tools/browser/attach.ts +194 -0
  1232. package/src/tools/browser/cmux/cmux-tab.ts +1400 -0
  1233. package/src/tools/browser/cmux/rpc.ts +206 -0
  1234. package/src/tools/browser/cmux/socket-client.ts +445 -0
  1235. package/src/tools/browser/launch.ts +788 -0
  1236. package/src/tools/browser/readable.ts +112 -0
  1237. package/src/tools/browser/registry.ts +287 -0
  1238. package/src/tools/browser/render.ts +226 -0
  1239. package/src/tools/browser/run-cancellation.ts +131 -0
  1240. package/src/tools/browser/run-output.ts +76 -0
  1241. package/src/tools/browser/tab-protocol.ts +115 -0
  1242. package/src/tools/browser/tab-supervisor.ts +1040 -0
  1243. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1244. package/src/tools/browser/tab-worker.ts +1842 -0
  1245. package/src/tools/browser.ts +457 -0
  1246. package/src/tools/builtin-names.ts +66 -0
  1247. package/src/tools/checkpoint.ts +150 -0
  1248. package/src/tools/computer/exposure.ts +38 -0
  1249. package/src/tools/computer/protocol.ts +28 -0
  1250. package/src/tools/computer/supervisor.ts +306 -0
  1251. package/src/tools/computer/worker-entry.ts +34 -0
  1252. package/src/tools/computer/worker.ts +131 -0
  1253. package/src/tools/computer-renderer.ts +108 -0
  1254. package/src/tools/computer.ts +516 -0
  1255. package/src/tools/conflict-detect.ts +815 -0
  1256. package/src/tools/context.ts +46 -0
  1257. package/src/tools/debug.ts +1121 -0
  1258. package/src/tools/default-renderer.ts +139 -0
  1259. package/src/tools/essential-tools.ts +46 -0
  1260. package/src/tools/eval-backends.ts +34 -0
  1261. package/src/tools/eval-format/index.ts +24 -0
  1262. package/src/tools/eval-format/javascript.ts +952 -0
  1263. package/src/tools/eval-format/julia.ts +446 -0
  1264. package/src/tools/eval-format/python.ts +544 -0
  1265. package/src/tools/eval-format/ruby.ts +380 -0
  1266. package/src/tools/eval-render.ts +784 -0
  1267. package/src/tools/eval.ts +774 -0
  1268. package/src/tools/fetch.ts +1889 -0
  1269. package/src/tools/file-recorder.ts +35 -0
  1270. package/src/tools/fs-cache-invalidation.ts +28 -0
  1271. package/src/tools/gh-cache-invalidation.ts +175 -0
  1272. package/src/tools/gh-format.ts +12 -0
  1273. package/src/tools/gh-renderer.ts +484 -0
  1274. package/src/tools/gh.ts +3959 -0
  1275. package/src/tools/github-cache.ts +663 -0
  1276. package/src/tools/glob.ts +682 -0
  1277. package/src/tools/grep.ts +1858 -0
  1278. package/src/tools/grouped-file-output.ts +210 -0
  1279. package/src/tools/hub/index.ts +579 -0
  1280. package/src/tools/hub/jobs.ts +714 -0
  1281. package/src/tools/hub/launch.ts +579 -0
  1282. package/src/tools/hub/messaging.ts +735 -0
  1283. package/src/tools/hub/types.ts +117 -0
  1284. package/src/tools/image-gen.ts +1689 -0
  1285. package/src/tools/image-providers.ts +50 -0
  1286. package/src/tools/index.ts +691 -0
  1287. package/src/tools/inspect-image-renderer.ts +133 -0
  1288. package/src/tools/inspect-image.ts +290 -0
  1289. package/src/tools/json-tree.ts +260 -0
  1290. package/src/tools/jtd-to-json-schema.ts +219 -0
  1291. package/src/tools/jtd-to-typescript.ts +136 -0
  1292. package/src/tools/jtd-utils.ts +102 -0
  1293. package/src/tools/learn.ts +141 -0
  1294. package/src/tools/list-limit.ts +40 -0
  1295. package/src/tools/manage-skill.ts +102 -0
  1296. package/src/tools/match-line-format.ts +20 -0
  1297. package/src/tools/memory-edit.ts +61 -0
  1298. package/src/tools/memory-recall.ts +102 -0
  1299. package/src/tools/memory-reflect.ts +88 -0
  1300. package/src/tools/memory-render.ts +211 -0
  1301. package/src/tools/memory-retain.ts +89 -0
  1302. package/src/tools/output-meta.ts +845 -0
  1303. package/src/tools/output-schema-validator.ts +307 -0
  1304. package/src/tools/path-utils.ts +1381 -0
  1305. package/src/tools/plan-mode-guard.ts +155 -0
  1306. package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
  1307. package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
  1308. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
  1309. package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
  1310. package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
  1311. package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
  1312. package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
  1313. package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
  1314. package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
  1315. package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
  1316. package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
  1317. package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
  1318. package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
  1319. package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
  1320. package/src/tools/read.ts +3742 -0
  1321. package/src/tools/render-utils.ts +924 -0
  1322. package/src/tools/renderers.ts +133 -0
  1323. package/src/tools/report-tool-issue.ts +568 -0
  1324. package/src/tools/resolve.ts +423 -0
  1325. package/src/tools/review.ts +103 -0
  1326. package/src/tools/shell-tokenize.ts +83 -0
  1327. package/src/tools/sqlite-reader.ts +884 -0
  1328. package/src/tools/terminal-output.ts +141 -0
  1329. package/src/tools/todo.ts +1226 -0
  1330. package/src/tools/tool-errors.ts +62 -0
  1331. package/src/tools/tool-result.ts +102 -0
  1332. package/src/tools/tool-timeouts.ts +37 -0
  1333. package/src/tools/tts.ts +266 -0
  1334. package/src/tools/vibe.ts +607 -0
  1335. package/src/tools/write.ts +1640 -0
  1336. package/src/tools/xdev.ts +508 -0
  1337. package/src/tools/yield.ts +486 -0
  1338. package/src/tts/downloader.ts +64 -0
  1339. package/src/tts/index.ts +10 -0
  1340. package/src/tts/models.ts +137 -0
  1341. package/src/tts/runtime.ts +21 -0
  1342. package/src/tts/speakable.ts +392 -0
  1343. package/src/tts/speech-enhancer.ts +206 -0
  1344. package/src/tts/streaming-player.ts +120 -0
  1345. package/src/tts/tts-client.ts +475 -0
  1346. package/src/tts/tts-protocol.ts +69 -0
  1347. package/src/tts/tts-worker.ts +434 -0
  1348. package/src/tts/vocalizer.ts +419 -0
  1349. package/src/tts/wav.ts +58 -0
  1350. package/src/tui/code-cell.ts +268 -0
  1351. package/src/tui/file-list.ts +55 -0
  1352. package/src/tui/hyperlink.ts +178 -0
  1353. package/src/tui/index.ts +13 -0
  1354. package/src/tui/output-block.ts +268 -0
  1355. package/src/tui/status-line.ts +54 -0
  1356. package/src/tui/tree-list.ts +172 -0
  1357. package/src/tui/types.ts +15 -0
  1358. package/src/tui/utils.ts +103 -0
  1359. package/src/tui/width-aware-text.ts +58 -0
  1360. package/src/utils/active-repo-context.ts +143 -0
  1361. package/src/utils/block-context.ts +312 -0
  1362. package/src/utils/changelog.ts +232 -0
  1363. package/src/utils/clipboard.ts +327 -0
  1364. package/src/utils/command-args.ts +76 -0
  1365. package/src/utils/commit-message-generator.ts +148 -0
  1366. package/src/utils/cpuprofile.ts +235 -0
  1367. package/src/utils/edit-mode.ts +61 -0
  1368. package/src/utils/enhanced-paste.ts +230 -0
  1369. package/src/utils/event-bus.ts +33 -0
  1370. package/src/utils/external-editor.ts +78 -0
  1371. package/src/utils/fetch-timeout.ts +10 -0
  1372. package/src/utils/file-display-mode.ts +44 -0
  1373. package/src/utils/file-mentions.ts +293 -0
  1374. package/src/utils/git.ts +2425 -0
  1375. package/src/utils/image-loading.ts +231 -0
  1376. package/src/utils/image-resize.ts +420 -0
  1377. package/src/utils/image-vision-fallback.ts +196 -0
  1378. package/src/utils/inspect-image-mode.ts +39 -0
  1379. package/src/utils/ipc.ts +38 -0
  1380. package/src/utils/jj.ts +416 -0
  1381. package/src/utils/lang-from-path.ts +251 -0
  1382. package/src/utils/local-date.ts +7 -0
  1383. package/src/utils/mac-file-urls.applescript +37 -0
  1384. package/src/utils/markit-cache.ts +166 -0
  1385. package/src/utils/markit.ts +223 -0
  1386. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1387. package/src/utils/open.ts +126 -0
  1388. package/src/utils/profile-tree.ts +111 -0
  1389. package/src/utils/prompt-path.ts +3 -0
  1390. package/src/utils/qrcode.ts +535 -0
  1391. package/src/utils/sample-profile.ts +437 -0
  1392. package/src/utils/session-color.ts +142 -0
  1393. package/src/utils/shell-snapshot-fn-env.sh +63 -0
  1394. package/src/utils/shell-snapshot.ts +316 -0
  1395. package/src/utils/sixel.ts +69 -0
  1396. package/src/utils/thinking-display.ts +163 -0
  1397. package/src/utils/title-generator.ts +597 -0
  1398. package/src/utils/token-rate.ts +72 -0
  1399. package/src/utils/tool-choice.ts +63 -0
  1400. package/src/utils/tools-manager.ts +411 -0
  1401. package/src/utils/turndown.ts +83 -0
  1402. package/src/utils/zip.ts +1106 -0
  1403. package/src/vibe/runtime.ts +1540 -0
  1404. package/src/vibe/state.ts +4 -0
  1405. package/src/web/kagi.ts +304 -0
  1406. package/src/web/parallel.ts +354 -0
  1407. package/src/web/scrapers/artifacthub.ts +207 -0
  1408. package/src/web/scrapers/arxiv.ts +83 -0
  1409. package/src/web/scrapers/aur.ts +162 -0
  1410. package/src/web/scrapers/biorxiv.ts +133 -0
  1411. package/src/web/scrapers/bluesky.ts +262 -0
  1412. package/src/web/scrapers/brew.ts +172 -0
  1413. package/src/web/scrapers/cheatsh.ts +68 -0
  1414. package/src/web/scrapers/chocolatey.ts +196 -0
  1415. package/src/web/scrapers/choosealicense.ts +95 -0
  1416. package/src/web/scrapers/cisa-kev.ts +87 -0
  1417. package/src/web/scrapers/clojars.ts +154 -0
  1418. package/src/web/scrapers/coingecko.ts +177 -0
  1419. package/src/web/scrapers/crates-io.ts +97 -0
  1420. package/src/web/scrapers/crossref.ts +136 -0
  1421. package/src/web/scrapers/devto.ts +147 -0
  1422. package/src/web/scrapers/discogs.ts +306 -0
  1423. package/src/web/scrapers/discourse.ts +197 -0
  1424. package/src/web/scrapers/dockerhub.ts +138 -0
  1425. package/src/web/scrapers/docs-rs.ts +663 -0
  1426. package/src/web/scrapers/fdroid.ts +134 -0
  1427. package/src/web/scrapers/firefox-addons.ts +191 -0
  1428. package/src/web/scrapers/flathub.ts +223 -0
  1429. package/src/web/scrapers/github-gist.ts +58 -0
  1430. package/src/web/scrapers/github.ts +800 -0
  1431. package/src/web/scrapers/gitlab.ts +401 -0
  1432. package/src/web/scrapers/go-pkg.ts +266 -0
  1433. package/src/web/scrapers/hackage.ts +140 -0
  1434. package/src/web/scrapers/hackernews.ts +189 -0
  1435. package/src/web/scrapers/hex.ts +105 -0
  1436. package/src/web/scrapers/huggingface.ts +321 -0
  1437. package/src/web/scrapers/iacr.ts +89 -0
  1438. package/src/web/scrapers/index.ts +252 -0
  1439. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1440. package/src/web/scrapers/lemmy.ts +203 -0
  1441. package/src/web/scrapers/lobsters.ts +175 -0
  1442. package/src/web/scrapers/mastodon.ts +292 -0
  1443. package/src/web/scrapers/maven.ts +138 -0
  1444. package/src/web/scrapers/mdn.ts +173 -0
  1445. package/src/web/scrapers/metacpan.ts +222 -0
  1446. package/src/web/scrapers/musicbrainz.ts +250 -0
  1447. package/src/web/scrapers/npm.ts +98 -0
  1448. package/src/web/scrapers/nuget.ts +183 -0
  1449. package/src/web/scrapers/nvd.ts +222 -0
  1450. package/src/web/scrapers/ollama.ts +239 -0
  1451. package/src/web/scrapers/open-vsx.ts +106 -0
  1452. package/src/web/scrapers/opencorporates.ts +292 -0
  1453. package/src/web/scrapers/openlibrary.ts +336 -0
  1454. package/src/web/scrapers/orcid.ts +286 -0
  1455. package/src/web/scrapers/osv.ts +176 -0
  1456. package/src/web/scrapers/packagist.ts +160 -0
  1457. package/src/web/scrapers/pub-dev.ts +143 -0
  1458. package/src/web/scrapers/pubmed.ts +211 -0
  1459. package/src/web/scrapers/pypi.ts +112 -0
  1460. package/src/web/scrapers/rawg.ts +110 -0
  1461. package/src/web/scrapers/readthedocs.ts +120 -0
  1462. package/src/web/scrapers/reddit.ts +95 -0
  1463. package/src/web/scrapers/repology.ts +251 -0
  1464. package/src/web/scrapers/rfc.ts +201 -0
  1465. package/src/web/scrapers/rubygems.ts +103 -0
  1466. package/src/web/scrapers/searchcode.ts +189 -0
  1467. package/src/web/scrapers/sec-edgar.ts +261 -0
  1468. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1469. package/src/web/scrapers/snapcraft.ts +187 -0
  1470. package/src/web/scrapers/sourcegraph.ts +336 -0
  1471. package/src/web/scrapers/spdx.ts +108 -0
  1472. package/src/web/scrapers/spotify.ts +198 -0
  1473. package/src/web/scrapers/stackoverflow.ts +120 -0
  1474. package/src/web/scrapers/terraform.ts +277 -0
  1475. package/src/web/scrapers/tldr.ts +47 -0
  1476. package/src/web/scrapers/twitter.ts +94 -0
  1477. package/src/web/scrapers/types.ts +354 -0
  1478. package/src/web/scrapers/utils.ts +109 -0
  1479. package/src/web/scrapers/vimeo.ts +133 -0
  1480. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1481. package/src/web/scrapers/w3c.ts +156 -0
  1482. package/src/web/scrapers/wikidata.ts +344 -0
  1483. package/src/web/scrapers/wikipedia.ts +84 -0
  1484. package/src/web/scrapers/youtube.ts +325 -0
  1485. package/src/web/search/index.ts +376 -0
  1486. package/src/web/search/provider.ts +272 -0
  1487. package/src/web/search/providers/anthropic.ts +401 -0
  1488. package/src/web/search/providers/base.ts +110 -0
  1489. package/src/web/search/providers/brave.ts +179 -0
  1490. package/src/web/search/providers/browser-headers.ts +109 -0
  1491. package/src/web/search/providers/browser-page.ts +123 -0
  1492. package/src/web/search/providers/codex.ts +749 -0
  1493. package/src/web/search/providers/duckduckgo.ts +213 -0
  1494. package/src/web/search/providers/ecosia.ts +182 -0
  1495. package/src/web/search/providers/exa.ts +511 -0
  1496. package/src/web/search/providers/firecrawl.ts +211 -0
  1497. package/src/web/search/providers/gemini.ts +628 -0
  1498. package/src/web/search/providers/google.ts +194 -0
  1499. package/src/web/search/providers/jina.ts +134 -0
  1500. package/src/web/search/providers/kagi.ts +95 -0
  1501. package/src/web/search/providers/kimi.ts +217 -0
  1502. package/src/web/search/providers/mojeek.ts +219 -0
  1503. package/src/web/search/providers/parallel.ts +182 -0
  1504. package/src/web/search/providers/perplexity-auth.ts +142 -0
  1505. package/src/web/search/providers/perplexity.ts +994 -0
  1506. package/src/web/search/providers/public.ts +199 -0
  1507. package/src/web/search/providers/searxng.ts +461 -0
  1508. package/src/web/search/providers/startpage.ts +219 -0
  1509. package/src/web/search/providers/synthetic.ts +120 -0
  1510. package/src/web/search/providers/tavily.ts +242 -0
  1511. package/src/web/search/providers/tinyfish.ts +164 -0
  1512. package/src/web/search/providers/utils.ts +128 -0
  1513. package/src/web/search/providers/xai.ts +372 -0
  1514. package/src/web/search/providers/zai.ts +437 -0
  1515. package/src/web/search/query.ts +850 -0
  1516. package/src/web/search/render.ts +262 -0
  1517. package/src/web/search/types.ts +507 -0
  1518. package/src/web/search/utils.ts +17 -0
  1519. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1754 @@
1
+ import {
2
+ Agent,
3
+ type AgentMessage,
4
+ type AgentTool,
5
+ AppendOnlyContextManager,
6
+ type CompactionSummaryMessage,
7
+ countTokens,
8
+ resolveTelemetry,
9
+ type StreamFn,
10
+ ThinkingLevel,
11
+ } from "@oh-my-pi/pi-agent-core";
12
+ import {
13
+ type CompactionResult,
14
+ calculateContextTokens,
15
+ compact,
16
+ compactionContextTokens,
17
+ createCompactionSummaryMessage,
18
+ estimateTokens,
19
+ prepareCompaction,
20
+ type SessionMessageEntry,
21
+ shouldCompact,
22
+ } from "@oh-my-pi/pi-agent-core/compaction";
23
+ import type {
24
+ AssistantMessage,
25
+ CodexCompactionContext,
26
+ Context,
27
+ Message,
28
+ Model,
29
+ ProviderSessionState,
30
+ ServiceTier,
31
+ SimpleStreamOptions,
32
+ } from "@oh-my-pi/pi-ai";
33
+ import { isUsageLimitOutcome, resolveModelServiceTier, streamSimple } from "@oh-my-pi/pi-ai";
34
+ import * as AIError from "@oh-my-pi/pi-ai/error";
35
+ import { modelsAreEqual } from "@oh-my-pi/pi-catalog/models";
36
+ import { extractHttpStatusFromError, extractRetryHint, logger } from "@oh-my-pi/pi-utils";
37
+ import {
38
+ ADVISOR_DEFAULT_TOOL_NAMES,
39
+ AdviseTool,
40
+ type AdvisorAgent,
41
+ type AdvisorConfig,
42
+ AdvisorEmissionGuard,
43
+ type AdvisorMessageDetails,
44
+ type AdvisorNote,
45
+ AdvisorOutputQuarantinedError,
46
+ AdvisorRuntime,
47
+ type AdvisorRuntimeStatus,
48
+ type AdvisorSeverity,
49
+ AdvisorTranscriptRecorder,
50
+ advisorTranscriptFilename,
51
+ buildAdvisorQuarantineSourceText,
52
+ formatAdvisorBatchContent,
53
+ getOrCreateAdvisorProviderSessionId,
54
+ isAdvisorInterruptImmuneTurnActive,
55
+ isInterruptingSeverity,
56
+ quarantineAdvisorUnsafeOutput,
57
+ resolveAdvisorDeliveryChannel,
58
+ slugifyAdvisorName,
59
+ } from "../advisor";
60
+ import type { ModelRegistry } from "../config/model-registry";
61
+ import {
62
+ formatModelString,
63
+ formatModelStringWithRouting,
64
+ resolveAdvisorRoleSelection,
65
+ resolveModelOverride,
66
+ } from "../config/model-resolver";
67
+ import { MODEL_ROLES } from "../config/model-roles";
68
+ import { serviceTierForAllFamilies, serviceTierSettingToTier } from "../config/service-tier";
69
+ import type { Settings } from "../config/settings";
70
+ import { CursorExecHandlers } from "../cursor";
71
+ import { estimateToolSchemaTokens } from "../modes/utils/context-usage";
72
+ import type { PlanModeState } from "../plan-mode/state";
73
+ import advisorSystemPrompt from "../prompts/advisor/system.md" with { type: "text" };
74
+ import type { SecretObfuscator } from "../secrets/obfuscator";
75
+ import {
76
+ concreteThinkingLevel,
77
+ resolveThinkingLevelForModel,
78
+ shouldDisableReasoning,
79
+ toReasoningEffort,
80
+ } from "../thinking";
81
+ import type { AgentSessionEvent } from "./agent-session-events";
82
+ import type { ClientBridge } from "./client-bridge";
83
+ import type { CustomMessage, CustomMessagePayload } from "./messages";
84
+ import { isAdvisorCard, isTerminalTextAssistantAnswer } from "./queued-messages";
85
+ import {
86
+ formatRetryFallbackSelector,
87
+ getRetryFallbackRevertPolicy,
88
+ parseRetryFallbackSelector,
89
+ type RetryFallbackSelector,
90
+ } from "./retry-fallback-chains";
91
+ import { formatSessionDumpText } from "./session-dump-format";
92
+ import type { CompactionEntry, SessionEntry } from "./session-entries";
93
+ import { formatSessionHistoryMarkdown } from "./session-history-format";
94
+ import type { SessionManager } from "./session-manager";
95
+ import { buildSessionMetadata } from "./session-metadata";
96
+ import type { YieldQueue } from "./yield-queue";
97
+
98
+ const ADVISOR_CODEX_SSE_MAX_ATTEMPTS = 1;
99
+ /** Advisor statistics for the advisor status command. */
100
+ export interface AdvisorStats {
101
+ configured: boolean;
102
+ active: boolean;
103
+ model?: Model;
104
+ contextWindow: number;
105
+ contextTokens: number;
106
+ tokens: {
107
+ input: number;
108
+ output: number;
109
+ reasoning: number;
110
+ cacheRead: number;
111
+ cacheWrite: number;
112
+ total: number;
113
+ };
114
+ cost: number;
115
+ messages: {
116
+ user: number;
117
+ assistant: number;
118
+ total: number;
119
+ };
120
+ /** Per-advisor breakdown for every configured advisor. */
121
+ advisors: PerAdvisorStat[];
122
+ }
123
+
124
+ /** One advisor's status, token usage, cost, and message counts. */
125
+ export interface PerAdvisorStat {
126
+ name: string;
127
+ status: AdvisorRuntimeStatus;
128
+ model?: Model;
129
+ contextWindow: number;
130
+ contextTokens: number;
131
+ tokens: AdvisorStats["tokens"];
132
+ cost: number;
133
+ messages: AdvisorStats["messages"];
134
+ sessionId?: string;
135
+ }
136
+
137
+ interface AdvisorRetryFallbackState {
138
+ role: string;
139
+ originalSelector: string;
140
+ originalThinkingLevel: ThinkingLevel;
141
+ lastAppliedThinkingLevel: ThinkingLevel;
142
+ }
143
+
144
+ interface ActiveAdvisor {
145
+ name: string;
146
+ slug: string;
147
+ agent: Agent;
148
+ runtime: AdvisorRuntime;
149
+ adviseTool: AdviseTool;
150
+ emissionGuard: AdvisorEmissionGuard;
151
+ recorder: AdvisorTranscriptRecorder;
152
+ recorderClosed: Promise<void>;
153
+ agentUnsubscribe?: () => void;
154
+ model: Model;
155
+ thinkingLevel: ThinkingLevel;
156
+ providerSessionId: string | undefined;
157
+ retryFallback?: AdvisorRetryFallbackState;
158
+ retryFallbackPendingSuccess: boolean;
159
+ signature: string;
160
+ }
161
+
162
+ interface AdvisorCompactionSummaryMessage extends CompactionSummaryMessage {
163
+ firstKeptEntryId?: string;
164
+ advisorUsageAnchorStartIndex?: number;
165
+ }
166
+
167
+ interface AdvisorRuntimeDescriptor {
168
+ config: AdvisorConfig;
169
+ name: string;
170
+ slug: string;
171
+ model: Model;
172
+ thinkingLevel: ThinkingLevel;
173
+ signature: string;
174
+ }
175
+
176
+ /** Inputs that configure the advisor roster owned by a session. */
177
+ export interface SessionAdvisorsOptions {
178
+ enabled: boolean;
179
+ tools?: AgentTool[];
180
+ watchdogPrompt?: string;
181
+ sharedInstructions?: string;
182
+ contextPrompt?: string;
183
+ configs?: AdvisorConfig[];
184
+ streamFn?: StreamFn;
185
+ transformProviderContext?: (context: Context, model: Model) => Context | Promise<Context>;
186
+ }
187
+
188
+ /** Options accepted when an advisor injects a primary-session message. */
189
+ export interface AdvisorMessageDeliveryOptions {
190
+ triggerTurn?: boolean;
191
+ deliverAs?: "steer" | "followUp" | "nextTurn";
192
+ queueChipText?: string;
193
+ acceptTerminalEmptyStop?: boolean;
194
+ }
195
+
196
+ /** Session capabilities borrowed by the advisor controller. */
197
+ export interface SessionAdvisorsHost {
198
+ agent: Agent;
199
+ sessionManager: SessionManager;
200
+ settings: Settings;
201
+ modelRegistry: ModelRegistry;
202
+ yieldQueue: YieldQueue;
203
+ obfuscator: SecretObfuscator | undefined;
204
+ providerSessionState: Map<string, ProviderSessionState>;
205
+ preferWebsockets: boolean | undefined;
206
+ onPayload: SimpleStreamOptions["onPayload"] | undefined;
207
+ onResponse: SimpleStreamOptions["onResponse"] | undefined;
208
+ onSseEvent: SimpleStreamOptions["onSseEvent"] | undefined;
209
+ agentKind(): "main" | "sub";
210
+ isDisposed(): boolean;
211
+ abortInProgress(): boolean;
212
+ allowAgentInitiatedTurns(): boolean;
213
+ planModeState(): PlanModeState | undefined;
214
+ clientBridge(): ClientBridge | undefined;
215
+ emitSessionEvent(event: AgentSessionEvent): Promise<void>;
216
+ emitNotice(level: "info" | "warning" | "error", message: string, source?: string): void;
217
+ sendCustomMessage(message: CustomMessagePayload, options?: AdvisorMessageDeliveryOptions): Promise<boolean>;
218
+ extractQueuedAdvisorCards(): CustomMessage[];
219
+ dropPendingAdvisorCards(): void;
220
+ preserveAdvisorCard(card: CustomMessage): void;
221
+ hasPendingNextTurnMessages(): boolean;
222
+ convertToLlmForSideRequest(messages: AgentMessage[]): Message[];
223
+ effectiveServiceTier(model: Model): ServiceTier | undefined;
224
+ resolveContextPromotionTarget(currentModel: Model, contextWindow: number): Promise<Model | undefined>;
225
+ resolveCompactionModelCandidates(preferredModel: Model | null | undefined, availableModels: Model[]): Model[];
226
+ resolveRetryFallbackRole(currentSelector: string, currentModel?: Model | null): string | undefined;
227
+ findRetryFallbackCandidates(
228
+ role: string,
229
+ currentSelector: string,
230
+ currentModel?: Model | null,
231
+ ): RetryFallbackSelector[];
232
+ isRetryFallbackSelectorSuppressed(selector: RetryFallbackSelector): boolean;
233
+ noteRetryFallbackCooldown(currentSelector: string, retryAfterMs: number | undefined, errorMessage: string): void;
234
+ createCodexCompactionContext(options: {
235
+ trigger: CodexCompactionContext["trigger"];
236
+ reason: CodexCompactionContext["reason"];
237
+ phase: CodexCompactionContext["phase"];
238
+ }): CodexCompactionContext;
239
+ sessionId(): string;
240
+ }
241
+
242
+ /** Owns advisor runtimes, delivery policy, context maintenance, and status reporting. */
243
+ export class SessionAdvisors {
244
+ readonly #host: SessionAdvisorsHost;
245
+ #advisorEnabled: boolean;
246
+ #advisorTools: AgentTool[] | undefined;
247
+ #advisorWatchdogPrompt: string | undefined;
248
+ #advisorSharedInstructions: string | undefined;
249
+ #advisorContextPrompt: string | undefined;
250
+ #advisorStreamFn: StreamFn | undefined;
251
+ #transformProviderContext: ((context: Context, model: Model) => Context | Promise<Context>) | undefined;
252
+ #advisors: ActiveAdvisor[] = [];
253
+ #advisorConfigs: AdvisorConfig[] | undefined;
254
+ #advisorStatuses = new Map<string, { name: string; status: AdvisorRuntimeStatus }>();
255
+ #advisorProviderSessionIds = new Map<string, string>();
256
+ #advisorCosts = new Map<string, number>();
257
+ #advisorRecorderClosed: Promise<void> = Promise.resolve();
258
+ #advisorAutoResumeSuppressed = false;
259
+ #preserveAdvisorAdvice = false;
260
+ #advisorPrimaryTurnsCompleted = 0;
261
+ #advisorInterruptImmuneTurnStart: number | undefined;
262
+ #pendingAdvisorCardEvents = new Set<Promise<void>>();
263
+ #advisorYieldQueueUnsubscribe: (() => void) | undefined;
264
+
265
+ constructor(host: SessionAdvisorsHost, options: SessionAdvisorsOptions) {
266
+ this.#host = host;
267
+ this.#advisorEnabled = options.enabled;
268
+ this.#advisorTools = options.tools;
269
+ this.#advisorWatchdogPrompt = options.watchdogPrompt;
270
+ this.#advisorSharedInstructions = options.sharedInstructions;
271
+ this.#advisorContextPrompt = options.contextPrompt;
272
+ this.#advisorConfigs = options.configs;
273
+ this.#advisorStreamFn = options.streamFn;
274
+ this.#transformProviderContext = options.transformProviderContext;
275
+ if (this.#advisorEnabled) this.#buildAdvisorRuntime();
276
+ }
277
+
278
+ /** Delivers one completed primary turn to every live advisor. */
279
+ async onPrimaryTurnEnd(
280
+ messages: AgentMessage[],
281
+ willContinue: boolean | undefined,
282
+ signal?: AbortSignal,
283
+ ): Promise<void> {
284
+ this.#advisorPrimaryTurnsCompleted++;
285
+ for (const advisor of this.#advisors) {
286
+ if (advisor.runtime.disposed) continue;
287
+ try {
288
+ advisor.runtime.onTurnEnd(messages, { willContinue });
289
+ } catch (error) {
290
+ logger.warn("advisor onTurnEnd threw; delta dropped", { advisor: advisor.name, err: String(error) });
291
+ }
292
+ }
293
+ const syncBacklog = this.#host.settings.get("advisor.syncBacklog");
294
+ if (this.#advisors.length === 0 || syncBacklog === "off") return;
295
+ const threshold = Number.parseInt(syncBacklog, 10);
296
+ await Promise.all(this.#advisors.map(advisor => advisor.runtime.waitForCatchup(30_000, threshold, signal)));
297
+ }
298
+
299
+ /** Rebuilds live advisors when role assignments alter their resolved runtime inputs. */
300
+ onModelRolesChanged(): void {
301
+ if (!this.#advisorEnabled || this.#host.isDisposed()) return;
302
+ if (this.#advisors.length > 0 && !this.#advisorRuntimeMatchesCurrentConfig()) this.#stopAdvisorRuntime();
303
+ this.#buildAdvisorRuntime(true);
304
+ }
305
+
306
+ /** Starts configured advisor runtimes when they are eligible. */
307
+ buildRuntime(seedToCurrent = false): boolean {
308
+ return this.#buildAdvisorRuntime(seedToCurrent);
309
+ }
310
+
311
+ /** Stops every advisor runtime and starts recorder shutdown. */
312
+ stopRuntime(): void {
313
+ this.#stopAdvisorRuntime();
314
+ }
315
+
316
+ /** Detaches and drains recorder feeds before transcript artifacts are removed. */
317
+ async detachAndCloseRecorders(): Promise<void> {
318
+ const closes: Promise<void>[] = [];
319
+ for (const advisor of this.#advisors) {
320
+ advisor.agentUnsubscribe?.();
321
+ advisor.agentUnsubscribe = undefined;
322
+ advisor.recorderClosed = advisor.recorder.close();
323
+ closes.push(advisor.recorderClosed);
324
+ }
325
+ await Promise.all(closes);
326
+ }
327
+
328
+ /** Re-primes advisor transcript views across a conversation boundary. */
329
+ resetSessionState(options: { preserveCost?: boolean } = {}): void {
330
+ this.#resetAdvisorSessionState(options.preserveCost === true);
331
+ }
332
+
333
+ /** Drop the recorded spend once a conversation boundary has committed. */
334
+ clearCost(): void {
335
+ this.#advisorCosts.clear();
336
+ }
337
+
338
+ /**
339
+ * Rebind every live advisor to the active primary conversation's provider
340
+ * identity (session id, prompt-cache key, credential + metadata resolvers,
341
+ * telemetry). Invoked on every provider-session change — including branch
342
+ * paths that skip conversation restore — so advisors never keep emitting the
343
+ * previous conversation's session id/metadata (issue #6625).
344
+ */
345
+ refreshProviderIdentity(): void {
346
+ for (const advisor of this.#advisors) this.#refreshAdvisorProviderIdentity(advisor);
347
+ }
348
+
349
+ /** Re-primes advisor transcript views after an in-conversation history rewrite. */
350
+ resetAllRuntimes(): void {
351
+ this.#resetAllAdvisorRuntimes();
352
+ }
353
+
354
+ /** Whether live runtimes still match the resolved advisor configuration. */
355
+ runtimeMatchesCurrentConfig(): boolean {
356
+ return this.#advisorRuntimeMatchesCurrentConfig();
357
+ }
358
+
359
+ /** Whether concern/blocker delivery is inside the post-interrupt immunity window. */
360
+ isInterruptImmuneTurnActive(): boolean {
361
+ return this.#isAdvisorInterruptImmuneTurnActive();
362
+ }
363
+
364
+ /** Latest aggregate recorder-close barrier. */
365
+ recorderClosed(): Promise<void> {
366
+ return this.#advisorRecorderClosed;
367
+ }
368
+
369
+ /** Whether a user interrupt currently suppresses advisor-driven auto-resume. */
370
+ get autoResumeSuppressed(): boolean {
371
+ return this.#advisorAutoResumeSuppressed;
372
+ }
373
+
374
+ set autoResumeSuppressed(value: boolean) {
375
+ this.#advisorAutoResumeSuppressed = value;
376
+ }
377
+
378
+ /** Tracks persistence of a visible advisor card emitted outside the primary loop. */
379
+ trackCardEvent(processing: Promise<void>): void {
380
+ this.#pendingAdvisorCardEvents.add(processing);
381
+ void processing.finally(() => this.#pendingAdvisorCardEvents.delete(processing)).catch(() => {});
382
+ }
383
+
384
+ /** Waits for all advisor-card persistence handlers currently in flight. */
385
+ async waitForPendingCardEvents(): Promise<void> {
386
+ await Promise.allSettled([...this.#pendingAdvisorCardEvents]);
387
+ }
388
+
389
+ // Advisor runtime lifecycle
390
+ // -------------------------------------------------------------------------
391
+ #advisorImmuneTurnLimit(): number {
392
+ const immuneTurns = this.#host.settings.get("advisor.immuneTurns") as number;
393
+ if (!Number.isFinite(immuneTurns) || immuneTurns <= 0) return 0;
394
+ return Math.trunc(immuneTurns);
395
+ }
396
+
397
+ #isAdvisorInterruptImmuneTurnActive(): boolean {
398
+ return isAdvisorInterruptImmuneTurnActive({
399
+ completedTurns: this.#advisorPrimaryTurnsCompleted,
400
+ immuneTurnStart: this.#advisorInterruptImmuneTurnStart,
401
+ immuneTurns: this.#advisorImmuneTurnLimit(),
402
+ });
403
+ }
404
+
405
+ // The next primary turn number starts the immune-turn window. While the
406
+ // interrupting steer is still in flight, completedTurns is lower than this
407
+ // start, so duplicate concern/blocker advice is also downgraded.
408
+ #recordAdvisorInterruptDelivered(): void {
409
+ this.#advisorInterruptImmuneTurnStart = this.#advisorPrimaryTurnsCompleted + 1;
410
+ }
411
+
412
+ /** Rebind one advisor to the active primary conversation's provider identity. */
413
+ #refreshAdvisorProviderIdentity(advisor: ActiveAdvisor): void {
414
+ const primaryProviderSessionId = this.#host.sessionId();
415
+ const providerSessionId = getOrCreateAdvisorProviderSessionId(
416
+ this.#advisorProviderSessionIds,
417
+ primaryProviderSessionId,
418
+ advisor.slug,
419
+ );
420
+ advisor.providerSessionId = providerSessionId;
421
+ advisor.agent.sessionId = providerSessionId;
422
+ advisor.agent.promptCacheKey = this.#host.agent.promptCacheKey ?? providerSessionId;
423
+ advisor.agent.getApiKey = requestModel => this.#host.modelRegistry.resolver(requestModel, providerSessionId);
424
+ advisor.agent.setMetadataResolver(
425
+ providerSessionId
426
+ ? provider => buildSessionMetadata(providerSessionId, provider, this.#host.modelRegistry.authStorage)
427
+ : undefined,
428
+ );
429
+
430
+ const telemetry = advisor.agent.telemetry;
431
+ if (telemetry?.agent) {
432
+ advisor.agent.setTelemetry({
433
+ ...telemetry,
434
+ agent: {
435
+ ...telemetry.agent,
436
+ id: advisor.slug
437
+ ? `${primaryProviderSessionId}-advisor-${advisor.slug}`
438
+ : `${primaryProviderSessionId}-advisor`,
439
+ },
440
+ });
441
+ }
442
+ }
443
+
444
+ /**
445
+ * Re-prime the advisor across a conversation boundary: `/new`, `/branch`,
446
+ * `/btw`, `/tree`, and session switch/resume. Beyond {@link AdvisorRuntime.reset}
447
+ * (which only re-primes the advisor's transcript view and is also fired by
448
+ * within-conversation rewrites like compaction/shake/rewind), this clears the
449
+ * session-level interrupt latches so the prior conversation's cooldown cannot
450
+ * leak into the new one: the post-interrupt immune-turn window
451
+ * (`#advisorPrimaryTurnsCompleted`, `#advisorInterruptImmuneTurnStart`) and the
452
+ * user-interrupt auto-resume suppression flag. It also drops advisor deliveries
453
+ * still queued against the prior conversation — pending asides in the yield
454
+ * queue (advisor entries use `skipIdleFlush`, so they linger until the next
455
+ * `drainLazy` rather than self-flushing), interrupting cards parked in the
456
+ * agent steer/follow-up queues, and preserved cards deferred to the next turn —
457
+ * so none of them inject into the new conversation.
458
+ */
459
+ #resetAdvisorSessionState(preserveCost: boolean): void {
460
+ if (!preserveCost) this.#advisorCosts.clear();
461
+ // Mute the recorder across the re-prime: AdvisorRuntime.reset() aborts the advisor
462
+ // loop, and that abort can emit an `aborted` message_end we must not attribute to
463
+ // either session's transcript. Detach, reset, then re-attach the live agent's feed.
464
+ for (const a of this.#advisors) {
465
+ a.agentUnsubscribe?.();
466
+ a.agentUnsubscribe = undefined;
467
+ a.runtime.reset();
468
+ a.adviseTool.resetDeliveredNotes();
469
+ a.emissionGuard.reset();
470
+ this.#attachAdvisorRecorderFeed(a);
471
+ }
472
+ this.#advisorPrimaryTurnsCompleted = 0;
473
+ this.#advisorInterruptImmuneTurnStart = undefined;
474
+ this.#advisorAutoResumeSuppressed = false;
475
+ this.#host.yieldQueue.clear("advisor");
476
+ this.#host.extractQueuedAdvisorCards();
477
+ this.#host.dropPendingAdvisorCards();
478
+ }
479
+
480
+ #resolveAdvisorRuntimeDescriptors(emitWarnings: boolean): AdvisorRuntimeDescriptor[] {
481
+ const legacy = !this.#advisorConfigs?.length;
482
+ const roster: AdvisorConfig[] = legacy ? [{ name: "default" }] : this.#advisorConfigs!;
483
+ const descriptors: AdvisorRuntimeDescriptor[] = [];
484
+ const usedSlugs = new Set<string>();
485
+ for (const config of roster) {
486
+ let slug = legacy ? "" : slugifyAdvisorName(config.name);
487
+ if (slug) {
488
+ let candidate = slug;
489
+ let n = 2;
490
+ while (usedSlugs.has(candidate)) candidate = `${slug}-${n++}`;
491
+ slug = candidate;
492
+ usedSlugs.add(slug);
493
+ }
494
+ // Per-advisor toggle: skip disabled advisors but keep them in the
495
+ // status map so they show `○` rather than disappearing.
496
+ if (config.enabled === false) {
497
+ this.#advisorStatuses.set(slug, { name: config.name, status: "paused" });
498
+ continue;
499
+ }
500
+
501
+ // Resolve the advisor's model: an explicit `model` override wins; else the
502
+ // `advisor` role chain. A model that fails to resolve skips just this advisor.
503
+ let model: Model | undefined;
504
+ let thinkingLevel: ThinkingLevel | undefined;
505
+ if (config.model) {
506
+ const resolved = resolveModelOverride([config.model], this.#host.modelRegistry, this.#host.settings);
507
+ model = resolved.model;
508
+ thinkingLevel = concreteThinkingLevel(resolved.thinkingLevel);
509
+ if (!model) {
510
+ this.#advisorStatuses.set(slug, { name: config.name, status: "no_model" });
511
+ if (emitWarnings) {
512
+ this.#host.emitNotice(
513
+ "warning",
514
+ `Advisor "${config.name}": no model matched "${config.model}"`,
515
+ "advisor",
516
+ );
517
+ }
518
+ continue;
519
+ }
520
+ } else {
521
+ const sel = resolveAdvisorRoleSelection(this.#host.settings, this.#host.modelRegistry.getAvailable());
522
+ if (!sel) {
523
+ this.#advisorStatuses.set(slug, { name: config.name, status: "no_model" });
524
+ if (emitWarnings) {
525
+ logger.debug("advisor enabled but no model assigned to the 'advisor' role; advisor inactive", {
526
+ advisor: config.name,
527
+ });
528
+ }
529
+ continue;
530
+ }
531
+ model = sel.model;
532
+ thinkingLevel = concreteThinkingLevel(sel.thinkingLevel);
533
+ }
534
+ // Clamp the effort against the resolved model. Historically we defaulted
535
+ // to `ThinkingLevel.Medium` unconditionally, which threw at first stream
536
+ // on reasoning models that expose no controllable effort surface
537
+ // (e.g. `devin-agent`: Cascade routes by sibling model id, not a wire
538
+ // param; `getSupportedEfforts` returns `[]`). `resolveThinkingLevelForModel`
539
+ // preserves an explicit `off`, clamps a concrete effort into the model's
540
+ // supported range, and returns `undefined` for reasoning models without
541
+ // controllable efforts — for that case we forward `Inherit` so no effort
542
+ // is sent and reasoning stays enabled (matching the `auto`-path fix for
543
+ // Devin models via `clampAutoThinkingEffort`). See #4579.
544
+ const requestedLevel = thinkingLevel ?? ThinkingLevel.Medium;
545
+ const resolvedLevel = resolveThinkingLevelForModel(model, requestedLevel);
546
+ const advisorThinkingLevel: ThinkingLevel = resolvedLevel ?? ThinkingLevel.Inherit;
547
+ // Record the status entry now (in roster order) so the Map's insertion
548
+ // order matches the configured roster even when earlier advisors were
549
+ // skipped as paused/no_model. The build loop overwrites this to "running"
550
+ // without changing insertion order.
551
+ this.#advisorStatuses.set(slug, { name: config.name, status: "running" });
552
+ descriptors.push({
553
+ config,
554
+ name: config.name,
555
+ slug,
556
+ model,
557
+ thinkingLevel: advisorThinkingLevel,
558
+ signature: this.#advisorRuntimeSignature(config, slug, model, advisorThinkingLevel),
559
+ });
560
+ }
561
+ return descriptors;
562
+ }
563
+
564
+ #advisorRuntimeSignature(config: AdvisorConfig, slug: string, model: Model, thinkingLevel: ThinkingLevel): string {
565
+ const tools = config.tools?.length ? config.tools.join("\u001e") : "";
566
+ const instructions = config.instructions?.trim() ?? "";
567
+ return [config.name, slug, formatModelStringWithRouting(model), thinkingLevel, tools, instructions].join(
568
+ "\u001f",
569
+ );
570
+ }
571
+
572
+ #advisorRuntimeMatchesCurrentConfig(): boolean {
573
+ const descriptors = this.#resolveAdvisorRuntimeDescriptors(false);
574
+ if (descriptors.length !== this.#advisors.length) return false;
575
+ for (let i = 0; i < descriptors.length; i++) {
576
+ if (descriptors[i].signature !== this.#advisors[i].signature) return false;
577
+ }
578
+ return true;
579
+ }
580
+
581
+ #buildAdvisorRuntime(seedToCurrent = false): boolean {
582
+ if (this.#host.isDisposed()) return false;
583
+ if (this.#advisors.length > 0) return true;
584
+ if (!this.#advisorEnabled) return false;
585
+ if (this.#host.agentKind() !== "main" && !this.#host.settings.get("advisor.subagents")) return false;
586
+
587
+ // Rebuild the status map from scratch so removed/renamed advisors don't
588
+ // leave stale entries. #resolveAdvisorRuntimeDescriptors populates every
589
+ // entry (`paused`/`no_model`/`running`) in roster order; the build loop
590
+ // below confirms `running` for successfully built advisors.
591
+ this.#advisorStatuses.clear();
592
+ const descriptors = this.#resolveAdvisorRuntimeDescriptors(true);
593
+
594
+ // Advisor service tier (`tier.advisor`): "none" (default) runs the advisor
595
+ // on standard processing; "inherit" tracks the session's live per-family
596
+ // tiers per request (like the main agent, including /fast toggles); a
597
+ // concrete value is broadcast across families and applied to the advisor
598
+ // model's family. One value for all advisors.
599
+ const advisorTierSetting = this.#host.settings.get("tier.advisor");
600
+ const advisorTierMap =
601
+ advisorTierSetting === "inherit"
602
+ ? undefined
603
+ : serviceTierForAllFamilies(serviceTierSettingToTier(advisorTierSetting));
604
+ const advisorServiceTierResolver = (model: Model): ServiceTier | undefined =>
605
+ advisorTierSetting === "inherit"
606
+ ? this.#host.effectiveServiceTier(model)
607
+ : resolveModelServiceTier(advisorTierMap, model);
608
+
609
+ for (const descriptor of descriptors) {
610
+ const {
611
+ config,
612
+ slug,
613
+ model: advisorModel,
614
+ name: advisorName,
615
+ thinkingLevel: advisorThinkingLevel,
616
+ signature,
617
+ } = descriptor;
618
+
619
+ const emissionGuard = new AdvisorEmissionGuard();
620
+ const adviseTool = new AdviseTool((note, severity) => this.#routeAdvice(advisorRef, note, severity));
621
+
622
+ // `#advisorWatchdogPrompt` already carries WATCHDOG.md + YAML shared
623
+ // instructions; `config.instructions` adds this advisor's specialization.
624
+ const systemPrompt = [advisorSystemPrompt];
625
+ if (this.#advisorContextPrompt) systemPrompt.push(this.#advisorContextPrompt);
626
+ if (this.#advisorWatchdogPrompt) systemPrompt.push(this.#advisorWatchdogPrompt);
627
+ if (this.#advisorSharedInstructions) systemPrompt.push(this.#advisorSharedInstructions);
628
+ if (config.instructions?.trim()) systemPrompt.push(config.instructions.trim());
629
+
630
+ const names = config.tools === undefined ? ADVISOR_DEFAULT_TOOL_NAMES : new Set(config.tools);
631
+ const tools = (this.#advisorTools ?? []).filter(t => names.has(t.name));
632
+ const advisorLoopTools: AgentTool<any>[] = [adviseTool, ...tools];
633
+ const advisorToolMap = new Map<string, AgentTool<any>>();
634
+ const availableAdvisorToolNames = new Set<string>();
635
+ for (const tool of advisorLoopTools) {
636
+ availableAdvisorToolNames.add(tool.name);
637
+ advisorToolMap.set(tool.name, tool);
638
+ if (tool.customWireName !== undefined) {
639
+ availableAdvisorToolNames.add(tool.customWireName);
640
+ advisorToolMap.set(tool.customWireName, tool);
641
+ }
642
+ }
643
+ let quarantinedAdvisorOutput: string | undefined;
644
+ let currentAdvisorInput = "";
645
+
646
+ const primaryProviderSessionId = this.#host.sessionId();
647
+ const advisorSessionLabel = slug
648
+ ? `${primaryProviderSessionId}-advisor-${slug}`
649
+ : `${primaryProviderSessionId}-advisor`;
650
+ const advisorProviderSessionId = getOrCreateAdvisorProviderSessionId(
651
+ this.#advisorProviderSessionIds,
652
+ primaryProviderSessionId,
653
+ slug,
654
+ );
655
+ const appendOnlyContext = new AppendOnlyContextManager();
656
+
657
+ // Thread the primary's telemetry into the advisor loop so the advisor
658
+ // model's GenAI spans + usage/cost hooks fire stamped with the local advisor
659
+ // identity. `conversationId` is cleared so provider telemetry falls back to
660
+ // the UUIDv7 provider session id, not the local `-advisor` label.
661
+ const advisorTelemetry = this.#host.agent.telemetry
662
+ ? {
663
+ ...this.#host.agent.telemetry,
664
+ agent: {
665
+ id: advisorSessionLabel,
666
+ name: slug ? `${MODEL_ROLES.advisor.name}: ${advisorName}` : MODEL_ROLES.advisor.name,
667
+ description: formatModelString(advisorModel),
668
+ },
669
+ conversationId: undefined,
670
+ }
671
+ : undefined;
672
+ // Mirror the SDK's provider-shaping options (streamFn/onPayload/...,
673
+ // providerSessionState, promptCacheKey, transformProviderContext) so each
674
+ // advisor's requests cache, route, and obfuscate like the main turn.
675
+ // `promptCacheKey` preserves an explicitly pinned provider cache key
676
+ // unchanged so tan/shared-session advisor calls read the exact shard the
677
+ // parent turn populated. Otherwise the advisor uses its provider UUIDv7 so
678
+ // Codex request identity remains UUID-shaped while local labels keep the
679
+ // `-advisor` suffix.
680
+ const advisorPromptCacheKey = this.#host.agent.promptCacheKey ?? advisorProviderSessionId;
681
+ // On the Cursor provider every tool runs server-side and is dispatched
682
+ // back through `cursorExecHandlers`; without this bridge the advisor's
683
+ // own tools (including the MCP `advise` tool) return `toolNotFound` and
684
+ // no advice is ever routed (issue #5680). Mirrors the primary agent's
685
+ // bridge (`sdk.ts`), scoped to this advisor's granted tool set.
686
+ // Cursor's native `delete` frame removes files directly, bypassing the
687
+ // tool map, so gate it on the advisor actually holding a file-mutating
688
+ // tool. A default read-only advisor (advise/read/grep/glob) never gets
689
+ // to delete workspace files it was never granted (issue #5680 review).
690
+ const advisorCanMutateFiles = advisorToolMap.has("write") || advisorToolMap.has("edit");
691
+ if (advisorCanMutateFiles) availableAdvisorToolNames.add("delete");
692
+ const advisorCursorExecHandlers = new CursorExecHandlers({
693
+ cwd: this.#host.sessionManager.getCwd(),
694
+ getCwd: () => this.#host.sessionManager.getCwd(),
695
+ tools: advisorToolMap,
696
+ allowNativeDelete: advisorCanMutateFiles,
697
+ });
698
+ const baseAdvisorStreamFn = this.#advisorStreamFn ?? streamSimple;
699
+ const advisorStreamFn: StreamFn = (requestModel, context, options) =>
700
+ baseAdvisorStreamFn(
701
+ requestModel,
702
+ context,
703
+ requestModel.api === "openai-codex-responses"
704
+ ? { ...options, codexSseMaxAttempts: ADVISOR_CODEX_SSE_MAX_ATTEMPTS }
705
+ : options,
706
+ );
707
+ const advisorAgent = new Agent({
708
+ initialState: {
709
+ systemPrompt,
710
+ model: advisorModel,
711
+ thinkingLevel: toReasoningEffort(advisorThinkingLevel),
712
+ tools: advisorLoopTools,
713
+ },
714
+ appendOnlyContext,
715
+ sessionId: advisorProviderSessionId,
716
+ promptCacheKey: advisorPromptCacheKey,
717
+ providerSessionState: this.#host.providerSessionState,
718
+ cursorExecHandlers: advisorCursorExecHandlers,
719
+ cwdResolver: () => this.#host.sessionManager.getCwd(),
720
+ preferWebsockets: this.#host.preferWebsockets,
721
+ getApiKey: requestModel => this.#host.modelRegistry.resolver(requestModel, advisorProviderSessionId),
722
+ streamFn: advisorStreamFn,
723
+ onPayload: this.#host.onPayload,
724
+ onResponse: this.#host.onResponse,
725
+ onSseEvent: this.#host.onSseEvent,
726
+ transformProviderContext: this.#transformProviderContext,
727
+ intentTracing: false,
728
+ transformAssistantMessage: message => {
729
+ quarantinedAdvisorOutput = quarantineAdvisorUnsafeOutput(
730
+ message,
731
+ availableAdvisorToolNames,
732
+ buildAdvisorQuarantineSourceText(currentAdvisorInput, advisorAgent.state.messages),
733
+ );
734
+ },
735
+ telemetry: advisorTelemetry,
736
+ serviceTier: undefined,
737
+ serviceTierResolver: advisorServiceTierResolver,
738
+ });
739
+ advisorAgent.setDisableReasoning(shouldDisableReasoning(advisorThinkingLevel));
740
+
741
+ const advisorAgentFacade: AdvisorAgent = {
742
+ prompt: async input => {
743
+ let quarantined: string | undefined;
744
+ try {
745
+ quarantinedAdvisorOutput = undefined;
746
+ currentAdvisorInput = input;
747
+ await advisorAgent.prompt(input);
748
+ quarantined = quarantinedAdvisorOutput;
749
+ } finally {
750
+ quarantinedAdvisorOutput = undefined;
751
+ currentAdvisorInput = "";
752
+ }
753
+ if (quarantined) throw new AdvisorOutputQuarantinedError(quarantined);
754
+ },
755
+ abort: reason => advisorAgent.abort(reason),
756
+ reset: () => {
757
+ advisorAgent.reset();
758
+ appendOnlyContext.log.clear();
759
+ },
760
+ rollbackTo: count => {
761
+ // Drop the failed user batch + synthetic assistant-error turn
762
+ // `Agent.#runLoop` appended for a turn ending in `stopReason: "error"`.
763
+ const messages = advisorAgent.state.messages;
764
+ if (count < messages.length) {
765
+ messages.length = count;
766
+ }
767
+ appendOnlyContext.resetSyncCursor();
768
+ advisorAgent.state.error = undefined;
769
+ },
770
+ state: advisorAgent.state,
771
+ };
772
+
773
+ // Persist this advisor's turns to `<session>/__advisor[.<slug>].jsonl`
774
+ // (resolved lazily so it follows session switches) for stats attribution
775
+ // and Agent Hub observability, without registering it as a peer.
776
+ const recorder = new AdvisorTranscriptRecorder(
777
+ () => this.#host.sessionManager.getSessionFile(),
778
+ () => this.#host.sessionManager.getCwd(),
779
+ advisorTranscriptFilename(slug),
780
+ // On the advisor on→off→on toggle, wait for the prior recorders' closes
781
+ // so two SessionManagers never hold the same file at once.
782
+ this.#advisorRecorderClosed,
783
+ );
784
+ const runtime = new AdvisorRuntime(advisorAgentFacade, {
785
+ snapshotMessages: () => this.#host.agent.state.messages,
786
+ enqueueAdvice: (note, severity) => this.#routeAdvice(advisorRef, note, severity),
787
+ maintainContext: incomingTokens => this.#maintainAdvisorContext(advisorRef, incomingTokens),
788
+ obfuscator: this.#host.obfuscator,
789
+ beginAdvisorUpdate: () => advisorRef.emissionGuard.beginUpdate(),
790
+ onTurnError: (error, failedMessages) => this.#recoverAdvisorTurn(advisorRef, error, failedMessages),
791
+ onTurnSuccess: async () => {
792
+ const fallback = advisorRef.retryFallback;
793
+ if (!advisorRef.retryFallbackPendingSuccess || !fallback) return;
794
+ advisorRef.retryFallbackPendingSuccess = false;
795
+ await this.#host.emitSessionEvent({
796
+ type: "retry_fallback_succeeded",
797
+ model: formatRetryFallbackSelector(advisorRef.agent.state.model, advisorRef.thinkingLevel),
798
+ role: fallback.role,
799
+ });
800
+ },
801
+ notifyFailure: error => {
802
+ this.#advisorStatuses.set(slug, { name: advisorName, status: "error" });
803
+ const message = error instanceof Error ? error.message : String(error);
804
+ this.#host.emitNotice(
805
+ "warning",
806
+ `Advisor${slug ? ` "${advisorName}"` : ""} unavailable for ${formatModelString(advisorAgent.state.model)}: ${message}`,
807
+ "advisor",
808
+ );
809
+ },
810
+ notifyQuotaExhausted: () => {
811
+ this.#advisorStatuses.set(slug, { name: advisorName, status: "quota_exhausted" });
812
+ this.#host.emitNotice(
813
+ "warning",
814
+ `Advisor "${advisorName}" quota exhausted — pausing until reset.`,
815
+ "advisor",
816
+ );
817
+ },
818
+ });
819
+
820
+ const advisorRef: ActiveAdvisor = {
821
+ name: advisorName,
822
+ slug,
823
+ agent: advisorAgent,
824
+ runtime,
825
+ adviseTool,
826
+ emissionGuard,
827
+ recorder,
828
+ recorderClosed: Promise.resolve(),
829
+ model: advisorModel,
830
+ thinkingLevel: advisorThinkingLevel,
831
+ providerSessionId: advisorProviderSessionId,
832
+ retryFallbackPendingSuccess: false,
833
+ signature,
834
+ };
835
+ this.#refreshAdvisorProviderIdentity(advisorRef);
836
+ this.#attachAdvisorRecorderFeed(advisorRef);
837
+ if (seedToCurrent) runtime.seedTo(this.#host.agent.state.messages.length);
838
+ this.#advisorStatuses.set(slug, { name: advisorName, status: "running" });
839
+ this.#advisors.push(advisorRef);
840
+ }
841
+
842
+ // One shared non-blocking aside channel for all advisors; the build callback
843
+ // aggregates every advisor's queued nits into one card (each entry already
844
+ // carries its own `advisor` name).
845
+ if (this.#advisors.length > 0 && !this.#advisorYieldQueueUnsubscribe) {
846
+ this.#advisorYieldQueueUnsubscribe = this.#host.yieldQueue.register<AdvisorNote>("advisor", {
847
+ build: entries =>
848
+ entries.length === 0
849
+ ? null
850
+ : ({
851
+ role: "custom",
852
+ customType: "advisor",
853
+ display: true,
854
+ attribution: "agent",
855
+ timestamp: Date.now(),
856
+ content: formatAdvisorBatchContent(entries),
857
+ details: { notes: entries } satisfies AdvisorMessageDetails,
858
+ } satisfies CustomMessage),
859
+ skipIdleFlush: true,
860
+ });
861
+ }
862
+
863
+ return this.#advisors.length > 0;
864
+ }
865
+
866
+ /**
867
+ * Route one accepted advice note from `advisor` to the primary. Concern and
868
+ * blocker interrupt the running agent through the steering channel; once the
869
+ * loop has yielded, `triggerTurn` resumes it. After a terminal text answer with
870
+ * no queued work, a concern is preserved as a visible advisor card, while a
871
+ * blocker wakes the primary to acknowledge work it handed off incorrectly.
872
+ * After a deliberate user interrupt auto-resume is suppressed while idle/unwinding
873
+ * (the note becomes a preserved card re-entering on resume); a live-streaming turn is
874
+ * steered in directly. A plain nit always rides the non-interrupting YieldQueue
875
+ * aside. Suppression by the per-advisor emission guard drops the note silently —
876
+ * the model still saw `Recorded.`, so it isn't tempted to rephrase the same note
877
+ * past the dedupe.
878
+ */
879
+ #hasTerminalTextAnswerWithoutQueuedWork(): boolean {
880
+ if (this.#host.agent.hasQueuedMessages() || this.#host.hasPendingNextTurnMessages()) return false;
881
+ const messages = this.#host.agent.state.messages;
882
+ let tail = messages.length - 1;
883
+ while (tail >= 0 && isAdvisorCard(messages[tail])) tail--;
884
+ return isTerminalTextAssistantAnswer(messages[tail]);
885
+ }
886
+
887
+ #routeAdvice(advisor: ActiveAdvisor, note: string, severity?: AdvisorSeverity): void {
888
+ if (!advisor.emissionGuard.accept(note)) {
889
+ logger.debug("advisor advice suppressed by emission guard", { severity, advisor: advisor.name });
890
+ return;
891
+ }
892
+ // The implicit single ("default") advisor stamps no source name, so its
893
+ // agent-facing `<advisory>` bytes stay identical to the pre-multi-advisor path.
894
+ const source = advisor.slug ? advisor.name : undefined;
895
+ const interrupting = isInterruptingSeverity(severity);
896
+ const channel = resolveAdvisorDeliveryChannel({
897
+ severity,
898
+ autoResumeSuppressed: this.#advisorAutoResumeSuppressed,
899
+ preserveOnly: this.#preserveAdvisorAdvice,
900
+ // Key on the live agent-core loop, not session `isStreaming` (which also
901
+ // counts `#promptInFlightCount` during post-turn unwind). Only a running
902
+ // loop consumes a steer at its next boundary.
903
+ streaming: this.#host.agent.state.isStreaming,
904
+ aborting: this.#host.abortInProgress(),
905
+ terminalAnswerNoQueuedWork: this.#hasTerminalTextAnswerWithoutQueuedWork(),
906
+ interruptImmuneTurnActive: interrupting && this.#isAdvisorInterruptImmuneTurnActive(),
907
+ });
908
+ if (channel === "aside") {
909
+ this.#host.yieldQueue.enqueue("advisor", { note, severity, advisor: source });
910
+ return;
911
+ }
912
+ const notes: AdvisorNote[] = [{ note, severity, advisor: source }];
913
+ const content = formatAdvisorBatchContent(notes);
914
+ const details = { notes } satisfies AdvisorMessageDetails;
915
+ if (channel === "preserve") {
916
+ this.#host.preserveAdvisorCard({
917
+ role: "custom",
918
+ customType: "advisor",
919
+ content,
920
+ display: true,
921
+ attribution: "agent",
922
+ details,
923
+ timestamp: Date.now(),
924
+ });
925
+ return;
926
+ }
927
+ // A steered interrupting note only continues the run when the session can
928
+ // actually start (or is already running) a turn. Two idle cases cannot, so
929
+ // `sendCustomMessage({ triggerTurn: true })` would silently bury the card in
930
+ // `#pendingNextTurnMessages` until the next user prompt — strictly worse than
931
+ // the visible preserved card. Preserve instead:
932
+ // - Plan mode: only user-driven turns converge on ask/resolve.
933
+ // - ACP bridges with `deferAgentInitiatedTurns`: the client cannot show an
934
+ // agent-initiated turn as busy, so idle triggers are refused (#5628 review).
935
+ const cannotAutoTrigger =
936
+ !this.#host.agent.state.isStreaming &&
937
+ this.#host.clientBridge()?.deferAgentInitiatedTurns === true &&
938
+ !this.#host.allowAgentInitiatedTurns();
939
+ if (this.#host.planModeState()?.enabled || cannotAutoTrigger) {
940
+ this.#host.preserveAdvisorCard({
941
+ role: "custom",
942
+ customType: "advisor",
943
+ content,
944
+ display: true,
945
+ attribution: "agent",
946
+ details,
947
+ timestamp: Date.now(),
948
+ });
949
+ return;
950
+ }
951
+ // Arm the post-interrupt immune window only now that a turn is actually
952
+ // being steered/triggered. A merely preserved card never interrupts, so
953
+ // arming earlier would downgrade the next `advisor.immuneTurns` worth of
954
+ // real concerns/blockers to skip-idle-flush asides (#5628 review).
955
+ this.#recordAdvisorInterruptDelivered();
956
+ void this.#host
957
+ .sendCustomMessage(
958
+ { customType: "advisor", content, display: true, attribution: "agent", details },
959
+ { deliverAs: "steer", triggerTurn: true },
960
+ )
961
+ .catch(err => logger.debug("advisor delivery failed", { err: String(err) }));
962
+ }
963
+
964
+ /** Re-prime every advisor's transcript view after an in-conversation history rewrite. */
965
+ #resetAllAdvisorRuntimes(): void {
966
+ for (const a of this.#advisors) a.runtime.reset();
967
+ }
968
+
969
+ #stopAdvisorRuntime(): void {
970
+ // Detach each recorder feed BEFORE aborting its advisor agent: dispose() aborts
971
+ // the loop, and an abort emits a final `message_end` we must not enqueue against
972
+ // a closing recorder (it would reopen and resurrect an already-released file).
973
+ const closes: Promise<void>[] = [];
974
+ for (const a of this.#advisors) {
975
+ a.agentUnsubscribe?.();
976
+ a.agentUnsubscribe = undefined;
977
+ a.runtime.dispose();
978
+ // Capture each close so dispose()/`/drop` can await the queued open+append+close —
979
+ // the last advisor turn would otherwise be lost on a fast process exit.
980
+ a.recorderClosed = a.recorder.close();
981
+ closes.push(a.recorderClosed);
982
+ }
983
+ this.#advisorRecorderClosed = Promise.all(closes).then(() => {});
984
+ this.#advisors = [];
985
+ this.#advisorYieldQueueUnsubscribe?.();
986
+ this.#advisorYieldQueueUnsubscribe = undefined;
987
+ }
988
+
989
+ #recordAdvisorCost(advisor: ActiveAdvisor, message: AssistantMessage): void {
990
+ this.#advisorCosts.set(advisor.slug, (this.#advisorCosts.get(advisor.slug) ?? 0) + message.usage.cost.total);
991
+ }
992
+
993
+ /** Subscribe the advisor agent's finalized messages into the transcript recorder.
994
+ * Idempotent-by-replacement: callers detach the prior feed first. Kept separate
995
+ * so the re-prime path can mute the feed across an abort-driven reset. */
996
+ #attachAdvisorRecorderFeed(advisor: ActiveAdvisor): void {
997
+ advisor.agentUnsubscribe = advisor.agent.subscribe(event => {
998
+ if (event.type !== "message_end") return;
999
+ if (event.message.role === "assistant") this.#recordAdvisorCost(advisor, event.message);
1000
+ advisor.recorder.record(event.message);
1001
+ });
1002
+ }
1003
+
1004
+ /** Switch one advisor model while preserving its context and effort invariants. */
1005
+ #setAdvisorModel(advisor: ActiveAdvisor, model: Model, requestedThinkingLevel: ThinkingLevel): ThinkingLevel {
1006
+ const resolvedThinkingLevel = resolveThinkingLevelForModel(model, requestedThinkingLevel);
1007
+ const nextThinkingLevel = resolvedThinkingLevel ?? ThinkingLevel.Inherit;
1008
+ advisor.agent.setModel(model);
1009
+ advisor.agent.setThinkingLevel(toReasoningEffort(nextThinkingLevel));
1010
+ advisor.agent.setDisableReasoning(shouldDisableReasoning(nextThinkingLevel));
1011
+ advisor.agent.appendOnlyContext?.invalidateForModelChange();
1012
+ advisor.model = model;
1013
+ advisor.thinkingLevel = nextThinkingLevel;
1014
+ return nextThinkingLevel;
1015
+ }
1016
+
1017
+ /** Restore an advisor's configured primary once its fallback cooldown expires. */
1018
+ async #maybeRestoreAdvisorRetryFallbackPrimary(advisor: ActiveAdvisor): Promise<void> {
1019
+ const fallback = advisor.retryFallback;
1020
+ if (!fallback || getRetryFallbackRevertPolicy(this.#host.settings) !== "cooldown-expiry") return;
1021
+
1022
+ const originalSelector = parseRetryFallbackSelector(fallback.originalSelector, this.#host.modelRegistry);
1023
+ if (!originalSelector) {
1024
+ advisor.retryFallback = undefined;
1025
+ advisor.retryFallbackPendingSuccess = false;
1026
+ return;
1027
+ }
1028
+ const currentSelector = formatRetryFallbackSelector(advisor.agent.state.model, advisor.thinkingLevel);
1029
+ if (currentSelector === originalSelector.raw) {
1030
+ if (!this.#host.isRetryFallbackSelectorSuppressed(originalSelector)) {
1031
+ advisor.retryFallback = undefined;
1032
+ advisor.retryFallbackPendingSuccess = false;
1033
+ }
1034
+ return;
1035
+ }
1036
+ if (this.#host.isRetryFallbackSelectorSuppressed(originalSelector)) return;
1037
+
1038
+ const resolvedPrimary = resolveModelOverride(
1039
+ [originalSelector.raw],
1040
+ this.#host.modelRegistry,
1041
+ this.#host.settings,
1042
+ );
1043
+ const primaryModel =
1044
+ resolvedPrimary.model ?? this.#host.modelRegistry.find(originalSelector.provider, originalSelector.id);
1045
+ if (!primaryModel) return;
1046
+ const apiKey = await this.#host.modelRegistry.getApiKey(primaryModel, advisor.providerSessionId);
1047
+ if (!apiKey) return;
1048
+
1049
+ const thinkingToApply =
1050
+ advisor.thinkingLevel === fallback.lastAppliedThinkingLevel
1051
+ ? fallback.originalThinkingLevel
1052
+ : advisor.thinkingLevel;
1053
+ this.#setAdvisorModel(advisor, primaryModel, thinkingToApply);
1054
+ this.#host.settings.getStorage()?.recordModelUsage(formatModelStringWithRouting(primaryModel));
1055
+ advisor.retryFallback = undefined;
1056
+ advisor.retryFallbackPendingSuccess = false;
1057
+ }
1058
+
1059
+ /**
1060
+ * Apply the advisor's configured provider-failure fallback chain after
1061
+ * same-provider credential rotation has no usable sibling.
1062
+ */
1063
+ async #recoverAdvisorTurn(
1064
+ advisor: ActiveAdvisor,
1065
+ error: unknown,
1066
+ failedMessages: readonly AgentMessage[],
1067
+ ): Promise<boolean> {
1068
+ if (error instanceof AdvisorOutputQuarantinedError) return false;
1069
+
1070
+ const failedMessage = failedMessages.findLast(
1071
+ (message): message is AssistantMessage => message.role === "assistant",
1072
+ );
1073
+ if (failedMessage?.stopReason !== "error") {
1074
+ // Stream setup can reject before any assistant turn is recorded (e.g.
1075
+ // an HTTP 429 thrown from prompt()); classify the raw error so a
1076
+ // structural usage limit still marks the exhausted credential.
1077
+ const message = error instanceof Error ? error.message : String(error);
1078
+ if (!AIError.isUsageLimit(error) && !isUsageLimitOutcome(extractHttpStatusFromError(error), message)) {
1079
+ return false;
1080
+ }
1081
+ const currentModel = advisor.agent.state.model;
1082
+ const outcome = await this.#host.modelRegistry.authStorage.markUsageLimitReached(
1083
+ currentModel.provider,
1084
+ advisor.providerSessionId,
1085
+ {
1086
+ retryAfterMs: extractRetryHint(undefined, message),
1087
+ baseUrl: currentModel.baseUrl,
1088
+ modelId: currentModel.id,
1089
+ },
1090
+ );
1091
+ return outcome.switched;
1092
+ }
1093
+ if (failedMessage.content.some(block => block.type === "toolCall")) return false;
1094
+
1095
+ const currentModel = advisor.agent.state.model;
1096
+ const message = failedMessage.errorMessage ?? (error instanceof Error ? error.message : String(error));
1097
+ const errorId = AIError.classifyMessage({
1098
+ api: currentModel.api,
1099
+ errorId: failedMessage.errorId,
1100
+ errorMessage: message,
1101
+ errorStatus: failedMessage.errorStatus,
1102
+ });
1103
+ if (AIError.is(errorId, AIError.Flag.Abort) || AIError.is(errorId, AIError.Flag.UserInterrupt)) return false;
1104
+ if (AIError.isContextOverflow(failedMessage, currentModel.contextWindow ?? 0)) return false;
1105
+
1106
+ const currentSelector = formatRetryFallbackSelector(currentModel, advisor.thinkingLevel);
1107
+
1108
+ const retryAfterMs = extractRetryHint(undefined, message);
1109
+ if (
1110
+ AIError.is(errorId, AIError.Flag.UsageLimit) ||
1111
+ isUsageLimitOutcome(extractHttpStatusFromError(error), message)
1112
+ ) {
1113
+ const outcome = await this.#host.modelRegistry.authStorage.markUsageLimitReached(
1114
+ currentModel.provider,
1115
+ advisor.providerSessionId,
1116
+ {
1117
+ retryAfterMs,
1118
+ baseUrl: currentModel.baseUrl,
1119
+ modelId: currentModel.id,
1120
+ },
1121
+ );
1122
+ if (outcome.switched) return true;
1123
+ }
1124
+
1125
+ const retrySettings = this.#host.settings.getGroup("retry");
1126
+ if (!retrySettings.enabled || !retrySettings.modelFallback) return false;
1127
+ const role = advisor.retryFallback?.role ?? this.#host.resolveRetryFallbackRole(currentSelector, currentModel);
1128
+ if (!role || this.#host.findRetryFallbackCandidates(role, currentSelector, currentModel).length === 0)
1129
+ return false;
1130
+
1131
+ this.#host.noteRetryFallbackCooldown(currentSelector, retryAfterMs, message);
1132
+ for (const selector of this.#host.findRetryFallbackCandidates(role, currentSelector, currentModel)) {
1133
+ if (this.#host.isRetryFallbackSelectorSuppressed(selector)) continue;
1134
+ const resolved = resolveModelOverride([selector.raw], this.#host.modelRegistry, this.#host.settings);
1135
+ const candidate = resolved.model ?? this.#host.modelRegistry.find(selector.provider, selector.id);
1136
+ if (!candidate || modelsAreEqual(candidate, currentModel)) continue;
1137
+ const apiKey = await this.#host.modelRegistry.getApiKey(candidate, advisor.providerSessionId);
1138
+ if (!apiKey) continue;
1139
+
1140
+ const originalThinkingLevel = advisor.thinkingLevel;
1141
+ const requestedThinkingLevel = selector.thinkingLevel ?? originalThinkingLevel;
1142
+ const nextThinkingLevel = this.#setAdvisorModel(advisor, candidate, requestedThinkingLevel);
1143
+ if (advisor.retryFallback) {
1144
+ advisor.retryFallback.lastAppliedThinkingLevel = nextThinkingLevel;
1145
+ } else {
1146
+ advisor.retryFallback = {
1147
+ role,
1148
+ originalSelector: currentSelector,
1149
+ originalThinkingLevel,
1150
+ lastAppliedThinkingLevel: nextThinkingLevel,
1151
+ };
1152
+ }
1153
+ advisor.retryFallbackPendingSuccess = true;
1154
+ this.#host.settings.getStorage()?.recordModelUsage(formatModelStringWithRouting(candidate));
1155
+ await this.#host.emitSessionEvent({
1156
+ type: "retry_fallback_applied",
1157
+ from: currentSelector,
1158
+ to: selector.raw,
1159
+ role,
1160
+ });
1161
+ return true;
1162
+ }
1163
+ return false;
1164
+ }
1165
+
1166
+ async #promoteAdvisorContextModel(advisor: ActiveAdvisor, currentModel: Model): Promise<boolean> {
1167
+ const promotionSettings = this.#host.settings.getGroup("contextPromotion");
1168
+ if (!promotionSettings.enabled) return false;
1169
+ const contextWindow = currentModel.contextWindow ?? 0;
1170
+ if (contextWindow <= 0) return false;
1171
+ const targetModel = await this.#host.resolveContextPromotionTarget(currentModel, contextWindow);
1172
+ if (!targetModel) return false;
1173
+
1174
+ // Preserve this advisor's own thinking level (a configured `model:...:high`
1175
+ // keeps its suffix across a promotion); only the model changes.
1176
+ const advisorThinkingLevel = advisor.thinkingLevel;
1177
+ try {
1178
+ this.#setAdvisorModel(advisor, targetModel, advisorThinkingLevel);
1179
+ logger.debug("Advisor context promotion switched model on overflow", {
1180
+ advisor: advisor.name,
1181
+ from: `${currentModel.provider}/${currentModel.id}`,
1182
+ to: `${targetModel.provider}/${targetModel.id}`,
1183
+ });
1184
+ return true;
1185
+ } catch (error) {
1186
+ logger.warn("Advisor context promotion failed", {
1187
+ advisor: advisor.name,
1188
+ from: `${currentModel.provider}/${currentModel.id}`,
1189
+ to: `${targetModel.provider}/${targetModel.id}`,
1190
+ error: String(error),
1191
+ });
1192
+ return false;
1193
+ }
1194
+ }
1195
+
1196
+ async #maintainAdvisorContext(advisor: ActiveAdvisor, incomingTokens: number): Promise<boolean> {
1197
+ await this.#maybeRestoreAdvisorRetryFallbackPrimary(advisor);
1198
+ const agent = advisor.agent;
1199
+
1200
+ const compactionSettings = this.#host.settings.getGroup("compaction");
1201
+ if (compactionSettings.strategy === "off") return false;
1202
+ if (!compactionSettings.enabled) return false;
1203
+
1204
+ const advisorModel = agent.state.model;
1205
+ const contextWindow = advisorModel.contextWindow ?? 0;
1206
+ if (contextWindow <= 0) return false;
1207
+
1208
+ const messages = agent.state.messages;
1209
+ const estimateOptions = { excludeEncryptedReasoning: true } as const;
1210
+ let storedConversationTokens = 0;
1211
+ for (const message of messages) {
1212
+ storedConversationTokens += estimateTokens(message, estimateOptions);
1213
+ }
1214
+ // Provider usage (including cache reads and generated output) is the
1215
+ // trustworthy anchor for accumulated context. Add only the trailing incoming
1216
+ // delta to that arm. Floor it by a full local estimate — fixed advisor system
1217
+ // prompt, tool schemas, stored messages, and incoming delta — so provider
1218
+ // under-reporting or payload transforms cannot suppress maintenance.
1219
+ const providerContextTokens = this.#estimateAdvisorContextTokens(messages) + incomingTokens;
1220
+ const localContextTokens =
1221
+ countTokens(agent.state.systemPrompt) +
1222
+ estimateToolSchemaTokens(agent.state.tools) +
1223
+ storedConversationTokens +
1224
+ incomingTokens;
1225
+ const contextTokens = compactionContextTokens(providerContextTokens, localContextTokens);
1226
+
1227
+ if (!shouldCompact(contextTokens, contextWindow, compactionSettings)) {
1228
+ return false;
1229
+ }
1230
+
1231
+ // 1. Try promotion first
1232
+ if (await this.#promoteAdvisorContextModel(advisor, advisorModel)) {
1233
+ // Promotion succeeded, check if new model has enough space
1234
+ const newModel = agent.state.model;
1235
+ const newWindow = newModel.contextWindow ?? 0;
1236
+ if (newWindow > 0) {
1237
+ const stillNeedsCompaction = shouldCompact(contextTokens, newWindow, compactionSettings);
1238
+ if (!stillNeedsCompaction) return false;
1239
+ }
1240
+ }
1241
+
1242
+ // 2. Run compaction on advisor messages
1243
+ const pathEntries: SessionEntry[] = messages.map((message, i) => {
1244
+ const id = `msg-${i}`;
1245
+ const parentId = i > 0 ? `msg-${i - 1}` : null;
1246
+ const timestamp = String(message.timestamp || Date.now());
1247
+
1248
+ if (message.role === "compactionSummary") {
1249
+ const advisorSummary = message as AdvisorCompactionSummaryMessage;
1250
+ return {
1251
+ type: "compaction",
1252
+ id,
1253
+ parentId,
1254
+ timestamp,
1255
+ summary: message.summary,
1256
+ shortSummary: message.shortSummary,
1257
+ firstKeptEntryId: advisorSummary.firstKeptEntryId || `msg-${i + 1}`,
1258
+ tokensBefore: message.tokensBefore,
1259
+ } satisfies CompactionEntry;
1260
+ }
1261
+
1262
+ return {
1263
+ type: "message",
1264
+ id,
1265
+ parentId,
1266
+ timestamp,
1267
+ message,
1268
+ } satisfies SessionMessageEntry;
1269
+ });
1270
+
1271
+ const availableModels = this.#host.modelRegistry.getAvailable();
1272
+ const candidates = this.#host.resolveCompactionModelCandidates(advisorModel, availableModels);
1273
+ if (candidates.length === 0) {
1274
+ // No compaction candidates, fallback to re-prime
1275
+ return true;
1276
+ }
1277
+ const advisorProviderSessionId = getOrCreateAdvisorProviderSessionId(
1278
+ this.#advisorProviderSessionIds,
1279
+ this.#host.sessionId(),
1280
+ advisor.slug,
1281
+ );
1282
+ const preparation = prepareCompaction(pathEntries, compactionSettings, advisorModel);
1283
+ if (!preparation) {
1284
+ // Cannot prepare compaction, fallback to re-prime
1285
+ return true;
1286
+ }
1287
+
1288
+ const advisorCompactionThinkingLevel: ThinkingLevel | undefined = agent.state.disableReasoning
1289
+ ? ThinkingLevel.Off
1290
+ : agent.state.thinkingLevel;
1291
+
1292
+ // Advisor state is in-memory-only, so snapcompact's frame archive has no
1293
+ // stable SessionEntry preserveData slot to carry across future advisor
1294
+ // maintenance runs. Use an LLM summary even when the primary session is
1295
+ // configured for snapcompact.
1296
+
1297
+ let compactResult: CompactionResult | undefined;
1298
+ let lastError: unknown;
1299
+ // Instrument the advisor's overflow-compaction one-shot like the primary
1300
+ // compaction path so the advisor model's maintenance call also emits spans.
1301
+ const telemetry = resolveTelemetry(agent.telemetry, advisorProviderSessionId);
1302
+
1303
+ const codexCompaction = this.#host.createCodexCompactionContext({
1304
+ trigger: "auto",
1305
+ reason: "context_limit",
1306
+ phase: "pre_turn",
1307
+ });
1308
+
1309
+ for (const candidate of candidates) {
1310
+ const apiKey = await this.#host.modelRegistry.getApiKey(candidate, advisorProviderSessionId);
1311
+ if (!apiKey) continue;
1312
+ // The advisor overflow-compaction one-shot bypasses the advisor `Agent`,
1313
+ // so its installed metadata resolver never runs. Emit the same
1314
+ // `metadata.user_id` identity here (resolved per candidate provider,
1315
+ // after the session-sticky credential is selected) so summarization
1316
+ // requests carry the advisor session id like every other advisor call
1317
+ // (issue #6625).
1318
+ const advisorMetadata = advisorProviderSessionId
1319
+ ? buildSessionMetadata(advisorProviderSessionId, candidate.provider, this.#host.modelRegistry.authStorage)
1320
+ : undefined;
1321
+ try {
1322
+ compactResult = await compact(
1323
+ preparation,
1324
+ candidate,
1325
+ this.#host.modelRegistry.resolver(candidate, advisorProviderSessionId),
1326
+ undefined,
1327
+ undefined,
1328
+ {
1329
+ thinkingLevel: advisorCompactionThinkingLevel,
1330
+ convertToLlm: messages => this.#host.convertToLlmForSideRequest(messages),
1331
+ telemetry,
1332
+ tools: agent.state.tools,
1333
+ sessionId: advisorProviderSessionId,
1334
+ promptCacheKey: advisorProviderSessionId,
1335
+ metadata: advisorMetadata,
1336
+ providerSessionState: this.#host.providerSessionState,
1337
+ codexCompaction,
1338
+ },
1339
+ );
1340
+ break;
1341
+ } catch (error) {
1342
+ lastError = error;
1343
+ }
1344
+ }
1345
+
1346
+ if (!compactResult) {
1347
+ logger.warn("Advisor compaction failed, falling back to re-prime", { error: String(lastError) });
1348
+ return true;
1349
+ }
1350
+
1351
+ const summary = compactResult.summary;
1352
+ const shortSummary = compactResult.shortSummary;
1353
+ const firstKeptEntryId = compactResult.firstKeptEntryId;
1354
+ const tokensBefore = compactResult.tokensBefore;
1355
+
1356
+ // The retained messages still carry provider usage from before this
1357
+ // compaction. Record their exact array boundary on the in-memory summary so
1358
+ // only assistants appended afterward can become the next usage anchor.
1359
+ const advisorUsageAnchorStartIndex = preparation.recentMessages.length + 1;
1360
+ const summaryMessage = {
1361
+ ...createCompactionSummaryMessage(summary, tokensBefore, new Date().toISOString(), shortSummary),
1362
+ firstKeptEntryId,
1363
+ advisorUsageAnchorStartIndex,
1364
+ } satisfies AdvisorCompactionSummaryMessage;
1365
+
1366
+ agent.replaceMessages([summaryMessage, ...preparation.recentMessages]);
1367
+ return false;
1368
+ }
1369
+ /**
1370
+ * Prevent advisor notes from starting hidden primary turns while a headless
1371
+ * caller prints and drains the final primary response.
1372
+ */
1373
+ prepareForHeadlessAdvisorDrain(): void {
1374
+ this.#preserveAdvisorAdvice = true;
1375
+ }
1376
+
1377
+ async #waitForPendingAdvisorCardEvents(timeoutMs: number): Promise<boolean> {
1378
+ const deadline = Date.now() + Math.max(0, timeoutMs);
1379
+ while (this.#pendingAdvisorCardEvents.size > 0) {
1380
+ const remainingMs = deadline - Date.now();
1381
+ if (remainingMs <= 0) return false;
1382
+ const settled = Promise.allSettled([...this.#pendingAdvisorCardEvents]).then(() => true as const);
1383
+ const { promise: timedOut, resolve } = Promise.withResolvers<false>();
1384
+ const timer = setTimeout(() => resolve(false), remainingMs);
1385
+ try {
1386
+ if (!(await Promise.race([settled, timedOut]))) return false;
1387
+ } finally {
1388
+ clearTimeout(timer);
1389
+ }
1390
+ }
1391
+ return true;
1392
+ }
1393
+
1394
+ /**
1395
+ * Wait for active advisor reviews and their emitted card events before a
1396
+ * headless caller disposes the session. Returns `false` and logs work disposal
1397
+ * will abandon when the shared deadline expires or an advisor fails.
1398
+ */
1399
+ async waitForAdvisorCatchup(timeoutMs: number): Promise<boolean> {
1400
+ const deadline = Date.now() + timeoutMs;
1401
+ const results = await Promise.all(this.#advisors.map(advisor => advisor.runtime.waitForCatchup(timeoutMs, 1)));
1402
+ const cardEventsCaughtUp = await this.#waitForPendingAdvisorCardEvents(Math.max(0, deadline - Date.now()));
1403
+ const abandoned = this.#advisors.filter(
1404
+ (advisor, index) => results[index] === false && advisor.runtime.backlog > 0,
1405
+ );
1406
+ if (abandoned.length > 0 || !cardEventsCaughtUp) {
1407
+ logger.warn("advisor shutdown drain incomplete; disposal will abandon reviews or cards", {
1408
+ timeoutMs,
1409
+ advisors: abandoned.map(advisor => ({ name: advisor.name, backlog: advisor.runtime.backlog })),
1410
+ pendingAdvisorCards: this.#pendingAdvisorCardEvents.size,
1411
+ });
1412
+ return false;
1413
+ }
1414
+ return true;
1415
+ }
1416
+ /**
1417
+ * Enable or disable the advisor for this session. The setting is overridden for the session,
1418
+ * and the runtime is started or stopped to match.
1419
+ *
1420
+ * @returns true when the advisor is actively running after the call.
1421
+ */
1422
+ setAdvisorEnabled(enabled: boolean): boolean {
1423
+ this.#advisorEnabled = enabled;
1424
+ if (enabled) {
1425
+ if (this.#advisors.length > 0 && !this.#advisorRuntimeMatchesCurrentConfig()) this.#stopAdvisorRuntime();
1426
+ return this.#buildAdvisorRuntime(true);
1427
+ }
1428
+ this.#stopAdvisorRuntime();
1429
+ return false;
1430
+ }
1431
+
1432
+ /**
1433
+ * Toggle the advisor setting and start/stop the runtime accordingly.
1434
+ *
1435
+ * @returns true when the advisor is actively running after the call.
1436
+ */
1437
+ toggleAdvisorEnabled(): boolean {
1438
+ return this.setAdvisorEnabled(!this.#advisorEnabled);
1439
+ }
1440
+
1441
+ /**
1442
+ * Replace the live advisor roster from an edited `WATCHDOG.yml` (the `/advisor
1443
+ * configure` save path). Swaps the configs + shared baseline, then rebuilds the
1444
+ * runtimes in place so the change applies without a restart. When the advisor is
1445
+ * disabled the new configs are simply stored for the next enable.
1446
+ *
1447
+ * @returns the number of advisors active after the rebuild.
1448
+ */
1449
+ applyAdvisorConfigs(advisors: AdvisorConfig[], sharedInstructions: string | undefined): number {
1450
+ this.#advisorConfigs = advisors;
1451
+ this.#advisorSharedInstructions = sharedInstructions;
1452
+ if (!this.#advisorEnabled) return 0;
1453
+ this.#stopAdvisorRuntime();
1454
+ this.#buildAdvisorRuntime(true);
1455
+ return this.#advisors.length;
1456
+ }
1457
+
1458
+ /**
1459
+ * Whether the advisor setting is enabled for this session.
1460
+ */
1461
+ isAdvisorEnabled(): boolean {
1462
+ return this.#advisorEnabled;
1463
+ }
1464
+
1465
+ /**
1466
+ * Whether a live advisor agent is attached to this session. True only when
1467
+ * `advisor.enabled` is set AND a model resolved for the `advisor` role AND
1468
+ * the advisor applies to this agent kind — i.e. the actual runtime exists,
1469
+ * not merely the setting. Drives the status-line badge and `/dump advisor`.
1470
+ */
1471
+ isAdvisorActive(): boolean {
1472
+ return this.#advisors.length > 0;
1473
+ }
1474
+
1475
+ /**
1476
+ * The names of the tools available to advisors this session (the pool a
1477
+ * `/advisor configure` editor lists). The advisor is a full agent, so this is the
1478
+ * full built tool set; a tool whose optional factory returns null (e.g. lsp with
1479
+ * no servers) is absent.
1480
+ */
1481
+ getAdvisorAvailableToolNames(): string[] {
1482
+ return (this.#advisorTools ?? []).map(tool => tool.name);
1483
+ }
1484
+
1485
+ /**
1486
+ * The live advisor `Agent`, or `undefined` when no advisor runtime is
1487
+ * attached. Surfaced for diagnostics (`/dump advisor` already serializes
1488
+ * its transcript via {@link formatAdvisorHistoryAsText}) and so callers can
1489
+ * verify the advisor inherits the session's provider-shaping options
1490
+ * (`streamFn`, `promptCacheKey`, `providerSessionState`, ...).
1491
+ */
1492
+ getAdvisorAgent(): Agent | undefined {
1493
+ return this.#advisors[0]?.agent;
1494
+ }
1495
+
1496
+ /**
1497
+ * Lightweight advisor status for the status line: returns just the configured
1498
+ * flag and per-advisor name/status without computing token/cost breakdowns.
1499
+ * Avoids re-tokenizing the advisor transcript on every render frame.
1500
+ */
1501
+ getAdvisorStatusOverview(): { configured: boolean; advisors: { name: string; status: AdvisorRuntimeStatus }[] } {
1502
+ // Override stale map entries with live runtime status: failureNotified/quotaExhausted
1503
+ // clear on reset() but #advisorStatuses lags until the next build.
1504
+ const liveStatusBySlug = new Map<string, AdvisorRuntimeStatus>();
1505
+ for (const a of this.#advisors) {
1506
+ liveStatusBySlug.set(
1507
+ a.slug,
1508
+ a.runtime.quotaExhausted ? "quota_exhausted" : a.runtime.failureNotified ? "error" : "running",
1509
+ );
1510
+ }
1511
+ const advisors = [...this.#advisorStatuses.entries()].map(([slug, { name, status }]) => ({
1512
+ name,
1513
+ status: liveStatusBySlug.get(slug) ?? status,
1514
+ }));
1515
+ return { configured: this.#advisorEnabled, advisors };
1516
+ }
1517
+
1518
+ /** Return cumulative advisor cost recorded for the current session. */
1519
+ getAdvisorCost(): number {
1520
+ let cost = 0;
1521
+ for (const advisorCost of this.#advisorCosts.values()) cost += advisorCost;
1522
+ return cost;
1523
+ }
1524
+ /**
1525
+ * Return structured advisor stats for the status command and TUI panel.
1526
+ */
1527
+ getAdvisorStats(): AdvisorStats {
1528
+ const configured = this.#advisorEnabled;
1529
+ const liveAdvisors = this.#advisors.map(a => this.#computeAdvisorStat(a));
1530
+ // Build the complete roster from #advisorStatuses, which already has the
1531
+ // correct de-duped slugs as keys. Live advisors (from #advisors) carry full
1532
+ // token/cost data; disabled/no-model/quota-exhausted advisors appear as
1533
+ // skeleton entries with just name + status so the status line renders a dot.
1534
+ const liveStatBySlug = new Map(this.#advisors.map((a, i) => [a.slug, liveAdvisors[i]]));
1535
+ const roster: PerAdvisorStat[] = [];
1536
+ for (const [slug, entry] of this.#advisorStatuses) {
1537
+ const live = liveStatBySlug.get(slug);
1538
+ if (live) {
1539
+ roster.push(live);
1540
+ } else {
1541
+ roster.push({
1542
+ name: entry.name,
1543
+ status: entry.status,
1544
+ contextWindow: 0,
1545
+ contextTokens: 0,
1546
+ tokens: { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
1547
+ cost: this.#advisorCosts.get(slug) ?? 0,
1548
+ messages: { user: 0, assistant: 0, total: 0 },
1549
+ });
1550
+ }
1551
+ }
1552
+ const active = liveAdvisors.length > 0;
1553
+ const cost = this.getAdvisorCost();
1554
+ if (liveAdvisors.length === 0) {
1555
+ return {
1556
+ configured,
1557
+ active,
1558
+ contextWindow: 0,
1559
+ contextTokens: 0,
1560
+ tokens: { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
1561
+ cost,
1562
+ messages: { user: 0, assistant: 0, total: 0 },
1563
+ advisors: roster,
1564
+ };
1565
+ }
1566
+ const tokens = { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
1567
+ const messages = { user: 0, assistant: 0, total: 0 };
1568
+ let contextTokens = 0;
1569
+ for (const a of liveAdvisors) {
1570
+ tokens.input += a.tokens.input;
1571
+ tokens.output += a.tokens.output;
1572
+ tokens.reasoning += a.tokens.reasoning;
1573
+ tokens.cacheRead += a.tokens.cacheRead;
1574
+ tokens.cacheWrite += a.tokens.cacheWrite;
1575
+ tokens.total += a.tokens.total;
1576
+ messages.user += a.messages.user;
1577
+ messages.assistant += a.messages.assistant;
1578
+ messages.total += a.messages.total;
1579
+ contextTokens += a.contextTokens;
1580
+ }
1581
+ // Single-advisor displays read the top-level model/window directly; surface the
1582
+ // first advisor's so the legacy status line stays byte-identical.
1583
+ return {
1584
+ configured,
1585
+ active,
1586
+ model: liveAdvisors[0].model,
1587
+ contextWindow: liveAdvisors[0].contextWindow,
1588
+ contextTokens,
1589
+ tokens,
1590
+ cost,
1591
+ messages,
1592
+ advisors: roster,
1593
+ };
1594
+ }
1595
+
1596
+ /** Compute one advisor's stats slice (tokens, cost, context, message counts). */
1597
+ #computeAdvisorStat(advisor: ActiveAdvisor): PerAdvisorStat {
1598
+ const model = advisor.agent.state.model;
1599
+ const messages = advisor.agent.state.messages;
1600
+ const contextTokens = this.#estimateAdvisorContextTokens(messages);
1601
+ let input = 0;
1602
+ let output = 0;
1603
+ let reasoning = 0;
1604
+ let cacheRead = 0;
1605
+ let cacheWrite = 0;
1606
+ let totalTokens = 0;
1607
+ let user = 0;
1608
+ let assistant = 0;
1609
+ for (const message of messages) {
1610
+ if (message.role === "user") user++;
1611
+ if (message.role === "assistant") {
1612
+ assistant++;
1613
+ const assistantMsg = message as AssistantMessage;
1614
+ input += assistantMsg.usage.input;
1615
+ output += assistantMsg.usage.output;
1616
+ reasoning += assistantMsg.usage.reasoningTokens ?? 0;
1617
+ cacheRead += assistantMsg.usage.cacheRead;
1618
+ cacheWrite += assistantMsg.usage.cacheWrite;
1619
+ totalTokens += assistantMsg.usage.totalTokens;
1620
+ }
1621
+ }
1622
+ return {
1623
+ name: advisor.name,
1624
+ status: advisor.runtime.quotaExhausted
1625
+ ? "quota_exhausted"
1626
+ : advisor.runtime.failureNotified
1627
+ ? "error"
1628
+ : "running",
1629
+ model,
1630
+ contextWindow: model.contextWindow ?? 0,
1631
+ contextTokens,
1632
+ tokens: { input, output, reasoning, cacheRead, cacheWrite, total: totalTokens },
1633
+ cost: this.#advisorCosts.get(advisor.slug) ?? 0,
1634
+ messages: { user, assistant, total: messages.length },
1635
+ sessionId: advisor.agent.sessionId,
1636
+ };
1637
+ }
1638
+
1639
+ /**
1640
+ * Format a concise advisor status line for ACP/text output.
1641
+ */
1642
+ formatAdvisorStatus(): string {
1643
+ const stats = this.getAdvisorStats();
1644
+ if (!stats.active && stats.advisors.length === 0) {
1645
+ return stats.configured
1646
+ ? "Advisor setting is enabled, but no model is assigned to the 'advisor' role."
1647
+ : "Advisor is disabled.";
1648
+ }
1649
+ if (stats.advisors.length <= 1) {
1650
+ const s = stats.advisors[0];
1651
+ if (s && s.status === "no_model") {
1652
+ return stats.configured
1653
+ ? "Advisor setting is enabled, but no model is assigned to the 'advisor' role."
1654
+ : "Advisor is disabled.";
1655
+ }
1656
+ const contextLine =
1657
+ s.contextWindow > 0
1658
+ ? `Context: ${s.contextTokens.toLocaleString()} / ${s.contextWindow.toLocaleString()} tokens (${Math.round((s.contextTokens / s.contextWindow) * 100)}%)`
1659
+ : `Context: ${s.contextTokens.toLocaleString()} tokens`;
1660
+ const spendParts = [`${s.tokens.input.toLocaleString()} input`, `${s.tokens.output.toLocaleString()} output`];
1661
+ if (s.tokens.cacheRead > 0) spendParts.push(`${s.tokens.cacheRead.toLocaleString()} cache read`);
1662
+ if (s.tokens.cacheWrite > 0) spendParts.push(`${s.tokens.cacheWrite.toLocaleString()} cache write`);
1663
+ const spendLine = `Spend: ${spendParts.join(", ")}, $${stats.cost.toFixed(4)}`;
1664
+ if (!s.model || s.status !== "running") return `Advisor "${s.name}" is ${s.status.replace("_", " ")}.`;
1665
+ return `Advisor is enabled (${s.model.provider}/${s.model.id}). ${contextLine}. ${spendLine}.`;
1666
+ }
1667
+ const lines = [`Advisors enabled (${stats.advisors.length}):`];
1668
+ for (const s of stats.advisors) {
1669
+ const ctx =
1670
+ s.contextWindow > 0
1671
+ ? `${s.contextTokens.toLocaleString()} / ${s.contextWindow.toLocaleString()} (${Math.round((s.contextTokens / s.contextWindow) * 100)}%)`
1672
+ : `${s.contextTokens.toLocaleString()}`;
1673
+ lines.push(
1674
+ ` • ${s.name}${s.model && s.status === "running" ? ` (${s.model.provider}/${s.model.id})` : ` [${s.status}]`} — context ${ctx} tokens, $${s.cost.toFixed(4)}`,
1675
+ );
1676
+ }
1677
+ lines.push(
1678
+ `Totals: ${stats.tokens.input.toLocaleString()} input, ${stats.tokens.output.toLocaleString()} output, $${stats.cost.toFixed(4)}.`,
1679
+ );
1680
+ return lines.join("\n");
1681
+ }
1682
+
1683
+ /**
1684
+ * Estimate the advisor's current context tokens. A successful provider usage
1685
+ * after the latest advisor compaction is ground truth for the prompt plus its
1686
+ * generated output; only messages after that anchor are estimated. Usage from
1687
+ * retained pre-compaction messages is stale and must not immediately retrigger
1688
+ * maintenance on the newly compacted context.
1689
+ */
1690
+ #estimateAdvisorContextTokens(messages: AgentMessage[]): number {
1691
+ let usageAnchorStartIndex = 0;
1692
+ for (let i = messages.length - 1; i >= 0; i--) {
1693
+ const message = messages[i];
1694
+ if (message.role !== "compactionSummary") continue;
1695
+ const advisorSummary = message as AdvisorCompactionSummaryMessage;
1696
+ // Advisor summaries created before this runtime-only boundary existed have
1697
+ // no trustworthy way to distinguish retained from newly appended messages.
1698
+ // Conservatively ignore every current assistant until the next compaction.
1699
+ usageAnchorStartIndex = advisorSummary.advisorUsageAnchorStartIndex ?? messages.length;
1700
+ break;
1701
+ }
1702
+
1703
+ let lastUsageIndex: number | undefined;
1704
+ let lastUsage: AssistantMessage["usage"] | undefined;
1705
+ for (let i = messages.length - 1; i >= usageAnchorStartIndex; i--) {
1706
+ const message = messages[i];
1707
+ if (message.role !== "assistant") continue;
1708
+ const assistant = message as AssistantMessage;
1709
+ if (assistant.stopReason !== "aborted" && assistant.stopReason !== "error" && assistant.usage) {
1710
+ lastUsage = assistant.usage;
1711
+ lastUsageIndex = i;
1712
+ break;
1713
+ }
1714
+ }
1715
+
1716
+ const estimateOptions = { excludeEncryptedReasoning: true } as const;
1717
+ if (!lastUsage || lastUsageIndex === undefined) {
1718
+ let estimated = 0;
1719
+ for (const message of messages) {
1720
+ estimated += estimateTokens(message, estimateOptions);
1721
+ }
1722
+ return estimated;
1723
+ }
1724
+ let trailingTokens = 0;
1725
+ for (let i = lastUsageIndex + 1; i < messages.length; i++) {
1726
+ trailingTokens += estimateTokens(messages[i], estimateOptions);
1727
+ }
1728
+ return calculateContextTokens(lastUsage) + trailingTokens;
1729
+ }
1730
+
1731
+ /**
1732
+ * Format the advisor agent's own transcript (its system prompt, config,
1733
+ * tools, and the markdown deltas it received plus its thinking/advise/read
1734
+ * calls) as plain text — the advisor-side equivalent of
1735
+ * {@link formatSessionAsText}. Returns null when no advisor is active.
1736
+ */
1737
+ formatAdvisorHistoryAsText(options?: { compact?: boolean }): string | null {
1738
+ if (this.#advisors.length === 0) return null;
1739
+ const dump = (a: ActiveAdvisor): string =>
1740
+ options?.compact
1741
+ ? formatSessionHistoryMarkdown(a.agent.state.messages)
1742
+ : formatSessionDumpText({
1743
+ messages: a.agent.state.messages,
1744
+ systemPrompt: a.agent.state.systemPrompt,
1745
+ model: a.agent.state.model,
1746
+ thinkingLevel: a.agent.state.thinkingLevel,
1747
+ tools: a.agent.state.tools,
1748
+ });
1749
+ if (this.#advisors.length === 1) return dump(this.#advisors[0]);
1750
+ return this.#advisors
1751
+ .map(a => `### Advisor: ${a.name} (${a.agent.state.model.provider}/${a.agent.state.model.id})\n\n${dump(a)}`)
1752
+ .join("\n\n");
1753
+ }
1754
+ }