@kr78/pi-coding-agent 17.2.10

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 (1593) hide show
  1. package/CHANGELOG.md +14861 -0
  2. package/README.md +35 -0
  3. package/dist/CHANGELOG-chtdxh1z.md +14861 -0
  4. package/dist/cli.js +20483 -0
  5. package/dist/template-c2hyaytt.js +1653 -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 +78 -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 +587 -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 +123 -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 +205 -0
  62. package/scripts/measure-prompt-tokens.ts +63 -0
  63. package/scripts/omp +51 -0
  64. package/scripts/omp.ts +19 -0
  65. package/scripts/security-compare.ts +40 -0
  66. package/src/advisor/advise-tool.ts +234 -0
  67. package/src/advisor/config.ts +341 -0
  68. package/src/advisor/emission-guard.ts +172 -0
  69. package/src/advisor/index.ts +6 -0
  70. package/src/advisor/runtime.ts +1412 -0
  71. package/src/advisor/transcript-recorder.ts +215 -0
  72. package/src/advisor/watchdog.ts +135 -0
  73. package/src/async/index.ts +1 -0
  74. package/src/async/job-manager.ts +847 -0
  75. package/src/auto-thinking/classifier.ts +220 -0
  76. package/src/autolearn/controller.ts +152 -0
  77. package/src/autolearn/managed-skills.ts +255 -0
  78. package/src/autoresearch/command-resume.md +14 -0
  79. package/src/autoresearch/dashboard.ts +436 -0
  80. package/src/autoresearch/git.ts +331 -0
  81. package/src/autoresearch/helpers.ts +218 -0
  82. package/src/autoresearch/index.ts +541 -0
  83. package/src/autoresearch/prompt-setup.md +43 -0
  84. package/src/autoresearch/prompt.md +103 -0
  85. package/src/autoresearch/resume-message.md +10 -0
  86. package/src/autoresearch/state.ts +273 -0
  87. package/src/autoresearch/storage.ts +700 -0
  88. package/src/autoresearch/tools/init-experiment.ts +268 -0
  89. package/src/autoresearch/tools/log-experiment.ts +520 -0
  90. package/src/autoresearch/tools/run-experiment.ts +407 -0
  91. package/src/autoresearch/tools/update-notes.ts +109 -0
  92. package/src/autoresearch/types.ts +168 -0
  93. package/src/capability/context-file.ts +44 -0
  94. package/src/capability/extension-module.ts +34 -0
  95. package/src/capability/extension.ts +47 -0
  96. package/src/capability/fs.ts +117 -0
  97. package/src/capability/hook.ts +40 -0
  98. package/src/capability/index.ts +467 -0
  99. package/src/capability/instruction.ts +37 -0
  100. package/src/capability/mcp.ts +115 -0
  101. package/src/capability/prompt.ts +35 -0
  102. package/src/capability/rule-buckets.ts +66 -0
  103. package/src/capability/rule.ts +298 -0
  104. package/src/capability/settings.ts +34 -0
  105. package/src/capability/skill.ts +69 -0
  106. package/src/capability/slash-command.ts +40 -0
  107. package/src/capability/ssh.ts +41 -0
  108. package/src/capability/system-prompt.ts +34 -0
  109. package/src/capability/tool.ts +38 -0
  110. package/src/capability/types.ts +187 -0
  111. package/src/cleanse/agent.ts +226 -0
  112. package/src/cleanse/balance.ts +79 -0
  113. package/src/cleanse/checkers.ts +996 -0
  114. package/src/cleanse/index.ts +190 -0
  115. package/src/cleanse/loop.ts +51 -0
  116. package/src/cleanse/parsers.ts +726 -0
  117. package/src/cleanse/progress.ts +50 -0
  118. package/src/cleanse/prompts/assignment.md +47 -0
  119. package/src/cleanse/types.ts +72 -0
  120. package/src/cli/agents-cli.ts +138 -0
  121. package/src/cli/args.ts +368 -0
  122. package/src/cli/auth-broker-cli.ts +940 -0
  123. package/src/cli/auth-gateway-cli.ts +674 -0
  124. package/src/cli/bench-cli.ts +990 -0
  125. package/src/cli/browser-relay-cli.ts +119 -0
  126. package/src/cli/classify-install-target.ts +76 -0
  127. package/src/cli/claude-trace-cli.ts +795 -0
  128. package/src/cli/command-help.ts +107 -0
  129. package/src/cli/commands/init-xdg.ts +27 -0
  130. package/src/cli/completion-gen.ts +550 -0
  131. package/src/cli/config-cli.ts +459 -0
  132. package/src/cli/dry-balance-cli.ts +864 -0
  133. package/src/cli/extension-flags.ts +48 -0
  134. package/src/cli/file-processor.ts +132 -0
  135. package/src/cli/flag-tables.ts +367 -0
  136. package/src/cli/gallery-cli.ts +272 -0
  137. package/src/cli/gallery-fixtures/agentic.ts +420 -0
  138. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  139. package/src/cli/gallery-fixtures/edit.ts +254 -0
  140. package/src/cli/gallery-fixtures/fs.ts +245 -0
  141. package/src/cli/gallery-fixtures/index.ts +40 -0
  142. package/src/cli/gallery-fixtures/interaction.ts +46 -0
  143. package/src/cli/gallery-fixtures/memory.ts +81 -0
  144. package/src/cli/gallery-fixtures/misc.ts +177 -0
  145. package/src/cli/gallery-fixtures/search.ts +135 -0
  146. package/src/cli/gallery-fixtures/shell.ts +241 -0
  147. package/src/cli/gallery-fixtures/types.ts +57 -0
  148. package/src/cli/gallery-fixtures/web.ts +158 -0
  149. package/src/cli/gallery-screenshot.ts +279 -0
  150. package/src/cli/gc-cli.ts +1566 -0
  151. package/src/cli/grep-cli.ts +161 -0
  152. package/src/cli/grievances-cli.ts +256 -0
  153. package/src/cli/help-extra.ts +89 -0
  154. package/src/cli/initial-message.ts +58 -0
  155. package/src/cli/models-cli.ts +385 -0
  156. package/src/cli/plugin-cli.ts +996 -0
  157. package/src/cli/profile-alias.ts +369 -0
  158. package/src/cli/profile-bootstrap.ts +233 -0
  159. package/src/cli/read-cli.ts +99 -0
  160. package/src/cli/session-picker.ts +110 -0
  161. package/src/cli/setup-cli.ts +312 -0
  162. package/src/cli/setup-model-picker.ts +43 -0
  163. package/src/cli/shell-cli.ts +176 -0
  164. package/src/cli/ssh-cli.ts +179 -0
  165. package/src/cli/startup-cwd.ts +58 -0
  166. package/src/cli/stats-cli.ts +229 -0
  167. package/src/cli/thinking-levels.ts +7 -0
  168. package/src/cli/tiny-models-cli.ts +153 -0
  169. package/src/cli/ttsr-cli.ts +1013 -0
  170. package/src/cli/update-cli.ts +1184 -0
  171. package/src/cli/usage-cli.ts +1084 -0
  172. package/src/cli/usage-error.ts +7 -0
  173. package/src/cli/web-search-cli.ts +144 -0
  174. package/src/cli/worktree-cli.ts +311 -0
  175. package/src/cli-commands.ts +308 -0
  176. package/src/cli.ts +428 -0
  177. package/src/collab/crypto.ts +63 -0
  178. package/src/collab/display-name.ts +13 -0
  179. package/src/collab/guest.ts +764 -0
  180. package/src/collab/host.ts +692 -0
  181. package/src/collab/protocol.ts +296 -0
  182. package/src/collab/relay-client.ts +282 -0
  183. package/src/collab/replication-shrink.ts +111 -0
  184. package/src/commands/acp.ts +35 -0
  185. package/src/commands/agents.ts +58 -0
  186. package/src/commands/auth-broker.ts +100 -0
  187. package/src/commands/auth-gateway.ts +70 -0
  188. package/src/commands/bench.ts +64 -0
  189. package/src/commands/browser-relay.ts +53 -0
  190. package/src/commands/cleanse.ts +45 -0
  191. package/src/commands/commit.ts +47 -0
  192. package/src/commands/complete.ts +67 -0
  193. package/src/commands/completions.ts +61 -0
  194. package/src/commands/config.ts +52 -0
  195. package/src/commands/dry-balance.ts +43 -0
  196. package/src/commands/gallery.ts +61 -0
  197. package/src/commands/gc.ts +47 -0
  198. package/src/commands/grep.ts +49 -0
  199. package/src/commands/grievances.ts +52 -0
  200. package/src/commands/install.ts +107 -0
  201. package/src/commands/join.ts +40 -0
  202. package/src/commands/launch-help.ts +116 -0
  203. package/src/commands/launch.ts +34 -0
  204. package/src/commands/models.ts +61 -0
  205. package/src/commands/plugin.ts +79 -0
  206. package/src/commands/read.ts +39 -0
  207. package/src/commands/say.ts +146 -0
  208. package/src/commands/setup.ts +68 -0
  209. package/src/commands/share.ts +71 -0
  210. package/src/commands/shell.ts +30 -0
  211. package/src/commands/ssh.ts +61 -0
  212. package/src/commands/stats.ts +30 -0
  213. package/src/commands/tiny-models.ts +36 -0
  214. package/src/commands/token.ts +164 -0
  215. package/src/commands/ttsr.ts +125 -0
  216. package/src/commands/update.ts +34 -0
  217. package/src/commands/usage.ts +55 -0
  218. package/src/commands/web-search.ts +43 -0
  219. package/src/commands/worktree.ts +63 -0
  220. package/src/commit/agentic/agent.ts +322 -0
  221. package/src/commit/agentic/fallback.ts +96 -0
  222. package/src/commit/agentic/index.ts +383 -0
  223. package/src/commit/agentic/lock-files.ts +107 -0
  224. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  225. package/src/commit/agentic/prompts/session-user.md +25 -0
  226. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  227. package/src/commit/agentic/prompts/system.md +38 -0
  228. package/src/commit/agentic/state.ts +60 -0
  229. package/src/commit/agentic/tools/analyze-file.ts +148 -0
  230. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  231. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  232. package/src/commit/agentic/tools/git-overview.ts +62 -0
  233. package/src/commit/agentic/tools/index.ts +54 -0
  234. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  235. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  236. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  237. package/src/commit/agentic/tools/schemas.ts +11 -0
  238. package/src/commit/agentic/tools/split-commit.ts +241 -0
  239. package/src/commit/agentic/topo-sort.ts +44 -0
  240. package/src/commit/agentic/trivial.ts +51 -0
  241. package/src/commit/agentic/validation.ts +183 -0
  242. package/src/commit/analysis/conventional.ts +64 -0
  243. package/src/commit/analysis/index.ts +4 -0
  244. package/src/commit/analysis/scope.ts +242 -0
  245. package/src/commit/analysis/summary.ts +107 -0
  246. package/src/commit/analysis/validation.ts +66 -0
  247. package/src/commit/changelog/detect.ts +40 -0
  248. package/src/commit/changelog/generate.ts +101 -0
  249. package/src/commit/changelog/index.ts +234 -0
  250. package/src/commit/changelog/parse.ts +44 -0
  251. package/src/commit/cli.ts +85 -0
  252. package/src/commit/git/diff.ts +148 -0
  253. package/src/commit/index.ts +5 -0
  254. package/src/commit/map-reduce/index.ts +69 -0
  255. package/src/commit/map-reduce/map-phase.ts +193 -0
  256. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  257. package/src/commit/map-reduce/utils.ts +9 -0
  258. package/src/commit/message.ts +11 -0
  259. package/src/commit/model-selection.ts +95 -0
  260. package/src/commit/pipeline.ts +244 -0
  261. package/src/commit/prompts/analysis-system.md +148 -0
  262. package/src/commit/prompts/analysis-user.md +38 -0
  263. package/src/commit/prompts/changelog-system.md +50 -0
  264. package/src/commit/prompts/changelog-user.md +18 -0
  265. package/src/commit/prompts/file-observer-system.md +24 -0
  266. package/src/commit/prompts/file-observer-user.md +8 -0
  267. package/src/commit/prompts/reduce-system.md +50 -0
  268. package/src/commit/prompts/reduce-user.md +17 -0
  269. package/src/commit/prompts/summary-retry.md +3 -0
  270. package/src/commit/prompts/summary-system.md +38 -0
  271. package/src/commit/prompts/summary-user.md +13 -0
  272. package/src/commit/prompts/types-description.md +2 -0
  273. package/src/commit/shared-llm.ts +70 -0
  274. package/src/commit/types.ts +118 -0
  275. package/src/commit/utils/exclusions.ts +42 -0
  276. package/src/commit/utils.ts +58 -0
  277. package/src/config/api-key-resolver.ts +81 -0
  278. package/src/config/append-only-context-mode.ts +76 -0
  279. package/src/config/config-file.ts +347 -0
  280. package/src/config/inline-tool-descriptors-mode.ts +26 -0
  281. package/src/config/keybindings.ts +703 -0
  282. package/src/config/mcp-schema.json +252 -0
  283. package/src/config/model-discovery.ts +1077 -0
  284. package/src/config/model-registry.ts +2822 -0
  285. package/src/config/model-resolver.ts +2115 -0
  286. package/src/config/model-roles.ts +113 -0
  287. package/src/config/models-config-schema-bundle.ts +315 -0
  288. package/src/config/models-config-schema.ts +14 -0
  289. package/src/config/models-config.ts +130 -0
  290. package/src/config/prompt-templates.ts +205 -0
  291. package/src/config/provider-globals.ts +25 -0
  292. package/src/config/resolve-config-value.ts +95 -0
  293. package/src/config/service-tier.ts +146 -0
  294. package/src/config/settings-schema.ts +5887 -0
  295. package/src/config/settings.ts +2394 -0
  296. package/src/config.ts +242 -0
  297. package/src/cursor-bridge-tools.ts +81 -0
  298. package/src/cursor.ts +960 -0
  299. package/src/dap/client.ts +1043 -0
  300. package/src/dap/config.ts +480 -0
  301. package/src/dap/defaults.json +212 -0
  302. package/src/dap/index.ts +4 -0
  303. package/src/dap/session.ts +1841 -0
  304. package/src/dap/types.ts +611 -0
  305. package/src/debug/index.ts +584 -0
  306. package/src/debug/log-formatting.ts +58 -0
  307. package/src/debug/log-viewer.ts +966 -0
  308. package/src/debug/profiler.ts +168 -0
  309. package/src/debug/protocol-probe.ts +267 -0
  310. package/src/debug/raw-sse-buffer.ts +421 -0
  311. package/src/debug/raw-sse.ts +312 -0
  312. package/src/debug/remote-debugger.ts +151 -0
  313. package/src/debug/report-bundle.ts +411 -0
  314. package/src/debug/system-info.ts +111 -0
  315. package/src/debug/terminal-info.ts +124 -0
  316. package/src/discovery/agent-plugin-format.ts +551 -0
  317. package/src/discovery/agent-plugins.ts +341 -0
  318. package/src/discovery/agents-md.ts +67 -0
  319. package/src/discovery/agents.ts +300 -0
  320. package/src/discovery/at-imports.ts +273 -0
  321. package/src/discovery/builtin-defaults.ts +39 -0
  322. package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
  323. package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
  324. package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
  325. package/src/discovery/builtin-rules/go-ioutil.md +37 -0
  326. package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
  327. package/src/discovery/builtin-rules/go-new-expr.md +44 -0
  328. package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
  329. package/src/discovery/builtin-rules/go-range-int.md +45 -0
  330. package/src/discovery/builtin-rules/index.ts +74 -0
  331. package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
  332. package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
  333. package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
  334. package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
  335. package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
  336. package/src/discovery/builtin-rules/rs-result-type.md +20 -0
  337. package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
  338. package/src/discovery/builtin-rules/ts-import-type.md +43 -0
  339. package/src/discovery/builtin-rules/ts-no-any.md +66 -0
  340. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
  341. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
  342. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +56 -0
  343. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  344. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  345. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  346. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  347. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -0
  348. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  349. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  350. package/src/discovery/builtin.ts +945 -0
  351. package/src/discovery/claude-plugins.ts +640 -0
  352. package/src/discovery/claude.ts +591 -0
  353. package/src/discovery/cline.ts +83 -0
  354. package/src/discovery/codex.ts +553 -0
  355. package/src/discovery/contained-path.ts +78 -0
  356. package/src/discovery/cursor.ts +223 -0
  357. package/src/discovery/gemini.ts +386 -0
  358. package/src/discovery/github.ts +337 -0
  359. package/src/discovery/helpers.ts +1183 -0
  360. package/src/discovery/index.ts +82 -0
  361. package/src/discovery/mcp-json.ts +182 -0
  362. package/src/discovery/omp-extension-roots.ts +272 -0
  363. package/src/discovery/omp-plugins.ts +409 -0
  364. package/src/discovery/opencode.ts +441 -0
  365. package/src/discovery/plugin-dir-roots.ts +28 -0
  366. package/src/discovery/ssh.ts +153 -0
  367. package/src/discovery/substitute-plugin-root.ts +77 -0
  368. package/src/discovery/vscode.ts +106 -0
  369. package/src/discovery/windsurf.ts +149 -0
  370. package/src/edit/apply-patch/index.ts +87 -0
  371. package/src/edit/apply-patch/parser.ts +174 -0
  372. package/src/edit/diff.ts +1008 -0
  373. package/src/edit/edit-clipboard.ts +23 -0
  374. package/src/edit/file-snapshot-store.ts +148 -0
  375. package/src/edit/hashline/block-resolver.ts +33 -0
  376. package/src/edit/hashline/diff.ts +402 -0
  377. package/src/edit/hashline/execute.ts +313 -0
  378. package/src/edit/hashline/filesystem.ts +247 -0
  379. package/src/edit/hashline/index.ts +5 -0
  380. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  381. package/src/edit/hashline/params.ts +12 -0
  382. package/src/edit/index.ts +699 -0
  383. package/src/edit/modes/apply-patch.lark +19 -0
  384. package/src/edit/modes/apply-patch.ts +53 -0
  385. package/src/edit/modes/patch.ts +1958 -0
  386. package/src/edit/modes/replace.ts +1191 -0
  387. package/src/edit/normalize.ts +345 -0
  388. package/src/edit/notebook.ts +242 -0
  389. package/src/edit/read-file.ts +25 -0
  390. package/src/edit/renderer.ts +998 -0
  391. package/src/edit/snapshot-details.ts +77 -0
  392. package/src/edit/streaming.ts +710 -0
  393. package/src/eval/agent-bridge.ts +224 -0
  394. package/src/eval/backend-helpers.ts +48 -0
  395. package/src/eval/backend.ts +71 -0
  396. package/src/eval/bridge-timeout.ts +65 -0
  397. package/src/eval/budget-bridge.ts +48 -0
  398. package/src/eval/completion-bridge.ts +212 -0
  399. package/src/eval/concurrency-bridge.ts +34 -0
  400. package/src/eval/executor-base.ts +562 -0
  401. package/src/eval/idle-timeout.ts +91 -0
  402. package/src/eval/index.ts +6 -0
  403. package/src/eval/jl/executor.ts +551 -0
  404. package/src/eval/jl/index.ts +54 -0
  405. package/src/eval/jl/kernel.ts +236 -0
  406. package/src/eval/jl/prelude.jl +736 -0
  407. package/src/eval/jl/prelude.ts +3 -0
  408. package/src/eval/jl/runner.jl +666 -0
  409. package/src/eval/jl/runtime.ts +118 -0
  410. package/src/eval/js/context-manager.ts +872 -0
  411. package/src/eval/js/executor.ts +178 -0
  412. package/src/eval/js/index.ts +41 -0
  413. package/src/eval/js/process-entry.ts +31 -0
  414. package/src/eval/js/shared/helpers.ts +170 -0
  415. package/src/eval/js/shared/indirect-eval.ts +30 -0
  416. package/src/eval/js/shared/local-module-loader.ts +364 -0
  417. package/src/eval/js/shared/prelude.ts +2 -0
  418. package/src/eval/js/shared/prelude.txt +294 -0
  419. package/src/eval/js/shared/rewrite-imports.ts +550 -0
  420. package/src/eval/js/shared/runtime.ts +590 -0
  421. package/src/eval/js/shared/types.ts +18 -0
  422. package/src/eval/js/tool-bridge.ts +163 -0
  423. package/src/eval/js/worker-core.ts +380 -0
  424. package/src/eval/js/worker-entry.ts +37 -0
  425. package/src/eval/js/worker-protocol.ts +47 -0
  426. package/src/eval/kernel-base.ts +569 -0
  427. package/src/eval/py/display.ts +71 -0
  428. package/src/eval/py/executor.ts +643 -0
  429. package/src/eval/py/index.ts +57 -0
  430. package/src/eval/py/kernel.ts +235 -0
  431. package/src/eval/py/prelude.py +673 -0
  432. package/src/eval/py/prelude.ts +3 -0
  433. package/src/eval/py/runner.py +1425 -0
  434. package/src/eval/py/runtime.ts +276 -0
  435. package/src/eval/py/spawn-options.ts +134 -0
  436. package/src/eval/py/tool-bridge.ts +201 -0
  437. package/src/eval/rb/executor.ts +511 -0
  438. package/src/eval/rb/index.ts +54 -0
  439. package/src/eval/rb/kernel.ts +231 -0
  440. package/src/eval/rb/prelude.rb +551 -0
  441. package/src/eval/rb/prelude.ts +3 -0
  442. package/src/eval/rb/runner.rb +581 -0
  443. package/src/eval/rb/runtime.ts +132 -0
  444. package/src/eval/runtime-env.ts +104 -0
  445. package/src/eval/session-id.ts +8 -0
  446. package/src/eval/types.ts +48 -0
  447. package/src/exa/index.ts +2 -0
  448. package/src/exa/mcp-client.ts +370 -0
  449. package/src/exa/types.ts +69 -0
  450. package/src/exec/bash-executor.ts +627 -0
  451. package/src/exec/direnv.ts +145 -0
  452. package/src/exec/exec.ts +53 -0
  453. package/src/exec/non-interactive-env.ts +118 -0
  454. package/src/export/custom-share.ts +65 -0
  455. package/src/export/html/args.ts +20 -0
  456. package/src/export/html/index.ts +320 -0
  457. package/src/export/html/share-loader.js +102 -0
  458. package/src/export/html/template.css +1355 -0
  459. package/src/export/html/template.html +55 -0
  460. package/src/export/html/template.js +1653 -0
  461. package/src/export/html/tool-views.generated.js +35 -0
  462. package/src/export/html/vendor/highlight.min.js +1213 -0
  463. package/src/export/html/vendor/marked.min.js +6 -0
  464. package/src/export/html/web-palette.ts +126 -0
  465. package/src/export/share.ts +686 -0
  466. package/src/export/ttsr.ts +590 -0
  467. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  468. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  469. package/src/extensibility/custom-commands/index.ts +2 -0
  470. package/src/extensibility/custom-commands/loader.ts +242 -0
  471. package/src/extensibility/custom-commands/types.ts +119 -0
  472. package/src/extensibility/custom-tools/index.ts +7 -0
  473. package/src/extensibility/custom-tools/loader.ts +301 -0
  474. package/src/extensibility/custom-tools/types.ts +287 -0
  475. package/src/extensibility/custom-tools/wrapper.ts +50 -0
  476. package/src/extensibility/extensions/compact-handler.ts +40 -0
  477. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  478. package/src/extensibility/extensions/index.ts +16 -0
  479. package/src/extensibility/extensions/load-errors.ts +13 -0
  480. package/src/extensibility/extensions/loader.ts +663 -0
  481. package/src/extensibility/extensions/managed-timers.ts +83 -0
  482. package/src/extensibility/extensions/model-api.ts +39 -0
  483. package/src/extensibility/extensions/runner.ts +1396 -0
  484. package/src/extensibility/extensions/types.ts +1603 -0
  485. package/src/extensibility/extensions/wrapper.ts +395 -0
  486. package/src/extensibility/hooks/index.ts +6 -0
  487. package/src/extensibility/hooks/loader.ts +243 -0
  488. package/src/extensibility/hooks/runner.ts +425 -0
  489. package/src/extensibility/hooks/tool-wrapper.ts +124 -0
  490. package/src/extensibility/hooks/types.ts +612 -0
  491. package/src/extensibility/legacy-pi-ai-shim.ts +161 -0
  492. package/src/extensibility/legacy-pi-coding-agent-shim.ts +1460 -0
  493. package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
  494. package/src/extensibility/legacy-typebox.ts +101 -0
  495. package/src/extensibility/plugins/bun-git-cache.ts +91 -0
  496. package/src/extensibility/plugins/doctor.ts +65 -0
  497. package/src/extensibility/plugins/git-url.ts +367 -0
  498. package/src/extensibility/plugins/index.ts +9 -0
  499. package/src/extensibility/plugins/installer.ts +201 -0
  500. package/src/extensibility/plugins/legacy-pi-compat.ts +2643 -0
  501. package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
  502. package/src/extensibility/plugins/loader.ts +535 -0
  503. package/src/extensibility/plugins/manager.ts +1142 -0
  504. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  505. package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
  506. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  507. package/src/extensibility/plugins/marketplace/manager.ts +927 -0
  508. package/src/extensibility/plugins/marketplace/registry.ts +192 -0
  509. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  510. package/src/extensibility/plugins/marketplace/types.ts +192 -0
  511. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  512. package/src/extensibility/plugins/parser.ts +107 -0
  513. package/src/extensibility/plugins/runtime-config.ts +9 -0
  514. package/src/extensibility/plugins/types.ts +194 -0
  515. package/src/extensibility/session-handler-types.ts +21 -0
  516. package/src/extensibility/shared-events.ts +401 -0
  517. package/src/extensibility/skills.ts +531 -0
  518. package/src/extensibility/slash-commands.ts +131 -0
  519. package/src/extensibility/tool-event-input.ts +80 -0
  520. package/src/extensibility/tool-proxy.ts +28 -0
  521. package/src/extensibility/utils.ts +192 -0
  522. package/src/goals/index.ts +3 -0
  523. package/src/goals/runtime.ts +521 -0
  524. package/src/goals/state.ts +37 -0
  525. package/src/goals/tools/goal-tool.ts +251 -0
  526. package/src/hindsight/backend.ts +354 -0
  527. package/src/hindsight/bank.ts +156 -0
  528. package/src/hindsight/client.ts +680 -0
  529. package/src/hindsight/config.ts +193 -0
  530. package/src/hindsight/content.ts +266 -0
  531. package/src/hindsight/index.ts +8 -0
  532. package/src/hindsight/mental-models.ts +429 -0
  533. package/src/hindsight/seeds.json +32 -0
  534. package/src/hindsight/state.ts +530 -0
  535. package/src/hindsight/transcript.ts +71 -0
  536. package/src/index.ts +66 -0
  537. package/src/internal-urls/agent-protocol.ts +180 -0
  538. package/src/internal-urls/artifact-protocol.ts +151 -0
  539. package/src/internal-urls/docs-index.ts +102 -0
  540. package/src/internal-urls/filesystem-resource.ts +34 -0
  541. package/src/internal-urls/history-protocol.ts +198 -0
  542. package/src/internal-urls/index.ts +28 -0
  543. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  544. package/src/internal-urls/json-query.ts +126 -0
  545. package/src/internal-urls/local-protocol.ts +471 -0
  546. package/src/internal-urls/mcp-protocol.ts +168 -0
  547. package/src/internal-urls/memory-protocol.ts +380 -0
  548. package/src/internal-urls/omp-protocol.ts +94 -0
  549. package/src/internal-urls/parse.ts +103 -0
  550. package/src/internal-urls/registry-helpers.ts +132 -0
  551. package/src/internal-urls/router.ts +153 -0
  552. package/src/internal-urls/rule-protocol.ts +45 -0
  553. package/src/internal-urls/security-protocol.ts +261 -0
  554. package/src/internal-urls/skill-protocol.ts +131 -0
  555. package/src/internal-urls/ssh-protocol.ts +368 -0
  556. package/src/internal-urls/types.ts +196 -0
  557. package/src/internal-urls/vault-protocol.ts +940 -0
  558. package/src/internal-urls/xd-protocol.ts +46 -0
  559. package/src/irc/bus.ts +380 -0
  560. package/src/jsonrpc/message-framing.ts +142 -0
  561. package/src/launch/broker.ts +1368 -0
  562. package/src/launch/client.ts +521 -0
  563. package/src/launch/ensure.ts +73 -0
  564. package/src/launch/paths.ts +14 -0
  565. package/src/launch/presence.ts +82 -0
  566. package/src/launch/protocol.ts +448 -0
  567. package/src/launch/spawn-options.ts +17 -0
  568. package/src/launch/terminal-output-worker-client.ts +53 -0
  569. package/src/launch/terminal-output-worker-protocol.ts +11 -0
  570. package/src/launch/terminal-output-worker.ts +23 -0
  571. package/src/launch/terminal-output.ts +46 -0
  572. package/src/lib/xai-http.ts +150 -0
  573. package/src/live/attestation.ts +91 -0
  574. package/src/live/controller.ts +517 -0
  575. package/src/live/prompts/agent-final-message.md +3 -0
  576. package/src/live/prompts/live-instructions.md +23 -0
  577. package/src/live/protocol.ts +233 -0
  578. package/src/live/transport.ts +422 -0
  579. package/src/live/visualizer.ts +221 -0
  580. package/src/live/voices.ts +18 -0
  581. package/src/lsp/client.ts +1465 -0
  582. package/src/lsp/clients/biome-client.ts +263 -0
  583. package/src/lsp/clients/index.ts +50 -0
  584. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  585. package/src/lsp/clients/swiftlint-client.ts +120 -0
  586. package/src/lsp/config.ts +549 -0
  587. package/src/lsp/defaults.json +499 -0
  588. package/src/lsp/deferred-diagnostics.ts +66 -0
  589. package/src/lsp/diagnostics-ledger.ts +51 -0
  590. package/src/lsp/edits.ts +288 -0
  591. package/src/lsp/format-options.ts +119 -0
  592. package/src/lsp/index.ts +2821 -0
  593. package/src/lsp/lspmux.ts +233 -0
  594. package/src/lsp/mux/daemon.ts +348 -0
  595. package/src/lsp/mux/protocol.ts +96 -0
  596. package/src/lsp/mux/server.ts +797 -0
  597. package/src/lsp/render.ts +668 -0
  598. package/src/lsp/startup-events.ts +13 -0
  599. package/src/lsp/types.ts +479 -0
  600. package/src/lsp/utils.ts +747 -0
  601. package/src/main.ts +1799 -0
  602. package/src/markit/NOTICE +32 -0
  603. package/src/markit/converters/docx.ts +56 -0
  604. package/src/markit/converters/epub.ts +136 -0
  605. package/src/markit/converters/pdf/columns.ts +103 -0
  606. package/src/markit/converters/pdf/extract.ts +598 -0
  607. package/src/markit/converters/pdf/grid.ts +780 -0
  608. package/src/markit/converters/pdf/headers.ts +106 -0
  609. package/src/markit/converters/pdf/index.ts +146 -0
  610. package/src/markit/converters/pdf/render.ts +501 -0
  611. package/src/markit/converters/pdf/types.ts +84 -0
  612. package/src/markit/converters/pptx.ts +325 -0
  613. package/src/markit/converters/xlsx.ts +173 -0
  614. package/src/markit/index.ts +2 -0
  615. package/src/markit/registry.ts +59 -0
  616. package/src/markit/types.ts +35 -0
  617. package/src/mcp/client.ts +511 -0
  618. package/src/mcp/config-writer.ts +377 -0
  619. package/src/mcp/config.ts +385 -0
  620. package/src/mcp/index.ts +29 -0
  621. package/src/mcp/json-rpc.ts +122 -0
  622. package/src/mcp/loader.ts +125 -0
  623. package/src/mcp/manager.ts +1524 -0
  624. package/src/mcp/oauth-credentials.ts +104 -0
  625. package/src/mcp/oauth-discovery.ts +587 -0
  626. package/src/mcp/oauth-flow.ts +830 -0
  627. package/src/mcp/render.ts +214 -0
  628. package/src/mcp/request-id.ts +24 -0
  629. package/src/mcp/smithery-auth.ts +108 -0
  630. package/src/mcp/smithery-connect.ts +154 -0
  631. package/src/mcp/smithery-registry.ts +500 -0
  632. package/src/mcp/startup-events.ts +116 -0
  633. package/src/mcp/timeout.ts +59 -0
  634. package/src/mcp/tool-bridge.ts +691 -0
  635. package/src/mcp/tool-cache.ts +117 -0
  636. package/src/mcp/transports/header-policy.ts +95 -0
  637. package/src/mcp/transports/http.ts +508 -0
  638. package/src/mcp/transports/index.ts +7 -0
  639. package/src/mcp/transports/sse.ts +372 -0
  640. package/src/mcp/transports/stdio.ts +905 -0
  641. package/src/mcp/types.ts +467 -0
  642. package/src/memories/index.ts +1434 -0
  643. package/src/memories/storage.ts +578 -0
  644. package/src/memory-backend/index.ts +19 -0
  645. package/src/memory-backend/local-backend.ts +47 -0
  646. package/src/memory-backend/messages.ts +19 -0
  647. package/src/memory-backend/off-backend.ts +25 -0
  648. package/src/memory-backend/resolve.ts +25 -0
  649. package/src/memory-backend/runtime.ts +66 -0
  650. package/src/memory-backend/tool-names.ts +2 -0
  651. package/src/memory-backend/types.ts +166 -0
  652. package/src/mnemopi/backend.ts +629 -0
  653. package/src/mnemopi/config.ts +267 -0
  654. package/src/mnemopi/embed-client.ts +293 -0
  655. package/src/mnemopi/embed-protocol.ts +35 -0
  656. package/src/mnemopi/embed-worker.ts +114 -0
  657. package/src/mnemopi/index.ts +3 -0
  658. package/src/mnemopi/state.ts +940 -0
  659. package/src/modes/acp/acp-agent.ts +2595 -0
  660. package/src/modes/acp/acp-client-bridge.ts +154 -0
  661. package/src/modes/acp/acp-event-mapper.ts +1084 -0
  662. package/src/modes/acp/acp-mode.ts +48 -0
  663. package/src/modes/acp/index.ts +2 -0
  664. package/src/modes/acp/terminal-auth.ts +37 -0
  665. package/src/modes/components/advisor-config.ts +635 -0
  666. package/src/modes/components/advisor-message.ts +109 -0
  667. package/src/modes/components/agent-dashboard.ts +1252 -0
  668. package/src/modes/components/agent-hub-projection.ts +248 -0
  669. package/src/modes/components/agent-hub-renderer.ts +194 -0
  670. package/src/modes/components/agent-hub.ts +1126 -0
  671. package/src/modes/components/agent-transcript-viewer.ts +647 -0
  672. package/src/modes/components/ask-dialog.ts +1017 -0
  673. package/src/modes/components/assistant-message.ts +978 -0
  674. package/src/modes/components/background-tan-message.ts +36 -0
  675. package/src/modes/components/bash-execution.ts +233 -0
  676. package/src/modes/components/bordered-loader.ts +41 -0
  677. package/src/modes/components/btw-panel.ts +161 -0
  678. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  679. package/src/modes/components/chat-block.ts +111 -0
  680. package/src/modes/components/chat-transcript-builder.ts +518 -0
  681. package/src/modes/components/codex-reset-fireworks.ts +369 -0
  682. package/src/modes/components/collab-prompt-message.ts +32 -0
  683. package/src/modes/components/compaction-summary-message.ts +221 -0
  684. package/src/modes/components/copy-selector.ts +218 -0
  685. package/src/modes/components/countdown-timer.ts +75 -0
  686. package/src/modes/components/custom-editor.ts +1036 -0
  687. package/src/modes/components/custom-message.ts +70 -0
  688. package/src/modes/components/diff.ts +254 -0
  689. package/src/modes/components/dynamic-border.ts +37 -0
  690. package/src/modes/components/error-banner.ts +33 -0
  691. package/src/modes/components/eval-execution.ts +169 -0
  692. package/src/modes/components/execution-shared.ts +101 -0
  693. package/src/modes/components/extensions/extension-dashboard.ts +492 -0
  694. package/src/modes/components/extensions/extension-list.ts +507 -0
  695. package/src/modes/components/extensions/index.ts +9 -0
  696. package/src/modes/components/extensions/inspector-panel.ts +326 -0
  697. package/src/modes/components/extensions/state-manager.ts +648 -0
  698. package/src/modes/components/extensions/types.ts +186 -0
  699. package/src/modes/components/footer.ts +274 -0
  700. package/src/modes/components/history-search.ts +268 -0
  701. package/src/modes/components/hook-editor.ts +213 -0
  702. package/src/modes/components/hook-input.ts +87 -0
  703. package/src/modes/components/hook-message.ts +67 -0
  704. package/src/modes/components/hook-selector.ts +691 -0
  705. package/src/modes/components/index.ts +42 -0
  706. package/src/modes/components/keybinding-hints.ts +56 -0
  707. package/src/modes/components/late-diagnostics-message.ts +60 -0
  708. package/src/modes/components/login-dialog.ts +197 -0
  709. package/src/modes/components/logout-account-selector.ts +130 -0
  710. package/src/modes/components/mcp-add-wizard.ts +1413 -0
  711. package/src/modes/components/message-frame.ts +98 -0
  712. package/src/modes/components/model-browser.ts +888 -0
  713. package/src/modes/components/model-hub.ts +2014 -0
  714. package/src/modes/components/model-picker.ts +237 -0
  715. package/src/modes/components/move-overlay.ts +293 -0
  716. package/src/modes/components/oauth-selector.ts +474 -0
  717. package/src/modes/components/omfg-panel.ts +141 -0
  718. package/src/modes/components/overlay-box.ts +109 -0
  719. package/src/modes/components/pause-screen.ts +208 -0
  720. package/src/modes/components/plan-review-overlay.ts +1226 -0
  721. package/src/modes/components/plan-toc.ts +138 -0
  722. package/src/modes/components/plugin-selector.ts +100 -0
  723. package/src/modes/components/plugin-settings.ts +745 -0
  724. package/src/modes/components/queue-mode-selector.ts +61 -0
  725. package/src/modes/components/read-tool-group.ts +856 -0
  726. package/src/modes/components/reset-usage-selector.ts +161 -0
  727. package/src/modes/components/segment-track.ts +89 -0
  728. package/src/modes/components/select-list-mouse-routing.ts +35 -0
  729. package/src/modes/components/selector-helpers.ts +129 -0
  730. package/src/modes/components/session-account-selector.ts +62 -0
  731. package/src/modes/components/session-selector.ts +1035 -0
  732. package/src/modes/components/settings-defs.ts +267 -0
  733. package/src/modes/components/settings-selector.ts +1445 -0
  734. package/src/modes/components/show-images-selector.ts +50 -0
  735. package/src/modes/components/skill-message.ts +110 -0
  736. package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
  737. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  738. package/src/modes/components/status-line/component.ts +1843 -0
  739. package/src/modes/components/status-line/context-thresholds.ts +86 -0
  740. package/src/modes/components/status-line/git-utils.ts +42 -0
  741. package/src/modes/components/status-line/index.ts +5 -0
  742. package/src/modes/components/status-line/presets.ts +106 -0
  743. package/src/modes/components/status-line/segments.ts +710 -0
  744. package/src/modes/components/status-line/separators.ts +55 -0
  745. package/src/modes/components/status-line/types.ts +159 -0
  746. package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
  747. package/src/modes/components/theme-selector.ts +68 -0
  748. package/src/modes/components/thinking-selector.ts +57 -0
  749. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  750. package/src/modes/components/tips.txt +26 -0
  751. package/src/modes/components/todo-reminder.ts +43 -0
  752. package/src/modes/components/tool-execution.ts +1467 -0
  753. package/src/modes/components/transcript-container.ts +527 -0
  754. package/src/modes/components/tree-selector.ts +1006 -0
  755. package/src/modes/components/ttsr-notification.ts +123 -0
  756. package/src/modes/components/usage-row.ts +52 -0
  757. package/src/modes/components/user-message-selector.ts +227 -0
  758. package/src/modes/components/user-message.ts +167 -0
  759. package/src/modes/components/visual-truncate.ts +63 -0
  760. package/src/modes/components/welcome.ts +578 -0
  761. package/src/modes/controllers/btw-controller.ts +246 -0
  762. package/src/modes/controllers/command-controller-shared.ts +109 -0
  763. package/src/modes/controllers/command-controller.ts +2024 -0
  764. package/src/modes/controllers/event-controller.ts +2173 -0
  765. package/src/modes/controllers/extension-ui-controller.ts +1243 -0
  766. package/src/modes/controllers/input-controller.ts +2037 -0
  767. package/src/modes/controllers/live-command-controller.ts +261 -0
  768. package/src/modes/controllers/mcp-command-controller.ts +2552 -0
  769. package/src/modes/controllers/omfg-controller.ts +287 -0
  770. package/src/modes/controllers/omfg-rule.ts +647 -0
  771. package/src/modes/controllers/selector-controller.ts +2058 -0
  772. package/src/modes/controllers/session-focus-controller.ts +117 -0
  773. package/src/modes/controllers/ssh-command-controller.ts +385 -0
  774. package/src/modes/controllers/streaming-reveal.ts +399 -0
  775. package/src/modes/controllers/tan-command-controller.ts +243 -0
  776. package/src/modes/controllers/todo-command-controller.ts +487 -0
  777. package/src/modes/controllers/tool-args-reveal.ts +591 -0
  778. package/src/modes/data/emojis.json +1 -0
  779. package/src/modes/emoji-autocomplete.ts +285 -0
  780. package/src/modes/github-ref-autocomplete.ts +75 -0
  781. package/src/modes/gradient-highlight.ts +99 -0
  782. package/src/modes/image-references.ts +137 -0
  783. package/src/modes/index.ts +10 -0
  784. package/src/modes/interactive-mode.ts +5055 -0
  785. package/src/modes/internal-url-autocomplete.ts +158 -0
  786. package/src/modes/loop-limit.ts +192 -0
  787. package/src/modes/magic-keyword-boundary.ts +23 -0
  788. package/src/modes/magic-keywords.ts +42 -0
  789. package/src/modes/markdown-prose.ts +247 -0
  790. package/src/modes/oauth-manual-input.ts +69 -0
  791. package/src/modes/orchestrate.ts +43 -0
  792. package/src/modes/print-mode.ts +282 -0
  793. package/src/modes/prompt-action-autocomplete.ts +322 -0
  794. package/src/modes/queue-input.ts +132 -0
  795. package/src/modes/rpc/host-tools.ts +204 -0
  796. package/src/modes/rpc/host-uris.ts +241 -0
  797. package/src/modes/rpc/rpc-client.ts +1213 -0
  798. package/src/modes/rpc/rpc-frame.ts +316 -0
  799. package/src/modes/rpc/rpc-input.ts +38 -0
  800. package/src/modes/rpc/rpc-messages.ts +127 -0
  801. package/src/modes/rpc/rpc-mode.ts +1519 -0
  802. package/src/modes/rpc/rpc-subagents.ts +265 -0
  803. package/src/modes/rpc/rpc-types.ts +544 -0
  804. package/src/modes/running-subagent-badge.ts +13 -0
  805. package/src/modes/runtime-init.ts +144 -0
  806. package/src/modes/session-observer-registry.ts +223 -0
  807. package/src/modes/session-teardown.ts +82 -0
  808. package/src/modes/setup-version.ts +11 -0
  809. package/src/modes/setup-wizard/index.ts +103 -0
  810. package/src/modes/setup-wizard/lazy.ts +16 -0
  811. package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
  812. package/src/modes/setup-wizard/scenes/model.ts +132 -0
  813. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  814. package/src/modes/setup-wizard/scenes/providers.ts +105 -0
  815. package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
  816. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  817. package/src/modes/setup-wizard/scenes/theme.ts +330 -0
  818. package/src/modes/setup-wizard/scenes/types.ts +65 -0
  819. package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
  820. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  821. package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
  822. package/src/modes/shared.ts +49 -0
  823. package/src/modes/skill-command.ts +91 -0
  824. package/src/modes/theme/dark.json +95 -0
  825. package/src/modes/theme/defaults/alabaster.json +93 -0
  826. package/src/modes/theme/defaults/amethyst.json +96 -0
  827. package/src/modes/theme/defaults/anthracite.json +93 -0
  828. package/src/modes/theme/defaults/basalt.json +91 -0
  829. package/src/modes/theme/defaults/birch.json +95 -0
  830. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  831. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  832. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  833. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  834. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  835. package/src/modes/theme/defaults/dark-copper.json +95 -0
  836. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  837. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  838. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  839. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  840. package/src/modes/theme/defaults/dark-ember.json +95 -0
  841. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  842. package/src/modes/theme/defaults/dark-forest.json +96 -0
  843. package/src/modes/theme/defaults/dark-github.json +105 -0
  844. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  845. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  846. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  847. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  848. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  849. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  850. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  851. package/src/modes/theme/defaults/dark-nord.json +97 -0
  852. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  853. package/src/modes/theme/defaults/dark-one.json +100 -0
  854. package/src/modes/theme/defaults/dark-poimandres.json +143 -0
  855. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  856. package/src/modes/theme/defaults/dark-reef.json +91 -0
  857. package/src/modes/theme/defaults/dark-retro.json +92 -0
  858. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  859. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  860. package/src/modes/theme/defaults/dark-slate.json +95 -0
  861. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  862. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  863. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  864. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  865. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  866. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  867. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  868. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  869. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  870. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  871. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  872. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  873. package/src/modes/theme/defaults/graphite.json +92 -0
  874. package/src/modes/theme/defaults/index.ts +199 -0
  875. package/src/modes/theme/defaults/light-arctic.json +107 -0
  876. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  877. package/src/modes/theme/defaults/light-canyon.json +91 -0
  878. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  879. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  880. package/src/modes/theme/defaults/light-coral.json +95 -0
  881. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  882. package/src/modes/theme/defaults/light-dawn.json +90 -0
  883. package/src/modes/theme/defaults/light-dunes.json +91 -0
  884. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  885. package/src/modes/theme/defaults/light-forest.json +100 -0
  886. package/src/modes/theme/defaults/light-frost.json +95 -0
  887. package/src/modes/theme/defaults/light-github.json +115 -0
  888. package/src/modes/theme/defaults/light-glacier.json +91 -0
  889. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  890. package/src/modes/theme/defaults/light-haze.json +90 -0
  891. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  892. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  893. package/src/modes/theme/defaults/light-lavender.json +95 -0
  894. package/src/modes/theme/defaults/light-meadow.json +91 -0
  895. package/src/modes/theme/defaults/light-mint.json +95 -0
  896. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  897. package/src/modes/theme/defaults/light-ocean.json +99 -0
  898. package/src/modes/theme/defaults/light-one.json +99 -0
  899. package/src/modes/theme/defaults/light-opal.json +91 -0
  900. package/src/modes/theme/defaults/light-orchard.json +91 -0
  901. package/src/modes/theme/defaults/light-paper.json +95 -0
  902. package/src/modes/theme/defaults/light-poimandres.json +143 -0
  903. package/src/modes/theme/defaults/light-prism.json +90 -0
  904. package/src/modes/theme/defaults/light-retro.json +98 -0
  905. package/src/modes/theme/defaults/light-sand.json +95 -0
  906. package/src/modes/theme/defaults/light-savanna.json +91 -0
  907. package/src/modes/theme/defaults/light-solarized.json +102 -0
  908. package/src/modes/theme/defaults/light-soleil.json +90 -0
  909. package/src/modes/theme/defaults/light-sunset.json +99 -0
  910. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  911. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  912. package/src/modes/theme/defaults/light-wetland.json +91 -0
  913. package/src/modes/theme/defaults/light-zenith.json +89 -0
  914. package/src/modes/theme/defaults/limestone.json +94 -0
  915. package/src/modes/theme/defaults/mahogany.json +97 -0
  916. package/src/modes/theme/defaults/marble.json +93 -0
  917. package/src/modes/theme/defaults/obsidian.json +91 -0
  918. package/src/modes/theme/defaults/onyx.json +91 -0
  919. package/src/modes/theme/defaults/pearl.json +93 -0
  920. package/src/modes/theme/defaults/porcelain.json +91 -0
  921. package/src/modes/theme/defaults/quartz.json +96 -0
  922. package/src/modes/theme/defaults/sandstone.json +95 -0
  923. package/src/modes/theme/defaults/titanium.json +90 -0
  924. package/src/modes/theme/light.json +93 -0
  925. package/src/modes/theme/mermaid-cache.ts +92 -0
  926. package/src/modes/theme/shimmer.ts +305 -0
  927. package/src/modes/theme/theme-schema.json +463 -0
  928. package/src/modes/theme/theme.ts +3171 -0
  929. package/src/modes/turn-budget.ts +31 -0
  930. package/src/modes/types.ts +494 -0
  931. package/src/modes/ultrathink.ts +42 -0
  932. package/src/modes/utils/context-usage.ts +518 -0
  933. package/src/modes/utils/copy-targets.ts +378 -0
  934. package/src/modes/utils/hotkeys-markdown.ts +65 -0
  935. package/src/modes/utils/interactive-context-helpers.ts +31 -0
  936. package/src/modes/utils/keybinding-matchers.ts +86 -0
  937. package/src/modes/utils/tools-markdown.ts +31 -0
  938. package/src/modes/utils/transcript-render-helpers.ts +253 -0
  939. package/src/modes/utils/ui-helpers.ts +976 -0
  940. package/src/modes/warp-events.ts +232 -0
  941. package/src/modes/workflow.ts +55 -0
  942. package/src/plan-mode/approved-plan.ts +194 -0
  943. package/src/plan-mode/model-transition.ts +51 -0
  944. package/src/plan-mode/plan-files.ts +40 -0
  945. package/src/plan-mode/plan-handoff.ts +37 -0
  946. package/src/plan-mode/plan-protection.ts +31 -0
  947. package/src/plan-mode/state.ts +6 -0
  948. package/src/priority.json +60 -0
  949. package/src/prompts/advisor/active-repo-watchdog.md +6 -0
  950. package/src/prompts/advisor/advise-tool.md +3 -0
  951. package/src/prompts/advisor/context-files.md +8 -0
  952. package/src/prompts/advisor/system.md +98 -0
  953. package/src/prompts/agents/designer.md +74 -0
  954. package/src/prompts/agents/frontmatter.md +12 -0
  955. package/src/prompts/agents/init.md +33 -0
  956. package/src/prompts/agents/librarian.md +119 -0
  957. package/src/prompts/agents/reviewer.md +139 -0
  958. package/src/prompts/agents/scout.md +58 -0
  959. package/src/prompts/agents/security-reviewer.md +75 -0
  960. package/src/prompts/agents/task.md +17 -0
  961. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  962. package/src/prompts/bench/cache-prefix.md +3 -0
  963. package/src/prompts/bench/cache-suffix.md +1 -0
  964. package/src/prompts/bench.md +6 -0
  965. package/src/prompts/ci-green-request.md +36 -0
  966. package/src/prompts/dry-balance-bench.md +8 -0
  967. package/src/prompts/goals/goal-budget-limit.md +16 -0
  968. package/src/prompts/goals/goal-continuation.md +28 -0
  969. package/src/prompts/goals/goal-mode-active.md +23 -0
  970. package/src/prompts/goals/goal-mode-context.md +4 -0
  971. package/src/prompts/goals/goal-todo-context.md +12 -0
  972. package/src/prompts/goals/guided-goal-interview.md +43 -0
  973. package/src/prompts/memories/consolidation.md +30 -0
  974. package/src/prompts/memories/consolidation_system.md +4 -0
  975. package/src/prompts/memories/read-path.md +17 -0
  976. package/src/prompts/memories/stage_one_input.md +6 -0
  977. package/src/prompts/memories/stage_one_system.md +21 -0
  978. package/src/prompts/review-custom-request.md +21 -0
  979. package/src/prompts/review-headless-request.md +16 -0
  980. package/src/prompts/review-request.md +68 -0
  981. package/src/prompts/security/scan-coordinator.md +7 -0
  982. package/src/prompts/security/scan-request.md +21 -0
  983. package/src/prompts/security/validate-request.md +8 -0
  984. package/src/prompts/session/launch-completion.md +1 -0
  985. package/src/prompts/skills/autoload.md +8 -0
  986. package/src/prompts/skills/user-invocation.md +11 -0
  987. package/src/prompts/steering/parent-irc.md +5 -0
  988. package/src/prompts/steering/user-interjection.md +6 -0
  989. package/src/prompts/system/active-repo-context.md +4 -0
  990. package/src/prompts/system/agent-creation-architect.md +50 -0
  991. package/src/prompts/system/agent-creation-user.md +6 -0
  992. package/src/prompts/system/auto-continue.md +1 -0
  993. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  994. package/src/prompts/system/auto-thinking-difficulty.md +14 -0
  995. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  996. package/src/prompts/system/autolearn-guidance.md +7 -0
  997. package/src/prompts/system/autolearn-nudge-autocontinue.md +5 -0
  998. package/src/prompts/system/background-tan-dispatch.md +8 -0
  999. package/src/prompts/system/btw-user.md +8 -0
  1000. package/src/prompts/system/commit-message-system.md +14 -0
  1001. package/src/prompts/system/computer-safety.md +14 -0
  1002. package/src/prompts/system/custom-system-prompt.md +64 -0
  1003. package/src/prompts/system/eager-task.md +7 -0
  1004. package/src/prompts/system/eager-todo.md +18 -0
  1005. package/src/prompts/system/empty-stop-retry.md +4 -0
  1006. package/src/prompts/system/gemini-tool-call-reminder.md +9 -0
  1007. package/src/prompts/system/interrupted-thinking.md +7 -0
  1008. package/src/prompts/system/irc-autoreply.md +6 -0
  1009. package/src/prompts/system/irc-incoming.md +9 -0
  1010. package/src/prompts/system/manual-continue.md +7 -0
  1011. package/src/prompts/system/mcp-xdev-guidance.md +11 -0
  1012. package/src/prompts/system/memory-consolidation-system.md +8 -0
  1013. package/src/prompts/system/memory-extraction-system.md +26 -0
  1014. package/src/prompts/system/mid-run-todo-nudge.md +3 -0
  1015. package/src/prompts/system/omfg-user.md +50 -0
  1016. package/src/prompts/system/orchestrate-notice.md +40 -0
  1017. package/src/prompts/system/personalities/default.md +18 -0
  1018. package/src/prompts/system/personalities/friendly.md +17 -0
  1019. package/src/prompts/system/personalities/pragmatic.md +15 -0
  1020. package/src/prompts/system/plan-mode-active.md +125 -0
  1021. package/src/prompts/system/plan-mode-approved.md +22 -0
  1022. package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
  1023. package/src/prompts/system/plan-mode-reference.md +10 -0
  1024. package/src/prompts/system/plan-mode-subagent.md +33 -0
  1025. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  1026. package/src/prompts/system/plan-yolo-handoff.md +5 -0
  1027. package/src/prompts/system/prewalk-checklist.md +7 -0
  1028. package/src/prompts/system/prewalk-continue.md +1 -0
  1029. package/src/prompts/system/prewalk-plan.md +13 -0
  1030. package/src/prompts/system/project-prompt.md +61 -0
  1031. package/src/prompts/system/recap-user.md +9 -0
  1032. package/src/prompts/system/resolve-device-reminder.md +3 -0
  1033. package/src/prompts/system/rewind-report.md +6 -0
  1034. package/src/prompts/system/side-channel-no-tools.md +3 -0
  1035. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  1036. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  1037. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  1038. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  1039. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  1040. package/src/prompts/system/speech-rewrite.md +15 -0
  1041. package/src/prompts/system/subagent-async-pending.md +6 -0
  1042. package/src/prompts/system/subagent-system-prompt.md +73 -0
  1043. package/src/prompts/system/subagent-user-prompt.md +3 -0
  1044. package/src/prompts/system/subagent-yield-reminder.md +23 -0
  1045. package/src/prompts/system/system-prompt.md +263 -0
  1046. package/src/prompts/system/tan-context-switch.md +17 -0
  1047. package/src/prompts/system/task-label.md +23 -0
  1048. package/src/prompts/system/thinking-loop-redirect.md +10 -0
  1049. package/src/prompts/system/title-marker-instruction.md +1 -0
  1050. package/src/prompts/system/title-system.md +16 -0
  1051. package/src/prompts/system/tool-call-loop-redirect.md +8 -0
  1052. package/src/prompts/system/ttsr-interrupt.md +7 -0
  1053. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  1054. package/src/prompts/system/ultrathink-notice.md +3 -0
  1055. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  1056. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  1057. package/src/prompts/system/vibe-mode-active.md +26 -0
  1058. package/src/prompts/system/web-search.md +25 -0
  1059. package/src/prompts/system/workflow-notice.md +112 -0
  1060. package/src/prompts/system/xdev-mount-notice.md +20 -0
  1061. package/src/prompts/tools/apply-patch.md +65 -0
  1062. package/src/prompts/tools/ask.md +22 -0
  1063. package/src/prompts/tools/ast-edit.md +11 -0
  1064. package/src/prompts/tools/ast-grep.md +19 -0
  1065. package/src/prompts/tools/async-result.md +8 -0
  1066. package/src/prompts/tools/bash.md +23 -0
  1067. package/src/prompts/tools/browser.md +29 -0
  1068. package/src/prompts/tools/checkpoint.md +15 -0
  1069. package/src/prompts/tools/computer.md +26 -0
  1070. package/src/prompts/tools/debug.md +3 -0
  1071. package/src/prompts/tools/eval.md +45 -0
  1072. package/src/prompts/tools/github.md +22 -0
  1073. package/src/prompts/tools/glob.md +16 -0
  1074. package/src/prompts/tools/goal.md +11 -0
  1075. package/src/prompts/tools/grep.md +13 -0
  1076. package/src/prompts/tools/hub.md +34 -0
  1077. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  1078. package/src/prompts/tools/image-attachment-describe.md +10 -0
  1079. package/src/prompts/tools/image-gen.md +7 -0
  1080. package/src/prompts/tools/inspect-image-system.md +20 -0
  1081. package/src/prompts/tools/inspect-image.md +22 -0
  1082. package/src/prompts/tools/learn.md +7 -0
  1083. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  1084. package/src/prompts/tools/lsp.md +19 -0
  1085. package/src/prompts/tools/manage-skill.md +9 -0
  1086. package/src/prompts/tools/memory-edit.md +12 -0
  1087. package/src/prompts/tools/patch.md +57 -0
  1088. package/src/prompts/tools/read.md +27 -0
  1089. package/src/prompts/tools/recall.md +7 -0
  1090. package/src/prompts/tools/reflect.md +5 -0
  1091. package/src/prompts/tools/replace.md +30 -0
  1092. package/src/prompts/tools/retain.md +6 -0
  1093. package/src/prompts/tools/rewind.md +14 -0
  1094. package/src/prompts/tools/security-publish.md +1 -0
  1095. package/src/prompts/tools/security-scan.md +1 -0
  1096. package/src/prompts/tools/task-async-contract.md +1 -0
  1097. package/src/prompts/tools/task-summary.md +20 -0
  1098. package/src/prompts/tools/task.md +83 -0
  1099. package/src/prompts/tools/todo.md +42 -0
  1100. package/src/prompts/tools/vibe-kill.md +3 -0
  1101. package/src/prompts/tools/vibe-list.md +3 -0
  1102. package/src/prompts/tools/vibe-send.md +9 -0
  1103. package/src/prompts/tools/vibe-spawn.md +10 -0
  1104. package/src/prompts/tools/vibe-turn-result.md +19 -0
  1105. package/src/prompts/tools/vibe-wait.md +8 -0
  1106. package/src/prompts/tools/web-search.md +8 -0
  1107. package/src/prompts/tools/write.md +14 -0
  1108. package/src/registry/agent-lifecycle.ts +505 -0
  1109. package/src/registry/agent-registry.ts +287 -0
  1110. package/src/registry/persisted-agents.ts +423 -0
  1111. package/src/sdk.ts +3820 -0
  1112. package/src/secrets/index.ts +375 -0
  1113. package/src/secrets/obfuscator.ts +2629 -0
  1114. package/src/secrets/regex.ts +21 -0
  1115. package/src/security/auth.ts +98 -0
  1116. package/src/security/cloud.ts +686 -0
  1117. package/src/security/comparison.ts +255 -0
  1118. package/src/security/contracts/ids.ts +111 -0
  1119. package/src/security/contracts/index.ts +4 -0
  1120. package/src/security/contracts/schemas.ts +219 -0
  1121. package/src/security/contracts/types.ts +254 -0
  1122. package/src/security/contracts/validation.ts +69 -0
  1123. package/src/security/coordinator.ts +708 -0
  1124. package/src/security/importers/codex-security.ts +387 -0
  1125. package/src/security/importers/index.ts +2 -0
  1126. package/src/security/importers/sarif.ts +357 -0
  1127. package/src/security/index.ts +13 -0
  1128. package/src/security/preflight.ts +405 -0
  1129. package/src/security/provenance.ts +106 -0
  1130. package/src/security/publication.ts +326 -0
  1131. package/src/security/remediation.ts +93 -0
  1132. package/src/security/resource-output.ts +50 -0
  1133. package/src/security/sarif.ts +78 -0
  1134. package/src/security/store.ts +430 -0
  1135. package/src/session/acp-permission-gate.ts +165 -0
  1136. package/src/session/agent-session-events.ts +67 -0
  1137. package/src/session/agent-session-types.ts +407 -0
  1138. package/src/session/agent-session.ts +9000 -0
  1139. package/src/session/agent-storage.ts +807 -0
  1140. package/src/session/artifacts.ts +154 -0
  1141. package/src/session/async-job-delivery.ts +82 -0
  1142. package/src/session/auth-broker-config.ts +92 -0
  1143. package/src/session/auth-storage.ts +25 -0
  1144. package/src/session/bash-runner.ts +326 -0
  1145. package/src/session/blob-store.ts +295 -0
  1146. package/src/session/checkpoint-entries.ts +81 -0
  1147. package/src/session/claude-session-store.ts +426 -0
  1148. package/src/session/client-bridge.ts +85 -0
  1149. package/src/session/codex-auto-reset.ts +673 -0
  1150. package/src/session/codex-session-store.ts +673 -0
  1151. package/src/session/compact-modes.ts +105 -0
  1152. package/src/session/credential-pin.ts +93 -0
  1153. package/src/session/eval-runner.ts +219 -0
  1154. package/src/session/exit-diagnostics.ts +310 -0
  1155. package/src/session/foreign-session-import.ts +52 -0
  1156. package/src/session/foreign-session-jsonl.ts +29 -0
  1157. package/src/session/foreign-session-store.ts +26 -0
  1158. package/src/session/history-storage.ts +329 -0
  1159. package/src/session/indexed-session-storage.ts +553 -0
  1160. package/src/session/irc-bridge.ts +203 -0
  1161. package/src/session/launch-completion.ts +37 -0
  1162. package/src/session/messages.ts +1304 -0
  1163. package/src/session/model-controls.ts +757 -0
  1164. package/src/session/prewalk.ts +279 -0
  1165. package/src/session/provider-image-budget.ts +86 -0
  1166. package/src/session/queued-messages.ts +99 -0
  1167. package/src/session/redis-session-storage.ts +257 -0
  1168. package/src/session/retry-fallback-chains.ts +455 -0
  1169. package/src/session/role-models.ts +85 -0
  1170. package/src/session/session-advisors.ts +1896 -0
  1171. package/src/session/session-context.ts +584 -0
  1172. package/src/session/session-dump-format.ts +216 -0
  1173. package/src/session/session-entries.ts +306 -0
  1174. package/src/session/session-handoff.ts +325 -0
  1175. package/src/session/session-history-format.ts +459 -0
  1176. package/src/session/session-listing.ts +715 -0
  1177. package/src/session/session-loader.ts +362 -0
  1178. package/src/session/session-maintenance.ts +3115 -0
  1179. package/src/session/session-manager.ts +2747 -0
  1180. package/src/session/session-memory.ts +222 -0
  1181. package/src/session/session-metadata.ts +53 -0
  1182. package/src/session/session-migrations.ts +78 -0
  1183. package/src/session/session-paths.ts +280 -0
  1184. package/src/session/session-persistence.ts +293 -0
  1185. package/src/session/session-provider-boundary.ts +306 -0
  1186. package/src/session/session-stats.ts +349 -0
  1187. package/src/session/session-storage.ts +774 -0
  1188. package/src/session/session-title-slot.ts +141 -0
  1189. package/src/session/session-tools.ts +1385 -0
  1190. package/src/session/session-workspace.ts +53 -0
  1191. package/src/session/settings-stream-fn.ts +79 -0
  1192. package/src/session/shake-types.ts +43 -0
  1193. package/src/session/snapcompact-inline.ts +545 -0
  1194. package/src/session/snapcompact-savings-journal.ts +113 -0
  1195. package/src/session/sql-session-storage.ts +374 -0
  1196. package/src/session/stream-guards.ts +417 -0
  1197. package/src/session/streaming-output.ts +1459 -0
  1198. package/src/session/todo-tracker.ts +380 -0
  1199. package/src/session/tool-choice-queue.ts +305 -0
  1200. package/src/session/ttsr-coordinator.ts +496 -0
  1201. package/src/session/turn-persistence.ts +142 -0
  1202. package/src/session/turn-recovery.ts +2005 -0
  1203. package/src/session/unexpected-stop-classifier.ts +141 -0
  1204. package/src/session/yield-queue.ts +288 -0
  1205. package/src/slash-commands/acp-builtins.ts +70 -0
  1206. package/src/slash-commands/available-commands.ts +105 -0
  1207. package/src/slash-commands/builtin-registry.ts +3149 -0
  1208. package/src/slash-commands/helpers/active-oauth-account.ts +80 -0
  1209. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  1210. package/src/slash-commands/helpers/context-report.ts +66 -0
  1211. package/src/slash-commands/helpers/format.ts +46 -0
  1212. package/src/slash-commands/helpers/logout.ts +108 -0
  1213. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  1214. package/src/slash-commands/helpers/mcp.ts +533 -0
  1215. package/src/slash-commands/helpers/parse.ts +85 -0
  1216. package/src/slash-commands/helpers/reset-usage.ts +68 -0
  1217. package/src/slash-commands/helpers/security.ts +451 -0
  1218. package/src/slash-commands/helpers/session-pin.ts +44 -0
  1219. package/src/slash-commands/helpers/ssh.ts +196 -0
  1220. package/src/slash-commands/helpers/stats-dashboard.ts +86 -0
  1221. package/src/slash-commands/helpers/todo.ts +285 -0
  1222. package/src/slash-commands/helpers/usage-report.ts +198 -0
  1223. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1224. package/src/slash-commands/types.ts +139 -0
  1225. package/src/ssh/config-writer.ts +183 -0
  1226. package/src/ssh/connection-manager.ts +667 -0
  1227. package/src/ssh/file-transfer.ts +214 -0
  1228. package/src/ssh/sshfs-mount.ts +163 -0
  1229. package/src/ssh/utils.ts +51 -0
  1230. package/src/startup-splash.ts +19 -0
  1231. package/src/stt/asr-client.ts +401 -0
  1232. package/src/stt/asr-protocol.ts +65 -0
  1233. package/src/stt/asr-worker.ts +603 -0
  1234. package/src/stt/downloader.ts +142 -0
  1235. package/src/stt/endpointer.ts +259 -0
  1236. package/src/stt/index.ts +6 -0
  1237. package/src/stt/models.ts +150 -0
  1238. package/src/stt/sherpa-runtime.ts +71 -0
  1239. package/src/stt/stt-controller.ts +320 -0
  1240. package/src/stt/submit-trigger.ts +74 -0
  1241. package/src/subprocess/worker-client.ts +463 -0
  1242. package/src/subprocess/worker-runtime.ts +494 -0
  1243. package/src/system-prompt.ts +921 -0
  1244. package/src/task/agents.ts +170 -0
  1245. package/src/task/commands.ts +132 -0
  1246. package/src/task/discovery.ts +145 -0
  1247. package/src/task/executor.ts +3431 -0
  1248. package/src/task/index.ts +1515 -0
  1249. package/src/task/isolation-ownership.ts +106 -0
  1250. package/src/task/isolation-runner.ts +444 -0
  1251. package/src/task/label.ts +40 -0
  1252. package/src/task/name-generator.ts +1577 -0
  1253. package/src/task/omp-command.ts +26 -0
  1254. package/src/task/output-manager.ts +115 -0
  1255. package/src/task/parallel.ts +221 -0
  1256. package/src/task/persisted-revive.ts +173 -0
  1257. package/src/task/prewalk.ts +6 -0
  1258. package/src/task/prompt-policy.ts +8 -0
  1259. package/src/task/provider-concurrency.ts +100 -0
  1260. package/src/task/read-only-policy.ts +27 -0
  1261. package/src/task/render.ts +1830 -0
  1262. package/src/task/renderer.ts +14 -0
  1263. package/src/task/repair-args.ts +118 -0
  1264. package/src/task/spawn-policy.ts +72 -0
  1265. package/src/task/structured-subagent.ts +676 -0
  1266. package/src/task/subprocess-tool-registry.ts +88 -0
  1267. package/src/task/types.ts +555 -0
  1268. package/src/task/worktree.ts +967 -0
  1269. package/src/task/yield-assembly.ts +198 -0
  1270. package/src/telemetry-export.ts +504 -0
  1271. package/src/thinking.ts +377 -0
  1272. package/src/tiny/device.ts +111 -0
  1273. package/src/tiny/dtype.ts +101 -0
  1274. package/src/tiny/message-preproc.ts +155 -0
  1275. package/src/tiny/models.ts +268 -0
  1276. package/src/tiny/text.ts +290 -0
  1277. package/src/tiny/title-client.ts +460 -0
  1278. package/src/tiny/title-protocol.ts +56 -0
  1279. package/src/tiny/worker.ts +354 -0
  1280. package/src/tools/acp-bridge.ts +125 -0
  1281. package/src/tools/approval.ts +245 -0
  1282. package/src/tools/ask.ts +1459 -0
  1283. package/src/tools/ast-edit.ts +718 -0
  1284. package/src/tools/ast-grep.ts +526 -0
  1285. package/src/tools/auto-generated-guard.ts +335 -0
  1286. package/src/tools/bash-interactive.ts +435 -0
  1287. package/src/tools/bash-interceptor.ts +148 -0
  1288. package/src/tools/bash-pty-selection.ts +14 -0
  1289. package/src/tools/bash-skill-urls.ts +350 -0
  1290. package/src/tools/bash.ts +1826 -0
  1291. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  1292. package/src/tools/browser/aria/aria-snapshot.ts +131 -0
  1293. package/src/tools/browser/attach.ts +219 -0
  1294. package/src/tools/browser/cmux/cmux-tab.ts +1531 -0
  1295. package/src/tools/browser/cmux/rpc.ts +200 -0
  1296. package/src/tools/browser/cmux/socket-client.ts +445 -0
  1297. package/src/tools/browser/launch.ts +939 -0
  1298. package/src/tools/browser/readable.ts +112 -0
  1299. package/src/tools/browser/registry.ts +447 -0
  1300. package/src/tools/browser/relay/bridge.ts +945 -0
  1301. package/src/tools/browser/relay/daemon.ts +117 -0
  1302. package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
  1303. package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
  1304. package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
  1305. package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
  1306. package/src/tools/browser/relay/kind.ts +41 -0
  1307. package/src/tools/browser/relay/protocol.ts +54 -0
  1308. package/src/tools/browser/relay/server.ts +141 -0
  1309. package/src/tools/browser/render.ts +229 -0
  1310. package/src/tools/browser/run-output.ts +76 -0
  1311. package/src/tools/browser/shared-daemon.ts +139 -0
  1312. package/src/tools/browser/tab-protocol.ts +123 -0
  1313. package/src/tools/browser/tab-supervisor.ts +1077 -0
  1314. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1315. package/src/tools/browser/tab-worker.ts +1982 -0
  1316. package/src/tools/browser.ts +487 -0
  1317. package/src/tools/builtin-names.ts +67 -0
  1318. package/src/tools/checkpoint.ts +137 -0
  1319. package/src/tools/computer/exposure.ts +14 -0
  1320. package/src/tools/computer/protocol.ts +69 -0
  1321. package/src/tools/computer/supervisor.ts +409 -0
  1322. package/src/tools/computer/worker-entry.ts +39 -0
  1323. package/src/tools/computer/worker.ts +745 -0
  1324. package/src/tools/computer-renderer.ts +147 -0
  1325. package/src/tools/computer.ts +222 -0
  1326. package/src/tools/conflict-detect.ts +815 -0
  1327. package/src/tools/context.ts +49 -0
  1328. package/src/tools/debug.ts +1121 -0
  1329. package/src/tools/default-renderer.ts +154 -0
  1330. package/src/tools/essential-tools.ts +46 -0
  1331. package/src/tools/eval-backends.ts +34 -0
  1332. package/src/tools/eval-format/index.ts +24 -0
  1333. package/src/tools/eval-format/javascript.ts +952 -0
  1334. package/src/tools/eval-format/julia.ts +446 -0
  1335. package/src/tools/eval-format/python.ts +544 -0
  1336. package/src/tools/eval-format/ruby.ts +380 -0
  1337. package/src/tools/eval-render.ts +784 -0
  1338. package/src/tools/eval.ts +774 -0
  1339. package/src/tools/fetch.ts +1889 -0
  1340. package/src/tools/file-recorder.ts +35 -0
  1341. package/src/tools/fs-cache-invalidation.ts +28 -0
  1342. package/src/tools/gh-cache-invalidation.ts +175 -0
  1343. package/src/tools/gh-format.ts +12 -0
  1344. package/src/tools/gh-renderer.ts +484 -0
  1345. package/src/tools/gh.ts +3958 -0
  1346. package/src/tools/github-cache.ts +663 -0
  1347. package/src/tools/glob.ts +691 -0
  1348. package/src/tools/grep.ts +1920 -0
  1349. package/src/tools/grouped-file-output.ts +210 -0
  1350. package/src/tools/hub/index.ts +579 -0
  1351. package/src/tools/hub/jobs.ts +714 -0
  1352. package/src/tools/hub/launch.ts +690 -0
  1353. package/src/tools/hub/messaging.ts +735 -0
  1354. package/src/tools/hub/types.ts +117 -0
  1355. package/src/tools/image-gen.ts +1689 -0
  1356. package/src/tools/image-providers.ts +50 -0
  1357. package/src/tools/index.ts +736 -0
  1358. package/src/tools/inspect-image-renderer.ts +133 -0
  1359. package/src/tools/inspect-image.ts +316 -0
  1360. package/src/tools/json-tree.ts +260 -0
  1361. package/src/tools/jtd-to-json-schema.ts +219 -0
  1362. package/src/tools/jtd-to-typescript.ts +136 -0
  1363. package/src/tools/jtd-utils.ts +102 -0
  1364. package/src/tools/learn.ts +141 -0
  1365. package/src/tools/list-limit.ts +40 -0
  1366. package/src/tools/manage-skill.ts +102 -0
  1367. package/src/tools/match-line-format.ts +20 -0
  1368. package/src/tools/memory-edit.ts +61 -0
  1369. package/src/tools/memory-recall.ts +102 -0
  1370. package/src/tools/memory-reflect.ts +88 -0
  1371. package/src/tools/memory-render.ts +211 -0
  1372. package/src/tools/memory-retain.ts +89 -0
  1373. package/src/tools/output-meta.ts +860 -0
  1374. package/src/tools/output-schema-validator.ts +307 -0
  1375. package/src/tools/path-utils.ts +1489 -0
  1376. package/src/tools/plan-mode-guard.ts +155 -0
  1377. package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
  1378. package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
  1379. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
  1380. package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
  1381. package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
  1382. package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
  1383. package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
  1384. package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
  1385. package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
  1386. package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
  1387. package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
  1388. package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
  1389. package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
  1390. package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
  1391. package/src/tools/read.ts +3762 -0
  1392. package/src/tools/render-utils.ts +926 -0
  1393. package/src/tools/renderers.ts +133 -0
  1394. package/src/tools/report-tool-issue.ts +568 -0
  1395. package/src/tools/resolve.ts +423 -0
  1396. package/src/tools/review.ts +103 -0
  1397. package/src/tools/run-scope.ts +417 -0
  1398. package/src/tools/security-scan.ts +287 -0
  1399. package/src/tools/shell-tokenize.ts +213 -0
  1400. package/src/tools/sqlite-reader.ts +884 -0
  1401. package/src/tools/terminal-output.ts +141 -0
  1402. package/src/tools/todo.ts +1226 -0
  1403. package/src/tools/tool-errors.ts +62 -0
  1404. package/src/tools/tool-result.ts +102 -0
  1405. package/src/tools/tool-timeouts.ts +38 -0
  1406. package/src/tools/tts.ts +266 -0
  1407. package/src/tools/vibe.ts +608 -0
  1408. package/src/tools/write.ts +1646 -0
  1409. package/src/tools/xdev.ts +560 -0
  1410. package/src/tools/yield.ts +486 -0
  1411. package/src/tts/downloader.ts +64 -0
  1412. package/src/tts/index.ts +10 -0
  1413. package/src/tts/models.ts +137 -0
  1414. package/src/tts/runtime.ts +21 -0
  1415. package/src/tts/speakable.ts +392 -0
  1416. package/src/tts/speech-enhancer.ts +206 -0
  1417. package/src/tts/streaming-player.ts +120 -0
  1418. package/src/tts/tts-client.ts +475 -0
  1419. package/src/tts/tts-protocol.ts +69 -0
  1420. package/src/tts/tts-worker.ts +434 -0
  1421. package/src/tts/vocalizer.ts +419 -0
  1422. package/src/tts/wav.ts +58 -0
  1423. package/src/tui/code-cell.ts +268 -0
  1424. package/src/tui/file-list.ts +55 -0
  1425. package/src/tui/hyperlink.ts +178 -0
  1426. package/src/tui/index.ts +13 -0
  1427. package/src/tui/output-block.ts +268 -0
  1428. package/src/tui/status-line.ts +54 -0
  1429. package/src/tui/tree-list.ts +172 -0
  1430. package/src/tui/types.ts +15 -0
  1431. package/src/tui/utils.ts +103 -0
  1432. package/src/tui/width-aware-text.ts +58 -0
  1433. package/src/utils/active-repo-context.ts +143 -0
  1434. package/src/utils/block-context.ts +312 -0
  1435. package/src/utils/changelog.ts +373 -0
  1436. package/src/utils/clipboard.ts +361 -0
  1437. package/src/utils/command-args.ts +74 -0
  1438. package/src/utils/commit-message-generator.ts +148 -0
  1439. package/src/utils/cpuprofile.ts +235 -0
  1440. package/src/utils/edit-mode.ts +61 -0
  1441. package/src/utils/enhanced-paste.ts +230 -0
  1442. package/src/utils/event-bus.ts +33 -0
  1443. package/src/utils/external-editor.ts +80 -0
  1444. package/src/utils/fetch-timeout.ts +10 -0
  1445. package/src/utils/file-display-mode.ts +44 -0
  1446. package/src/utils/file-mentions.ts +293 -0
  1447. package/src/utils/git.ts +2472 -0
  1448. package/src/utils/image-loading.ts +236 -0
  1449. package/src/utils/image-resize.ts +420 -0
  1450. package/src/utils/image-vision-fallback.ts +196 -0
  1451. package/src/utils/inspect-image-mode.ts +39 -0
  1452. package/src/utils/ipc.ts +38 -0
  1453. package/src/utils/jj.ts +422 -0
  1454. package/src/utils/lang-from-path.ts +251 -0
  1455. package/src/utils/late-cleanup.ts +17 -0
  1456. package/src/utils/local-date.ts +7 -0
  1457. package/src/utils/mac-file-urls.applescript +37 -0
  1458. package/src/utils/markit-cache.ts +166 -0
  1459. package/src/utils/markit.ts +223 -0
  1460. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1461. package/src/utils/open.ts +126 -0
  1462. package/src/utils/profile-tree.ts +111 -0
  1463. package/src/utils/prompt-path.ts +3 -0
  1464. package/src/utils/qrcode.ts +535 -0
  1465. package/src/utils/sample-profile.ts +437 -0
  1466. package/src/utils/session-color.ts +142 -0
  1467. package/src/utils/shell-snapshot-fn-env.sh +63 -0
  1468. package/src/utils/shell-snapshot.ts +326 -0
  1469. package/src/utils/sixel.ts +69 -0
  1470. package/src/utils/thinking-display.ts +163 -0
  1471. package/src/utils/title-generator.ts +597 -0
  1472. package/src/utils/token-rate.ts +72 -0
  1473. package/src/utils/tool-choice.ts +50 -0
  1474. package/src/utils/tools-manager.ts +411 -0
  1475. package/src/utils/turndown.ts +82 -0
  1476. package/src/utils/zip.ts +1106 -0
  1477. package/src/vibe/runtime.ts +1684 -0
  1478. package/src/vibe/state.ts +4 -0
  1479. package/src/web/kagi.ts +305 -0
  1480. package/src/web/parallel.ts +354 -0
  1481. package/src/web/scrapers/artifacthub.ts +207 -0
  1482. package/src/web/scrapers/arxiv.ts +83 -0
  1483. package/src/web/scrapers/aur.ts +162 -0
  1484. package/src/web/scrapers/biorxiv.ts +133 -0
  1485. package/src/web/scrapers/bluesky.ts +262 -0
  1486. package/src/web/scrapers/brew.ts +172 -0
  1487. package/src/web/scrapers/cheatsh.ts +68 -0
  1488. package/src/web/scrapers/chocolatey.ts +196 -0
  1489. package/src/web/scrapers/choosealicense.ts +95 -0
  1490. package/src/web/scrapers/cisa-kev.ts +87 -0
  1491. package/src/web/scrapers/clojars.ts +154 -0
  1492. package/src/web/scrapers/coingecko.ts +177 -0
  1493. package/src/web/scrapers/crates-io.ts +97 -0
  1494. package/src/web/scrapers/crossref.ts +136 -0
  1495. package/src/web/scrapers/devto.ts +147 -0
  1496. package/src/web/scrapers/discogs.ts +306 -0
  1497. package/src/web/scrapers/discourse.ts +197 -0
  1498. package/src/web/scrapers/dockerhub.ts +138 -0
  1499. package/src/web/scrapers/docs-rs.ts +663 -0
  1500. package/src/web/scrapers/fdroid.ts +134 -0
  1501. package/src/web/scrapers/firefox-addons.ts +191 -0
  1502. package/src/web/scrapers/flathub.ts +223 -0
  1503. package/src/web/scrapers/github-gist.ts +58 -0
  1504. package/src/web/scrapers/github.ts +800 -0
  1505. package/src/web/scrapers/gitlab.ts +401 -0
  1506. package/src/web/scrapers/go-pkg.ts +266 -0
  1507. package/src/web/scrapers/hackage.ts +129 -0
  1508. package/src/web/scrapers/hackernews.ts +189 -0
  1509. package/src/web/scrapers/hex.ts +105 -0
  1510. package/src/web/scrapers/huggingface.ts +321 -0
  1511. package/src/web/scrapers/iacr.ts +89 -0
  1512. package/src/web/scrapers/index.ts +252 -0
  1513. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1514. package/src/web/scrapers/lemmy.ts +203 -0
  1515. package/src/web/scrapers/lobsters.ts +175 -0
  1516. package/src/web/scrapers/mastodon.ts +292 -0
  1517. package/src/web/scrapers/maven.ts +138 -0
  1518. package/src/web/scrapers/mdn.ts +173 -0
  1519. package/src/web/scrapers/metacpan.ts +222 -0
  1520. package/src/web/scrapers/musicbrainz.ts +250 -0
  1521. package/src/web/scrapers/npm.ts +98 -0
  1522. package/src/web/scrapers/nuget.ts +183 -0
  1523. package/src/web/scrapers/nvd.ts +222 -0
  1524. package/src/web/scrapers/ollama.ts +239 -0
  1525. package/src/web/scrapers/open-vsx.ts +106 -0
  1526. package/src/web/scrapers/opencorporates.ts +292 -0
  1527. package/src/web/scrapers/openlibrary.ts +336 -0
  1528. package/src/web/scrapers/orcid.ts +286 -0
  1529. package/src/web/scrapers/osv.ts +176 -0
  1530. package/src/web/scrapers/packagist.ts +160 -0
  1531. package/src/web/scrapers/pub-dev.ts +143 -0
  1532. package/src/web/scrapers/pubmed.ts +211 -0
  1533. package/src/web/scrapers/pypi.ts +112 -0
  1534. package/src/web/scrapers/rawg.ts +110 -0
  1535. package/src/web/scrapers/readthedocs.ts +121 -0
  1536. package/src/web/scrapers/reddit.ts +95 -0
  1537. package/src/web/scrapers/repology.ts +251 -0
  1538. package/src/web/scrapers/rfc.ts +201 -0
  1539. package/src/web/scrapers/rubygems.ts +103 -0
  1540. package/src/web/scrapers/searchcode.ts +189 -0
  1541. package/src/web/scrapers/sec-edgar.ts +261 -0
  1542. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1543. package/src/web/scrapers/snapcraft.ts +187 -0
  1544. package/src/web/scrapers/sourcegraph.ts +336 -0
  1545. package/src/web/scrapers/spdx.ts +108 -0
  1546. package/src/web/scrapers/spotify.ts +198 -0
  1547. package/src/web/scrapers/stackoverflow.ts +120 -0
  1548. package/src/web/scrapers/terraform.ts +277 -0
  1549. package/src/web/scrapers/tldr.ts +47 -0
  1550. package/src/web/scrapers/twitter.ts +94 -0
  1551. package/src/web/scrapers/types.ts +354 -0
  1552. package/src/web/scrapers/utils.ts +109 -0
  1553. package/src/web/scrapers/vimeo.ts +133 -0
  1554. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1555. package/src/web/scrapers/w3c.ts +156 -0
  1556. package/src/web/scrapers/wikidata.ts +344 -0
  1557. package/src/web/scrapers/wikipedia.ts +84 -0
  1558. package/src/web/scrapers/youtube.ts +325 -0
  1559. package/src/web/search/index.ts +393 -0
  1560. package/src/web/search/provider.ts +272 -0
  1561. package/src/web/search/providers/anthropic.ts +406 -0
  1562. package/src/web/search/providers/base.ts +112 -0
  1563. package/src/web/search/providers/brave.ts +181 -0
  1564. package/src/web/search/providers/browser-headers.ts +82 -0
  1565. package/src/web/search/providers/browser-page.ts +125 -0
  1566. package/src/web/search/providers/codex.ts +788 -0
  1567. package/src/web/search/providers/duckduckgo.ts +382 -0
  1568. package/src/web/search/providers/ecosia.ts +183 -0
  1569. package/src/web/search/providers/exa.ts +513 -0
  1570. package/src/web/search/providers/firecrawl.ts +213 -0
  1571. package/src/web/search/providers/gemini.ts +634 -0
  1572. package/src/web/search/providers/google.ts +195 -0
  1573. package/src/web/search/providers/jina.ts +144 -0
  1574. package/src/web/search/providers/kagi.ts +98 -0
  1575. package/src/web/search/providers/kimi.ts +221 -0
  1576. package/src/web/search/providers/mojeek.ts +220 -0
  1577. package/src/web/search/providers/parallel.ts +186 -0
  1578. package/src/web/search/providers/perplexity-auth.ts +142 -0
  1579. package/src/web/search/providers/perplexity.ts +997 -0
  1580. package/src/web/search/providers/public.ts +199 -0
  1581. package/src/web/search/providers/searxng.ts +467 -0
  1582. package/src/web/search/providers/startpage.ts +225 -0
  1583. package/src/web/search/providers/synthetic.ts +126 -0
  1584. package/src/web/search/providers/tavily.ts +244 -0
  1585. package/src/web/search/providers/tinyfish.ts +166 -0
  1586. package/src/web/search/providers/utils.ts +130 -0
  1587. package/src/web/search/providers/xai.ts +372 -0
  1588. package/src/web/search/providers/zai.ts +452 -0
  1589. package/src/web/search/query.ts +850 -0
  1590. package/src/web/search/render.ts +262 -0
  1591. package/src/web/search/types.ts +518 -0
  1592. package/src/web/search/utils.ts +17 -0
  1593. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1843 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
4
+ import type { AssistantMessage, UsageLimit, UsageReport } from "@oh-my-pi/pi-ai";
5
+ import { type Component, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
6
+ import { getProjectDir } from "@oh-my-pi/pi-utils";
7
+ import { settings } from "../../../config/settings";
8
+ import type { AgentSession } from "../../../session/agent-session";
9
+ import type { OAuthAccountIdentity } from "../../../session/auth-storage";
10
+ import { limitMatchesActiveAccount } from "../../../slash-commands/helpers/active-oauth-account";
11
+ import { type ActiveRepoContext, resolveActiveRepoContextSync } from "../../../utils/active-repo-context";
12
+ import * as git from "../../../utils/git";
13
+ import * as jj from "../../../utils/jj";
14
+ import { getSessionAccentAnsi, getSessionAccentHex } from "../../../utils/session-color";
15
+ import { calculateTokensPerSecond } from "../../../utils/token-rate";
16
+ import { sanitizeStatusText } from "../../shared";
17
+ import { theme } from "../../theme/theme";
18
+ import {
19
+ type CodexResetFireworksEvent,
20
+ type CodexResetUsageSnapshot,
21
+ detectCodexResetFireworks,
22
+ } from "../codex-reset-fireworks";
23
+ import { canReuseCachedPr, createPrCacheContext, isSamePrCacheContext, type PrCacheContext } from "./git-utils";
24
+ import { getPreset } from "./presets";
25
+ import { renderSegment, type SegmentContext } from "./segments";
26
+ import { getSeparator } from "./separators";
27
+ import type {
28
+ CollabStatus,
29
+ EffectiveStatusLineSettings,
30
+ StatusLineSegmentId,
31
+ StatusLineSegmentOptions,
32
+ StatusLineSettings,
33
+ } from "./types";
34
+
35
+ const JJ_REFRESH_TTL_MS = 5000;
36
+ const WATCHER_FAILURE_POLL_TTL_MS = 5000;
37
+
38
+ function normalizeCodexIdentityValue(value: unknown): string | undefined {
39
+ return typeof value === "string" && value.trim() ? value.trim().toLowerCase() : undefined;
40
+ }
41
+
42
+ /**
43
+ * Fireworks are stateful, so their report match must be stricter than the
44
+ * status display's fallback matching: every known credential identifier must
45
+ * be present and equal or a workspace sibling can mutate this account's
46
+ * baseline.
47
+ */
48
+ function codexReportMatchesExactIdentity(report: UsageReport, identity: OAuthAccountIdentity | undefined): boolean {
49
+ if (!identity) return false;
50
+ const accountId = normalizeCodexIdentityValue(identity.accountId);
51
+ const email = normalizeCodexIdentityValue(identity.email);
52
+ const projectId = normalizeCodexIdentityValue(identity.projectId);
53
+ const orgId = normalizeCodexIdentityValue(identity.orgId);
54
+ if (!accountId && !email && !projectId && !orgId) return false;
55
+
56
+ const metadata = report.metadata ?? {};
57
+ const reportAccountId =
58
+ normalizeCodexIdentityValue(metadata.accountId) ?? normalizeCodexIdentityValue(metadata.account_id);
59
+ const reportProjectId =
60
+ normalizeCodexIdentityValue(metadata.projectId) ?? normalizeCodexIdentityValue(metadata.project_id);
61
+ if (accountId && reportAccountId !== accountId) return false;
62
+ if (email && normalizeCodexIdentityValue(metadata.email) !== email) return false;
63
+ if (projectId && reportProjectId !== projectId) return false;
64
+ if (orgId && normalizeCodexIdentityValue(metadata.orgId) !== orgId) return false;
65
+ return true;
66
+ }
67
+
68
+ // ═══════════════════════════════════════════════════════════════════════════
69
+ // Context-usage memo
70
+ // ═══════════════════════════════════════════════════════════════════════════
71
+
72
+ /**
73
+ * Cheap structural fingerprint of a message's tokenizable content. O(blocks) —
74
+ * only reads string `.length` and primitives, never copies or serializes.
75
+ * Detects in-place growth of the streaming tail (and other in-place mutations)
76
+ * so the cached `getContextUsage()` result is recomputed when — and only when —
77
+ * the numbers it depends on change.
78
+ */
79
+ function messageFingerprint(msg: AgentMessage): string {
80
+ const role = (msg as { role?: string }).role ?? "";
81
+ const ts = (msg as { timestamp?: number }).timestamp ?? 0;
82
+ let textLen = 0;
83
+ let blocks = 0;
84
+ let images = 0;
85
+ if (role === "bashExecution") {
86
+ const b = msg as { command?: unknown; output?: unknown };
87
+ if (typeof b.command === "string") textLen += b.command.length;
88
+ if (typeof b.output === "string") textLen += b.output.length;
89
+ } else if (role === "user") {
90
+ const content = (msg as { content?: unknown }).content;
91
+ if (typeof content === "string") {
92
+ textLen += content.length;
93
+ } else if (Array.isArray(content)) {
94
+ blocks = content.length;
95
+ for (const block of content) {
96
+ if (block?.type === "text" && typeof block.text === "string") textLen += block.text.length;
97
+ }
98
+ }
99
+ } else if (role === "assistant") {
100
+ const assistantMsg = msg as AssistantMessage;
101
+ const usageExt = assistantMsg.usage as unknown as { promptTokensDetails?: unknown };
102
+ const usageTotal = assistantMsg.usage?.totalTokens ?? 0;
103
+ const promptBuckets = usageExt?.promptTokensDetails ? 1 : 0;
104
+ const stopReason = assistantMsg.stopReason ?? "";
105
+
106
+ let signatureLen = 0;
107
+ let redactedLen = 0;
108
+ const msgExt = assistantMsg as unknown as {
109
+ thinkingSignature?: string;
110
+ textSignature?: string;
111
+ thoughtSignature?: string;
112
+ redactedThinking?: { data?: string };
113
+ };
114
+ const thinkingSignature = msgExt.thinkingSignature;
115
+ if (typeof thinkingSignature === "string") {
116
+ signatureLen += thinkingSignature.length;
117
+ }
118
+ const textSignature = msgExt.textSignature;
119
+ if (typeof textSignature === "string") {
120
+ signatureLen += textSignature.length;
121
+ }
122
+ const thoughtSignature = msgExt.thoughtSignature;
123
+ if (typeof thoughtSignature === "string") {
124
+ signatureLen += thoughtSignature.length;
125
+ }
126
+ const redactedData = msgExt.redactedThinking?.data;
127
+ if (typeof redactedData === "string") {
128
+ redactedLen += redactedData.length;
129
+ }
130
+
131
+ const content = (msg as { content?: unknown }).content;
132
+ if (Array.isArray(content)) {
133
+ blocks = content.length;
134
+ for (const block of content) {
135
+ if (!block || typeof block !== "object") continue;
136
+ const b = block as {
137
+ type?: string;
138
+ text?: string;
139
+ thinking?: string;
140
+ thinkingSignature?: string;
141
+ signature?: string;
142
+ textSignature?: string;
143
+ thoughtSignature?: string;
144
+ data?: string;
145
+ name?: string;
146
+ arguments?: unknown;
147
+ };
148
+ if (b.type === "text" && typeof b.text === "string") textLen += b.text.length;
149
+ else if (b.type === "thinking") {
150
+ if (typeof b.thinking === "string") textLen += b.thinking.length;
151
+ if (typeof b.thinkingSignature === "string") signatureLen += b.thinkingSignature.length;
152
+ if (typeof b.signature === "string") signatureLen += b.signature.length;
153
+ if (typeof b.textSignature === "string") signatureLen += b.textSignature.length;
154
+ if (typeof b.thoughtSignature === "string") signatureLen += b.thoughtSignature.length;
155
+ } else if (b.type === "redactedThinking" && typeof b.data === "string") {
156
+ redactedLen += b.data.length;
157
+ } else if (b.type === "toolCall") {
158
+ if (typeof b.name === "string") textLen += b.name.length;
159
+ if (b.arguments !== undefined) {
160
+ try {
161
+ textLen += JSON.stringify(b.arguments, (_key, value) =>
162
+ typeof value === "bigint" ? value.toString() : value,
163
+ ).length;
164
+ } catch {
165
+ textLen += String(b.arguments).length;
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+ return `${role}:${ts}:${textLen}:${blocks}:${images}:${signatureLen}:${redactedLen}:${usageTotal}:${promptBuckets}:${stopReason}`;
172
+ } else if (role === "toolResult" || role === "hookMessage") {
173
+ const content = (msg as { content?: unknown }).content;
174
+ if (typeof content === "string") {
175
+ textLen += content.length;
176
+ } else if (Array.isArray(content)) {
177
+ blocks = content.length;
178
+ for (const block of content) {
179
+ if (!block || typeof block !== "object") continue;
180
+ const b = block as { type?: string; text?: string };
181
+ if (b.type === "text" && typeof b.text === "string") textLen += b.text.length;
182
+ else if (b.type === "image") images++;
183
+ }
184
+ }
185
+ } else if (role === "branchSummary" || role === "compactionSummary") {
186
+ const s = (msg as { summary?: unknown }).summary;
187
+ if (typeof s === "string") textLen += s.length;
188
+ }
189
+ return `${role}:${ts}:${textLen}:${blocks}:${images}`;
190
+ }
191
+
192
+ interface ContextUsageMemo {
193
+ messagesRef: readonly AgentMessage[];
194
+ length: number;
195
+ lastFingerprint: string | undefined;
196
+ modelContextWindow: number;
197
+ contextUsageRevision: number;
198
+ usedTokens: number;
199
+ contextWindow: number;
200
+ systemPromptRef: readonly string[] | undefined;
201
+ toolsRef: readonly any[] | undefined;
202
+ skillsRef: readonly any[] | undefined;
203
+ }
204
+
205
+ interface ActiveRepoCache {
206
+ projectDir: string;
207
+ activeRepo: ActiveRepoContext | null;
208
+ effectiveGitCwd: string;
209
+ /** Project + worktree dir name when `projectDir` is a linked worktree, else null. */
210
+ worktree: WorktreeContext | null;
211
+ }
212
+
213
+ interface BranchResolveRequest {
214
+ id: number;
215
+ cwd: string;
216
+ controller: AbortController;
217
+ }
218
+
219
+ interface JjResolveRequest {
220
+ id: number;
221
+ controller: AbortController;
222
+ }
223
+
224
+ interface WorktreeContext {
225
+ /** Primary-checkout (project) name shown by the path segment. */
226
+ projectName: string;
227
+ /** Worktree directory name — suppressed from the path when it equals the branch. */
228
+ worktreeName: string;
229
+ }
230
+
231
+ /**
232
+ * Project + worktree-dir names when `cwd` is a linked git worktree, else null.
233
+ * The project name comes from the shared primary checkout; bare-repo worktrees
234
+ * resolve to the shared `foo.git` dir, so a trailing `.git` is stripped.
235
+ */
236
+ function resolveWorktreeContext(cwd: string): WorktreeContext | null {
237
+ const worktree = git.repo.linkedWorktreeSync(cwd);
238
+ if (!worktree) return null;
239
+ const base = path.basename(worktree.primaryRoot);
240
+ const projectName = base.endsWith(".git") ? base.slice(0, -4) : base;
241
+ if (!projectName) return null;
242
+ return { projectName, worktreeName: path.basename(worktree.root) };
243
+ }
244
+
245
+ /**
246
+ * Per-{@link AgentSession} active-processing meter for the `time_spent`
247
+ * segment. `activeMs` is the union of every completed `agent_start`→
248
+ * `agent_end` window; `activeStartedAt` is the start timestamp of the
249
+ * currently-running window, or `null` when idle.
250
+ *
251
+ * `sessionFile` snapshots the loaded session-file path at meter-creation
252
+ * time. `AgentSession.switchSession` (/resume, /move, ACP fork, RPC
253
+ * `switch_session`, extension `switchSession`) mutates the loaded file
254
+ * under the same {@link AgentSession} ref, so the WeakMap key alone
255
+ * cannot tell two conversations apart. `#meter()` compares this snapshot
256
+ * against the live `session.sessionFile`, and a real-to-real change
257
+ * starts the meter fresh instead of crediting the new conversation with
258
+ * the previous one's accumulated active time. The undefined → real
259
+ * first-save transition does not reset, since the session identity has
260
+ * not changed.
261
+ */
262
+ interface ActiveMeter {
263
+ activeMs: number;
264
+ activeStartedAt: number | null;
265
+ sessionFile: string | undefined;
266
+ }
267
+
268
+ const EMPTY_MESSAGES: readonly AgentMessage[] = [];
269
+ const STATUS_USAGE_START_DELAY_MS = 0;
270
+ const STATUS_USAGE_REFRESH_TIMEOUT_MS = 2_000;
271
+
272
+ function hasContextSegment(segments: readonly StatusLineSegmentId[]): boolean {
273
+ return segments.includes("context_pct") || segments.includes("context_total");
274
+ }
275
+ function hasGitSegment(segments: readonly StatusLineSegmentId[]): boolean {
276
+ return segments.includes("git");
277
+ }
278
+
279
+ function hasPrSegment(segments: readonly StatusLineSegmentId[]): boolean {
280
+ return segments.includes("pr");
281
+ }
282
+ function hasPathSegment(segments: readonly StatusLineSegmentId[]): boolean {
283
+ return segments.includes("path");
284
+ }
285
+
286
+ function hasGitBackedSegment(segments: readonly StatusLineSegmentId[]): boolean {
287
+ return hasGitSegment(segments) || hasPrSegment(segments);
288
+ }
289
+
290
+ // ═══════════════════════════════════════════════════════════════════════════
291
+ // StatusLineComponent
292
+ // ═══════════════════════════════════════════════════════════════════════════
293
+
294
+ export class StatusLineComponent implements Component {
295
+ #settings: StatusLineSettings = {};
296
+ #effectiveSettings: EffectiveStatusLineSettings | undefined;
297
+ #cachedBranch: string | null | undefined = undefined;
298
+ #cachedBranchRepoId: string | null | undefined = undefined;
299
+ #cachedBranchCwd: string | undefined = undefined;
300
+ #cachedBranchHasGitRepository = false;
301
+ // In-flight reftable resolve slot. Ownership is the launch id, not the cwd:
302
+ // two live resolves can share a cwd string across an invalidation, and a
303
+ // stale one must never free (or poison) a slot it no longer owns.
304
+ #branchResolveSeq = 0;
305
+ #branchResolveActive: BranchResolveRequest | undefined = undefined;
306
+ // Bumped on every branch-cache reset (#invalidateGitCaches — a HEAD move or
307
+ // repo-context change). An in-flight reftable resolve captures this at
308
+ // launch; a mismatch on resolve means the cache was invalidated underneath
309
+ // it (a newer resolve superseded it), so its result is stale and must be
310
+ // dropped rather than overwrite the value the newer resolve committed.
311
+ // Mirrors #jjCacheGeneration / #getJjBranch in this file.
312
+ // Timestamp of the latest branch read; only bounds cache freshness when the
313
+ // HEAD watcher could not be installed.
314
+ #branchLastFetch: number | undefined = undefined;
315
+ // Bumped on every branch-cache reset (invalidateGitCaches — a HEAD move or
316
+ // repo-context change). An in-flight reftable resolve captures this at
317
+ // launch; a mismatch on resolve means the cache was invalidated underneath
318
+ // it (a newer resolve superseded it), so its result is stale and must be
319
+ // dropped rather than overwrite the value the newer resolve committed.
320
+ // Mirrors #jjCacheGeneration / #getJjBranch in this file.
321
+ #branchCacheGeneration = 0;
322
+ #gitWatcher: fs.FSWatcher | null = null;
323
+ #gitWatcherErrorListener: (() => void) | undefined = undefined;
324
+ #gitWatcherUnavailable = false;
325
+ #onBranchChange: (() => void) | null = null;
326
+ #disposed = false;
327
+ #autoCompactEnabled: boolean = true;
328
+ #hookStatuses: Map<string, string> = new Map();
329
+ #subagentCount: number = 0;
330
+ /**
331
+ * Active-processing accounting for the `time_spent` segment, keyed per
332
+ * {@link AgentSession} so the focus-controller mid-turn attach path
333
+ * cannot leak an unmatched synthesized `agent_start` from a subagent
334
+ * into the main session's meter.
335
+ *
336
+ * Each meter is `{ activeMs, activeStartedAt }`: `activeMs` is the union
337
+ * of every completed `agent_start`→`agent_end` window since
338
+ * {@link resetActiveTime} last reset it; `activeStartedAt` is the start
339
+ * timestamp of the currently-running window (or `null` when idle).
340
+ * `getActiveMs()` returns `activeMs + (now - activeStartedAt)` for the
341
+ * currently-attached session, so the counter ticks live during a turn
342
+ * and freezes the instant the agent yields.
343
+ *
344
+ * WeakMap so meters die with their session (e.g. a parked subagent
345
+ * dropped from the registry); the main session's meter survives focus
346
+ * round-trips because the same {@link AgentSession} ref is reused.
347
+ */
348
+ #activeMeters: WeakMap<AgentSession, ActiveMeter> = new WeakMap();
349
+ #planModeStatus: { enabled: boolean; paused: boolean } | null = null;
350
+ #loopModeStatus: SegmentContext["loopMode"] = null;
351
+ #goalModeStatus: { enabled: boolean; paused: boolean } | null = null;
352
+ #vibeModeStatus: { enabled: boolean } | null = null;
353
+ /**
354
+ * Injected aggregator that returns the aggregate tok/s of this session's
355
+ * live vibe worker sessions, or null when no workers are streaming. Kept as
356
+ * a callback so the render layer doesn't import the heavy vibe/task
357
+ * dependency graph; interactive-mode wires it to VibeSessionRegistry.
358
+ */
359
+ #vibeWorkerTokenRate: (() => number | null) | null = null;
360
+ #collabStatus: CollabStatus | null = null;
361
+ #focusedAgentId: string | undefined;
362
+ #activeRepoCache: ActiveRepoCache | undefined;
363
+
364
+ // Git status caching (1s TTL)
365
+ #cachedGitStatus: { staged: number; unstaged: number; untracked: number } | null = null;
366
+ #cachedGitStatusCwd: string | undefined = undefined;
367
+ #gitStatusLastFetch = 0;
368
+ #gitStatusInFlightCwd: string | undefined = undefined;
369
+ #jjRoot: string | null | undefined = undefined;
370
+ #jjRootCwd: string | undefined = undefined;
371
+ #cachedJjBranch: string | null = null;
372
+ #jjBranchLastFetch = 0;
373
+ #jjResolveSeq = 0;
374
+ #jjBranchActive: JjResolveRequest | undefined = undefined;
375
+ #cachedJjStatus: { staged: number; unstaged: number; untracked: number } | null = null;
376
+ #jjStatusLastFetch = 0;
377
+ #jjStatusActive: JjResolveRequest | undefined = undefined;
378
+ // Bumped on every jj-cache reset — a cwd switch (#jjRootFor) or a HEAD /
379
+ // bookmark move (#invalidateGitCaches). An in-flight jj query captures this
380
+ // at launch; a mismatch on resolve means the caches were reset underneath it
381
+ // (including a reset that re-resolves to the SAME root, which a root-equality
382
+ // check cannot detect), so the result is stale and must be dropped rather
383
+ // than poison the fresh cache or advance its throttle.
384
+ #jjCacheGeneration = 0;
385
+
386
+ // PR lookup caching (invalidated on branch/repo context changes)
387
+ #cachedPr: { number: number; url: string } | null | undefined = undefined;
388
+ #cachedPrContext: PrCacheContext | undefined = undefined;
389
+ #prLookupInFlight = false;
390
+ #defaultBranch?: string;
391
+ #defaultBranchCwd: string | undefined = undefined;
392
+ #lastTokensPerSecond: number | null = null;
393
+ #lastTokensPerSecondTimestamp: number | null = null;
394
+
395
+ // Provider usage caching (5-min TTL, OAuth/sub only)
396
+ #cachedUsage: {
397
+ tier?: string;
398
+ fiveHour?: { percent: number; resetMinutes?: number };
399
+ sevenDay?: { percent: number; resetHours?: number };
400
+ } | null = null;
401
+ #cachedUsageContextKey: string | null = null;
402
+ #usageFetchedAt = 0;
403
+ #usageInFlight = false;
404
+ #usageStartTimer: Timer | null = null;
405
+ // A timed-out request may still resolve. Its result remains eligible only
406
+ // until a newer request has applied.
407
+ #usageRefreshSequence = 0;
408
+ #latestAppliedUsageRefreshSequence = 0;
409
+ #codexResetSnapshots = new Map<string, CodexResetUsageSnapshot>();
410
+ #onCodexResetFireworks: ((event: CodexResetFireworksEvent) => void) | undefined;
411
+ // Context-usage memo. The status line redraws on every agent event, so the
412
+ // hot path must not recompute context tokens unless an input changed.
413
+ // `getContextUsage()` anchors on the last assistant's real prompt-token
414
+ // count (matching the provider and the `/context` panel), so a stable
415
+ // message list + model window yields a stable result we can return verbatim.
416
+ #contextUsageCache: ContextUsageMemo | undefined;
417
+
418
+ constructor(private session: AgentSession) {
419
+ this.#settings = {
420
+ preset: settings.get("statusLine.preset"),
421
+ leftSegments: settings.get("statusLine.leftSegments"),
422
+ rightSegments: settings.get("statusLine.rightSegments"),
423
+ separator: settings.get("statusLine.separator"),
424
+ showHookStatus: settings.get("statusLine.showHookStatus"),
425
+ segmentOptions: settings.getGroup("statusLine").segmentOptions,
426
+ sessionAccent: settings.get("statusLine.sessionAccent"),
427
+ transparent: settings.get("statusLine.transparent"),
428
+ compactThinkingLevel: settings.get("statusLine.compactThinkingLevel"),
429
+ };
430
+ }
431
+ #gitEnabled(): boolean {
432
+ return settings.get("git.enabled");
433
+ }
434
+ #hasGitBackedSegment(): boolean {
435
+ const effectiveSettings = this.#resolveSettings();
436
+ return (
437
+ hasGitBackedSegment(effectiveSettings.leftSegments) || hasGitBackedSegment(effectiveSettings.rightSegments)
438
+ );
439
+ }
440
+
441
+ #resolveActiveRepoCache(): ActiveRepoCache {
442
+ const projectDir = getProjectDir();
443
+ if (this.#activeRepoCache?.projectDir === projectDir) {
444
+ return this.#activeRepoCache;
445
+ }
446
+
447
+ const activeRepo = resolveActiveRepoContextSync(projectDir);
448
+ const effectiveGitCwd = activeRepo?.repoRoot ?? projectDir;
449
+ // Only collapse the bare-cwd case: a single-direct-child-repo context
450
+ // (activeRepo set) renders `<parent> ↳ <child>`, which we leave intact.
451
+ const worktree = activeRepo ? null : resolveWorktreeContext(effectiveGitCwd);
452
+ this.#activeRepoCache = { projectDir, activeRepo, effectiveGitCwd, worktree };
453
+ return this.#activeRepoCache;
454
+ }
455
+
456
+ /**
457
+ * Re-point the status line at another session (focus proxy). Invalidate: model/context/usage all derive
458
+ * from it. `focusedAgentId` is the focused subagent id while the view is proxied, undefined for main.
459
+ */
460
+ setSession(session: AgentSession, focusedAgentId?: string): void {
461
+ const sessionChanged = this.session !== session;
462
+ if (!sessionChanged && this.#focusedAgentId === focusedAgentId) return;
463
+ this.session = session;
464
+ this.#focusedAgentId = focusedAgentId;
465
+ if (sessionChanged) {
466
+ this.#invalidateSessionCaches();
467
+ this.#closeStaleActiveWindow();
468
+ }
469
+ this.invalidate();
470
+ }
471
+
472
+ /**
473
+ * Drop a meter's in-flight window when the newly-attached session is no
474
+ * longer streaming. Handles the case where the focus controller
475
+ * synthesized an `agent_start` on a mid-turn attach but the matching
476
+ * real `agent_end` never reached us — the user detached before it
477
+ * fired, and re-focusing later (after the agent finished) would
478
+ * otherwise tick over the entire detached gap. Crediting that gap to
479
+ * `activeMs` would be wrong (the agent finished at some point we never
480
+ * observed), so the window is dropped rather than folded in.
481
+ */
482
+ #closeStaleActiveWindow(): void {
483
+ const meter = this.#meter();
484
+ if (meter.activeStartedAt === null) return;
485
+ if (this.session.isStreaming) return;
486
+ meter.activeStartedAt = null;
487
+ }
488
+
489
+ updateSettings(settings: StatusLineSettings): void {
490
+ this.#settings = settings;
491
+ this.#effectiveSettings = undefined;
492
+ if (this.#onBranchChange) this.#setupGitWatcher();
493
+ }
494
+
495
+ getEffectiveSettingsForTest(): EffectiveStatusLineSettings {
496
+ return this.#resolveSettings();
497
+ }
498
+
499
+ setAutoCompactEnabled(enabled: boolean): void {
500
+ this.#autoCompactEnabled = enabled;
501
+ }
502
+
503
+ setSubagentCount(count: number): void {
504
+ this.#subagentCount = count;
505
+ }
506
+
507
+ /**
508
+ * Compatibility shim for callers predating the simplified subagent badge.
509
+ * The status line now intentionally shows only the active count.
510
+ */
511
+ setSubagentHubHint(_hint: string | undefined): void {}
512
+
513
+ /** Active subagent count as currently displayed (collab state mirroring). */
514
+ get subagentCount(): number {
515
+ return this.#subagentCount;
516
+ }
517
+
518
+ /**
519
+ * Reset the currently-attached session's active-time accumulators so
520
+ * the `time_spent` segment starts from zero. Called from `/clear`,
521
+ * fresh-session, and joined-collab paths; both the completed
522
+ * accumulator and any in-flight window are dropped, so a reset
523
+ * mid-turn ignores the running window (the matching `markActivityEnd`
524
+ * will see an idle meter and no-op).
525
+ */
526
+ resetActiveTime(): void {
527
+ const meter = this.#meter();
528
+ meter.activeMs = 0;
529
+ meter.activeStartedAt = null;
530
+ }
531
+
532
+ /**
533
+ * Mark the currently-attached session as having started a unit of
534
+ * active processing. Idempotent: a second start while a window is
535
+ * already open is a no-op, so reentrant `agent_start` events (e.g.
536
+ * nested auto-compaction loops, focus-controller mid-turn attach onto
537
+ * an already-running window) do not double-count.
538
+ */
539
+ markActivityStart(): void {
540
+ const meter = this.#meter();
541
+ if (meter.activeStartedAt !== null) return;
542
+ meter.activeStartedAt = Date.now();
543
+ }
544
+
545
+ /**
546
+ * Close the currently-attached session's open active-processing
547
+ * window, folding its elapsed time into the accumulator. Idempotent
548
+ * when the meter is already idle so callers can fire it on every
549
+ * `agent_end` without guarding.
550
+ */
551
+ markActivityEnd(): void {
552
+ const meter = this.#meter();
553
+ if (meter.activeStartedAt === null) return;
554
+ meter.activeMs += Math.max(0, Date.now() - meter.activeStartedAt);
555
+ meter.activeStartedAt = null;
556
+ }
557
+
558
+ /**
559
+ * Snapshot of total active-processing time for the currently-attached
560
+ * session, including any in-flight window. Exposed for the segment
561
+ * context builder; tests assert against this too.
562
+ */
563
+ getActiveMs(): number {
564
+ const meter = this.#meter();
565
+ if (meter.activeStartedAt === null) return meter.activeMs;
566
+ return meter.activeMs + Math.max(0, Date.now() - meter.activeStartedAt);
567
+ }
568
+
569
+ /**
570
+ * Return (lazily creating) the meter for the currently-attached
571
+ * session. Detects an in-place session-file swap under the same
572
+ * {@link AgentSession} ref (`switchSession` paths: `/resume`, `/move`,
573
+ * ACP fork/load, RPC `switch_session`, extension `switchSession`):
574
+ * a real-to-real change starts the meter fresh so the new
575
+ * conversation does not inherit the previous one's accumulated active
576
+ * time. The undefined → real first-save transition only refreshes the
577
+ * snapshot — the conversation identity has not changed.
578
+ */
579
+ #meter(): ActiveMeter {
580
+ const currentFile = this.session.sessionFile;
581
+ let meter = this.#activeMeters.get(this.session);
582
+ if (meter) {
583
+ const switched =
584
+ currentFile !== undefined && meter.sessionFile !== undefined && meter.sessionFile !== currentFile;
585
+ if (switched) {
586
+ meter = undefined;
587
+ } else {
588
+ meter.sessionFile = currentFile;
589
+ }
590
+ }
591
+ if (!meter) {
592
+ meter = { activeMs: 0, activeStartedAt: null, sessionFile: currentFile };
593
+ this.#activeMeters.set(this.session, meter);
594
+ }
595
+ return meter;
596
+ }
597
+
598
+ setPlanModeStatus(status: { enabled: boolean; paused: boolean } | undefined): void {
599
+ this.#planModeStatus = status ?? null;
600
+ }
601
+
602
+ setLoopModeStatus(status: NonNullable<SegmentContext["loopMode"]> | undefined): void {
603
+ this.#loopModeStatus = status ?? null;
604
+ }
605
+
606
+ setGoalModeStatus(status: { enabled: boolean; paused: boolean } | undefined): void {
607
+ this.#goalModeStatus = status ?? null;
608
+ }
609
+
610
+ setVibeModeStatus(status: { enabled: boolean } | undefined): void {
611
+ this.#vibeModeStatus = status ?? null;
612
+ }
613
+
614
+ /**
615
+ * Inject the aggregator that returns the aggregate tok/s of this session's
616
+ * live vibe worker sessions (null when no workers are streaming). Wired by
617
+ * interactive-mode, which owns the VibeSessionRegistry coupling, so the
618
+ * render layer stays off the heavy vibe/task dependency graph. Pass
619
+ * `undefined` to clear.
620
+ */
621
+ setVibeWorkerTokenRateProvider(provider: (() => number | null) | undefined): void {
622
+ this.#vibeWorkerTokenRate = provider ?? null;
623
+ }
624
+
625
+ setCollabStatus(status: CollabStatus | null): void {
626
+ this.#collabStatus = status;
627
+ }
628
+
629
+ /** Set the callback that presents detected Codex reset celebrations, or clear it with `undefined`. */
630
+ setCodexResetFireworksHandler(handler: ((event: CodexResetFireworksEvent) => void) | undefined): void {
631
+ this.#onCodexResetFireworks = handler;
632
+ }
633
+
634
+ setHookStatus(key: string, text: string | undefined): void {
635
+ if (text === undefined) {
636
+ this.#hookStatuses.delete(key);
637
+ } else {
638
+ this.#hookStatuses.set(key, text);
639
+ }
640
+ }
641
+
642
+ watchBranch(onBranchChange: () => void): void {
643
+ this.#onBranchChange = onBranchChange;
644
+ this.#setupGitWatcher();
645
+ }
646
+
647
+ #setupGitWatcher(): void {
648
+ this.#retireGitWatcher();
649
+ this.#gitWatcherUnavailable = false;
650
+
651
+ if (!this.#gitEnabled() || !this.#hasGitBackedSegment()) {
652
+ this.invalidateGitCaches();
653
+ return;
654
+ }
655
+
656
+ const { effectiveGitCwd } = this.#resolveActiveRepoCache();
657
+ const repository = git.repo.resolveSync(effectiveGitCwd);
658
+ if (!repository) {
659
+ // There is no path to watch yet. Cache the negative result only for the
660
+ // fallback poll interval so a later `git init` becomes visible without
661
+ // generic invalidations or a render-path probe on every paint.
662
+ this.#gitWatcherUnavailable = true;
663
+ return;
664
+ }
665
+
666
+ const watchPath = git.repo.isReftableSync(repository)
667
+ ? path.join(repository.gitDir, "reftable")
668
+ : repository.headPath;
669
+
670
+ try {
671
+ const watcher = fs.watch(watchPath, () => {
672
+ if (this.#disposed || this.#gitWatcher !== watcher) return;
673
+ this.invalidateGitCaches();
674
+ this.#onBranchChange?.();
675
+ });
676
+ const onError = () => {
677
+ if (this.#gitWatcher !== watcher) return;
678
+ this.#retireGitWatcher();
679
+ this.#gitWatcherUnavailable = true;
680
+ if (this.#disposed) return;
681
+ this.invalidateGitCaches();
682
+ this.#onBranchChange?.();
683
+ };
684
+ this.#gitWatcher = watcher;
685
+ this.#gitWatcherErrorListener = onError;
686
+ watcher.on("error", onError);
687
+ } catch {
688
+ this.#gitWatcherUnavailable = true;
689
+ }
690
+ }
691
+
692
+ #retireGitWatcher(): void {
693
+ const watcher = this.#gitWatcher;
694
+ const onError = this.#gitWatcherErrorListener;
695
+ this.#gitWatcher = null;
696
+ this.#gitWatcherErrorListener = undefined;
697
+ if (!watcher) return;
698
+ if (onError) watcher.off("error", onError);
699
+ watcher.close();
700
+ }
701
+
702
+ dispose(): void {
703
+ this.#disposed = true;
704
+ this.#branchResolveActive?.controller.abort();
705
+ this.#branchResolveActive = undefined;
706
+ this.#resetJjRequests();
707
+ this.#onBranchChange = null;
708
+ this.#clearUsageStartTimer();
709
+ this.#onCodexResetFireworks = undefined;
710
+ this.#codexResetSnapshots.clear();
711
+ this.#retireGitWatcher();
712
+ }
713
+
714
+ #clearUsageStartTimer(): void {
715
+ if (!this.#usageStartTimer) return;
716
+ clearTimeout(this.#usageStartTimer);
717
+ this.#usageStartTimer = null;
718
+ }
719
+
720
+ invalidate(): void {
721
+ // Generic repaint invalidation (theme change, message event, model
722
+ // switch, …). Must NOT abort or restart a live reftable HEAD/PR resolve:
723
+ // the render path self-invalidates via cwd/context cache-miss checks, so
724
+ // a generic paint only needs to re-render — not tear down in-flight VCS
725
+ // work. Aborting here would fan out a new git subprocess on every agent
726
+ // event, re-introducing the render-path spawn churn the async resolve
727
+ // was designed to avoid. Explicit Git/repository invalidation (watcher
728
+ // HEAD-move, cwd/repo switch) goes through {@link invalidateGitCaches}.
729
+ // A tool may open, close, or merge a PR without moving HEAD. Expire the
730
+ // settled PR context on ordinary activity while leaving HEAD work intact.
731
+ this.#cachedPrContext = undefined;
732
+ }
733
+ #invalidateSessionCaches(): void {
734
+ this.#clearUsageStartTimer();
735
+ this.#cachedUsage = null;
736
+ this.#usageFetchedAt = 0;
737
+ this.#usageInFlight = false;
738
+ this.#contextUsageCache = undefined;
739
+ this.#lastTokensPerSecond = null;
740
+ this.#lastTokensPerSecondTimestamp = null;
741
+ }
742
+
743
+ /**
744
+ * Explicit Git/repository cache invalidation. Aborts any in-flight
745
+ * reftable HEAD/PR resolve, bumps the stale-result generation, and drops
746
+ * the branch/PR/jj caches so the next render refetches from disk. Called
747
+ * by the git watcher on a HEAD move and by {@link applyCwdChange} on a
748
+ * repo/cwd switch. Generic repaints use {@link invalidate} instead and
749
+ * must never reach this path.
750
+ */
751
+ invalidateGitCaches(): void {
752
+ this.#cachedBranch = undefined;
753
+ this.#cachedBranchRepoId = undefined;
754
+ this.#cachedBranchCwd = undefined;
755
+ this.#cachedBranchHasGitRepository = false;
756
+ // Abort before releasing the in-flight slot. Releasing alone would allow
757
+ // repeated invalidations to fan out still-running git subprocesses.
758
+ this.#branchResolveActive?.controller.abort();
759
+ this.#branchResolveActive = undefined;
760
+ this.#branchLastFetch = undefined;
761
+ this.#branchCacheGeneration++;
762
+ this.#cachedPrContext = undefined;
763
+ // jj label/status share the git segment's lifecycle: a HEAD move (e.g. a
764
+ // colocated `jj new`/bookmark move) must drop the throttled jj caches too,
765
+ // mirroring #jjRootFor's per-cwd reset so the next render refetches.
766
+ this.#resetJjRequests();
767
+ this.#jjRoot = undefined;
768
+ this.#jjRootCwd = undefined;
769
+ this.#cachedJjBranch = null;
770
+ this.#jjBranchLastFetch = 0;
771
+ this.#cachedJjStatus = null;
772
+ this.#jjStatusLastFetch = 0;
773
+ this.#jjCacheGeneration++;
774
+ }
775
+
776
+ /**
777
+ * Re-point the status line's VCS watcher and caches at a new cwd/repository.
778
+ * Atomically retires the old watcher/listeners, invalidates VCS caches and
779
+ * in-flight controllers, then runs watcher setup for the new cwd and requests
780
+ * a repaint. Called by {@link InteractiveMode.applyCwdChange} after the
781
+ * SessionManager's cwd has moved — the watcher ownership always follows the
782
+ * effective cwd/repo, so a stale watcher for the previous repo can never
783
+ * invalidate the new one. Generic repaints use {@link invalidate} and must
784
+ * never retire the watcher or abort a live resolve.
785
+ */
786
+ applyCwdChange(): void {
787
+ this.#retireGitWatcher();
788
+ this.invalidateGitCaches();
789
+ this.#setupGitWatcher();
790
+ this.#onBranchChange?.();
791
+ }
792
+
793
+ #resetJjRequests(): void {
794
+ this.#jjBranchActive?.controller.abort();
795
+ this.#jjBranchActive = undefined;
796
+ this.#jjStatusActive?.controller.abort();
797
+ this.#jjStatusActive = undefined;
798
+ }
799
+ #getCurrentBranch(effectiveGitCwd?: string): string | null {
800
+ if (!this.#gitEnabled()) return null;
801
+
802
+ const gitCwd = effectiveGitCwd ?? this.#resolveActiveRepoCache().effectiveGitCwd;
803
+ const fallbackCacheExpired =
804
+ this.#gitWatcherUnavailable &&
805
+ (this.#branchLastFetch === undefined || Date.now() - this.#branchLastFetch >= WATCHER_FAILURE_POLL_TTL_MS);
806
+ if (this.#cachedBranch !== undefined && this.#cachedBranchCwd === gitCwd && !fallbackCacheExpired) {
807
+ return this.#cachedBranch;
808
+ }
809
+
810
+ // A reftable repo resolves HEAD by spawning `git symbolic-ref` +
811
+ // `git rev-parse` — the unbounded spawn that froze the render path (F7).
812
+ // A non-reftable repo resolves HEAD with cheap sync filesystem reads, so
813
+ // only the reftable branch moves off the render path, mirroring
814
+ // #getGitStatus and #getJjBranch in this file.
815
+ const repository = git.repo.resolveSync(gitCwd);
816
+ if (repository && git.repo.isReftableSync(repository)) {
817
+ if (this.#branchResolveActive !== undefined) {
818
+ return this.#branchResolveActive.cwd === gitCwd && this.#cachedBranchCwd === gitCwd
819
+ ? (this.#cachedBranch ?? null)
820
+ : null;
821
+ }
822
+ const request: BranchResolveRequest = {
823
+ id: ++this.#branchResolveSeq,
824
+ cwd: gitCwd,
825
+ controller: new AbortController(),
826
+ };
827
+ this.#branchResolveActive = request;
828
+ // Capture the cache generation at launch. invalidateGitCaches bumps it
829
+ // on a HEAD move and clears the in-flight slot, so a fresher resolve can
830
+ // start while this one is still pending. Without a generation check the
831
+ // older resolve would finish later, install its stale HEAD, and clear the
832
+ // slot — dropping the fresh result and freezing the status line on the
833
+ // pre-change branch. Mirrors #jjCacheGeneration / #getJjBranch.
834
+ const generation = this.#branchCacheGeneration;
835
+ (async () => {
836
+ let next: string | null = null;
837
+ let repoId: string | null = null;
838
+ try {
839
+ const headState = await git.head.resolve(gitCwd, request.controller.signal);
840
+ repoId = headState?.headPath ?? null;
841
+ next = !headState
842
+ ? null
843
+ : headState.kind === "ref"
844
+ ? (headState.branchName ?? headState.ref)
845
+ : "detached";
846
+ } catch {
847
+ next = null;
848
+ } finally {
849
+ // Release the slot only if this resolve still owns it: after an
850
+ // invalidation a fresher resolve may hold it, and freeing that
851
+ // slot here would let a third same-generation resolve launch and
852
+ // race the fresh one to the cache commit.
853
+ if (this.#branchResolveActive?.id === request.id) this.#branchResolveActive = undefined;
854
+ }
855
+ // Only the latest generation may update the cache; a mismatch means a
856
+ // newer resolve superseded this one (or the component disposed).
857
+ if (this.#branchCacheGeneration !== generation || this.#disposed) return;
858
+ const prev = this.#cachedBranchCwd === gitCwd ? this.#cachedBranch : undefined;
859
+ this.#cachedBranchCwd = gitCwd;
860
+ this.#cachedBranchRepoId = repoId;
861
+ this.#cachedBranchHasGitRepository = next === null;
862
+ this.#cachedBranch = next;
863
+ this.#branchLastFetch = Date.now();
864
+ if (prev !== next && this.#onBranchChange) this.#onBranchChange();
865
+ })();
866
+ return this.#cachedBranchCwd === gitCwd ? (this.#cachedBranch ?? null) : null;
867
+ }
868
+
869
+ // Non-reftable: cheap sync filesystem read, safe on the render path.
870
+ const head = git.head.resolveSync(gitCwd);
871
+ const gitHeadPath = head?.headPath ?? null;
872
+ this.#cachedBranchCwd = gitCwd;
873
+ this.#cachedBranchRepoId = gitHeadPath;
874
+ this.#branchLastFetch = Date.now();
875
+ if (!head) {
876
+ this.#cachedBranch = null;
877
+ return null;
878
+ }
879
+ this.#cachedBranch = head.kind === "ref" ? (head.branchName ?? head.ref) : "detached";
880
+ return this.#cachedBranch ?? null;
881
+ }
882
+
883
+ #isDefaultBranch(branch: string, effectiveGitCwd: string): boolean {
884
+ if (this.#defaultBranchCwd !== effectiveGitCwd) {
885
+ this.#defaultBranch = undefined;
886
+ this.#defaultBranchCwd = effectiveGitCwd;
887
+ }
888
+
889
+ if (this.#defaultBranch === undefined) {
890
+ this.#defaultBranch = "main";
891
+ const lookupCwd = effectiveGitCwd;
892
+ (async () => {
893
+ const resolved = await git.branch.default(lookupCwd);
894
+ if (this.#disposed || this.#defaultBranchCwd !== lookupCwd) return;
895
+ if (resolved) {
896
+ this.#defaultBranch = resolved;
897
+ if (this.#onBranchChange) {
898
+ this.#onBranchChange();
899
+ }
900
+ }
901
+ })();
902
+ }
903
+ return branch === this.#defaultBranch;
904
+ }
905
+
906
+ #getGitStatus(effectiveGitCwd?: string): { staged: number; unstaged: number; untracked: number } | null {
907
+ if (!this.#gitEnabled()) return null;
908
+
909
+ const gitCwd = effectiveGitCwd ?? this.#resolveActiveRepoCache().effectiveGitCwd;
910
+ if (this.#gitStatusInFlightCwd !== undefined) {
911
+ return this.#cachedGitStatusCwd === gitCwd ? this.#cachedGitStatus : null;
912
+ }
913
+ if (this.#cachedGitStatusCwd === gitCwd && Date.now() - this.#gitStatusLastFetch < 1000) {
914
+ return this.#cachedGitStatus;
915
+ }
916
+
917
+ this.#gitStatusInFlightCwd = gitCwd;
918
+
919
+ (async () => {
920
+ let nextStatus: { staged: number; unstaged: number; untracked: number } | null = null;
921
+ try {
922
+ nextStatus = await git.status.summary(gitCwd);
923
+ } catch {
924
+ nextStatus = null;
925
+ } finally {
926
+ if (this.#gitStatusInFlightCwd === gitCwd) {
927
+ const prev = this.#cachedGitStatusCwd === gitCwd ? this.#cachedGitStatus : null;
928
+ this.#cachedGitStatus = nextStatus;
929
+ this.#cachedGitStatusCwd = gitCwd;
930
+ this.#gitStatusLastFetch = Date.now();
931
+ this.#gitStatusInFlightCwd = undefined;
932
+ if (!this.#disposed && this.#onBranchChange && JSON.stringify(prev) !== JSON.stringify(nextStatus)) {
933
+ this.#onBranchChange();
934
+ }
935
+ }
936
+ }
937
+ })();
938
+
939
+ return this.#cachedGitStatusCwd === gitCwd ? this.#cachedGitStatus : null;
940
+ }
941
+
942
+ // Resolve (and cache per cwd) the jj workspace root, resetting both jj caches
943
+ // on a cwd change so a directory switch refetches label + status.
944
+ #jjRootFor(cwd: string): string | null {
945
+ if (this.#jjRoot === undefined || this.#jjRootCwd !== cwd) {
946
+ this.#jjRootCwd = cwd;
947
+ this.#jjRoot = jj.repo.rootSync(cwd);
948
+ this.#cachedJjBranch = null;
949
+ this.#jjBranchLastFetch = 0;
950
+ this.#cachedJjStatus = null;
951
+ this.#jjStatusLastFetch = 0;
952
+ this.#jjCacheGeneration++;
953
+ }
954
+ return this.#jjRoot;
955
+ }
956
+
957
+ // jj working-copy bookmark label (nearest bookmark, change-id fallback), shown
958
+ // in the `git` segment where git HEAD is detached/absent under jj. Throttled,
959
+ // cached, and repaints on resolve.
960
+ #getJjBranch(effectiveGitCwd?: string): string | null {
961
+ const cwd = effectiveGitCwd ?? this.#resolveActiveRepoCache().effectiveGitCwd;
962
+ const root = this.#jjRootFor(cwd);
963
+ if (!root) return null;
964
+ if (this.#jjBranchActive || Date.now() - this.#jjBranchLastFetch < JJ_REFRESH_TTL_MS) {
965
+ return this.#cachedJjBranch;
966
+ }
967
+ const request: JjResolveRequest = {
968
+ id: ++this.#jjResolveSeq,
969
+ controller: new AbortController(),
970
+ };
971
+ this.#jjBranchActive = request;
972
+ const generation = this.#jjCacheGeneration;
973
+ (async () => {
974
+ let next: string | null = null;
975
+ try {
976
+ next = await jj.workingCopy.label(root, {
977
+ signal: request.controller.signal,
978
+ timeoutMs: jj.JJ_COMMAND_TIMEOUT_MS,
979
+ });
980
+ } finally {
981
+ if (this.#jjBranchActive?.id === request.id) this.#jjBranchActive = undefined;
982
+ // Advance the throttle only if no reset raced this query; a reset
983
+ // leaves LastFetch at 0 so the current root refetches instead of
984
+ // being throttled on a superseded result.
985
+ if (this.#jjCacheGeneration === generation) this.#jjBranchLastFetch = Date.now();
986
+ }
987
+ // Drop a result whose caches were reset mid-flight — a repo switch OR a
988
+ // same-root HEAD/bookmark move — so a superseded label never lands in
989
+ // the live cache.
990
+ if (this.#jjCacheGeneration !== generation || this.#disposed) return;
991
+ const changed = next !== this.#cachedJjBranch;
992
+ this.#cachedJjBranch = next;
993
+ if (changed) this.#onBranchChange?.();
994
+ })();
995
+ return this.#cachedJjBranch;
996
+ }
997
+
998
+ // jj working-copy status counts (`@` vs its parent), used in place of git
999
+ // status in a jj repo where `git status` has no `.git` to read. Throttled,
1000
+ // cached, and repaints on resolve like #getJjBranch.
1001
+ #getJjStatus(effectiveGitCwd?: string): { staged: number; unstaged: number; untracked: number } | null {
1002
+ const cwd = effectiveGitCwd ?? this.#resolveActiveRepoCache().effectiveGitCwd;
1003
+ const root = this.#jjRootFor(cwd);
1004
+ if (!root) return null;
1005
+ if (this.#jjStatusActive || Date.now() - this.#jjStatusLastFetch < JJ_REFRESH_TTL_MS) {
1006
+ return this.#cachedJjStatus;
1007
+ }
1008
+ const request: JjResolveRequest = {
1009
+ id: ++this.#jjResolveSeq,
1010
+ controller: new AbortController(),
1011
+ };
1012
+ this.#jjStatusActive = request;
1013
+ const generation = this.#jjCacheGeneration;
1014
+ (async () => {
1015
+ let next: { staged: number; unstaged: number; untracked: number } | null = null;
1016
+ try {
1017
+ next = await jj.status.summary(root, {
1018
+ signal: request.controller.signal,
1019
+ timeoutMs: jj.JJ_COMMAND_TIMEOUT_MS,
1020
+ });
1021
+ } finally {
1022
+ if (this.#jjStatusActive?.id === request.id) this.#jjStatusActive = undefined;
1023
+ if (this.#jjCacheGeneration === generation) this.#jjStatusLastFetch = Date.now();
1024
+ }
1025
+ if (this.#jjCacheGeneration !== generation || this.#disposed) return;
1026
+ const prev = this.#cachedJjStatus;
1027
+ this.#cachedJjStatus = next;
1028
+ if (JSON.stringify(prev) !== JSON.stringify(next)) this.#onBranchChange?.();
1029
+ })();
1030
+ return this.#cachedJjStatus;
1031
+ }
1032
+
1033
+ #lookupPr(effectiveGitCwd?: string): { number: number; url: string } | null {
1034
+ if (!this.#gitEnabled()) return null;
1035
+
1036
+ const gitCwd = effectiveGitCwd ?? this.#resolveActiveRepoCache().effectiveGitCwd;
1037
+ const branch = this.#getCurrentBranch(gitCwd);
1038
+ const currentContext = branch ? createPrCacheContext(branch, this.#cachedBranchRepoId ?? null) : null;
1039
+
1040
+ if (canReuseCachedPr(this.#cachedPr, this.#cachedPrContext, currentContext)) {
1041
+ return this.#cachedPr ?? null;
1042
+ }
1043
+
1044
+ const stalePr = this.#cachedPr;
1045
+
1046
+ if (!branch) {
1047
+ this.#cachedPr = null;
1048
+ this.#cachedPrContext = undefined;
1049
+ return null;
1050
+ }
1051
+
1052
+ // Don't look up if detached, default branch, or already in flight.
1053
+ if (branch === "detached" || this.#isDefaultBranch(branch, gitCwd) || this.#prLookupInFlight) {
1054
+ return stalePr ?? null;
1055
+ }
1056
+
1057
+ this.#prLookupInFlight = true;
1058
+ const lookupContext = currentContext;
1059
+ const lookupCwd = gitCwd;
1060
+
1061
+ // Fire async lookup, keep stale value visible until resolved
1062
+ (async () => {
1063
+ // Helper: only write cache if branch/repo context hasn't changed since launch
1064
+ const setCachedPr = (value: { number: number; url: string } | null) => {
1065
+ const latestBranch = this.#getCurrentBranch(lookupCwd);
1066
+ const latestContext = latestBranch
1067
+ ? createPrCacheContext(latestBranch, this.#cachedBranchRepoId ?? null)
1068
+ : undefined;
1069
+ if (lookupContext && isSamePrCacheContext(latestContext, lookupContext)) {
1070
+ this.#cachedPr = value;
1071
+ this.#cachedPrContext = lookupContext;
1072
+ }
1073
+ };
1074
+ try {
1075
+ // Route through the shared `gh` helper so the child inherits
1076
+ // `GH_NON_INTERACTIVE_ENV` (disables terminal/keychain prompts) and
1077
+ // hard-terminates on the git command deadline instead of stalling
1078
+ // the status-line indefinitely (#4234). Requires `gh repo set-default`;
1079
+ // non-zero exit still falls through to the null cache below.
1080
+ const result = await git.github.run(
1081
+ lookupCwd,
1082
+ ["pr", "view", "--json", "number,url"],
1083
+ AbortSignal.timeout(git.GIT_COMMAND_TIMEOUT_MS),
1084
+ );
1085
+ if (this.#disposed) return;
1086
+ if (result.exitCode !== 0) {
1087
+ setCachedPr(null);
1088
+ return;
1089
+ }
1090
+ const pr = JSON.parse(result.stdout) as { number: number; url: string };
1091
+ if (typeof pr.number === "number") {
1092
+ setCachedPr({ number: pr.number, url: pr.url });
1093
+ } else {
1094
+ setCachedPr(null);
1095
+ }
1096
+ } catch {
1097
+ if (this.#disposed) return;
1098
+ setCachedPr(null);
1099
+ } finally {
1100
+ this.#prLookupInFlight = false;
1101
+ if (!this.#disposed && this.#onBranchChange) {
1102
+ this.#onBranchChange();
1103
+ }
1104
+ }
1105
+ })();
1106
+
1107
+ return stalePr ?? null;
1108
+ }
1109
+
1110
+ #getTokensPerSecond(): number | null {
1111
+ // Aggregate tok/s across the main session AND every live vibe worker.
1112
+ // In vibe mode the director is often idle while workers stream, so the
1113
+ // main session's own rate alone would show a stale/zero value while
1114
+ // parallel work is actively generating tokens.
1115
+ const workerRate = this.#getVibeWorkerTokensPerSecond();
1116
+ if (workerRate !== null) {
1117
+ // At least one worker is streaming — add the director's live rate
1118
+ // only when it is itself streaming (a finalized last-turn rate would
1119
+ // double-count and overstate throughput).
1120
+ const mainRate = this.session.isStreaming ? calculateTokensPerSecond(this.session.state.messages, true) : 0;
1121
+ return (mainRate ?? 0) + workerRate;
1122
+ }
1123
+
1124
+ // No workers streaming — fall back to the main session's own rate with
1125
+ // its sticky per-assistant-message cache so the badge doesn't flicker
1126
+ // off in the brief gap between stream end and the finalized message.
1127
+ return this.#getMainSessionTokensPerSecond();
1128
+ }
1129
+
1130
+ /**
1131
+ * Main session's tok/s with sticky caching keyed on the last assistant
1132
+ * message timestamp. Preserves the pre-aggregation behavior when no vibe
1133
+ * workers are active.
1134
+ */
1135
+ #getMainSessionTokensPerSecond(): number | null {
1136
+ let lastAssistantTimestamp: number | null = null;
1137
+ for (let i = this.session.state.messages.length - 1; i >= 0; i--) {
1138
+ const message = this.session.state.messages[i];
1139
+ if (message?.role === "assistant") {
1140
+ lastAssistantTimestamp = message.timestamp;
1141
+ break;
1142
+ }
1143
+ }
1144
+
1145
+ if (lastAssistantTimestamp === null) {
1146
+ this.#lastTokensPerSecond = null;
1147
+ this.#lastTokensPerSecondTimestamp = null;
1148
+ return null;
1149
+ }
1150
+
1151
+ const rate = calculateTokensPerSecond(this.session.state.messages, this.session.isStreaming);
1152
+ if (rate !== null) {
1153
+ this.#lastTokensPerSecond = rate;
1154
+ this.#lastTokensPerSecondTimestamp = lastAssistantTimestamp;
1155
+ return rate;
1156
+ }
1157
+
1158
+ if (this.#lastTokensPerSecondTimestamp === lastAssistantTimestamp) {
1159
+ return this.#lastTokensPerSecond;
1160
+ }
1161
+
1162
+ return null;
1163
+ }
1164
+
1165
+ /**
1166
+ * Aggregate tok/s across every live vibe worker session owned by this
1167
+ * session. Returns null when no workers are streaming (so the main
1168
+ * session's own rate shines through unchanged). The aggregation itself is
1169
+ * injected via {@link setVibeWorkerTokenRateProvider} to keep this render
1170
+ * layer off the heavy vibe/task dependency graph.
1171
+ */
1172
+ #getVibeWorkerTokensPerSecond(): number | null {
1173
+ return this.#vibeWorkerTokenRate?.() ?? null;
1174
+ }
1175
+
1176
+ #formatUsageContextKey(activeProvider: string | undefined, identity: OAuthAccountIdentity | undefined): string {
1177
+ if (!activeProvider) return "";
1178
+ // orgId is part of the key: rotating between two same-email Anthropic
1179
+ // subscriptions must invalidate the cached usage immediately instead of
1180
+ // showing the previous org's quota for the rest of the cache TTL.
1181
+ return [
1182
+ activeProvider,
1183
+ identity?.accountId ?? "",
1184
+ identity?.email ?? "",
1185
+ identity?.projectId ?? "",
1186
+ identity?.orgId ?? "",
1187
+ ].join("\0");
1188
+ }
1189
+
1190
+ #getUsageContextKey(session: AgentSession): string {
1191
+ const activeProvider = session.state.model?.provider ?? session.model?.provider;
1192
+ const identity = activeProvider
1193
+ ? session.modelRegistry?.authStorage?.getOAuthAccountIdentity(activeProvider, session.sessionId)
1194
+ : undefined;
1195
+ return this.#formatUsageContextKey(activeProvider, identity);
1196
+ }
1197
+
1198
+ /**
1199
+ * Startup redraws only arm a short-delayed task; timeout releases the render
1200
+ * cadence while a late successful fetch can still refresh the cached segment.
1201
+ */
1202
+ refreshUsageInBackground(): void {
1203
+ const now = Date.now();
1204
+ const session = this.session;
1205
+ const usageContextKey = this.#getUsageContextKey(session);
1206
+ if (this.#cachedUsageContextKey !== usageContextKey) {
1207
+ this.#cachedUsage = null;
1208
+ this.#usageFetchedAt = 0;
1209
+ this.#cachedUsageContextKey = usageContextKey;
1210
+ }
1211
+ if (this.#usageInFlight || this.#usageStartTimer) return;
1212
+ if (this.#usageFetchedAt > 0 && now - this.#usageFetchedAt < 5 * 60_000) return;
1213
+ const fetcher = (session as { fetchUsageReports?: (signal?: AbortSignal) => Promise<unknown> }).fetchUsageReports;
1214
+ if (typeof fetcher !== "function") return;
1215
+ this.#usageInFlight = true;
1216
+ this.#usageStartTimer = setTimeout(() => {
1217
+ this.#usageStartTimer = null;
1218
+ void this.#runUsageRefresh(session, fetcher);
1219
+ }, STATUS_USAGE_START_DELAY_MS);
1220
+ }
1221
+
1222
+ async #runUsageRefresh(session: AgentSession, fetcher: (signal?: AbortSignal) => Promise<unknown>): Promise<void> {
1223
+ if (this.#disposed || this.session !== session) {
1224
+ this.#usageInFlight = false;
1225
+ return;
1226
+ }
1227
+ const sequence = ++this.#usageRefreshSequence;
1228
+ const signal = AbortSignal.timeout(STATUS_USAGE_REFRESH_TIMEOUT_MS);
1229
+ let reportsPromise: Promise<unknown> | undefined;
1230
+ try {
1231
+ reportsPromise = fetcher.call(session, signal);
1232
+ this.#applyUsageRefreshReports(
1233
+ session,
1234
+ await this.#raceUsageRefreshWithSignal(reportsPromise, signal),
1235
+ sequence,
1236
+ );
1237
+ } catch {
1238
+ if (this.session !== session) return;
1239
+ this.#usageFetchedAt = Date.now();
1240
+ if (signal.aborted && reportsPromise) {
1241
+ this.#observeLateUsageRefresh(session, reportsPromise, sequence);
1242
+ }
1243
+ } finally {
1244
+ if (this.session === session) this.#usageInFlight = false;
1245
+ }
1246
+ }
1247
+
1248
+ #applyUsageRefreshReports(session: AgentSession, reports: unknown, sequence: number): void {
1249
+ if (this.#disposed || this.session !== session || sequence < this.#latestAppliedUsageRefreshSequence) {
1250
+ return;
1251
+ }
1252
+ this.#latestAppliedUsageRefreshSequence = sequence;
1253
+ const activeProvider = session.state.model?.provider ?? session.model?.provider;
1254
+ const activeIdentity =
1255
+ activeProvider && session.modelRegistry?.authStorage
1256
+ ? session.modelRegistry.authStorage.getOAuthAccountIdentity(activeProvider, session.sessionId)
1257
+ : undefined;
1258
+ const normalized = this.#normalizeUsageReports(reports, activeProvider, activeIdentity);
1259
+ const resetSnapshot =
1260
+ activeProvider === "openai-codex" ? this.#normalizeCodexResetSnapshot(reports, activeIdentity) : null;
1261
+ this.#cachedUsage = normalized;
1262
+ this.#usageFetchedAt = Date.now();
1263
+ if (!resetSnapshot) return;
1264
+ const contextKey = this.#formatUsageContextKey(activeProvider, activeIdentity);
1265
+ const previous = this.#codexResetSnapshots.get(contextKey);
1266
+ this.#codexResetSnapshots.set(contextKey, resetSnapshot);
1267
+ if (!previous || !settings.get("tui.codexResetFireworks")) return;
1268
+ const event = detectCodexResetFireworks(previous, resetSnapshot);
1269
+ if (event) this.#onCodexResetFireworks?.(event);
1270
+ }
1271
+
1272
+ #observeLateUsageRefresh(session: AgentSession, reportsPromise: Promise<unknown>, sequence: number): void {
1273
+ void reportsPromise
1274
+ .then(reports => {
1275
+ this.#applyUsageRefreshReports(session, reports, sequence);
1276
+ })
1277
+ .catch(() => {
1278
+ if (this.#disposed || this.session !== session || sequence < this.#latestAppliedUsageRefreshSequence) {
1279
+ return;
1280
+ }
1281
+ this.#usageFetchedAt = Date.now();
1282
+ });
1283
+ }
1284
+
1285
+ async #raceUsageRefreshWithSignal(promise: Promise<unknown>, signal: AbortSignal): Promise<unknown> {
1286
+ if (signal.aborted) throw signal.reason;
1287
+ const aborted = Promise.withResolvers<never>();
1288
+ const onAbort = () => aborted.reject(signal.reason);
1289
+ signal.addEventListener("abort", onAbort, { once: true });
1290
+ try {
1291
+ return await Promise.race([promise, aborted.promise]);
1292
+ } finally {
1293
+ signal.removeEventListener("abort", onAbort);
1294
+ }
1295
+ }
1296
+
1297
+ #normalizeCodexResetSnapshot(
1298
+ reports: unknown,
1299
+ activeIdentity: OAuthAccountIdentity | undefined,
1300
+ ): CodexResetUsageSnapshot | null {
1301
+ if (!Array.isArray(reports)) return null;
1302
+ let matchingReport: UsageReport | undefined;
1303
+ for (const report of reports) {
1304
+ if (!report || typeof report !== "object") continue;
1305
+ if (
1306
+ !("provider" in report) ||
1307
+ report.provider !== "openai-codex" ||
1308
+ !("limits" in report) ||
1309
+ !Array.isArray(report.limits)
1310
+ ) {
1311
+ continue;
1312
+ }
1313
+ // The report boundary above validates the fields this extractor iterates;
1314
+ // optional metadata and credit fields are narrowed again before use.
1315
+ const usageReport = report as UsageReport;
1316
+ if (!codexReportMatchesExactIdentity(usageReport, activeIdentity)) continue;
1317
+ matchingReport = usageReport;
1318
+ break;
1319
+ }
1320
+ if (!matchingReport) return null;
1321
+
1322
+ const plan =
1323
+ typeof matchingReport.metadata?.planType === "string" && matchingReport.metadata.planType
1324
+ ? matchingReport.metadata.planType
1325
+ : undefined;
1326
+ let sevenDay: CodexResetUsageSnapshot["sevenDay"];
1327
+ let sevenDayTier: string | undefined;
1328
+ for (const limit of matchingReport.limits) {
1329
+ if (!limit || typeof limit !== "object") continue;
1330
+ const candidate = limit as {
1331
+ scope?: { windowId?: string; tier?: string };
1332
+ window?: { resetsAt?: number };
1333
+ amount?: { usedFraction?: number };
1334
+ };
1335
+ const fraction = candidate.amount?.usedFraction;
1336
+ if (candidate.scope?.windowId !== "7d" || typeof fraction !== "number" || !Number.isFinite(fraction)) {
1337
+ continue;
1338
+ }
1339
+ const tier =
1340
+ typeof candidate.scope?.tier === "string" && candidate.scope.tier ? candidate.scope.tier : undefined;
1341
+ if (sevenDay && (sevenDayTier === undefined || tier)) continue;
1342
+ const resetsAt = candidate.window?.resetsAt;
1343
+ sevenDay = {
1344
+ percent: fraction * 100,
1345
+ resetsAt: typeof resetsAt === "number" && Number.isFinite(resetsAt) ? resetsAt : undefined,
1346
+ tier,
1347
+ plan,
1348
+ };
1349
+ sevenDayTier = tier;
1350
+ }
1351
+
1352
+ const fetchedAt = matchingReport.fetchedAt;
1353
+ const availableCount = matchingReport.resetCredits?.availableCount;
1354
+ const observedAt = typeof fetchedAt === "number" && Number.isFinite(fetchedAt) ? fetchedAt : undefined;
1355
+ const savedResets =
1356
+ typeof availableCount === "number" && Number.isFinite(availableCount)
1357
+ ? Math.max(0, Math.trunc(availableCount))
1358
+ : undefined;
1359
+ if (!sevenDay && savedResets === undefined) return null;
1360
+ return { observedAt, sevenDay, savedResets };
1361
+ }
1362
+
1363
+ #normalizeUsageReports(
1364
+ reports: unknown,
1365
+ activeProvider?: string,
1366
+ activeIdentity?: OAuthAccountIdentity,
1367
+ ): {
1368
+ tier?: string;
1369
+ fiveHour?: { percent: number; resetMinutes?: number };
1370
+ sevenDay?: { percent: number; resetHours?: number };
1371
+ } | null {
1372
+ if (!Array.isArray(reports)) return null;
1373
+ let fiveHour: { percent: number; resetMinutes?: number } | undefined;
1374
+ let sevenDay: { percent: number; resetHours?: number } | undefined;
1375
+ let fiveHourTier: string | undefined;
1376
+ let sevenDayTier: string | undefined;
1377
+ const now = Date.now();
1378
+ for (const report of reports) {
1379
+ if (!report || typeof report !== "object") continue;
1380
+ const provider = (report as { provider?: unknown }).provider;
1381
+ if (activeProvider && provider !== activeProvider) continue;
1382
+ const limits = (report as { limits?: unknown }).limits;
1383
+ if (!Array.isArray(limits)) continue;
1384
+ const usageReport = report as UsageReport;
1385
+ for (const limit of limits) {
1386
+ if (!limit || typeof limit !== "object") continue;
1387
+ if (activeIdentity && !limitMatchesActiveAccount(usageReport, limit as UsageLimit, activeIdentity)) {
1388
+ continue;
1389
+ }
1390
+ const l = limit as {
1391
+ scope?: { windowId?: string; tier?: string };
1392
+ window?: { resetsAt?: number };
1393
+ amount?: { usedFraction?: number };
1394
+ };
1395
+ const fraction = l.amount?.usedFraction;
1396
+ if (typeof fraction !== "number") continue;
1397
+ const windowId = l.scope?.windowId;
1398
+ const tier = l.scope?.tier;
1399
+ const resetsAt = l.window?.resetsAt;
1400
+ // Accept tiered limits, but prefer untiered (backward compat with Anthropic).
1401
+ // An untiered limit always replaces a tiered one; among same-tieredness, first wins.
1402
+ if (windowId === "5h" && (!fiveHour || (fiveHourTier !== undefined && !tier))) {
1403
+ fiveHour = {
1404
+ percent: fraction * 100,
1405
+ resetMinutes:
1406
+ typeof resetsAt === "number" ? Math.max(0, Math.round((resetsAt - now) / 60_000)) : undefined,
1407
+ };
1408
+ fiveHourTier = tier || undefined;
1409
+ }
1410
+ if (windowId === "7d" && (!sevenDay || (sevenDayTier !== undefined && !tier))) {
1411
+ sevenDay = {
1412
+ percent: fraction * 100,
1413
+ resetHours:
1414
+ typeof resetsAt === "number" ? Math.max(0, Math.round((resetsAt - now) / 3_600_000)) : undefined,
1415
+ };
1416
+ sevenDayTier = tier || undefined;
1417
+ }
1418
+ }
1419
+ }
1420
+ if (!fiveHour && !sevenDay) return null;
1421
+ // Single compact label; prefer the five-hour tier if displayed windows ever disagree.
1422
+ const effectiveTier = fiveHourTier ?? sevenDayTier;
1423
+ return { tier: effectiveTier, fiveHour, sevenDay };
1424
+ }
1425
+
1426
+ /**
1427
+ * Used-tokens / context-window totals for the status-line context% segment,
1428
+ * memoized so the per-event redraw stays O(1) when nothing changed.
1429
+ *
1430
+ * The numerator comes from `session.getContextUsage()`, which anchors on the
1431
+ * last assistant's real prompt-token count — so the bar matches the provider
1432
+ * and the `/context` panel — and reports `null` while that count is unknown
1433
+ * (right after compaction, before the next response). Exposed (non-private)
1434
+ * for unit tests and the collab host's state broadcast.
1435
+ */
1436
+ getCachedContextBreakdown(): { usedTokens: number; contextWindow: number } {
1437
+ const messages = this.session.messages ?? EMPTY_MESSAGES;
1438
+ const modelContextWindow = this.session.model?.contextWindow ?? 0;
1439
+ const length = messages.length;
1440
+ const lastFingerprint = length > 0 ? messageFingerprint(messages[length - 1]!) : undefined;
1441
+ // Bumps when the in-flight pending snapshot is set/cleared. Without it a
1442
+ // value computed mid-turn (estimate of the active tail) would survive after
1443
+ // the turn ends/aborts, since clearing the snapshot touches no message.
1444
+ const contextUsageRevision = this.session.contextUsageRevision ?? 0;
1445
+
1446
+ const systemPrompt = this.session.systemPrompt;
1447
+ const tools = this.session.agent?.state?.tools;
1448
+ const skills = this.session.skills;
1449
+
1450
+ const cache = this.#contextUsageCache;
1451
+ if (
1452
+ cache &&
1453
+ cache.messagesRef === messages &&
1454
+ cache.length === length &&
1455
+ cache.lastFingerprint === lastFingerprint &&
1456
+ cache.modelContextWindow === modelContextWindow &&
1457
+ cache.contextUsageRevision === contextUsageRevision &&
1458
+ cache.systemPromptRef === systemPrompt &&
1459
+ cache.toolsRef === tools &&
1460
+ cache.skillsRef === skills
1461
+ ) {
1462
+ return { usedTokens: cache.usedTokens, contextWindow: cache.contextWindow };
1463
+ }
1464
+
1465
+ const usage = this.session.getContextUsage();
1466
+ const usedTokens = usage?.tokens ?? 0;
1467
+ const contextWindow = usage?.contextWindow ?? modelContextWindow;
1468
+ this.#contextUsageCache = {
1469
+ messagesRef: messages,
1470
+ length,
1471
+ lastFingerprint,
1472
+ modelContextWindow,
1473
+ contextUsageRevision,
1474
+ usedTokens,
1475
+ contextWindow,
1476
+ systemPromptRef: systemPrompt,
1477
+ toolsRef: tools,
1478
+ skillsRef: skills,
1479
+ };
1480
+ return { usedTokens, contextWindow };
1481
+ }
1482
+
1483
+ #buildSegmentContext(
1484
+ width: number,
1485
+ segmentOptions: StatusLineSettings["segmentOptions"],
1486
+ includePath: boolean,
1487
+ includeContext: boolean,
1488
+ includeGit: boolean,
1489
+ includePr: boolean,
1490
+ ): SegmentContext {
1491
+ const state = this.session.state;
1492
+
1493
+ // Trigger background fetch (5-min TTL); render uses cached value
1494
+ this.refreshUsageInBackground();
1495
+
1496
+ // Get usage statistics
1497
+ const aggregateUsageStats = this.session.sessionManager?.getUsageStatistics() ?? {
1498
+ input: 0,
1499
+ output: 0,
1500
+ cacheRead: 0,
1501
+ cacheWrite: 0,
1502
+ totalTokens: 0,
1503
+ orchestrationInput: 0,
1504
+ orchestrationOutput: 0,
1505
+ orchestrationCacheRead: 0,
1506
+ premiumRequests: 0,
1507
+ cost: 0,
1508
+ };
1509
+ const usageStats = {
1510
+ ...aggregateUsageStats,
1511
+ tokensPerSecond: this.#getTokensPerSecond(),
1512
+ };
1513
+
1514
+ let contextWindow = state.model?.contextWindow ?? this.session.model?.contextWindow ?? 0;
1515
+ let contextPercent: number | null = 0;
1516
+ let contextTokens = 0;
1517
+ if (includeContext) {
1518
+ const breakdown = this.getCachedContextBreakdown();
1519
+ contextTokens = breakdown.usedTokens;
1520
+ contextWindow = breakdown.contextWindow || contextWindow;
1521
+ contextPercent = contextWindow > 0 ? (breakdown.usedTokens / contextWindow) * 100 : null;
1522
+ }
1523
+
1524
+ // Collab guest: context comes from the host's state frames — the local
1525
+ // replica does no accounting of its own.
1526
+ const collabState = this.#collabStatus?.stateOverride;
1527
+ if (collabState?.contextUsage) {
1528
+ contextWindow = collabState.contextUsage.contextWindow || contextWindow;
1529
+ contextTokens = collabState.contextUsage.tokens ?? contextTokens;
1530
+ contextPercent = collabState.contextUsage.percent ?? contextPercent;
1531
+ }
1532
+
1533
+ const shouldResolveActiveRepo = this.#gitEnabled() && (includePath || includeGit || includePr);
1534
+ const projectDir = getProjectDir();
1535
+ const activeRepoCache = shouldResolveActiveRepo
1536
+ ? this.#resolveActiveRepoCache()
1537
+ : { projectDir, activeRepo: null, effectiveGitCwd: projectDir, worktree: null };
1538
+ let gitBranch = includeGit || includePr ? this.#getCurrentBranch(activeRepoCache.effectiveGitCwd) : null;
1539
+ // A jj repo has no git branch to read: git HEAD is detached (colocated) or
1540
+ // absent. A pending reftable resolve owns this cwd as an explicit Git repo,
1541
+ // so it must not be mistaken for an absent Git checkout and fall through to
1542
+ // an ancestor jj workspace.
1543
+ const gitHeadResolvePending = this.#branchResolveActive?.cwd === activeRepoCache.effectiveGitCwd;
1544
+ const gitHeadIsJjLike =
1545
+ !this.#cachedBranchHasGitRepository &&
1546
+ !gitHeadResolvePending &&
1547
+ (gitBranch === "detached" || gitBranch === null);
1548
+ if (includeGit && gitHeadIsJjLike) {
1549
+ gitBranch = this.#getJjBranch(activeRepoCache.effectiveGitCwd) ?? gitBranch;
1550
+ }
1551
+ const gitStatus = includeGit
1552
+ ? ((gitHeadIsJjLike ? this.#getJjStatus(activeRepoCache.effectiveGitCwd) : null) ??
1553
+ this.#getGitStatus(activeRepoCache.effectiveGitCwd))
1554
+ : null;
1555
+ const gitPr = includePr ? this.#lookupPr(activeRepoCache.effectiveGitCwd) : null;
1556
+ return {
1557
+ session: this.session,
1558
+ focusedAgentId: this.#focusedAgentId,
1559
+ activeRepo: activeRepoCache.activeRepo,
1560
+ width,
1561
+ options: segmentOptions ?? {},
1562
+ compactThinkingLevel: this.#resolveSettings().compactThinkingLevel ?? false,
1563
+ planMode: this.#planModeStatus,
1564
+ loopMode: this.#loopModeStatus,
1565
+ prewalk:
1566
+ typeof this.session.getPrewalkState === "function" && this.session.getPrewalkState()
1567
+ ? { enabled: true }
1568
+ : null,
1569
+ goalMode: this.#goalModeStatus,
1570
+ vibeMode: this.#vibeModeStatus,
1571
+ collab: this.#collabStatus,
1572
+ usageStats,
1573
+ contextPercent,
1574
+ contextTokens,
1575
+ contextWindow,
1576
+ autoCompactEnabled: this.#autoCompactEnabled,
1577
+ subagentCount: this.#subagentCount,
1578
+ activeMs: this.getActiveMs(),
1579
+ git: {
1580
+ branch: gitBranch,
1581
+ status: gitStatus,
1582
+ pr: gitPr,
1583
+ },
1584
+ worktree: activeRepoCache.worktree,
1585
+ usage: this.#cachedUsage,
1586
+ };
1587
+ }
1588
+
1589
+ #resolveSettings(): EffectiveStatusLineSettings {
1590
+ if (this.#effectiveSettings === undefined) {
1591
+ this.#effectiveSettings = this.#computeEffectiveSettings();
1592
+ }
1593
+ return this.#effectiveSettings;
1594
+ }
1595
+
1596
+ #computeEffectiveSettings(): EffectiveStatusLineSettings {
1597
+ const preset = this.#settings.preset ?? "default";
1598
+ const presetDef = getPreset(preset);
1599
+ const useCustomSegments = preset === "custom";
1600
+ const mergedSegmentOptions: StatusLineSettings["segmentOptions"] = {};
1601
+
1602
+ for (const [segment, options] of Object.entries(presetDef.segmentOptions ?? {})) {
1603
+ mergedSegmentOptions[segment as keyof StatusLineSegmentOptions] = { ...(options as Record<string, unknown>) };
1604
+ }
1605
+
1606
+ for (const [segment, options] of Object.entries(this.#settings.segmentOptions ?? {})) {
1607
+ const current = mergedSegmentOptions[segment as keyof StatusLineSegmentOptions] ?? {};
1608
+ mergedSegmentOptions[segment as keyof StatusLineSegmentOptions] = {
1609
+ ...(current as Record<string, unknown>),
1610
+ ...(options as Record<string, unknown>),
1611
+ };
1612
+ }
1613
+
1614
+ const leftSegments = useCustomSegments
1615
+ ? (this.#settings.leftSegments ?? presetDef.leftSegments)
1616
+ : presetDef.leftSegments;
1617
+ const rightSegments = useCustomSegments
1618
+ ? (this.#settings.rightSegments ?? presetDef.rightSegments)
1619
+ : presetDef.rightSegments;
1620
+
1621
+ return {
1622
+ ...this.#settings,
1623
+ leftSegments,
1624
+ rightSegments,
1625
+ separator: this.#settings.separator ?? presetDef.separator,
1626
+ segmentOptions: mergedSegmentOptions,
1627
+ };
1628
+ }
1629
+
1630
+ #subagentBadgeText(): string | undefined {
1631
+ if (this.#subagentCount === 0) return undefined;
1632
+ const noun = this.#subagentCount === 1 ? "agent" : "agents";
1633
+ return theme.fg("statusLineSubagents", `${theme.icon.agents} ${this.#subagentCount} ${noun}`);
1634
+ }
1635
+
1636
+ #buildStatusLine(width: number): string {
1637
+ const effectiveSettings = this.#resolveSettings();
1638
+ const includePath =
1639
+ hasPathSegment(effectiveSettings.leftSegments) || hasPathSegment(effectiveSettings.rightSegments);
1640
+ const includeContext =
1641
+ hasContextSegment(effectiveSettings.leftSegments) || hasContextSegment(effectiveSettings.rightSegments);
1642
+ const gitEnabled = this.#gitEnabled();
1643
+ const includeGit =
1644
+ gitEnabled &&
1645
+ (hasGitSegment(effectiveSettings.leftSegments) || hasGitSegment(effectiveSettings.rightSegments));
1646
+ const includePr =
1647
+ gitEnabled && (hasPrSegment(effectiveSettings.leftSegments) || hasPrSegment(effectiveSettings.rightSegments));
1648
+ const ctx = this.#buildSegmentContext(
1649
+ width,
1650
+ effectiveSettings.segmentOptions,
1651
+ includePath,
1652
+ includeContext,
1653
+ includeGit,
1654
+ includePr,
1655
+ );
1656
+ const separatorDef = getSeparator(effectiveSettings.separator ?? "powerline-thin", theme);
1657
+
1658
+ // `transparent` reuses the empty-string sentinel (`\x1b[49m`) so the bar
1659
+ // inherits the terminal's default background, matching custom themes that
1660
+ // set `statusLineBg: ""`. Powerline end caps need a contrasting fill to
1661
+ // bridge the bar into the surrounding terminal; without one they read as
1662
+ // stray glyphs, so the cap renderer drops them when the fill is empty.
1663
+ const TRANSPARENT_BG_ANSI = "\x1b[49m";
1664
+ const themeBgAnsi = theme.getBgAnsi("statusLineBg");
1665
+ const bgAnsi = effectiveSettings.transparent ? TRANSPARENT_BG_ANSI : themeBgAnsi;
1666
+ const transparentBg = bgAnsi === TRANSPARENT_BG_ANSI;
1667
+ const fgAnsi = theme.getFgAnsi("text");
1668
+ const sepAnsi = theme.getFgAnsi("statusLineSep");
1669
+ const subagentBadge = this.#subagentBadgeText();
1670
+
1671
+ // Collect visible segment contents
1672
+ const leftParts: string[] = [];
1673
+ const leftSegIds: StatusLineSegmentId[] = [];
1674
+ for (const segId of effectiveSettings.leftSegments) {
1675
+ if (subagentBadge && segId === "subagents") continue;
1676
+ const rendered = renderSegment(segId, ctx);
1677
+ if (rendered.visible && rendered.content) {
1678
+ leftParts.push(rendered.content);
1679
+ leftSegIds.push(segId);
1680
+ }
1681
+ }
1682
+
1683
+ const rightParts: string[] = [];
1684
+ for (const segId of effectiveSettings.rightSegments) {
1685
+ if (subagentBadge && segId === "subagents") continue;
1686
+ const rendered = renderSegment(segId, ctx);
1687
+ if (rendered.visible && rendered.content) {
1688
+ rightParts.push(rendered.content);
1689
+ }
1690
+ }
1691
+
1692
+ const runningBackgroundJobs = this.session.getAsyncJobSnapshot()?.running.length ?? 0;
1693
+ if (runningBackgroundJobs > 0) {
1694
+ rightParts.unshift(theme.fg("statusLineSubagents", `${theme.icon.job} ${runningBackgroundJobs}`));
1695
+ }
1696
+ if (subagentBadge) {
1697
+ rightParts.unshift(subagentBadge);
1698
+ }
1699
+ const topFillWidth = Math.max(0, width);
1700
+ const left = [...leftParts];
1701
+ const right = [...rightParts];
1702
+
1703
+ const leftSepWidth = visibleWidth(separatorDef.left);
1704
+ const rightSepWidth = visibleWidth(separatorDef.right);
1705
+ // Transparent mode drops powerline caps (they need a bg fill to bridge),
1706
+ // so the width budget excludes them too.
1707
+ const leftCapWidth = separatorDef.endCaps && !transparentBg ? visibleWidth(separatorDef.endCaps.right) : 0;
1708
+ const rightCapWidth = separatorDef.endCaps && !transparentBg ? visibleWidth(separatorDef.endCaps.left) : 0;
1709
+
1710
+ const groupWidth = (parts: string[], capWidth: number, sepWidth: number): number => {
1711
+ if (parts.length === 0) return 0;
1712
+ const partsWidth = parts.reduce((sum, part) => sum + visibleWidth(part), 0);
1713
+ const sepTotal = Math.max(0, parts.length - 1) * (sepWidth + 2);
1714
+ return partsWidth + sepTotal + 2 + capWidth;
1715
+ };
1716
+
1717
+ let leftWidth = groupWidth(left, leftCapWidth, leftSepWidth);
1718
+ let rightWidth = groupWidth(right, rightCapWidth, rightSepWidth);
1719
+ const totalWidth = () => leftWidth + rightWidth + (left.length > 0 && right.length > 0 ? 1 : 0);
1720
+
1721
+ if (topFillWidth > 0) {
1722
+ while (totalWidth() > topFillWidth && right.length > 0) {
1723
+ right.pop();
1724
+ rightWidth = groupWidth(right, rightCapWidth, rightSepWidth);
1725
+ }
1726
+ // Shrink path before dropping left segments — path is the only elastic segment
1727
+ const pathIdx = leftSegIds.indexOf("path");
1728
+ if (pathIdx >= 0 && totalWidth() > topFillWidth) {
1729
+ const overflow = totalWidth() - topFillWidth;
1730
+ const currentPathVW = visibleWidth(left[pathIdx]);
1731
+ const minPathVW = 8; // icon + ellipsis + a few chars
1732
+ const shrinkable = currentPathVW - minPathVW;
1733
+ if (shrinkable > 0) {
1734
+ const shrinkBy = Math.min(shrinkable, overflow);
1735
+ const currentMaxLen = ctx.options.path?.maxLength ?? 40;
1736
+ let newMaxLen = Math.max(4, Math.min(currentMaxLen, currentPathVW) - shrinkBy);
1737
+ const pathCtx = (maxLen: number): SegmentContext => ({
1738
+ ...ctx,
1739
+ options: { ...ctx.options, path: { ...ctx.options.path, maxLength: maxLen } },
1740
+ });
1741
+ let reRendered = renderSegment("path", pathCtx(newMaxLen));
1742
+ if (reRendered.visible && reRendered.content) {
1743
+ // maxLength governs path text, not icon prefix; iterate to compensate
1744
+ for (let i = 0; i < 8; i++) {
1745
+ const saved = currentPathVW - visibleWidth(reRendered.content);
1746
+ if (saved >= shrinkBy) break;
1747
+ const nextMaxLen = Math.max(4, newMaxLen - (shrinkBy - saved));
1748
+ if (nextMaxLen >= newMaxLen) break; // no progress or hit floor
1749
+ newMaxLen = nextMaxLen;
1750
+ const adjusted = renderSegment("path", pathCtx(newMaxLen));
1751
+ if (!adjusted.visible || !adjusted.content) break;
1752
+ reRendered = adjusted;
1753
+ }
1754
+ left[pathIdx] = reRendered.content;
1755
+ leftWidth = groupWidth(left, leftCapWidth, leftSepWidth);
1756
+ }
1757
+ }
1758
+ }
1759
+ const leftOverflowDropIndex = (): number => {
1760
+ // Preserve the current working directory as long as possible. The
1761
+ // previous right-to-left pop could collapse a normal-width bar to
1762
+ // just the model segment, hiding the path before less-critical left
1763
+ // segments such as model/mode/collab were removed.
1764
+ for (let i = leftSegIds.length - 1; i >= 0; i--) {
1765
+ if (leftSegIds[i] !== "path") return i;
1766
+ }
1767
+ return left.length - 1;
1768
+ };
1769
+
1770
+ while (totalWidth() > topFillWidth && left.length > 0) {
1771
+ const dropIdx = leftOverflowDropIndex();
1772
+ left.splice(dropIdx, 1);
1773
+ leftSegIds.splice(dropIdx, 1);
1774
+ leftWidth = groupWidth(left, leftCapWidth, leftSepWidth);
1775
+ }
1776
+ }
1777
+
1778
+ const renderGroup = (parts: string[], direction: "left" | "right"): string => {
1779
+ if (parts.length === 0) return "";
1780
+ const sep = direction === "left" ? separatorDef.left : separatorDef.right;
1781
+ const cap =
1782
+ separatorDef.endCaps && !transparentBg
1783
+ ? direction === "left"
1784
+ ? separatorDef.endCaps.right
1785
+ : separatorDef.endCaps.left
1786
+ : "";
1787
+ const capPrefix = separatorDef.endCaps?.useBgAsFg ? bgAnsi.replace("\x1b[48;", "\x1b[38;") : bgAnsi + sepAnsi;
1788
+ const capText = cap ? `${capPrefix}${this.#focusedAgentId ? "\x1b[22m" : ""}${cap}\x1b[0m` : "";
1789
+
1790
+ let content = bgAnsi + fgAnsi;
1791
+ content += ` ${parts.join(` ${sepAnsi}${sep}${fgAnsi} `)} `;
1792
+ content += "\x1b[0m";
1793
+
1794
+ if (capText) {
1795
+ return direction === "right" ? capText + content : content + capText;
1796
+ }
1797
+ return content;
1798
+ };
1799
+
1800
+ const leftGroup = renderGroup(left, "left");
1801
+ const rightGroup = renderGroup(right, "right");
1802
+ if (!leftGroup && !rightGroup) return "";
1803
+
1804
+ if (topFillWidth === 0 || left.length === 0 || right.length === 0) {
1805
+ return leftGroup + (leftGroup && rightGroup ? " " : "") + rightGroup;
1806
+ }
1807
+
1808
+ const gapWidth = Math.max(1, topFillWidth - leftWidth - rightWidth);
1809
+ const sessionName =
1810
+ effectiveSettings.sessionAccent !== false ? this.session.sessionManager?.getSessionName() : undefined;
1811
+ const accentHex = sessionName
1812
+ ? getSessionAccentHex(sessionName, theme.getMajorThemeColorHexes(), theme.accentSurfaceLuminance)
1813
+ : undefined;
1814
+ const gapColor = getSessionAccentAnsi(accentHex) ?? theme.getFgAnsi("border");
1815
+ const gapFill = `${gapColor}${theme.boxRound.horizontal.repeat(gapWidth)}\x1b[39m`;
1816
+ return leftGroup + gapFill + rightGroup;
1817
+ }
1818
+
1819
+ getTopBorder(width: number): { content: string; width: number } {
1820
+ let content = this.#buildStatusLine(width);
1821
+ if (this.#focusedAgentId && content) {
1822
+ // Dim the whole bar while focus-proxied. Group/cap terminators emit full
1823
+ // `\x1b[0m` resets that would cancel faint mid-bar, so re-open it after each.
1824
+ content = `\x1b[2m${content.replaceAll("\x1b[0m", "\x1b[0m\x1b[2m")}\x1b[22m`;
1825
+ }
1826
+ return {
1827
+ content,
1828
+ width: visibleWidth(content),
1829
+ };
1830
+ }
1831
+
1832
+ render(width: number): readonly string[] {
1833
+ // Only render hook statuses - main status is in editor's top border
1834
+ const showHooks = this.#settings.showHookStatus ?? true;
1835
+ if (!showHooks || this.#hookStatuses.size === 0) {
1836
+ return [];
1837
+ }
1838
+
1839
+ return Array.from(this.#hookStatuses.entries())
1840
+ .sort(([a], [b]) => a.localeCompare(b))
1841
+ .map(([, text]) => truncateToWidth(sanitizeStatusText(text), width));
1842
+ }
1843
+ }