@wahack/pi-coding-agent 15.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1152) hide show
  1. package/CHANGELOG.md +10031 -0
  2. package/README.md +36 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +104 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/extensions/README.md +142 -0
  7. package/examples/extensions/api-demo.ts +79 -0
  8. package/examples/extensions/chalk-logger.ts +25 -0
  9. package/examples/extensions/hello.ts +31 -0
  10. package/examples/extensions/pirate.ts +43 -0
  11. package/examples/extensions/plan-mode.ts +549 -0
  12. package/examples/extensions/reload-runtime.ts +38 -0
  13. package/examples/extensions/thinking-note.ts +13 -0
  14. package/examples/extensions/tools.ts +145 -0
  15. package/examples/extensions/with-deps/index.ts +36 -0
  16. package/examples/extensions/with-deps/package-lock.json +31 -0
  17. package/examples/extensions/with-deps/package.json +17 -0
  18. package/examples/hooks/README.md +56 -0
  19. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  20. package/examples/hooks/confirm-destructive.ts +58 -0
  21. package/examples/hooks/custom-compaction.ts +115 -0
  22. package/examples/hooks/dirty-repo-guard.ts +51 -0
  23. package/examples/hooks/file-trigger.ts +40 -0
  24. package/examples/hooks/git-checkpoint.ts +52 -0
  25. package/examples/hooks/handoff.ts +149 -0
  26. package/examples/hooks/permission-gate.ts +33 -0
  27. package/examples/hooks/protected-paths.ts +29 -0
  28. package/examples/hooks/qna.ts +118 -0
  29. package/examples/hooks/status-line.ts +39 -0
  30. package/examples/sdk/01-minimal.ts +21 -0
  31. package/examples/sdk/02-custom-model.ts +49 -0
  32. package/examples/sdk/03-custom-prompt.ts +46 -0
  33. package/examples/sdk/04-skills.ts +43 -0
  34. package/examples/sdk/06-extensions.ts +82 -0
  35. package/examples/sdk/06-hooks.ts +61 -0
  36. package/examples/sdk/07-context-files.ts +35 -0
  37. package/examples/sdk/08-prompt-templates.ts +41 -0
  38. package/examples/sdk/08-slash-commands.ts +46 -0
  39. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  40. package/examples/sdk/11-sessions.ts +47 -0
  41. package/examples/sdk/12-redis-sessions.ts +54 -0
  42. package/examples/sdk/13-sql-sessions.ts +61 -0
  43. package/examples/sdk/README.md +172 -0
  44. package/package.json +554 -0
  45. package/scripts/build-binary.ts +100 -0
  46. package/scripts/bundle-dist.ts +90 -0
  47. package/scripts/format-prompts.ts +68 -0
  48. package/scripts/generate-docs-index.ts +40 -0
  49. package/scripts/generate-template.ts +33 -0
  50. package/scripts/omp +42 -0
  51. package/scripts/omp.ts +19 -0
  52. package/src/async/index.ts +1 -0
  53. package/src/async/job-manager.ts +625 -0
  54. package/src/auto-thinking/classifier.ts +185 -0
  55. package/src/autoresearch/command-resume.md +14 -0
  56. package/src/autoresearch/dashboard.ts +436 -0
  57. package/src/autoresearch/git.ts +319 -0
  58. package/src/autoresearch/helpers.ts +218 -0
  59. package/src/autoresearch/index.ts +536 -0
  60. package/src/autoresearch/prompt-setup.md +43 -0
  61. package/src/autoresearch/prompt.md +103 -0
  62. package/src/autoresearch/resume-message.md +10 -0
  63. package/src/autoresearch/state.ts +273 -0
  64. package/src/autoresearch/storage.ts +699 -0
  65. package/src/autoresearch/tools/init-experiment.ts +272 -0
  66. package/src/autoresearch/tools/log-experiment.ts +524 -0
  67. package/src/autoresearch/tools/run-experiment.ts +407 -0
  68. package/src/autoresearch/tools/update-notes.ts +109 -0
  69. package/src/autoresearch/types.ts +168 -0
  70. package/src/bun-imports.d.ts +28 -0
  71. package/src/capability/context-file.ts +44 -0
  72. package/src/capability/extension-module.ts +34 -0
  73. package/src/capability/extension.ts +47 -0
  74. package/src/capability/fs.ts +117 -0
  75. package/src/capability/hook.ts +40 -0
  76. package/src/capability/index.ts +436 -0
  77. package/src/capability/instruction.ts +37 -0
  78. package/src/capability/mcp.ts +74 -0
  79. package/src/capability/prompt.ts +35 -0
  80. package/src/capability/rule-buckets.ts +66 -0
  81. package/src/capability/rule.ts +261 -0
  82. package/src/capability/settings.ts +34 -0
  83. package/src/capability/skill.ts +63 -0
  84. package/src/capability/slash-command.ts +40 -0
  85. package/src/capability/ssh.ts +41 -0
  86. package/src/capability/system-prompt.ts +34 -0
  87. package/src/capability/tool.ts +38 -0
  88. package/src/capability/types.ts +168 -0
  89. package/src/cli/agents-cli.ts +138 -0
  90. package/src/cli/args.ts +340 -0
  91. package/src/cli/auth-broker-cli.ts +895 -0
  92. package/src/cli/auth-gateway-cli.ts +611 -0
  93. package/src/cli/classify-install-target.ts +76 -0
  94. package/src/cli/claude-trace-cli.ts +795 -0
  95. package/src/cli/commands/init-xdg.ts +27 -0
  96. package/src/cli/completion-gen.ts +550 -0
  97. package/src/cli/config-cli.ts +418 -0
  98. package/src/cli/dry-balance-cli.ts +856 -0
  99. package/src/cli/extension-flags.ts +48 -0
  100. package/src/cli/file-processor.ts +133 -0
  101. package/src/cli/gallery-cli.ts +230 -0
  102. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  103. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  104. package/src/cli/gallery-fixtures/edit.ts +194 -0
  105. package/src/cli/gallery-fixtures/fs.ts +220 -0
  106. package/src/cli/gallery-fixtures/index.ts +40 -0
  107. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  108. package/src/cli/gallery-fixtures/memory.ts +81 -0
  109. package/src/cli/gallery-fixtures/misc.ts +250 -0
  110. package/src/cli/gallery-fixtures/search.ts +213 -0
  111. package/src/cli/gallery-fixtures/shell.ts +167 -0
  112. package/src/cli/gallery-fixtures/types.ts +57 -0
  113. package/src/cli/gallery-fixtures/web.ts +158 -0
  114. package/src/cli/gallery-screenshot.ts +279 -0
  115. package/src/cli/grep-cli.ts +160 -0
  116. package/src/cli/grievances-cli.ts +256 -0
  117. package/src/cli/initial-message.ts +58 -0
  118. package/src/cli/list-models.ts +194 -0
  119. package/src/cli/plugin-cli.ts +996 -0
  120. package/src/cli/read-cli.ts +57 -0
  121. package/src/cli/session-picker.ts +79 -0
  122. package/src/cli/setup-cli.ts +231 -0
  123. package/src/cli/shell-cli.ts +176 -0
  124. package/src/cli/ssh-cli.ts +179 -0
  125. package/src/cli/startup-cwd.ts +68 -0
  126. package/src/cli/stats-cli.ts +238 -0
  127. package/src/cli/tiny-models-cli.ts +127 -0
  128. package/src/cli/update-cli.ts +611 -0
  129. package/src/cli/usage-cli.ts +603 -0
  130. package/src/cli/web-search-cli.ts +132 -0
  131. package/src/cli/worktree-cli.ts +291 -0
  132. package/src/cli-commands.ts +79 -0
  133. package/src/cli.ts +200 -0
  134. package/src/commands/acp.ts +24 -0
  135. package/src/commands/agents.ts +57 -0
  136. package/src/commands/auth-broker.ts +99 -0
  137. package/src/commands/auth-gateway.ts +69 -0
  138. package/src/commands/commit.ts +46 -0
  139. package/src/commands/complete.ts +66 -0
  140. package/src/commands/completions.ts +60 -0
  141. package/src/commands/config.ts +51 -0
  142. package/src/commands/dry-balance.ts +43 -0
  143. package/src/commands/gallery.ts +52 -0
  144. package/src/commands/grep.ts +48 -0
  145. package/src/commands/grievances.ts +51 -0
  146. package/src/commands/install.ts +107 -0
  147. package/src/commands/launch.ts +169 -0
  148. package/src/commands/plugin.ts +78 -0
  149. package/src/commands/read.ts +38 -0
  150. package/src/commands/setup.ts +67 -0
  151. package/src/commands/shell.ts +29 -0
  152. package/src/commands/ssh.ts +60 -0
  153. package/src/commands/stats.ts +29 -0
  154. package/src/commands/tiny-models.ts +36 -0
  155. package/src/commands/update.ts +21 -0
  156. package/src/commands/usage.ts +35 -0
  157. package/src/commands/web-search.ts +42 -0
  158. package/src/commands/worktree.ts +56 -0
  159. package/src/commit/agentic/agent.ts +317 -0
  160. package/src/commit/agentic/fallback.ts +96 -0
  161. package/src/commit/agentic/index.ts +355 -0
  162. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  163. package/src/commit/agentic/prompts/session-user.md +25 -0
  164. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  165. package/src/commit/agentic/prompts/system.md +38 -0
  166. package/src/commit/agentic/state.ts +60 -0
  167. package/src/commit/agentic/tools/analyze-file.ts +146 -0
  168. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  169. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  170. package/src/commit/agentic/tools/git-overview.ts +81 -0
  171. package/src/commit/agentic/tools/index.ts +54 -0
  172. package/src/commit/agentic/tools/propose-changelog.ts +144 -0
  173. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  174. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  175. package/src/commit/agentic/tools/schemas.ts +23 -0
  176. package/src/commit/agentic/tools/split-commit.ts +245 -0
  177. package/src/commit/agentic/topo-sort.ts +44 -0
  178. package/src/commit/agentic/trivial.ts +51 -0
  179. package/src/commit/agentic/validation.ts +183 -0
  180. package/src/commit/analysis/conventional.ts +64 -0
  181. package/src/commit/analysis/index.ts +4 -0
  182. package/src/commit/analysis/scope.ts +242 -0
  183. package/src/commit/analysis/summary.ts +105 -0
  184. package/src/commit/analysis/validation.ts +66 -0
  185. package/src/commit/changelog/detect.ts +40 -0
  186. package/src/commit/changelog/generate.ts +97 -0
  187. package/src/commit/changelog/index.ts +234 -0
  188. package/src/commit/changelog/parse.ts +44 -0
  189. package/src/commit/cli.ts +85 -0
  190. package/src/commit/git/diff.ts +148 -0
  191. package/src/commit/index.ts +5 -0
  192. package/src/commit/map-reduce/index.ts +69 -0
  193. package/src/commit/map-reduce/map-phase.ts +193 -0
  194. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  195. package/src/commit/map-reduce/utils.ts +9 -0
  196. package/src/commit/message.ts +11 -0
  197. package/src/commit/model-selection.ts +92 -0
  198. package/src/commit/pipeline.ts +243 -0
  199. package/src/commit/prompts/analysis-system.md +148 -0
  200. package/src/commit/prompts/analysis-user.md +38 -0
  201. package/src/commit/prompts/changelog-system.md +50 -0
  202. package/src/commit/prompts/changelog-user.md +18 -0
  203. package/src/commit/prompts/file-observer-system.md +24 -0
  204. package/src/commit/prompts/file-observer-user.md +8 -0
  205. package/src/commit/prompts/reduce-system.md +50 -0
  206. package/src/commit/prompts/reduce-user.md +17 -0
  207. package/src/commit/prompts/summary-retry.md +3 -0
  208. package/src/commit/prompts/summary-system.md +38 -0
  209. package/src/commit/prompts/summary-user.md +13 -0
  210. package/src/commit/prompts/types-description.md +2 -0
  211. package/src/commit/shared-llm.ts +77 -0
  212. package/src/commit/types.ts +118 -0
  213. package/src/commit/utils/exclusions.ts +42 -0
  214. package/src/commit/utils.ts +58 -0
  215. package/src/config/api-key-resolver.ts +60 -0
  216. package/src/config/append-only-context-mode.ts +31 -0
  217. package/src/config/config-file.ts +317 -0
  218. package/src/config/file-lock.ts +164 -0
  219. package/src/config/keybindings.ts +628 -0
  220. package/src/config/mcp-schema.json +230 -0
  221. package/src/config/model-discovery.ts +554 -0
  222. package/src/config/model-registry.ts +2090 -0
  223. package/src/config/model-resolver.ts +1502 -0
  224. package/src/config/model-roles.ts +74 -0
  225. package/src/config/models-config-schema.ts +226 -0
  226. package/src/config/models-config.ts +129 -0
  227. package/src/config/prompt-templates.ts +185 -0
  228. package/src/config/resolve-config-value.ts +94 -0
  229. package/src/config/settings-schema.ts +3530 -0
  230. package/src/config/settings.ts +1178 -0
  231. package/src/config.ts +242 -0
  232. package/src/cursor.ts +340 -0
  233. package/src/dap/client.ts +760 -0
  234. package/src/dap/config.ts +189 -0
  235. package/src/dap/defaults.json +212 -0
  236. package/src/dap/index.ts +4 -0
  237. package/src/dap/session.ts +1441 -0
  238. package/src/dap/types.ts +610 -0
  239. package/src/debug/index.ts +515 -0
  240. package/src/debug/log-formatting.ts +58 -0
  241. package/src/debug/log-viewer.ts +908 -0
  242. package/src/debug/profiler.ts +162 -0
  243. package/src/debug/protocol-probe.ts +267 -0
  244. package/src/debug/raw-sse-buffer.ts +273 -0
  245. package/src/debug/raw-sse.ts +292 -0
  246. package/src/debug/report-bundle.ts +374 -0
  247. package/src/debug/system-info.ts +111 -0
  248. package/src/debug/terminal-info.ts +124 -0
  249. package/src/discovery/agents-md.ts +67 -0
  250. package/src/discovery/agents.ts +230 -0
  251. package/src/discovery/at-imports.ts +273 -0
  252. package/src/discovery/builtin-defaults.ts +39 -0
  253. package/src/discovery/builtin-rules/index.ts +54 -0
  254. package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
  255. package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
  256. package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
  257. package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
  258. package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
  259. package/src/discovery/builtin-rules/rs-result-type.md +19 -0
  260. package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
  261. package/src/discovery/builtin-rules/ts-import-type.md +42 -0
  262. package/src/discovery/builtin-rules/ts-no-any.md +56 -0
  263. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
  264. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
  265. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  266. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  267. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  268. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
  269. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  270. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  271. package/src/discovery/builtin.ts +906 -0
  272. package/src/discovery/claude-plugins.ts +386 -0
  273. package/src/discovery/claude.ts +584 -0
  274. package/src/discovery/cline.ts +83 -0
  275. package/src/discovery/codex.ts +522 -0
  276. package/src/discovery/cursor.ts +220 -0
  277. package/src/discovery/gemini.ts +383 -0
  278. package/src/discovery/github.ts +154 -0
  279. package/src/discovery/helpers.ts +1016 -0
  280. package/src/discovery/index.ts +81 -0
  281. package/src/discovery/mcp-json.ts +171 -0
  282. package/src/discovery/omp-extension-roots.ts +190 -0
  283. package/src/discovery/omp-plugins.ts +383 -0
  284. package/src/discovery/opencode.ts +398 -0
  285. package/src/discovery/plugin-dir-roots.ts +28 -0
  286. package/src/discovery/ssh.ts +153 -0
  287. package/src/discovery/substitute-plugin-root.ts +29 -0
  288. package/src/discovery/vscode.ts +105 -0
  289. package/src/discovery/windsurf.ts +147 -0
  290. package/src/edit/apply-patch/index.ts +87 -0
  291. package/src/edit/apply-patch/parser.ts +174 -0
  292. package/src/edit/diff.ts +999 -0
  293. package/src/edit/file-snapshot-store.ts +91 -0
  294. package/src/edit/hashline/block-resolver.ts +33 -0
  295. package/src/edit/hashline/diff.ts +290 -0
  296. package/src/edit/hashline/execute.ts +242 -0
  297. package/src/edit/hashline/filesystem.ts +130 -0
  298. package/src/edit/hashline/index.ts +5 -0
  299. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  300. package/src/edit/hashline/params.ts +18 -0
  301. package/src/edit/index.ts +571 -0
  302. package/src/edit/modes/apply-patch.lark +19 -0
  303. package/src/edit/modes/apply-patch.ts +53 -0
  304. package/src/edit/modes/patch.ts +1891 -0
  305. package/src/edit/modes/replace.ts +1137 -0
  306. package/src/edit/normalize.ts +345 -0
  307. package/src/edit/notebook.ts +242 -0
  308. package/src/edit/read-file.ts +25 -0
  309. package/src/edit/renderer.ts +769 -0
  310. package/src/edit/streaming.ts +517 -0
  311. package/src/eval/__tests__/agent-bridge.test.ts +708 -0
  312. package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
  313. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  314. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  315. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  316. package/src/eval/__tests__/idle-timeout.test.ts +80 -0
  317. package/src/eval/__tests__/js-context-manager.test.ts +241 -0
  318. package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
  319. package/src/eval/agent-bridge.ts +319 -0
  320. package/src/eval/backend.ts +71 -0
  321. package/src/eval/bridge-timeout.ts +44 -0
  322. package/src/eval/budget-bridge.ts +48 -0
  323. package/src/eval/completion-bridge.ts +207 -0
  324. package/src/eval/concurrency-bridge.ts +34 -0
  325. package/src/eval/idle-timeout.ts +91 -0
  326. package/src/eval/index.ts +4 -0
  327. package/src/eval/js/context-manager.ts +502 -0
  328. package/src/eval/js/executor.ts +173 -0
  329. package/src/eval/js/index.ts +51 -0
  330. package/src/eval/js/shared/helpers.ts +283 -0
  331. package/src/eval/js/shared/indirect-eval.ts +30 -0
  332. package/src/eval/js/shared/local-module-loader.ts +342 -0
  333. package/src/eval/js/shared/prelude.ts +2 -0
  334. package/src/eval/js/shared/prelude.txt +246 -0
  335. package/src/eval/js/shared/rewrite-imports.ts +532 -0
  336. package/src/eval/js/shared/runtime.ts +352 -0
  337. package/src/eval/js/shared/types.ts +18 -0
  338. package/src/eval/js/tool-bridge.ts +162 -0
  339. package/src/eval/js/worker-core.ts +132 -0
  340. package/src/eval/js/worker-entry.ts +30 -0
  341. package/src/eval/js/worker-protocol.ts +47 -0
  342. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  343. package/src/eval/py/display.ts +71 -0
  344. package/src/eval/py/executor.ts +742 -0
  345. package/src/eval/py/index.ts +68 -0
  346. package/src/eval/py/kernel.ts +748 -0
  347. package/src/eval/py/prelude.py +658 -0
  348. package/src/eval/py/prelude.ts +3 -0
  349. package/src/eval/py/runner.py +1133 -0
  350. package/src/eval/py/runtime.ts +276 -0
  351. package/src/eval/py/spawn-options.ts +126 -0
  352. package/src/eval/py/tool-bridge.ts +182 -0
  353. package/src/eval/session-id.ts +8 -0
  354. package/src/eval/types.ts +48 -0
  355. package/src/exa/index.ts +2 -0
  356. package/src/exa/mcp-client.ts +370 -0
  357. package/src/exa/types.ts +69 -0
  358. package/src/exec/bash-executor.ts +419 -0
  359. package/src/exec/exec.ts +53 -0
  360. package/src/exec/non-interactive-env.ts +48 -0
  361. package/src/export/custom-share.ts +65 -0
  362. package/src/export/html/index.ts +164 -0
  363. package/src/export/html/template.css +1051 -0
  364. package/src/export/html/template.generated.ts +2 -0
  365. package/src/export/html/template.html +46 -0
  366. package/src/export/html/template.js +2271 -0
  367. package/src/export/html/template.macro.ts +25 -0
  368. package/src/export/html/vendor/highlight.min.js +1213 -0
  369. package/src/export/html/vendor/marked.min.js +6 -0
  370. package/src/export/ttsr.ts +583 -0
  371. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  372. package/src/extensibility/custom-commands/bundled/review/index.ts +489 -0
  373. package/src/extensibility/custom-commands/index.ts +2 -0
  374. package/src/extensibility/custom-commands/loader.ts +238 -0
  375. package/src/extensibility/custom-commands/types.ts +113 -0
  376. package/src/extensibility/custom-tools/index.ts +7 -0
  377. package/src/extensibility/custom-tools/loader.ts +269 -0
  378. package/src/extensibility/custom-tools/types.ts +270 -0
  379. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  380. package/src/extensibility/extensions/compact-handler.ts +40 -0
  381. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  382. package/src/extensibility/extensions/index.ts +16 -0
  383. package/src/extensibility/extensions/loader.ts +572 -0
  384. package/src/extensibility/extensions/runner.ts +922 -0
  385. package/src/extensibility/extensions/types.ts +1322 -0
  386. package/src/extensibility/extensions/wrapper.ts +223 -0
  387. package/src/extensibility/hooks/index.ts +5 -0
  388. package/src/extensibility/hooks/loader.ts +257 -0
  389. package/src/extensibility/hooks/runner.ts +425 -0
  390. package/src/extensibility/hooks/tool-wrapper.ts +107 -0
  391. package/src/extensibility/hooks/types.ts +606 -0
  392. package/src/extensibility/legacy-pi-ai-shim.ts +24 -0
  393. package/src/extensibility/legacy-pi-coding-agent-shim.ts +15 -0
  394. package/src/extensibility/plugins/doctor.ts +65 -0
  395. package/src/extensibility/plugins/git-url.ts +367 -0
  396. package/src/extensibility/plugins/index.ts +9 -0
  397. package/src/extensibility/plugins/installer.ts +192 -0
  398. package/src/extensibility/plugins/legacy-pi-compat.ts +682 -0
  399. package/src/extensibility/plugins/loader.ts +313 -0
  400. package/src/extensibility/plugins/manager.ts +827 -0
  401. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  402. package/src/extensibility/plugins/marketplace/fetcher.ts +317 -0
  403. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  404. package/src/extensibility/plugins/marketplace/manager.ts +770 -0
  405. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  406. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  407. package/src/extensibility/plugins/marketplace/types.ts +191 -0
  408. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  409. package/src/extensibility/plugins/parser.ts +105 -0
  410. package/src/extensibility/plugins/types.ts +194 -0
  411. package/src/extensibility/shared-events.ts +343 -0
  412. package/src/extensibility/skills.ts +312 -0
  413. package/src/extensibility/slash-commands.ts +227 -0
  414. package/src/extensibility/tool-proxy.ts +25 -0
  415. package/src/extensibility/typebox.ts +418 -0
  416. package/src/extensibility/utils.ts +44 -0
  417. package/src/goals/index.ts +3 -0
  418. package/src/goals/runtime.ts +528 -0
  419. package/src/goals/state.ts +37 -0
  420. package/src/goals/tools/goal-tool.ts +251 -0
  421. package/src/hindsight/backend.ts +354 -0
  422. package/src/hindsight/bank.ts +156 -0
  423. package/src/hindsight/client.ts +598 -0
  424. package/src/hindsight/config.ts +175 -0
  425. package/src/hindsight/content.ts +210 -0
  426. package/src/hindsight/index.ts +8 -0
  427. package/src/hindsight/mental-models.ts +429 -0
  428. package/src/hindsight/seeds.json +32 -0
  429. package/src/hindsight/state.ts +488 -0
  430. package/src/hindsight/transcript.ts +71 -0
  431. package/src/index.ts +59 -0
  432. package/src/internal-urls/agent-protocol.ts +146 -0
  433. package/src/internal-urls/artifact-protocol.ts +107 -0
  434. package/src/internal-urls/docs-index.generated.ts +106 -0
  435. package/src/internal-urls/history-protocol.ts +113 -0
  436. package/src/internal-urls/index.ts +25 -0
  437. package/src/internal-urls/issue-pr-protocol.ts +584 -0
  438. package/src/internal-urls/json-query.ts +126 -0
  439. package/src/internal-urls/local-protocol.ts +287 -0
  440. package/src/internal-urls/mcp-protocol.ts +151 -0
  441. package/src/internal-urls/memory-protocol.ts +169 -0
  442. package/src/internal-urls/omp-protocol.ts +93 -0
  443. package/src/internal-urls/parse.ts +72 -0
  444. package/src/internal-urls/registry-helpers.ts +25 -0
  445. package/src/internal-urls/router.ts +105 -0
  446. package/src/internal-urls/rule-protocol.ts +45 -0
  447. package/src/internal-urls/skill-protocol.ts +96 -0
  448. package/src/internal-urls/types.ts +152 -0
  449. package/src/internal-urls/vault-protocol.ts +936 -0
  450. package/src/irc/bus.ts +292 -0
  451. package/src/lib/xai-http.ts +124 -0
  452. package/src/lsp/client.ts +1193 -0
  453. package/src/lsp/clients/biome-client.ts +264 -0
  454. package/src/lsp/clients/index.ts +50 -0
  455. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  456. package/src/lsp/clients/swiftlint-client.ts +120 -0
  457. package/src/lsp/config.ts +502 -0
  458. package/src/lsp/defaults.json +493 -0
  459. package/src/lsp/diagnostics-ledger.ts +51 -0
  460. package/src/lsp/edits.ts +267 -0
  461. package/src/lsp/index.ts +2477 -0
  462. package/src/lsp/lspmux.ts +233 -0
  463. package/src/lsp/render.ts +694 -0
  464. package/src/lsp/startup-events.ts +13 -0
  465. package/src/lsp/types.ts +455 -0
  466. package/src/lsp/utils.ts +718 -0
  467. package/src/main.ts +1325 -0
  468. package/src/mcp/client.ts +484 -0
  469. package/src/mcp/config-writer.ts +225 -0
  470. package/src/mcp/config.ts +365 -0
  471. package/src/mcp/index.ts +29 -0
  472. package/src/mcp/json-rpc.ts +122 -0
  473. package/src/mcp/loader.ts +124 -0
  474. package/src/mcp/manager.ts +1275 -0
  475. package/src/mcp/oauth-discovery.ts +442 -0
  476. package/src/mcp/oauth-flow.ts +442 -0
  477. package/src/mcp/render.ts +132 -0
  478. package/src/mcp/smithery-auth.ts +104 -0
  479. package/src/mcp/smithery-connect.ts +145 -0
  480. package/src/mcp/smithery-registry.ts +477 -0
  481. package/src/mcp/timeout.ts +59 -0
  482. package/src/mcp/tool-bridge.ts +426 -0
  483. package/src/mcp/tool-cache.ts +117 -0
  484. package/src/mcp/transports/http.ts +519 -0
  485. package/src/mcp/transports/index.ts +6 -0
  486. package/src/mcp/transports/stdio.ts +528 -0
  487. package/src/mcp/types.ts +423 -0
  488. package/src/memories/index.ts +1150 -0
  489. package/src/memories/storage.ts +577 -0
  490. package/src/memory-backend/index.ts +18 -0
  491. package/src/memory-backend/local-backend.ts +39 -0
  492. package/src/memory-backend/off-backend.ts +25 -0
  493. package/src/memory-backend/resolve.ts +25 -0
  494. package/src/memory-backend/runtime.ts +66 -0
  495. package/src/memory-backend/types.ts +166 -0
  496. package/src/mnemopi/backend.ts +547 -0
  497. package/src/mnemopi/config.ts +160 -0
  498. package/src/mnemopi/index.ts +3 -0
  499. package/src/mnemopi/state.ts +584 -0
  500. package/src/modes/acp/acp-agent.ts +2407 -0
  501. package/src/modes/acp/acp-client-bridge.ts +154 -0
  502. package/src/modes/acp/acp-event-mapper.ts +929 -0
  503. package/src/modes/acp/acp-mode.ts +23 -0
  504. package/src/modes/acp/index.ts +2 -0
  505. package/src/modes/acp/terminal-auth.ts +37 -0
  506. package/src/modes/components/agent-dashboard.ts +1206 -0
  507. package/src/modes/components/agent-hub.ts +1071 -0
  508. package/src/modes/components/assistant-message.ts +307 -0
  509. package/src/modes/components/bash-execution.ts +220 -0
  510. package/src/modes/components/bordered-loader.ts +41 -0
  511. package/src/modes/components/branch-summary-message.ts +45 -0
  512. package/src/modes/components/btw-panel.ts +104 -0
  513. package/src/modes/components/chat-block.ts +111 -0
  514. package/src/modes/components/compaction-summary-message.ts +87 -0
  515. package/src/modes/components/copy-selector.ts +206 -0
  516. package/src/modes/components/countdown-timer.ts +75 -0
  517. package/src/modes/components/custom-editor.ts +398 -0
  518. package/src/modes/components/custom-message.ts +63 -0
  519. package/src/modes/components/diff.ts +277 -0
  520. package/src/modes/components/dynamic-border.ts +34 -0
  521. package/src/modes/components/error-banner.ts +33 -0
  522. package/src/modes/components/eval-execution.ts +158 -0
  523. package/src/modes/components/execution-shared.ts +101 -0
  524. package/src/modes/components/extensions/extension-dashboard.ts +399 -0
  525. package/src/modes/components/extensions/extension-list.ts +502 -0
  526. package/src/modes/components/extensions/index.ts +9 -0
  527. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  528. package/src/modes/components/extensions/state-manager.ts +627 -0
  529. package/src/modes/components/extensions/types.ts +186 -0
  530. package/src/modes/components/footer.ts +274 -0
  531. package/src/modes/components/history-search.ts +280 -0
  532. package/src/modes/components/hook-editor.ts +167 -0
  533. package/src/modes/components/hook-input.ts +87 -0
  534. package/src/modes/components/hook-message.ts +66 -0
  535. package/src/modes/components/hook-selector.ts +660 -0
  536. package/src/modes/components/index.ts +38 -0
  537. package/src/modes/components/keybinding-hints.ts +65 -0
  538. package/src/modes/components/late-diagnostics-message.ts +60 -0
  539. package/src/modes/components/login-dialog.ts +164 -0
  540. package/src/modes/components/mcp-add-wizard.ts +1340 -0
  541. package/src/modes/components/message-frame.ts +88 -0
  542. package/src/modes/components/model-selector.ts +1271 -0
  543. package/src/modes/components/oauth-selector.ts +368 -0
  544. package/src/modes/components/omfg-panel.ts +141 -0
  545. package/src/modes/components/overlay-box.ts +108 -0
  546. package/src/modes/components/plan-review-overlay.ts +820 -0
  547. package/src/modes/components/plan-toc.ts +138 -0
  548. package/src/modes/components/plugin-selector.ts +95 -0
  549. package/src/modes/components/plugin-settings.ts +722 -0
  550. package/src/modes/components/queue-mode-selector.ts +56 -0
  551. package/src/modes/components/read-tool-group.ts +670 -0
  552. package/src/modes/components/segment-track.ts +52 -0
  553. package/src/modes/components/session-selector.ts +625 -0
  554. package/src/modes/components/settings-defs.ts +189 -0
  555. package/src/modes/components/settings-selector.ts +651 -0
  556. package/src/modes/components/show-images-selector.ts +45 -0
  557. package/src/modes/components/skill-message.ts +89 -0
  558. package/src/modes/components/status-line/component.ts +869 -0
  559. package/src/modes/components/status-line/context-thresholds.ts +79 -0
  560. package/src/modes/components/status-line/git-utils.ts +42 -0
  561. package/src/modes/components/status-line/index.ts +5 -0
  562. package/src/modes/components/status-line/presets.ts +106 -0
  563. package/src/modes/components/status-line/segments.ts +584 -0
  564. package/src/modes/components/status-line/separators.ts +55 -0
  565. package/src/modes/components/status-line/token-rate.ts +66 -0
  566. package/src/modes/components/status-line/types.ts +108 -0
  567. package/src/modes/components/theme-selector.ts +63 -0
  568. package/src/modes/components/thinking-selector.ts +52 -0
  569. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  570. package/src/modes/components/tips.txt +19 -0
  571. package/src/modes/components/todo-reminder.ts +38 -0
  572. package/src/modes/components/tool-execution.ts +1024 -0
  573. package/src/modes/components/transcript-container.ts +608 -0
  574. package/src/modes/components/tree-selector.ts +978 -0
  575. package/src/modes/components/ttsr-notification.ts +122 -0
  576. package/src/modes/components/user-message-selector.ts +227 -0
  577. package/src/modes/components/user-message.ts +66 -0
  578. package/src/modes/components/visual-truncate.ts +63 -0
  579. package/src/modes/components/welcome.ts +493 -0
  580. package/src/modes/controllers/btw-controller.ts +105 -0
  581. package/src/modes/controllers/command-controller-shared.ts +109 -0
  582. package/src/modes/controllers/command-controller.ts +1566 -0
  583. package/src/modes/controllers/event-controller.ts +1054 -0
  584. package/src/modes/controllers/extension-ui-controller.ts +886 -0
  585. package/src/modes/controllers/input-controller.ts +1073 -0
  586. package/src/modes/controllers/mcp-command-controller.ts +2017 -0
  587. package/src/modes/controllers/omfg-controller.ts +283 -0
  588. package/src/modes/controllers/omfg-rule.ts +647 -0
  589. package/src/modes/controllers/selector-controller.ts +1108 -0
  590. package/src/modes/controllers/ssh-command-controller.ts +384 -0
  591. package/src/modes/controllers/streaming-reveal.ts +279 -0
  592. package/src/modes/controllers/tan-command-controller.ts +173 -0
  593. package/src/modes/controllers/todo-command-controller.ts +485 -0
  594. package/src/modes/data/emojis.json +1 -0
  595. package/src/modes/emoji-autocomplete.ts +285 -0
  596. package/src/modes/gradient-highlight.ts +87 -0
  597. package/src/modes/image-references.ts +117 -0
  598. package/src/modes/index.ts +17 -0
  599. package/src/modes/interactive-mode.ts +3370 -0
  600. package/src/modes/internal-url-autocomplete.ts +143 -0
  601. package/src/modes/loop-limit.ts +140 -0
  602. package/src/modes/magic-keywords.ts +20 -0
  603. package/src/modes/markdown-prose.ts +247 -0
  604. package/src/modes/oauth-manual-input.ts +69 -0
  605. package/src/modes/orchestrate.ts +42 -0
  606. package/src/modes/print-mode.ts +126 -0
  607. package/src/modes/prompt-action-autocomplete.ts +260 -0
  608. package/src/modes/rpc/host-tools.ts +186 -0
  609. package/src/modes/rpc/host-uris.ts +235 -0
  610. package/src/modes/rpc/rpc-client.ts +963 -0
  611. package/src/modes/rpc/rpc-mode.ts +947 -0
  612. package/src/modes/rpc/rpc-subagents.ts +265 -0
  613. package/src/modes/rpc/rpc-types.ts +458 -0
  614. package/src/modes/runtime-init.ts +116 -0
  615. package/src/modes/session-observer-registry.ts +146 -0
  616. package/src/modes/setup-version.ts +11 -0
  617. package/src/modes/setup-wizard/index.ts +99 -0
  618. package/src/modes/setup-wizard/lazy.ts +16 -0
  619. package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
  620. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  621. package/src/modes/setup-wizard/scenes/providers.ts +69 -0
  622. package/src/modes/setup-wizard/scenes/sign-in.ts +205 -0
  623. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  624. package/src/modes/setup-wizard/scenes/theme.ts +299 -0
  625. package/src/modes/setup-wizard/scenes/types.ts +48 -0
  626. package/src/modes/setup-wizard/scenes/web-search.ts +129 -0
  627. package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
  628. package/src/modes/shared.ts +47 -0
  629. package/src/modes/theme/dark.json +95 -0
  630. package/src/modes/theme/defaults/alabaster.json +93 -0
  631. package/src/modes/theme/defaults/amethyst.json +96 -0
  632. package/src/modes/theme/defaults/anthracite.json +93 -0
  633. package/src/modes/theme/defaults/basalt.json +91 -0
  634. package/src/modes/theme/defaults/birch.json +95 -0
  635. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  636. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  637. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  638. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  639. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  640. package/src/modes/theme/defaults/dark-copper.json +95 -0
  641. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  642. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  643. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  644. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  645. package/src/modes/theme/defaults/dark-ember.json +95 -0
  646. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  647. package/src/modes/theme/defaults/dark-forest.json +96 -0
  648. package/src/modes/theme/defaults/dark-github.json +105 -0
  649. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  650. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  651. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  652. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  653. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  654. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  655. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  656. package/src/modes/theme/defaults/dark-nord.json +97 -0
  657. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  658. package/src/modes/theme/defaults/dark-one.json +100 -0
  659. package/src/modes/theme/defaults/dark-poimandres.json +142 -0
  660. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  661. package/src/modes/theme/defaults/dark-reef.json +91 -0
  662. package/src/modes/theme/defaults/dark-retro.json +92 -0
  663. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  664. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  665. package/src/modes/theme/defaults/dark-slate.json +95 -0
  666. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  667. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  668. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  669. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  670. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  671. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  672. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  673. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  674. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  675. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  676. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  677. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  678. package/src/modes/theme/defaults/graphite.json +92 -0
  679. package/src/modes/theme/defaults/index.ts +199 -0
  680. package/src/modes/theme/defaults/light-arctic.json +107 -0
  681. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  682. package/src/modes/theme/defaults/light-canyon.json +91 -0
  683. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  684. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  685. package/src/modes/theme/defaults/light-coral.json +95 -0
  686. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  687. package/src/modes/theme/defaults/light-dawn.json +90 -0
  688. package/src/modes/theme/defaults/light-dunes.json +91 -0
  689. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  690. package/src/modes/theme/defaults/light-forest.json +100 -0
  691. package/src/modes/theme/defaults/light-frost.json +95 -0
  692. package/src/modes/theme/defaults/light-github.json +115 -0
  693. package/src/modes/theme/defaults/light-glacier.json +91 -0
  694. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  695. package/src/modes/theme/defaults/light-haze.json +90 -0
  696. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  697. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  698. package/src/modes/theme/defaults/light-lavender.json +95 -0
  699. package/src/modes/theme/defaults/light-meadow.json +91 -0
  700. package/src/modes/theme/defaults/light-mint.json +95 -0
  701. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  702. package/src/modes/theme/defaults/light-ocean.json +99 -0
  703. package/src/modes/theme/defaults/light-one.json +99 -0
  704. package/src/modes/theme/defaults/light-opal.json +91 -0
  705. package/src/modes/theme/defaults/light-orchard.json +91 -0
  706. package/src/modes/theme/defaults/light-paper.json +95 -0
  707. package/src/modes/theme/defaults/light-poimandres.json +142 -0
  708. package/src/modes/theme/defaults/light-prism.json +90 -0
  709. package/src/modes/theme/defaults/light-retro.json +98 -0
  710. package/src/modes/theme/defaults/light-sand.json +95 -0
  711. package/src/modes/theme/defaults/light-savanna.json +91 -0
  712. package/src/modes/theme/defaults/light-solarized.json +102 -0
  713. package/src/modes/theme/defaults/light-soleil.json +90 -0
  714. package/src/modes/theme/defaults/light-sunset.json +99 -0
  715. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  716. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  717. package/src/modes/theme/defaults/light-wetland.json +91 -0
  718. package/src/modes/theme/defaults/light-zenith.json +89 -0
  719. package/src/modes/theme/defaults/limestone.json +94 -0
  720. package/src/modes/theme/defaults/mahogany.json +97 -0
  721. package/src/modes/theme/defaults/marble.json +93 -0
  722. package/src/modes/theme/defaults/obsidian.json +91 -0
  723. package/src/modes/theme/defaults/onyx.json +91 -0
  724. package/src/modes/theme/defaults/pearl.json +93 -0
  725. package/src/modes/theme/defaults/porcelain.json +91 -0
  726. package/src/modes/theme/defaults/quartz.json +96 -0
  727. package/src/modes/theme/defaults/sandstone.json +95 -0
  728. package/src/modes/theme/defaults/titanium.json +90 -0
  729. package/src/modes/theme/light.json +93 -0
  730. package/src/modes/theme/mermaid-cache.ts +29 -0
  731. package/src/modes/theme/shimmer.ts +235 -0
  732. package/src/modes/theme/theme-schema.json +459 -0
  733. package/src/modes/theme/theme.ts +2676 -0
  734. package/src/modes/turn-budget.ts +31 -0
  735. package/src/modes/types.ts +359 -0
  736. package/src/modes/ultrathink.ts +41 -0
  737. package/src/modes/utils/context-usage.ts +339 -0
  738. package/src/modes/utils/copy-targets.ts +360 -0
  739. package/src/modes/utils/hotkeys-markdown.ts +61 -0
  740. package/src/modes/utils/keybinding-matchers.ts +51 -0
  741. package/src/modes/utils/tools-markdown.ts +27 -0
  742. package/src/modes/utils/ui-helpers.ts +801 -0
  743. package/src/modes/workflow.ts +42 -0
  744. package/src/plan-mode/approved-plan.ts +186 -0
  745. package/src/plan-mode/plan-handoff.ts +37 -0
  746. package/src/plan-mode/plan-protection.ts +31 -0
  747. package/src/plan-mode/state.ts +6 -0
  748. package/src/priority.json +41 -0
  749. package/src/prompts/agents/designer.md +66 -0
  750. package/src/prompts/agents/explore.md +58 -0
  751. package/src/prompts/agents/frontmatter.md +11 -0
  752. package/src/prompts/agents/init.md +33 -0
  753. package/src/prompts/agents/librarian.md +119 -0
  754. package/src/prompts/agents/oracle.md +55 -0
  755. package/src/prompts/agents/plan.md +48 -0
  756. package/src/prompts/agents/reviewer.md +140 -0
  757. package/src/prompts/agents/task.md +16 -0
  758. package/src/prompts/ci-green-request.md +36 -0
  759. package/src/prompts/dry-balance-bench.md +8 -0
  760. package/src/prompts/goals/goal-budget-limit.md +16 -0
  761. package/src/prompts/goals/goal-continuation.md +28 -0
  762. package/src/prompts/goals/goal-mode-active.md +23 -0
  763. package/src/prompts/memories/consolidation.md +30 -0
  764. package/src/prompts/memories/read-path.md +11 -0
  765. package/src/prompts/memories/stage_one_input.md +6 -0
  766. package/src/prompts/memories/stage_one_system.md +21 -0
  767. package/src/prompts/review-custom-request.md +22 -0
  768. package/src/prompts/review-headless-request.md +16 -0
  769. package/src/prompts/review-request.md +69 -0
  770. package/src/prompts/steering/user-interjection.md +10 -0
  771. package/src/prompts/system/agent-creation-architect.md +50 -0
  772. package/src/prompts/system/agent-creation-user.md +6 -0
  773. package/src/prompts/system/auto-continue.md +1 -0
  774. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  775. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  776. package/src/prompts/system/background-tan-dispatch.md +8 -0
  777. package/src/prompts/system/btw-user.md +8 -0
  778. package/src/prompts/system/commit-message-system.md +14 -0
  779. package/src/prompts/system/custom-system-prompt.md +64 -0
  780. package/src/prompts/system/eager-todo.md +13 -0
  781. package/src/prompts/system/empty-stop-retry.md +6 -0
  782. package/src/prompts/system/irc-incoming.md +7 -0
  783. package/src/prompts/system/manual-continue.md +7 -0
  784. package/src/prompts/system/memory-consolidation-system.md +8 -0
  785. package/src/prompts/system/memory-extraction-system.md +26 -0
  786. package/src/prompts/system/omfg-user.md +50 -0
  787. package/src/prompts/system/orchestrate-notice.md +40 -0
  788. package/src/prompts/system/plan-mode-active.md +109 -0
  789. package/src/prompts/system/plan-mode-approved.md +25 -0
  790. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  791. package/src/prompts/system/plan-mode-reference.md +11 -0
  792. package/src/prompts/system/plan-mode-subagent.md +33 -0
  793. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  794. package/src/prompts/system/project-prompt.md +52 -0
  795. package/src/prompts/system/subagent-system-prompt.md +64 -0
  796. package/src/prompts/system/subagent-user-prompt.md +3 -0
  797. package/src/prompts/system/subagent-yield-reminder.md +12 -0
  798. package/src/prompts/system/system-prompt.md +258 -0
  799. package/src/prompts/system/tiny-title-system.md +8 -0
  800. package/src/prompts/system/title-system.md +16 -0
  801. package/src/prompts/system/ttsr-interrupt.md +7 -0
  802. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  803. package/src/prompts/system/ultrathink-notice.md +3 -0
  804. package/src/prompts/system/web-search.md +25 -0
  805. package/src/prompts/system/workflow-notice.md +70 -0
  806. package/src/prompts/tools/apply-patch.md +65 -0
  807. package/src/prompts/tools/ask.md +30 -0
  808. package/src/prompts/tools/ast-edit.md +39 -0
  809. package/src/prompts/tools/ast-grep.md +42 -0
  810. package/src/prompts/tools/async-result.md +8 -0
  811. package/src/prompts/tools/bash.md +46 -0
  812. package/src/prompts/tools/browser.md +73 -0
  813. package/src/prompts/tools/checkpoint.md +16 -0
  814. package/src/prompts/tools/debug.md +34 -0
  815. package/src/prompts/tools/eval.md +92 -0
  816. package/src/prompts/tools/find.md +36 -0
  817. package/src/prompts/tools/github.md +21 -0
  818. package/src/prompts/tools/goal.md +18 -0
  819. package/src/prompts/tools/image-gen.md +7 -0
  820. package/src/prompts/tools/inspect-image-system.md +20 -0
  821. package/src/prompts/tools/inspect-image.md +32 -0
  822. package/src/prompts/tools/irc.md +59 -0
  823. package/src/prompts/tools/job.md +19 -0
  824. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  825. package/src/prompts/tools/lsp.md +42 -0
  826. package/src/prompts/tools/memory-edit.md +8 -0
  827. package/src/prompts/tools/patch.md +70 -0
  828. package/src/prompts/tools/read.md +84 -0
  829. package/src/prompts/tools/recall.md +5 -0
  830. package/src/prompts/tools/reflect.md +5 -0
  831. package/src/prompts/tools/render-mermaid.md +9 -0
  832. package/src/prompts/tools/replace.md +30 -0
  833. package/src/prompts/tools/resolve.md +9 -0
  834. package/src/prompts/tools/retain.md +6 -0
  835. package/src/prompts/tools/rewind.md +13 -0
  836. package/src/prompts/tools/search-tool-bm25.md +32 -0
  837. package/src/prompts/tools/search.md +24 -0
  838. package/src/prompts/tools/ssh.md +31 -0
  839. package/src/prompts/tools/task-summary.md +17 -0
  840. package/src/prompts/tools/task.md +88 -0
  841. package/src/prompts/tools/todo.md +62 -0
  842. package/src/prompts/tools/web-search.md +10 -0
  843. package/src/prompts/tools/write.md +14 -0
  844. package/src/registry/agent-lifecycle.ts +218 -0
  845. package/src/registry/agent-registry.ts +151 -0
  846. package/src/sdk.ts +2558 -0
  847. package/src/secrets/index.ts +123 -0
  848. package/src/secrets/obfuscator.ts +298 -0
  849. package/src/secrets/regex.ts +21 -0
  850. package/src/session/agent-session.ts +10121 -0
  851. package/src/session/agent-storage.ts +455 -0
  852. package/src/session/artifacts.ts +135 -0
  853. package/src/session/auth-broker-config.ts +131 -0
  854. package/src/session/auth-storage.ts +29 -0
  855. package/src/session/blob-store.ts +255 -0
  856. package/src/session/client-bridge.ts +85 -0
  857. package/src/session/history-storage.ts +348 -0
  858. package/src/session/indexed-session-storage.ts +430 -0
  859. package/src/session/messages.ts +541 -0
  860. package/src/session/redis-session-storage.ts +170 -0
  861. package/src/session/session-dump-format.ts +209 -0
  862. package/src/session/session-history-format.ts +246 -0
  863. package/src/session/session-manager.ts +3676 -0
  864. package/src/session/session-storage.ts +529 -0
  865. package/src/session/shake-types.ts +43 -0
  866. package/src/session/sql-session-storage.ts +314 -0
  867. package/src/session/streaming-output.ts +1330 -0
  868. package/src/session/tool-choice-queue.ts +213 -0
  869. package/src/session/yield-queue.ts +173 -0
  870. package/src/slash-commands/acp-builtins.ts +70 -0
  871. package/src/slash-commands/builtin-registry.ts +1798 -0
  872. package/src/slash-commands/helpers/context-report.ts +39 -0
  873. package/src/slash-commands/helpers/format.ts +46 -0
  874. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  875. package/src/slash-commands/helpers/mcp.ts +532 -0
  876. package/src/slash-commands/helpers/parse.ts +85 -0
  877. package/src/slash-commands/helpers/ssh.ts +195 -0
  878. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  879. package/src/slash-commands/helpers/todo.ts +279 -0
  880. package/src/slash-commands/helpers/usage-report.ts +95 -0
  881. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  882. package/src/slash-commands/types.ts +135 -0
  883. package/src/ssh/config-writer.ts +183 -0
  884. package/src/ssh/connection-manager.ts +509 -0
  885. package/src/ssh/ssh-executor.ts +189 -0
  886. package/src/ssh/sshfs-mount.ts +140 -0
  887. package/src/ssh/utils.ts +8 -0
  888. package/src/stt/downloader.ts +71 -0
  889. package/src/stt/index.ts +3 -0
  890. package/src/stt/recorder.ts +351 -0
  891. package/src/stt/setup.ts +52 -0
  892. package/src/stt/stt-controller.ts +160 -0
  893. package/src/stt/transcribe.py +70 -0
  894. package/src/stt/transcriber.ts +91 -0
  895. package/src/stubs/natives/index.ts +814 -0
  896. package/src/stubs/natives/package.json +7 -0
  897. package/src/stubs/tui/index.ts +282 -0
  898. package/src/stubs/tui/package.json +7 -0
  899. package/src/system-prompt.ts +611 -0
  900. package/src/task/agents.ts +167 -0
  901. package/src/task/commands.ts +132 -0
  902. package/src/task/discovery.ts +122 -0
  903. package/src/task/executor.ts +2133 -0
  904. package/src/task/index.ts +1419 -0
  905. package/src/task/name-generator.ts +1577 -0
  906. package/src/task/omp-command.ts +26 -0
  907. package/src/task/output-manager.ts +88 -0
  908. package/src/task/parallel.ts +116 -0
  909. package/src/task/render.ts +1381 -0
  910. package/src/task/repair-args.ts +129 -0
  911. package/src/task/subprocess-tool-registry.ts +88 -0
  912. package/src/task/types.ts +336 -0
  913. package/src/task/worktree.ts +514 -0
  914. package/src/telemetry-export.ts +144 -0
  915. package/src/thinking.ts +167 -0
  916. package/src/tiny/compiled-runtime.ts +179 -0
  917. package/src/tiny/device.ts +111 -0
  918. package/src/tiny/dtype.ts +101 -0
  919. package/src/tiny/models.ts +242 -0
  920. package/src/tiny/text.ts +165 -0
  921. package/src/tiny/title-client.ts +543 -0
  922. package/src/tiny/title-protocol.ts +56 -0
  923. package/src/tiny/worker.ts +568 -0
  924. package/src/tool-discovery/mode.ts +24 -0
  925. package/src/tool-discovery/tool-index.ts +256 -0
  926. package/src/tools/approval.ts +189 -0
  927. package/src/tools/archive-reader.ts +721 -0
  928. package/src/tools/ask.ts +928 -0
  929. package/src/tools/ast-edit.ts +642 -0
  930. package/src/tools/ast-grep.ts +452 -0
  931. package/src/tools/auto-generated-guard.ts +322 -0
  932. package/src/tools/bash-command-fixup.ts +37 -0
  933. package/src/tools/bash-interactive.ts +408 -0
  934. package/src/tools/bash-interceptor.ts +67 -0
  935. package/src/tools/bash-pty-selection.ts +14 -0
  936. package/src/tools/bash-skill-urls.ts +248 -0
  937. package/src/tools/bash.ts +1386 -0
  938. package/src/tools/browser/attach.ts +175 -0
  939. package/src/tools/browser/launch.ts +660 -0
  940. package/src/tools/browser/readable.ts +112 -0
  941. package/src/tools/browser/registry.ts +197 -0
  942. package/src/tools/browser/render.ts +216 -0
  943. package/src/tools/browser/tab-protocol.ts +105 -0
  944. package/src/tools/browser/tab-supervisor.ts +628 -0
  945. package/src/tools/browser/tab-worker-entry.ts +21 -0
  946. package/src/tools/browser/tab-worker.ts +1226 -0
  947. package/src/tools/browser.ts +343 -0
  948. package/src/tools/checkpoint.ts +136 -0
  949. package/src/tools/conflict-detect.ts +718 -0
  950. package/src/tools/context.ts +39 -0
  951. package/src/tools/debug.ts +1067 -0
  952. package/src/tools/eval-backends.ts +27 -0
  953. package/src/tools/eval-render.ts +752 -0
  954. package/src/tools/eval.ts +577 -0
  955. package/src/tools/fetch.ts +1926 -0
  956. package/src/tools/file-recorder.ts +35 -0
  957. package/src/tools/find.ts +609 -0
  958. package/src/tools/fs-cache-invalidation.ts +28 -0
  959. package/src/tools/gh-cache-invalidation.ts +255 -0
  960. package/src/tools/gh-format.ts +12 -0
  961. package/src/tools/gh-renderer.ts +481 -0
  962. package/src/tools/gh.ts +3720 -0
  963. package/src/tools/github-cache.ts +637 -0
  964. package/src/tools/grouped-file-output.ts +210 -0
  965. package/src/tools/image-gen.ts +1517 -0
  966. package/src/tools/index.ts +599 -0
  967. package/src/tools/inspect-image-renderer.ts +132 -0
  968. package/src/tools/inspect-image.ts +174 -0
  969. package/src/tools/irc.ts +723 -0
  970. package/src/tools/job.ts +557 -0
  971. package/src/tools/json-tree.ts +243 -0
  972. package/src/tools/jtd-to-json-schema.ts +219 -0
  973. package/src/tools/jtd-to-typescript.ts +136 -0
  974. package/src/tools/jtd-utils.ts +102 -0
  975. package/src/tools/list-limit.ts +40 -0
  976. package/src/tools/match-line-format.ts +20 -0
  977. package/src/tools/memory-edit.ts +59 -0
  978. package/src/tools/memory-recall.ts +100 -0
  979. package/src/tools/memory-reflect.ts +88 -0
  980. package/src/tools/memory-render.ts +202 -0
  981. package/src/tools/memory-retain.ts +91 -0
  982. package/src/tools/output-meta.ts +754 -0
  983. package/src/tools/output-schema-validator.ts +132 -0
  984. package/src/tools/path-utils.ts +1054 -0
  985. package/src/tools/plan-mode-guard.ts +108 -0
  986. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  987. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  988. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  989. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  990. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  991. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  992. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  993. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  994. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  995. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  996. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  997. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  998. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  999. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  1000. package/src/tools/read.ts +2929 -0
  1001. package/src/tools/render-mermaid.ts +69 -0
  1002. package/src/tools/render-utils.ts +838 -0
  1003. package/src/tools/renderers.ts +77 -0
  1004. package/src/tools/report-tool-issue.ts +534 -0
  1005. package/src/tools/resolve.ts +276 -0
  1006. package/src/tools/review.ts +253 -0
  1007. package/src/tools/search-tool-bm25.ts +351 -0
  1008. package/src/tools/search.ts +1580 -0
  1009. package/src/tools/sqlite-reader.ts +828 -0
  1010. package/src/tools/ssh.ts +349 -0
  1011. package/src/tools/todo.ts +982 -0
  1012. package/src/tools/tool-errors.ts +62 -0
  1013. package/src/tools/tool-result.ts +94 -0
  1014. package/src/tools/tool-timeouts.ts +30 -0
  1015. package/src/tools/tts.ts +133 -0
  1016. package/src/tools/write.ts +1217 -0
  1017. package/src/tools/yield.ts +269 -0
  1018. package/src/tui/code-cell.ts +216 -0
  1019. package/src/tui/file-list.ts +55 -0
  1020. package/src/tui/hyperlink.ts +175 -0
  1021. package/src/tui/index.ts +12 -0
  1022. package/src/tui/output-block.ts +240 -0
  1023. package/src/tui/status-line.ts +54 -0
  1024. package/src/tui/tree-list.ts +84 -0
  1025. package/src/tui/types.ts +15 -0
  1026. package/src/tui/utils.ts +103 -0
  1027. package/src/utils/block-context.ts +312 -0
  1028. package/src/utils/changelog.ts +132 -0
  1029. package/src/utils/clipboard.ts +193 -0
  1030. package/src/utils/command-args.ts +76 -0
  1031. package/src/utils/commit-message-generator.ts +151 -0
  1032. package/src/utils/edit-mode.ts +41 -0
  1033. package/src/utils/enhanced-paste.ts +230 -0
  1034. package/src/utils/event-bus.ts +33 -0
  1035. package/src/utils/external-editor.ts +65 -0
  1036. package/src/utils/file-display-mode.ts +45 -0
  1037. package/src/utils/file-mentions.ts +281 -0
  1038. package/src/utils/git.ts +1833 -0
  1039. package/src/utils/image-loading.ts +132 -0
  1040. package/src/utils/image-resize.ts +309 -0
  1041. package/src/utils/jj.ts +248 -0
  1042. package/src/utils/lang-from-path.ts +239 -0
  1043. package/src/utils/markit.ts +89 -0
  1044. package/src/utils/open.ts +55 -0
  1045. package/src/utils/session-color.ts +68 -0
  1046. package/src/utils/shell-snapshot.ts +187 -0
  1047. package/src/utils/sixel.ts +69 -0
  1048. package/src/utils/title-generator.ts +373 -0
  1049. package/src/utils/tool-choice.ts +33 -0
  1050. package/src/utils/tools-manager.ts +363 -0
  1051. package/src/web/kagi.ts +305 -0
  1052. package/src/web/parallel.ts +353 -0
  1053. package/src/web/scrapers/artifacthub.ts +207 -0
  1054. package/src/web/scrapers/arxiv.ts +83 -0
  1055. package/src/web/scrapers/aur.ts +162 -0
  1056. package/src/web/scrapers/biorxiv.ts +133 -0
  1057. package/src/web/scrapers/bluesky.ts +262 -0
  1058. package/src/web/scrapers/brew.ts +172 -0
  1059. package/src/web/scrapers/cheatsh.ts +68 -0
  1060. package/src/web/scrapers/chocolatey.ts +196 -0
  1061. package/src/web/scrapers/choosealicense.ts +95 -0
  1062. package/src/web/scrapers/cisa-kev.ts +87 -0
  1063. package/src/web/scrapers/clojars.ts +154 -0
  1064. package/src/web/scrapers/coingecko.ts +177 -0
  1065. package/src/web/scrapers/crates-io.ts +97 -0
  1066. package/src/web/scrapers/crossref.ts +136 -0
  1067. package/src/web/scrapers/devto.ts +147 -0
  1068. package/src/web/scrapers/discogs.ts +306 -0
  1069. package/src/web/scrapers/discourse.ts +197 -0
  1070. package/src/web/scrapers/dockerhub.ts +138 -0
  1071. package/src/web/scrapers/docs-rs.ts +653 -0
  1072. package/src/web/scrapers/fdroid.ts +134 -0
  1073. package/src/web/scrapers/firefox-addons.ts +191 -0
  1074. package/src/web/scrapers/flathub.ts +223 -0
  1075. package/src/web/scrapers/github-gist.ts +58 -0
  1076. package/src/web/scrapers/github.ts +704 -0
  1077. package/src/web/scrapers/gitlab.ts +401 -0
  1078. package/src/web/scrapers/go-pkg.ts +266 -0
  1079. package/src/web/scrapers/hackage.ts +140 -0
  1080. package/src/web/scrapers/hackernews.ts +189 -0
  1081. package/src/web/scrapers/hex.ts +105 -0
  1082. package/src/web/scrapers/huggingface.ts +321 -0
  1083. package/src/web/scrapers/iacr.ts +89 -0
  1084. package/src/web/scrapers/index.ts +252 -0
  1085. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1086. package/src/web/scrapers/lemmy.ts +203 -0
  1087. package/src/web/scrapers/lobsters.ts +175 -0
  1088. package/src/web/scrapers/mastodon.ts +292 -0
  1089. package/src/web/scrapers/maven.ts +138 -0
  1090. package/src/web/scrapers/mdn.ts +173 -0
  1091. package/src/web/scrapers/metacpan.ts +222 -0
  1092. package/src/web/scrapers/musicbrainz.ts +250 -0
  1093. package/src/web/scrapers/npm.ts +98 -0
  1094. package/src/web/scrapers/nuget.ts +183 -0
  1095. package/src/web/scrapers/nvd.ts +222 -0
  1096. package/src/web/scrapers/ollama.ts +239 -0
  1097. package/src/web/scrapers/open-vsx.ts +106 -0
  1098. package/src/web/scrapers/opencorporates.ts +292 -0
  1099. package/src/web/scrapers/openlibrary.ts +336 -0
  1100. package/src/web/scrapers/orcid.ts +286 -0
  1101. package/src/web/scrapers/osv.ts +176 -0
  1102. package/src/web/scrapers/packagist.ts +160 -0
  1103. package/src/web/scrapers/pub-dev.ts +143 -0
  1104. package/src/web/scrapers/pubmed.ts +211 -0
  1105. package/src/web/scrapers/pypi.ts +112 -0
  1106. package/src/web/scrapers/rawg.ts +110 -0
  1107. package/src/web/scrapers/readthedocs.ts +120 -0
  1108. package/src/web/scrapers/reddit.ts +95 -0
  1109. package/src/web/scrapers/repology.ts +251 -0
  1110. package/src/web/scrapers/rfc.ts +201 -0
  1111. package/src/web/scrapers/rubygems.ts +103 -0
  1112. package/src/web/scrapers/searchcode.ts +189 -0
  1113. package/src/web/scrapers/sec-edgar.ts +261 -0
  1114. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1115. package/src/web/scrapers/snapcraft.ts +187 -0
  1116. package/src/web/scrapers/sourcegraph.ts +336 -0
  1117. package/src/web/scrapers/spdx.ts +108 -0
  1118. package/src/web/scrapers/spotify.ts +198 -0
  1119. package/src/web/scrapers/stackoverflow.ts +120 -0
  1120. package/src/web/scrapers/terraform.ts +277 -0
  1121. package/src/web/scrapers/tldr.ts +47 -0
  1122. package/src/web/scrapers/twitter.ts +94 -0
  1123. package/src/web/scrapers/types.ts +397 -0
  1124. package/src/web/scrapers/utils.ts +109 -0
  1125. package/src/web/scrapers/vimeo.ts +133 -0
  1126. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1127. package/src/web/scrapers/w3c.ts +156 -0
  1128. package/src/web/scrapers/wikidata.ts +344 -0
  1129. package/src/web/scrapers/wikipedia.ts +84 -0
  1130. package/src/web/scrapers/youtube.ts +325 -0
  1131. package/src/web/search/index.ts +292 -0
  1132. package/src/web/search/provider.ts +157 -0
  1133. package/src/web/search/providers/anthropic.ts +318 -0
  1134. package/src/web/search/providers/base.ts +89 -0
  1135. package/src/web/search/providers/brave.ts +152 -0
  1136. package/src/web/search/providers/codex.ts +591 -0
  1137. package/src/web/search/providers/exa.ts +400 -0
  1138. package/src/web/search/providers/gemini.ts +460 -0
  1139. package/src/web/search/providers/jina.ts +111 -0
  1140. package/src/web/search/providers/kagi.ts +86 -0
  1141. package/src/web/search/providers/kimi.ts +196 -0
  1142. package/src/web/search/providers/parallel.ts +225 -0
  1143. package/src/web/search/providers/perplexity.ts +730 -0
  1144. package/src/web/search/providers/searxng.ts +313 -0
  1145. package/src/web/search/providers/synthetic.ts +114 -0
  1146. package/src/web/search/providers/tavily.ts +176 -0
  1147. package/src/web/search/providers/utils.ts +128 -0
  1148. package/src/web/search/providers/zai.ts +333 -0
  1149. package/src/web/search/render.ts +262 -0
  1150. package/src/web/search/types.ts +482 -0
  1151. package/src/web/search/utils.ts +17 -0
  1152. package/src/workspace-tree.ts +286 -0
@@ -0,0 +1,1073 @@
1
+ import * as fs from "node:fs/promises";
2
+ import type { ImageContent } from "@oh-my-pi/pi-ai";
3
+ import type { AutocompleteProvider, SlashCommand } from './stubs/tui/index.ts';
4
+ import { $env, logger, sanitizeText } from "@oh-my-pi/pi-utils";
5
+ import { getRoleInfo } from "../../config/model-roles";
6
+ import { isSettingsInitialized, settings } from "../../config/settings";
7
+ import { renderSegmentTrack } from "../../modes/components/segment-track";
8
+ import { TinyTitleDownloadProgressComponent } from "../../modes/components/tiny-title-download-progress";
9
+ import { expandEmoticons } from "../../modes/emoji-autocomplete";
10
+ import { materializeImageReferenceLinks } from "../../modes/image-references";
11
+ import { createPromptActionAutocompleteProvider } from "../../modes/prompt-action-autocomplete";
12
+ import type { InteractiveModeContext } from "../../modes/types";
13
+ import manualContinuePrompt from "../../prompts/system/manual-continue.md" with { type: "text" };
14
+ import { SKILL_PROMPT_MESSAGE_TYPE, type SkillPromptDetails, USER_INTERRUPT_LABEL } from "../../session/messages";
15
+ import { executeBuiltinSlashCommand } from "../../slash-commands/builtin-registry";
16
+ import { isTinyTitleLocalModelKey } from "../../tiny/models";
17
+ import { isLowSignalTitleInput } from "../../tiny/text";
18
+ import { tinyTitleClient } from "../../tiny/title-client";
19
+ import type { TinyTitleProgressEvent } from "../../tiny/title-protocol";
20
+ import { copyToClipboard, readImageFromClipboard, readTextFromClipboard } from "../../utils/clipboard";
21
+ import { EnhancedPasteController } from "../../utils/enhanced-paste";
22
+ import { getEditorCommand, openInEditor } from "../../utils/external-editor";
23
+ import { ensureSupportedImageInput, ImageInputTooLargeError, loadImageInput } from "../../utils/image-loading";
24
+ import { resizeImage } from "../../utils/image-resize";
25
+ import { generateSessionTitle, setSessionTerminalTitle } from "../../utils/title-generator";
26
+
27
+ interface Expandable {
28
+ setExpanded(expanded: boolean): void;
29
+ }
30
+
31
+ function isExpandable(obj: unknown): obj is Expandable {
32
+ return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
33
+ }
34
+
35
+ /** Minimal contract for any component that can receive a paste payload directly. */
36
+ interface PasteTarget {
37
+ pasteText(text: string): void;
38
+ }
39
+
40
+ function hasPasteText(value: unknown): value is PasteTarget {
41
+ return typeof value === "object" && value !== null && typeof (value as PasteTarget).pasteText === "function";
42
+ }
43
+
44
+ const TINY_TITLE_PROGRESS_DONE_TTL_MS = 3_000;
45
+ // A cached model fires its file-load events in a short burst and then goes silent
46
+ // while onnxruntime builds the session; a genuine download keeps streaming progress
47
+ // events for seconds. Only reveal the bar once a still-incomplete event arrives after
48
+ // this grace window, so an already-downloaded model never flashes the bar.
49
+ const TINY_TITLE_PROGRESS_REVEAL_DELAY_MS = 1_000;
50
+
51
+ export class InputController {
52
+ constructor(private ctx: InteractiveModeContext) {}
53
+
54
+ #enhancedPaste?: EnhancedPasteController;
55
+
56
+ #showTinyTitleDownloadProgress(modelKey: string): void {
57
+ if (!isTinyTitleLocalModelKey(modelKey)) return;
58
+ const component = new TinyTitleDownloadProgressComponent(modelKey);
59
+ let added = false;
60
+ let disposed = false;
61
+ let removeTimer: NodeJS.Timeout | undefined;
62
+ const remove = (): void => {
63
+ if (disposed) return;
64
+ disposed = true;
65
+ unsubscribe();
66
+ if (removeTimer) {
67
+ clearTimeout(removeTimer);
68
+ removeTimer = undefined;
69
+ }
70
+ if (added) {
71
+ this.ctx.chatContainer.removeChild(component);
72
+ this.ctx.ui.requestRender();
73
+ }
74
+ };
75
+ const scheduleRemove = (): void => {
76
+ if (removeTimer) clearTimeout(removeTimer);
77
+ removeTimer = setTimeout(remove, TINY_TITLE_PROGRESS_DONE_TTL_MS);
78
+ removeTimer.unref?.();
79
+ };
80
+ let revealAt = 0;
81
+ const update = (event: TinyTitleProgressEvent): void => {
82
+ if (disposed || event.modelKey !== modelKey) return;
83
+ component.update(event);
84
+ if (revealAt === 0) revealAt = performance.now() + TINY_TITLE_PROGRESS_REVEAL_DELAY_MS;
85
+ const complete = component.isComplete();
86
+ // Reveal only for a download still in flight past the grace window. Cache hits
87
+ // either complete or fall silent (onnx init emits no events) before this fires.
88
+ if (!added && !complete && performance.now() >= revealAt) {
89
+ this.ctx.chatContainer.addChild(component);
90
+ added = true;
91
+ }
92
+ if (added) this.ctx.ui.requestRender();
93
+ if (complete) {
94
+ if (added) scheduleRemove();
95
+ else remove();
96
+ }
97
+ };
98
+ const unsubscribe = tinyTitleClient.onProgress(update);
99
+ }
100
+
101
+ setupKeyHandlers(): void {
102
+ this.ctx.editor.setActionKeys("app.interrupt", this.ctx.keybindings.getKeys("app.interrupt"));
103
+ this.ctx.editor.onEscape = () => {
104
+ if (this.ctx.loopModeEnabled) {
105
+ this.ctx.pauseLoop();
106
+ if (this.ctx.session.isStreaming) {
107
+ this.ctx.notifyInterrupting();
108
+ void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
109
+ } else {
110
+ this.ctx.cancelPendingSubmission();
111
+ }
112
+ return;
113
+ }
114
+ if (this.ctx.hasActiveBtw() && this.ctx.handleBtwEscape()) {
115
+ return;
116
+ }
117
+ if (this.ctx.hasActiveOmfg() && this.ctx.handleOmfgEscape()) {
118
+ return;
119
+ }
120
+ if (this.ctx.loadingAnimation) {
121
+ if (this.ctx.cancelPendingSubmission()) {
122
+ return;
123
+ }
124
+ this.restoreQueuedMessagesToEditor({ abort: true });
125
+ } else if (this.ctx.session.isBashRunning) {
126
+ this.ctx.session.abortBash();
127
+ } else if (this.ctx.isBashMode) {
128
+ this.ctx.editor.setText("");
129
+ this.ctx.isBashMode = false;
130
+ this.ctx.updateEditorBorderColor();
131
+ } else if (this.ctx.session.isEvalRunning) {
132
+ this.ctx.session.abortEval();
133
+ } else if (this.ctx.isPythonMode) {
134
+ this.ctx.editor.setText("");
135
+ this.ctx.isPythonMode = false;
136
+ this.ctx.updateEditorBorderColor();
137
+ } else if (this.ctx.session.isStreaming) {
138
+ this.ctx.notifyInterrupting();
139
+ void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
140
+ } else if (!this.ctx.editor.getText().trim()) {
141
+ // Double-interrupt with empty editor triggers /tree, /branch, or nothing based on setting
142
+ const action = settings.get("doubleEscapeAction");
143
+ if (action !== "none") {
144
+ const now = Date.now();
145
+ if (now - this.ctx.lastEscapeTime < 500) {
146
+ if (action === "tree") {
147
+ this.ctx.showTreeSelector();
148
+ } else {
149
+ this.ctx.showUserMessageSelector();
150
+ }
151
+ this.ctx.lastEscapeTime = 0;
152
+ } else {
153
+ this.ctx.lastEscapeTime = now;
154
+ }
155
+ }
156
+ }
157
+ };
158
+
159
+ this.ctx.editor.setActionKeys("app.clear", this.ctx.keybindings.getKeys("app.clear"));
160
+ this.ctx.editor.onClear = () => this.handleCtrlC();
161
+ this.ctx.editor.setActionKeys("app.exit", this.ctx.keybindings.getKeys("app.exit"));
162
+ this.ctx.editor.setActionKeys("app.display.reset", this.ctx.keybindings.getKeys("app.display.reset"));
163
+ this.ctx.editor.onDisplayReset = () => this.ctx.ui.resetDisplay();
164
+ this.ctx.editor.onExit = () => this.handleCtrlD();
165
+ this.ctx.editor.setActionKeys("app.suspend", this.ctx.keybindings.getKeys("app.suspend"));
166
+ this.ctx.editor.onSuspend = () => this.handleCtrlZ();
167
+ this.ctx.editor.setActionKeys("app.thinking.cycle", this.ctx.keybindings.getKeys("app.thinking.cycle"));
168
+ this.ctx.editor.onCycleThinkingLevel = () => this.cycleThinkingLevel();
169
+ this.ctx.editor.setActionKeys("app.model.cycleForward", this.ctx.keybindings.getKeys("app.model.cycleForward"));
170
+ this.ctx.editor.onCycleModelForward = () => this.cycleRoleModel("forward");
171
+ this.ctx.editor.setActionKeys("app.model.cycleBackward", this.ctx.keybindings.getKeys("app.model.cycleBackward"));
172
+ this.ctx.editor.onCycleModelBackward = () => this.cycleRoleModel("backward");
173
+ this.ctx.editor.setActionKeys(
174
+ "app.model.selectTemporary",
175
+ this.ctx.keybindings.getKeys("app.model.selectTemporary"),
176
+ );
177
+ this.ctx.editor.onSelectModelTemporary = () => this.ctx.showModelSelector({ temporaryOnly: true });
178
+
179
+ // Global debug handler on TUI (works regardless of focus)
180
+ this.ctx.ui.onDebug = () => this.ctx.showDebugSelector();
181
+ this.ctx.editor.setActionKeys("app.model.select", this.ctx.keybindings.getKeys("app.model.select"));
182
+ this.ctx.editor.onSelectModel = () => this.ctx.showModelSelector();
183
+ this.ctx.editor.setActionKeys("app.history.search", this.ctx.keybindings.getKeys("app.history.search"));
184
+ this.ctx.editor.onHistorySearch = () => this.ctx.showHistorySearch();
185
+ this.ctx.editor.setActionKeys("app.thinking.toggle", this.ctx.keybindings.getKeys("app.thinking.toggle"));
186
+ this.ctx.editor.onToggleThinking = () => this.ctx.toggleThinkingBlockVisibility();
187
+ this.ctx.editor.setActionKeys("app.editor.external", this.ctx.keybindings.getKeys("app.editor.external"));
188
+ this.ctx.editor.onExternalEditor = () => void this.openExternalEditor();
189
+ this.ctx.editor.setActionKeys(
190
+ "app.clipboard.pasteImage",
191
+ this.ctx.keybindings.getKeys("app.clipboard.pasteImage"),
192
+ );
193
+ this.ctx.editor.onPasteImage = () => this.handleImagePaste();
194
+ this.ctx.editor.onPasteImagePath = path => this.handleImagePathPaste(path);
195
+ this.ctx.editor.setActionKeys(
196
+ "app.clipboard.pasteTextRaw",
197
+ this.ctx.keybindings.getKeys("app.clipboard.pasteTextRaw"),
198
+ );
199
+ this.ctx.editor.onPasteTextRaw = () => void this.handleClipboardTextRawPaste();
200
+ this.ctx.editor.setActionKeys(
201
+ "app.clipboard.copyPrompt",
202
+ this.ctx.keybindings.getKeys("app.clipboard.copyPrompt"),
203
+ );
204
+ this.ctx.editor.onCopyPrompt = () => this.handleCopyPrompt();
205
+ this.ctx.editor.setActionKeys("app.tools.expand", this.ctx.keybindings.getKeys("app.tools.expand"));
206
+ this.ctx.editor.onExpandTools = () => this.toggleToolOutputExpansion();
207
+ this.ctx.editor.setActionKeys("app.message.dequeue", this.ctx.keybindings.getKeys("app.message.dequeue"));
208
+ this.ctx.editor.onDequeue = () => this.handleDequeue();
209
+ this.ctx.editor.clearCustomKeyHandlers();
210
+ // Wire up extension shortcuts
211
+ this.registerExtensionShortcuts();
212
+ const planModeKeys = this.ctx.keybindings.getKeys("app.plan.toggle");
213
+ for (const key of planModeKeys) {
214
+ this.ctx.editor.setCustomKeyHandler(key, () => void this.ctx.handlePlanModeCommand());
215
+ }
216
+
217
+ for (const key of this.ctx.keybindings.getKeys("app.session.new")) {
218
+ this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.handleClearCommand());
219
+ }
220
+ for (const key of this.ctx.keybindings.getKeys("app.session.tree")) {
221
+ this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.showTreeSelector());
222
+ }
223
+ for (const key of this.ctx.keybindings.getKeys("app.session.fork")) {
224
+ this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.showUserMessageSelector());
225
+ }
226
+ for (const key of this.ctx.keybindings.getKeys("app.session.resume")) {
227
+ this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.showSessionSelector());
228
+ }
229
+ for (const key of this.ctx.keybindings.getKeys("app.message.followUp")) {
230
+ this.ctx.editor.setCustomKeyHandler(key, () => void this.handleFollowUp());
231
+ }
232
+ for (const key of this.ctx.keybindings.getKeys("app.stt.toggle")) {
233
+ this.ctx.editor.setCustomKeyHandler(key, () => void this.ctx.handleSTTToggle());
234
+ }
235
+ for (const key of this.ctx.keybindings.getKeys("app.clipboard.copyLine")) {
236
+ this.ctx.editor.setCustomKeyHandler(key, () => this.handleCopyCurrentLine());
237
+ }
238
+ const hubKeys = new Set([
239
+ ...this.ctx.keybindings.getKeys("app.agents.hub"),
240
+ ...this.ctx.keybindings.getKeys("app.session.observe"),
241
+ ]);
242
+ for (const key of hubKeys) {
243
+ this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.showAgentHub());
244
+ }
245
+
246
+ // Double-tap left arrow on an empty editor opens the agent hub — same
247
+ // 500ms window as the double-escape state machine above.
248
+ this.ctx.editor.onLeftAtStart = () => {
249
+ const now = Date.now();
250
+ if (now - this.ctx.lastLeftTapTime < 500) {
251
+ this.ctx.lastLeftTapTime = 0;
252
+ this.ctx.showAgentHub();
253
+ } else {
254
+ this.ctx.lastLeftTapTime = now;
255
+ }
256
+ };
257
+
258
+ this.#setupEnhancedPaste();
259
+
260
+ this.ctx.editor.onChange = (text: string) => {
261
+ const wasBashMode = this.ctx.isBashMode;
262
+ const wasPythonMode = this.ctx.isPythonMode;
263
+ const trimmed = text.trimStart();
264
+ this.ctx.isBashMode = text.trimStart().startsWith("!");
265
+ this.ctx.isPythonMode = trimmed.startsWith("$") && !trimmed.startsWith("${");
266
+ if (wasBashMode !== this.ctx.isBashMode || wasPythonMode !== this.ctx.isPythonMode) {
267
+ this.ctx.updateEditorBorderColor();
268
+ }
269
+ };
270
+ }
271
+
272
+ #setupEnhancedPaste(): void {
273
+ if (this.#enhancedPaste) return;
274
+
275
+ this.#enhancedPaste = new EnhancedPasteController({
276
+ write: data => this.ctx.ui.terminal.write(data),
277
+ pasteText: text => {
278
+ // Route enhanced-paste text to the currently focused component when it
279
+ // exposes a `pasteText` hook (modal Input prompts: OAuth API-key entry,
280
+ // Perplexity OTP, GitHub Enterprise URL, manual redirect URL). Falling
281
+ // back to the main editor would have buried the text in the detached
282
+ // editor while the modal Input had focus (#2127).
283
+ const focused = this.ctx.ui.getFocused();
284
+ const target = focused && focused !== this.ctx.editor && hasPasteText(focused) ? focused : this.ctx.editor;
285
+ target.pasteText(text);
286
+ this.ctx.ui.requestRender();
287
+ },
288
+ pasteImage: async image => {
289
+ // Images can only land in the main editor — when a modal Input is
290
+ // focused, refuse rather than dump the binary blob in a hidden buffer.
291
+ const focused = this.ctx.ui.getFocused();
292
+ if (focused && focused !== this.ctx.editor && hasPasteText(focused)) {
293
+ this.ctx.showStatus("Image paste is not supported in this prompt");
294
+ return;
295
+ }
296
+ await this.#normalizeAndInsertPastedImage(image, `Unsupported pasted image format: ${image.mimeType}`);
297
+ },
298
+ showStatus: message => this.ctx.showStatus(message),
299
+ });
300
+ this.ctx.ui.addInputListener(data => (this.#enhancedPaste?.handleInput(data) ? { consume: true } : undefined));
301
+ this.ctx.ui.addStartListener(() => this.#enhancedPaste?.enable());
302
+ }
303
+
304
+ setupEditorSubmitHandler(): void {
305
+ this.ctx.editor.onSubmit = async (text: string) => {
306
+ text = text.trim();
307
+ if ((!isSettingsInitialized() || settings.get("emojiAutocomplete")) && text) text = expandEmoticons(text);
308
+
309
+ // Empty submit while streaming with queued steering: interrupt now and
310
+ // immediately resume so the visible `Steer:` entry is sent without
311
+ // waiting for the current tool/model boundary.
312
+ if (!text && this.ctx.session.isStreaming) {
313
+ const queuedMessages = this.ctx.session.getQueuedMessages();
314
+ if (queuedMessages.steering.length > 0) {
315
+ await this.ctx.session.interruptAndFlushQueuedMessages({ reason: USER_INTERRUPT_LABEL });
316
+ this.ctx.updatePendingMessagesDisplay();
317
+ this.ctx.ui.requestRender();
318
+ return;
319
+ }
320
+ if (this.ctx.session.queuedMessageCount > 0) {
321
+ // Preserve the existing empty-submit flush for non-steer queues.
322
+ await this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
323
+ return;
324
+ }
325
+ }
326
+
327
+ if (!text) return;
328
+
329
+ // Continue shortcuts: "." or "c" resume the agent with a hidden agent-authored
330
+ // developer directive (no visible user message) instead of an empty turn, so the
331
+ // model continues the prior intent rather than second-guessing the interrupt.
332
+ if (text === "." || text === "c") {
333
+ if (this.ctx.onInputCallback) {
334
+ this.ctx.editor.setText("");
335
+ this.ctx.pendingImages = [];
336
+ this.ctx.pendingImageLinks = [];
337
+ this.ctx.editor.imageLinks = undefined;
338
+ this.ctx.onInputCallback({
339
+ text: manualContinuePrompt,
340
+ cancelled: false,
341
+ started: true,
342
+ synthetic: true,
343
+ });
344
+ }
345
+ return;
346
+ }
347
+
348
+ const runner = this.ctx.session.extensionRunner;
349
+ let inputImages = this.ctx.pendingImages.length > 0 ? [...this.ctx.pendingImages] : undefined;
350
+ let inputImageLinks = this.ctx.pendingImageLinks.length > 0 ? [...this.ctx.pendingImageLinks] : undefined;
351
+
352
+ if (runner?.hasHandlers("input")) {
353
+ const result = await runner.emitInput(text, inputImages, "interactive");
354
+ if (result?.handled) {
355
+ this.ctx.editor.setText("");
356
+ this.ctx.pendingImages = [];
357
+ this.ctx.pendingImageLinks = [];
358
+ this.ctx.editor.imageLinks = undefined;
359
+ return;
360
+ }
361
+ if (result?.text !== undefined) {
362
+ text = result.text.trim();
363
+ }
364
+ if (result?.images !== undefined) {
365
+ inputImages = result.images;
366
+ inputImageLinks = await materializeImageReferenceLinks(
367
+ inputImages,
368
+ this.ctx.sessionManager.putBlob.bind(this.ctx.sessionManager),
369
+ );
370
+ }
371
+ }
372
+
373
+ if (!text) return;
374
+
375
+ // Handle built-in slash commands
376
+ const slashResult = await executeBuiltinSlashCommand(text, {
377
+ ctx: this.ctx,
378
+ });
379
+ if (slashResult === true) {
380
+ return;
381
+ }
382
+ if (typeof slashResult === "string") {
383
+ // Command handled but returned remaining text to use as prompt
384
+ text = slashResult;
385
+ }
386
+
387
+ // Handle skill commands (/skill:name [args]). Enter ⇒ steer (matches the
388
+ // free-text Enter semantics applied a few lines below at the streaming
389
+ // branch). Ctrl+Enter routes through `handleFollowUp` and dispatches the
390
+ // same helper with `"followUp"`.
391
+ if (await this.#invokeSkillCommand(text, "steer")) {
392
+ return;
393
+ }
394
+
395
+ // Handle bash command (! for normal, !! for excluded from context)
396
+ if (text.startsWith("!")) {
397
+ const isExcluded = text.startsWith("!!");
398
+ const command = isExcluded ? text.slice(2).trim() : text.slice(1).trim();
399
+ if (command) {
400
+ if (this.ctx.session.isBashRunning) {
401
+ this.ctx.showWarning("A bash command is already running. Press Esc to cancel it first.");
402
+ this.ctx.editor.setText(text);
403
+ return;
404
+ }
405
+ this.ctx.editor.addToHistory(text);
406
+ await this.ctx.handleBashCommand(command, isExcluded);
407
+ this.ctx.isBashMode = false;
408
+ this.ctx.updateEditorBorderColor();
409
+ return;
410
+ }
411
+ }
412
+
413
+ // Handle python command ($ for normal, $$ for excluded from context)
414
+ if (text.startsWith("$")) {
415
+ const isExcluded = text.startsWith("$$");
416
+ const code = isExcluded ? text.slice(2).trim() : text.slice(1).trim();
417
+ if (code) {
418
+ if (this.ctx.session.isEvalRunning) {
419
+ this.ctx.showWarning("A Python execution is already running. Press Esc to cancel it first.");
420
+ this.ctx.editor.setText(text);
421
+ return;
422
+ }
423
+ this.ctx.editor.addToHistory(text);
424
+ await this.ctx.handlePythonCommand(code, isExcluded);
425
+ this.ctx.isPythonMode = false;
426
+ this.ctx.updateEditorBorderColor();
427
+ return;
428
+ }
429
+ }
430
+
431
+ // While loop mode is on, every user-typed prompt becomes the new loop
432
+ // prompt that auto-resubmits after each yield.
433
+ if (this.ctx.loopModeEnabled) {
434
+ this.ctx.loopPrompt = text;
435
+ }
436
+
437
+ // Queue input during compaction
438
+ if (this.ctx.session.isCompacting) {
439
+ const images = inputImages && inputImages.length > 0 ? [...inputImages] : undefined;
440
+ this.ctx.queueCompactionMessage(text, "steer", images);
441
+ return;
442
+ }
443
+
444
+ // If streaming, use prompt() with steer behavior
445
+ // This handles extension commands (execute immediately), prompt template expansion, and queueing
446
+ if (this.ctx.session.isStreaming) {
447
+ this.ctx.editor.addToHistory(text);
448
+ this.ctx.editor.setText("");
449
+ this.ctx.editor.imageLinks = undefined;
450
+ const images = inputImages && inputImages.length > 0 ? [...inputImages] : undefined;
451
+ this.ctx.pendingImages = [];
452
+ this.ctx.pendingImageLinks = [];
453
+ // Record the signature so the queued message's eventual delivery
454
+ // (a user-role `message_start` event) leaves any draft the user has
455
+ // typed since queuing intact. Same protection as #783, applied to
456
+ // the streaming/queue path.
457
+ await this.ctx.withLocalSubmission(
458
+ text,
459
+ () => this.ctx.session.prompt(text, { streamingBehavior: "steer", images }),
460
+ { imageCount: images?.length ?? 0 },
461
+ );
462
+ this.ctx.updatePendingMessagesDisplay();
463
+ this.ctx.ui.requestRender();
464
+ return;
465
+ }
466
+
467
+ // Normal message submission
468
+ // First, move any pending bash components to chat
469
+ this.ctx.flushPendingBashComponents();
470
+
471
+ // Auto-generate a session title while the session is still unnamed.
472
+ // Greetings / acknowledgements / empty input carry no task, so they are
473
+ // skipped deterministically (no model invoked, no download-progress UI)
474
+ // and the session stays unnamed — the next user message gets a fresh
475
+ // chance, so titling defers past "hi" instead of latching onto it.
476
+ if (!this.ctx.sessionManager.getSessionName() && !$env.PI_NO_TITLE && !isLowSignalTitleInput(text)) {
477
+ this.#showTinyTitleDownloadProgress(this.ctx.settings.get("providers.tinyModel"));
478
+ const registry = this.ctx.session.modelRegistry;
479
+ generateSessionTitle(
480
+ text,
481
+ registry,
482
+ this.ctx.settings,
483
+ this.ctx.session.sessionId,
484
+ this.ctx.session.model,
485
+ provider => this.ctx.session.agent.metadataForProvider(provider),
486
+ this.ctx.titleSystemPrompt,
487
+ )
488
+ .then(async title => {
489
+ // Re-check: a concurrent attempt for an earlier message may have
490
+ // already named the session. Don't clobber it.
491
+ if (title && !this.ctx.sessionManager.getSessionName()) {
492
+ const applied = await this.ctx.sessionManager.setSessionName(title, "auto");
493
+ if (applied) {
494
+ setSessionTerminalTitle(
495
+ this.ctx.sessionManager.getSessionName()!,
496
+ this.ctx.sessionManager.getCwd(),
497
+ );
498
+ this.ctx.updateEditorBorderColor();
499
+ }
500
+ }
501
+ })
502
+ .catch(err => {
503
+ logger.warn("title-generator: uncaught auto-title error", {
504
+ sessionId: this.ctx.session.sessionId,
505
+ reason: "uncaught-auto-title-error",
506
+ error: err instanceof Error ? err.message : String(err),
507
+ });
508
+ });
509
+ }
510
+
511
+ if (this.ctx.onInputCallback) {
512
+ // Include any pending images from clipboard paste
513
+ this.ctx.editor.imageLinks = undefined;
514
+ const images = inputImages && inputImages.length > 0 ? [...inputImages] : undefined;
515
+ this.ctx.pendingImages = [];
516
+ this.ctx.pendingImageLinks = [];
517
+
518
+ // Render user message immediately, then let session events catch up
519
+ const submission = this.ctx.startPendingSubmission({
520
+ text,
521
+ images,
522
+ imageLinks: inputImageLinks,
523
+ });
524
+
525
+ this.ctx.onInputCallback(submission);
526
+ }
527
+ this.ctx.editor.addToHistory(text);
528
+ };
529
+ }
530
+
531
+ handleCtrlC(): void {
532
+ const now = Date.now();
533
+ if (now - this.ctx.lastSigintTime < 500) {
534
+ void this.ctx.shutdown();
535
+ } else {
536
+ this.ctx.clearEditor();
537
+ this.ctx.lastSigintTime = now;
538
+ }
539
+ }
540
+
541
+ handleCtrlD(): void {
542
+ // Editor text (if any) is snapshotted at the start of shutdown() and
543
+ // persisted as a draft for the next resume. Empty text is also fine —
544
+ // shutdown clears any stale sidecar in that case.
545
+ void this.ctx.shutdown();
546
+ }
547
+
548
+ handleCtrlZ(): void {
549
+ // SIGTSTP is POSIX job-control: Windows has no equivalent and
550
+ // `process.kill(_, "SIGTSTP")` throws `TypeError: Unknown signal:
551
+ // SIGTSTP` there, taking the whole agent down via an uncaught
552
+ // exception (issue #2036). No-op on platforms that cannot suspend.
553
+ if (process.platform === "win32") {
554
+ this.ctx.showStatus("Suspend (Ctrl+Z) is not supported on this platform");
555
+ return;
556
+ }
557
+
558
+ // Capture the listener so we can detach it if the signal never
559
+ // fires; otherwise a failed suspend would leave a stale SIGCONT
560
+ // handler that fires on the next unrelated continue and tries to
561
+ // re-`start()` an already-running TUI.
562
+ const onResume = (): void => {
563
+ this.ctx.ui.start();
564
+ this.ctx.ui.requestRender(true);
565
+ };
566
+ process.once("SIGCONT", onResume);
567
+
568
+ // Stop the TUI (restore terminal to normal mode) before sending the
569
+ // signal so the parent shell sees a sane terminal state.
570
+ this.ctx.ui.stop();
571
+
572
+ try {
573
+ // pid=0 → entire foreground process group; the shell receives
574
+ // SIGTSTP and parks the job.
575
+ process.kill(0, "SIGTSTP");
576
+ } catch (err) {
577
+ // Either the runtime refused the signal or the kernel rejected
578
+ // it (some sandboxes block sending to pid=0). Tear the resume
579
+ // hook down and bring the TUI back so the user is not stranded
580
+ // on a frozen prompt.
581
+ process.removeListener("SIGCONT", onResume);
582
+ this.ctx.ui.start();
583
+ this.ctx.ui.requestRender(true);
584
+ const reason = err instanceof Error ? err.message : String(err);
585
+ this.ctx.showError(`Failed to suspend: ${reason}`);
586
+ }
587
+ }
588
+
589
+ handleDequeue(): void {
590
+ const restored = this.restoreQueuedMessagesToEditor();
591
+ if (restored === 0) {
592
+ this.ctx.showStatus("No queued messages to restore");
593
+ } else {
594
+ this.ctx.showStatus(`Restored ${restored} queued message${restored > 1 ? "s" : ""} to editor`);
595
+ }
596
+ }
597
+
598
+ /**
599
+ * Dispatch a `/skill:<name> [args]` invocation through `promptCustomMessage`
600
+ * using the supplied `streamingBehavior`. Returns true if the text was a
601
+ * recognised skill command and was dispatched. A failure to load the skill
602
+ * file is surfaced via `showError` but still returns true — the editor was
603
+ * already cleared on the success path, so falling through to plain-text
604
+ * handling at that point would double-submit. Returns false when the text
605
+ * isn't a `/skill:` prefix or the command name isn't a registered skill,
606
+ * so the caller can fall through to plain-text handling (this branch
607
+ * leaves the editor state untouched). `streamingBehavior` is only consulted
608
+ * while the agent is streaming; the idle path of `promptCustomMessage`
609
+ * ignores it.
610
+ */
611
+ async #invokeSkillCommand(text: string, streamingBehavior: "steer" | "followUp"): Promise<boolean> {
612
+ if (!text.startsWith("/skill:")) return false;
613
+ const spaceIndex = text.indexOf(" ");
614
+ const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
615
+ const args = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
616
+ const skillPath = this.ctx.skillCommands?.get(commandName);
617
+ if (!skillPath) return false;
618
+ this.ctx.editor.addToHistory(text);
619
+ this.ctx.editor.setText("");
620
+ try {
621
+ const content = await Bun.file(skillPath).text();
622
+ const body = content.replace(/^---\n[\s\S]*?\n---\n/, "").trim();
623
+ const metaLines = [`Skill: ${skillPath}`];
624
+ if (args) {
625
+ metaLines.push(`User: ${args}`);
626
+ }
627
+ const message = `${body}\n\n---\n\n${metaLines.join("\n")}`;
628
+ const skillName = commandName.slice("skill:".length);
629
+ const details: SkillPromptDetails = {
630
+ name: skillName || commandName,
631
+ path: skillPath,
632
+ args: args || undefined,
633
+ lineCount: body ? body.split("\n").length : 0,
634
+ };
635
+ // When the agent is streaming, register the compact slash-form text as
636
+ // the pending-display twin BEFORE dispatching the CustomMessage. The
637
+ // returned tag is embedded in details so AgentSession.#handleAgentEvent
638
+ // can remove the matching display entry when the agent consumes this
639
+ // message (mirrors the user-message dequeue path).
640
+ if (this.ctx.session.isStreaming) {
641
+ const tag = this.ctx.session.enqueueCustomMessageDisplay(text, streamingBehavior);
642
+ details.__pendingDisplayTag = tag;
643
+ }
644
+ await this.ctx.session.promptCustomMessage(
645
+ {
646
+ customType: SKILL_PROMPT_MESSAGE_TYPE,
647
+ content: message,
648
+ display: true,
649
+ details,
650
+ attribution: "user",
651
+ },
652
+ { streamingBehavior },
653
+ );
654
+ if (this.ctx.session.isStreaming) {
655
+ this.ctx.updatePendingMessagesDisplay();
656
+ this.ctx.ui.requestRender();
657
+ }
658
+ } catch (err) {
659
+ this.ctx.showError(`Failed to load skill: ${err instanceof Error ? err.message : String(err)}`);
660
+ }
661
+ return true;
662
+ }
663
+
664
+ /** Send editor text as a follow-up message (queued behind current stream). */
665
+ async handleFollowUp(): Promise<void> {
666
+ let text = this.ctx.editor.getText().trim();
667
+ if (!text) return;
668
+
669
+ // Compaction first: while compacting, free text gets queued via
670
+ // `queueCompactionMessage`, and `/skill:*` rides the same queue so a
671
+ // skill typed during compaction is not lost or short-circuited through
672
+ // `promptCustomMessage`. The skill text is queued verbatim; whether
673
+ // the queued entry is later re-parsed into a skill invocation is a
674
+ // separate concern owned by the compaction-resume path.
675
+ if (this.ctx.session.isCompacting) {
676
+ const images = this.ctx.pendingImages.length > 0 ? [...this.ctx.pendingImages] : undefined;
677
+ this.ctx.queueCompactionMessage(text, "followUp", images);
678
+ return;
679
+ }
680
+
681
+ const slashResult = await executeBuiltinSlashCommand(text, {
682
+ ctx: this.ctx,
683
+ });
684
+ if (slashResult === true) {
685
+ return;
686
+ }
687
+ if (typeof slashResult === "string") {
688
+ text = slashResult;
689
+ }
690
+
691
+ // Skill commands invoke through the custom-message path regardless of
692
+ // which keybinding submitted them. Enter routes them as `steer`;
693
+ // Ctrl+Enter (this handler) routes them as `followUp`.
694
+ if (await this.#invokeSkillCommand(text, "followUp")) {
695
+ return;
696
+ }
697
+
698
+ // Forward any pending clipboard-pasted images alongside the queued text;
699
+ // otherwise the follow-up would drop the image (mirrors the Enter/steer path).
700
+ const images = this.ctx.pendingImages.length > 0 ? [...this.ctx.pendingImages] : undefined;
701
+
702
+ if (this.ctx.session.isStreaming) {
703
+ this.ctx.editor.addToHistory(text);
704
+ this.ctx.editor.setText("");
705
+ this.ctx.editor.imageLinks = undefined;
706
+ this.ctx.pendingImages = [];
707
+ this.ctx.pendingImageLinks = [];
708
+ await this.ctx.withLocalSubmission(
709
+ text,
710
+ () => this.ctx.session.prompt(text, { streamingBehavior: "followUp", images }),
711
+ { imageCount: images?.length ?? 0 },
712
+ );
713
+ this.ctx.updatePendingMessagesDisplay();
714
+ this.ctx.ui.requestRender();
715
+ return;
716
+ }
717
+
718
+ // Not streaming — just submit normally
719
+ this.ctx.editor.addToHistory(text);
720
+ this.ctx.editor.setText("");
721
+ this.ctx.editor.imageLinks = undefined;
722
+ this.ctx.pendingImages = [];
723
+ this.ctx.pendingImageLinks = [];
724
+ await this.ctx.withLocalSubmission(text, () => this.ctx.session.prompt(text, { images }), {
725
+ imageCount: images?.length ?? 0,
726
+ });
727
+ }
728
+
729
+ restoreQueuedMessagesToEditor(options?: { abort?: boolean; currentText?: string }): number {
730
+ this.ctx.locallySubmittedUserSignatures.clear();
731
+ const { steering, followUp } = this.ctx.session.clearQueue();
732
+ const allQueued = [...steering, ...followUp];
733
+ if (allQueued.length === 0) {
734
+ this.ctx.updatePendingMessagesDisplay();
735
+ if (options?.abort) {
736
+ this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
737
+ }
738
+ return 0;
739
+ }
740
+ const queuedText = allQueued.join("\n\n");
741
+ const currentText = options?.currentText ?? this.ctx.editor.getText();
742
+ const combinedText = [queuedText, currentText].filter(t => t.trim()).join("\n\n");
743
+ this.ctx.editor.setText(combinedText);
744
+ this.ctx.updatePendingMessagesDisplay();
745
+ if (options?.abort) {
746
+ this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
747
+ }
748
+ return allQueued.length;
749
+ }
750
+
751
+ async #insertPendingImage(imageData: ImageContent): Promise<void> {
752
+ const imageLink = (
753
+ await materializeImageReferenceLinks(
754
+ [
755
+ {
756
+ type: "image",
757
+ data: imageData.data,
758
+ mimeType: imageData.mimeType,
759
+ },
760
+ ],
761
+ this.ctx.sessionManager.putBlob.bind(this.ctx.sessionManager),
762
+ )
763
+ )?.[0];
764
+ this.ctx.pendingImages.push({
765
+ type: "image",
766
+ data: imageData.data,
767
+ mimeType: imageData.mimeType,
768
+ });
769
+ this.ctx.pendingImageLinks.push(imageLink);
770
+ this.ctx.editor.imageLinks = this.ctx.pendingImageLinks;
771
+ const imageNum = this.ctx.pendingImages.length;
772
+ const dims = await this.#imageDimensions(imageData);
773
+ const label = dims ? `[Image #${imageNum}, ${dims.width}x${dims.height}]` : `[Image #${imageNum}]`;
774
+ this.ctx.editor.insertText(`${label} `);
775
+ this.ctx.ui.requestRender();
776
+ }
777
+
778
+ /** Probe pixel dimensions for the marker label (`[Image #N, WxH]`). Returns undefined when the
779
+ * header can't be decoded, so the caller falls back to a bare `[Image #N]`. */
780
+ async #imageDimensions(image: ImageContent): Promise<{ width: number; height: number } | undefined> {
781
+ try {
782
+ const { width, height } = await new Bun.Image(Buffer.from(image.data, "base64")).metadata();
783
+ if (width && height) return { width, height };
784
+ } catch {
785
+ // Unknown/corrupt header — fall back to a bare label.
786
+ }
787
+ return undefined;
788
+ }
789
+
790
+ async #normalizeAndInsertPastedImage(image: ImageContent, unsupportedMessage: string): Promise<boolean> {
791
+ let imageData = await ensureSupportedImageInput(image);
792
+ if (!imageData) {
793
+ this.ctx.showStatus(unsupportedMessage);
794
+ return false;
795
+ }
796
+ if (settings.get("images.autoResize")) {
797
+ try {
798
+ const resized = await resizeImage({
799
+ type: "image",
800
+ data: imageData.data,
801
+ mimeType: imageData.mimeType,
802
+ });
803
+ imageData = { type: "image", data: resized.data, mimeType: resized.mimeType };
804
+ } catch {
805
+ // Keep the normalized image when resize fails.
806
+ }
807
+ }
808
+ await this.#insertPendingImage(imageData);
809
+ return true;
810
+ }
811
+
812
+ async handleImagePathPaste(path: string): Promise<void> {
813
+ try {
814
+ const image = await loadImageInput({
815
+ path,
816
+ cwd: this.ctx.sessionManager.getCwd(),
817
+ autoResize: false,
818
+ });
819
+ if (!image) {
820
+ this.ctx.editor.pasteText(path);
821
+ this.ctx.ui.requestRender();
822
+ this.ctx.showStatus("Pasted path is not a supported image");
823
+ return;
824
+ }
825
+ await this.#normalizeAndInsertPastedImage(
826
+ { type: "image", data: image.data, mimeType: image.mimeType },
827
+ `Unsupported pasted image format: ${image.mimeType}`,
828
+ );
829
+ } catch (error) {
830
+ this.ctx.editor.pasteText(path);
831
+ this.ctx.ui.requestRender();
832
+ this.ctx.showStatus(
833
+ error instanceof ImageInputTooLargeError ? error.message : "Failed to read pasted image path",
834
+ );
835
+ }
836
+ }
837
+
838
+ async handleImagePaste(): Promise<boolean> {
839
+ try {
840
+ const image = await readImageFromClipboard();
841
+ if (!image) {
842
+ this.ctx.showStatus("No image in clipboard (use terminal paste for text)");
843
+ return false;
844
+ }
845
+ return await this.#normalizeAndInsertPastedImage(
846
+ {
847
+ type: "image",
848
+ data: image.data.toBase64(),
849
+ mimeType: image.mimeType,
850
+ },
851
+ `Unsupported clipboard image format: ${image.mimeType}`,
852
+ );
853
+ } catch {
854
+ this.ctx.showStatus("Failed to read clipboard");
855
+ return false;
856
+ }
857
+ }
858
+
859
+ async handleClipboardTextRawPaste(): Promise<void> {
860
+ try {
861
+ const text = await readTextFromClipboard();
862
+ if (text) {
863
+ this.ctx.editor.insertText(text);
864
+ this.ctx.ui.requestRender();
865
+ this.ctx.showStatus("No text in clipboard to paste raw");
866
+ }
867
+ } catch {
868
+ this.ctx.showStatus("Failed to paste raw text from clipboard");
869
+ }
870
+ }
871
+
872
+ createAutocompleteProvider(commands: SlashCommand[], basePath: string): AutocompleteProvider {
873
+ return createPromptActionAutocompleteProvider({
874
+ commands,
875
+ basePath,
876
+ keybindings: this.ctx.keybindings,
877
+ copyCurrentLine: () => this.handleCopyCurrentLine(),
878
+ copyPrompt: () => this.handleCopyPrompt(),
879
+ undo: prefix => this.ctx.editor.undoPastTransientText(prefix),
880
+ moveCursorToMessageEnd: () => this.ctx.editor.moveToMessageEnd(),
881
+ moveCursorToMessageStart: () => this.ctx.editor.moveToMessageStart(),
882
+ moveCursorToLineStart: () => this.ctx.editor.moveToLineStart(),
883
+ moveCursorToLineEnd: () => this.ctx.editor.moveToLineEnd(),
884
+ });
885
+ }
886
+
887
+ /** Copy the current editor line to the system clipboard. */
888
+ handleCopyCurrentLine(): void {
889
+ const { line } = this.ctx.editor.getCursor();
890
+ const text = this.ctx.editor.getLines()[line] || "";
891
+ if (!text) {
892
+ this.ctx.showStatus("Nothing to copy");
893
+ return;
894
+ }
895
+ try {
896
+ copyToClipboard(text);
897
+ const sanitized = sanitizeText(text);
898
+ const preview = sanitized.length > 30 ? `${sanitized.slice(0, 30)}...` : sanitized;
899
+ this.ctx.showStatus(`Copied line: ${preview}`);
900
+ } catch {
901
+ this.ctx.showWarning("Failed to copy to clipboard");
902
+ }
903
+ }
904
+
905
+ /** Copy current prompt text to system clipboard. */
906
+ handleCopyPrompt(): void {
907
+ const text = this.ctx.editor.getText();
908
+ if (!text) {
909
+ this.ctx.showStatus("Nothing to copy");
910
+ return;
911
+ }
912
+ try {
913
+ copyToClipboard(text);
914
+ const sanitized = sanitizeText(text);
915
+ const preview = sanitized.length > 30 ? `${sanitized.slice(0, 30)}...` : sanitized;
916
+ this.ctx.showStatus(`Copied: ${preview}`);
917
+ } catch {
918
+ this.ctx.showWarning("Failed to copy to clipboard");
919
+ }
920
+ }
921
+
922
+ cycleThinkingLevel(): void {
923
+ const newLevel = this.ctx.session.cycleThinkingLevel();
924
+ if (newLevel === undefined) {
925
+ this.ctx.showStatus("Current model does not support thinking");
926
+ } else {
927
+ this.ctx.statusLine.invalidate();
928
+ this.ctx.updateEditorBorderColor();
929
+ }
930
+ }
931
+
932
+ async cycleRoleModel(direction: "forward" | "backward" = "forward"): Promise<void> {
933
+ try {
934
+ const cycleOrder = settings.get("cycleOrder");
935
+ const result = await this.ctx.session.cycleRoleModels(cycleOrder, direction);
936
+ if (!result) {
937
+ this.ctx.showStatus("Only one role model available");
938
+ return;
939
+ }
940
+
941
+ this.ctx.statusLine.invalidate();
942
+ this.ctx.updateEditorBorderColor();
943
+ // The status line already reports the resolved model + thinking level, so
944
+ // the cycle status is just a status-line-style chip track (active role
945
+ // filled), matching the plan-approval model slider.
946
+ const track = renderSegmentTrack(
947
+ cycleOrder.map(role => ({ label: role, color: getRoleInfo(role, settings).color })),
948
+ cycleOrder.indexOf(result.role),
949
+ );
950
+ this.ctx.showStatus(track, { dim: false });
951
+ } catch (error) {
952
+ this.ctx.showError(error instanceof Error ? error.message : String(error));
953
+ }
954
+ }
955
+
956
+ toggleToolOutputExpansion(): void {
957
+ this.setToolsExpanded(!this.ctx.toolOutputExpanded);
958
+ }
959
+
960
+ setToolsExpanded(expanded: boolean): void {
961
+ this.ctx.toolOutputExpanded = expanded;
962
+ for (const child of this.ctx.chatContainer.children) {
963
+ if (isExpandable(child)) {
964
+ child.setExpanded(expanded);
965
+ }
966
+ }
967
+ // Toggling expansion mutates every block, but on ED3-risk terminals the
968
+ // transcript freezes a snapshot of each block once it scrolls past the live
969
+ // region (committed native scrollback is immutable there). A plain repaint
970
+ // replays those stale snapshots, so the toggle appears to do nothing above
971
+ // the live block. resetDisplay() invalidates the snapshots and forces a
972
+ // full clear + replay — the keyboard-accessible resize-reset equivalent —
973
+ // which is the only path that re-emits the whole transcript at its new
974
+ // heights.
975
+ this.ctx.ui.resetDisplay();
976
+ }
977
+
978
+ toggleThinkingBlockVisibility(): void {
979
+ this.ctx.hideThinkingBlock = !this.ctx.hideThinkingBlock;
980
+ settings.set("hideThinkingBlock", this.ctx.hideThinkingBlock);
981
+ this.ctx.session.agent.hideThinkingSummary = this.ctx.hideThinkingBlock;
982
+
983
+ // Rebuild chat from session messages
984
+ this.ctx.chatContainer.clear();
985
+ this.ctx.rebuildChatFromMessages();
986
+
987
+ // If streaming, re-add the streaming component with updated visibility and re-render
988
+ if (this.ctx.streamingComponent && this.ctx.streamingMessage) {
989
+ this.ctx.streamingComponent.setHideThinkingBlock(this.ctx.hideThinkingBlock);
990
+ this.ctx.streamingComponent.updateContent(this.ctx.streamingMessage);
991
+ this.ctx.chatContainer.addChild(this.ctx.streamingComponent);
992
+ }
993
+
994
+ this.ctx.showStatus(`Thinking blocks: ${this.ctx.hideThinkingBlock ? "hidden" : "visible"}`);
995
+ }
996
+
997
+ #getEditorTerminalPath(): string | null {
998
+ if (process.platform === "win32") {
999
+ return null;
1000
+ }
1001
+ return "/dev/tty";
1002
+ }
1003
+
1004
+ async #openEditorTerminalHandle(): Promise<fs.FileHandle | null> {
1005
+ const terminalPath = this.#getEditorTerminalPath();
1006
+ if (!terminalPath) {
1007
+ return null;
1008
+ }
1009
+ try {
1010
+ return await fs.open(terminalPath, "r+");
1011
+ } catch {
1012
+ return null;
1013
+ }
1014
+ }
1015
+
1016
+ async openExternalEditor(): Promise<void> {
1017
+ const editorCmd = getEditorCommand();
1018
+ if (!editorCmd) {
1019
+ this.ctx.showWarning("No editor configured. Set $VISUAL or $EDITOR environment variable.");
1020
+ return;
1021
+ }
1022
+
1023
+ const currentText = this.ctx.editor.getExpandedText?.() ?? this.ctx.editor.getText();
1024
+
1025
+ let ttyHandle: fs.FileHandle | null = null;
1026
+ try {
1027
+ ttyHandle = await this.#openEditorTerminalHandle();
1028
+ this.ctx.ui.stop();
1029
+
1030
+ const stdio: [number | "inherit", number | "inherit", number | "inherit"] = ttyHandle
1031
+ ? [ttyHandle.fd, ttyHandle.fd, ttyHandle.fd]
1032
+ : ["inherit", "inherit", "inherit"];
1033
+
1034
+ const result = await openInEditor(editorCmd, currentText, { extension: ".omp.md", stdio });
1035
+ if (result !== null) {
1036
+ this.ctx.editor.setText(result);
1037
+ }
1038
+ } catch (error) {
1039
+ this.ctx.showWarning(
1040
+ `Failed to open external editor: ${error instanceof Error ? error.message : String(error)}`,
1041
+ );
1042
+ } finally {
1043
+ if (ttyHandle) {
1044
+ await ttyHandle.close();
1045
+ }
1046
+
1047
+ this.ctx.ui.start();
1048
+ this.ctx.ui.requestRender();
1049
+ }
1050
+ }
1051
+
1052
+ registerExtensionShortcuts(): void {
1053
+ const runner = this.ctx.session.extensionRunner;
1054
+ if (!runner) return;
1055
+
1056
+ const shortcuts = runner.getShortcuts();
1057
+ for (const [keyId, shortcut] of shortcuts) {
1058
+ this.ctx.editor.setCustomKeyHandler(keyId, () => {
1059
+ const ctx = runner.createCommandContext();
1060
+ try {
1061
+ shortcut.handler(ctx);
1062
+ } catch (err) {
1063
+ runner.emitError({
1064
+ extensionPath: shortcut.extensionPath,
1065
+ event: "shortcut",
1066
+ error: err instanceof Error ? err.message : String(err),
1067
+ stack: err instanceof Error ? err.stack : undefined,
1068
+ });
1069
+ }
1070
+ });
1071
+ }
1072
+ }
1073
+ }