@ai-agent-forge/agent-forge 0.85.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 (1654) hide show
  1. package/CHANGELOG.md +5969 -0
  2. package/README.md +629 -0
  3. package/dist/artifacts/artifact-store.d.ts +51 -0
  4. package/dist/artifacts/artifact-store.d.ts.map +1 -0
  5. package/dist/artifacts/artifact-store.js +87 -0
  6. package/dist/artifacts/artifact-store.js.map +1 -0
  7. package/dist/artifacts/paged-read.d.ts +51 -0
  8. package/dist/artifacts/paged-read.d.ts.map +1 -0
  9. package/dist/artifacts/paged-read.js +55 -0
  10. package/dist/artifacts/paged-read.js.map +1 -0
  11. package/dist/bun/cli.d.ts +3 -0
  12. package/dist/bun/cli.d.ts.map +1 -0
  13. package/dist/bun/cli.js +11 -0
  14. package/dist/bun/cli.js.map +1 -0
  15. package/dist/bun/register-bedrock.d.ts +2 -0
  16. package/dist/bun/register-bedrock.d.ts.map +1 -0
  17. package/dist/bun/register-bedrock.js +4 -0
  18. package/dist/bun/register-bedrock.js.map +1 -0
  19. package/dist/bun/restore-sandbox-env.d.ts +17 -0
  20. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  21. package/dist/bun/restore-sandbox-env.js +36 -0
  22. package/dist/bun/restore-sandbox-env.js.map +1 -0
  23. package/dist/bundle/.build-manifest.json +3566 -0
  24. package/dist/bundle/chunks/anthropic-messages-RJYU4TCY.js +6 -0
  25. package/dist/bundle/chunks/anthropic.js +75 -0
  26. package/dist/bundle/chunks/azure-openai-responses-LESTCUL7.js +2 -0
  27. package/dist/bundle/chunks/bedrock-converse-stream.js +78 -0
  28. package/dist/bundle/chunks/chunk-3QKHSPQL.js +8 -0
  29. package/dist/bundle/chunks/chunk-4L3WN2XY.js +2 -0
  30. package/dist/bundle/chunks/chunk-4NKZMFSZ.js +1579 -0
  31. package/dist/bundle/chunks/chunk-6CYCI3EJ.js +12 -0
  32. package/dist/bundle/chunks/chunk-6R7UI4IY.js +2 -0
  33. package/dist/bundle/chunks/chunk-7ZC4UXSL.js +2 -0
  34. package/dist/bundle/chunks/chunk-7ZY7IXZD.js +4 -0
  35. package/dist/bundle/chunks/chunk-DRQDKNXA.js +2 -0
  36. package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +42 -0
  37. package/dist/bundle/chunks/chunk-EWXX34QG.js +2 -0
  38. package/dist/bundle/chunks/chunk-GMWCTUPB.js +2 -0
  39. package/dist/bundle/chunks/chunk-JUUC5AZY.js +2 -0
  40. package/dist/bundle/chunks/chunk-KQEGUM34.js +2 -0
  41. package/dist/bundle/chunks/chunk-L2ZPNLYD.js +2 -0
  42. package/dist/bundle/chunks/chunk-MDOTREMR.js +11 -0
  43. package/dist/bundle/chunks/chunk-NUHFSC37.js +25 -0
  44. package/dist/bundle/chunks/chunk-PGXDEOVV.js +2 -0
  45. package/dist/bundle/chunks/chunk-PJACZCIR.js +2 -0
  46. package/dist/bundle/chunks/chunk-PRRNXB7S.js +2 -0
  47. package/dist/bundle/chunks/chunk-SER2HCLE.js +38 -0
  48. package/dist/bundle/chunks/chunk-TEPMHNKQ.js +2 -0
  49. package/dist/bundle/chunks/chunk-V46XUTK3.js +2 -0
  50. package/dist/bundle/chunks/chunk-WGLBM2BP.js +2 -0
  51. package/dist/bundle/chunks/chunk-WW3LMV3F.js +2 -0
  52. package/dist/bundle/chunks/chunk-XDUWOHPL.js +6 -0
  53. package/dist/bundle/chunks/github-copilot.js +2 -0
  54. package/dist/bundle/chunks/google-generative-ai-NZ66X6K7.js +2 -0
  55. package/dist/bundle/chunks/google-vertex-2ZZOFBNQ.js +2 -0
  56. package/dist/bundle/chunks/https-proxy-agent-UDEHOBGS.js +13 -0
  57. package/dist/bundle/chunks/image-resize-worker.js +2 -0
  58. package/dist/bundle/chunks/kimi-coding.js +2 -0
  59. package/dist/bundle/chunks/lib-HGQMNYVT.js +9 -0
  60. package/dist/bundle/chunks/mistral-conversations-B6DZRMEK.js +5 -0
  61. package/dist/bundle/chunks/multipart-parser-SQ6GDJL7.js +3 -0
  62. package/dist/bundle/chunks/node-O3RIBJRH.js +16 -0
  63. package/dist/bundle/chunks/node-TWVVAGPO.js +2 -0
  64. package/dist/bundle/chunks/openai-codex-responses-UFH6O5K6.js +10 -0
  65. package/dist/bundle/chunks/openai-codex.js +75 -0
  66. package/dist/bundle/chunks/openai-completions-A55GHA4O.js +7 -0
  67. package/dist/bundle/chunks/openai-responses-TJLXRAXR.js +2 -0
  68. package/dist/bundle/chunks/openrouter-images-G3GT5BVT.js +2 -0
  69. package/dist/bundle/chunks/openrouter.js +75 -0
  70. package/dist/bundle/chunks/pi-messages-SLF355GF.js +8 -0
  71. package/dist/bundle/chunks/radius.js +75 -0
  72. package/dist/bundle/chunks/src-UK77SYZE.js +4 -0
  73. package/dist/bundle/chunks/xai.js +2 -0
  74. package/dist/bundle/cli.js +3 -0
  75. package/dist/bundle/client.js +2 -0
  76. package/dist/bundle/index.js +8 -0
  77. package/dist/bundle/rpc-entry.js +3 -0
  78. package/dist/capabilities/builtin.d.ts +46 -0
  79. package/dist/capabilities/builtin.d.ts.map +1 -0
  80. package/dist/capabilities/builtin.js +68 -0
  81. package/dist/capabilities/builtin.js.map +1 -0
  82. package/dist/cli/args.d.ts +102 -0
  83. package/dist/cli/args.d.ts.map +1 -0
  84. package/dist/cli/args.js +712 -0
  85. package/dist/cli/args.js.map +1 -0
  86. package/dist/cli/auth-check.d.ts +19 -0
  87. package/dist/cli/auth-check.d.ts.map +1 -0
  88. package/dist/cli/auth-check.js +50 -0
  89. package/dist/cli/auth-check.js.map +1 -0
  90. package/dist/cli/auth-command.d.ts +24 -0
  91. package/dist/cli/auth-command.d.ts.map +1 -0
  92. package/dist/cli/auth-command.js +102 -0
  93. package/dist/cli/auth-command.js.map +1 -0
  94. package/dist/cli/config-selector.d.ts +23 -0
  95. package/dist/cli/config-selector.d.ts.map +1 -0
  96. package/dist/cli/config-selector.js +51 -0
  97. package/dist/cli/config-selector.js.map +1 -0
  98. package/dist/cli/credential-print.d.ts +13 -0
  99. package/dist/cli/credential-print.d.ts.map +1 -0
  100. package/dist/cli/credential-print.js +76 -0
  101. package/dist/cli/credential-print.js.map +1 -0
  102. package/dist/cli/experimental/auth.d.ts +16 -0
  103. package/dist/cli/experimental/auth.d.ts.map +1 -0
  104. package/dist/cli/experimental/auth.js +13 -0
  105. package/dist/cli/experimental/auth.js.map +1 -0
  106. package/dist/cli/experimental/cli.d.ts +6 -0
  107. package/dist/cli/experimental/cli.d.ts.map +1 -0
  108. package/dist/cli/experimental/cli.js +5 -0
  109. package/dist/cli/experimental/cli.js.map +1 -0
  110. package/dist/cli/experimental/command-options.d.ts +17 -0
  111. package/dist/cli/experimental/command-options.d.ts.map +1 -0
  112. package/dist/cli/experimental/command-options.js +35 -0
  113. package/dist/cli/experimental/command-options.js.map +1 -0
  114. package/dist/cli/experimental/command.d.ts +63 -0
  115. package/dist/cli/experimental/command.d.ts.map +1 -0
  116. package/dist/cli/experimental/command.js +130 -0
  117. package/dist/cli/experimental/command.js.map +1 -0
  118. package/dist/cli/experimental/commands/client.d.ts +13 -0
  119. package/dist/cli/experimental/commands/client.d.ts.map +1 -0
  120. package/dist/cli/experimental/commands/client.js +25 -0
  121. package/dist/cli/experimental/commands/client.js.map +1 -0
  122. package/dist/cli/experimental/commands/pi.d.ts +15 -0
  123. package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
  124. package/dist/cli/experimental/commands/pi.js +26 -0
  125. package/dist/cli/experimental/commands/pi.js.map +1 -0
  126. package/dist/cli/experimental/commands/server.d.ts +13 -0
  127. package/dist/cli/experimental/commands/server.d.ts.map +1 -0
  128. package/dist/cli/experimental/commands/server.js +25 -0
  129. package/dist/cli/experimental/commands/server.js.map +1 -0
  130. package/dist/cli/experimental/transport-address.d.ts +10 -0
  131. package/dist/cli/experimental/transport-address.d.ts.map +1 -0
  132. package/dist/cli/experimental/transport-address.js +38 -0
  133. package/dist/cli/experimental/transport-address.js.map +1 -0
  134. package/dist/cli/file-processor.d.ts +15 -0
  135. package/dist/cli/file-processor.d.ts.map +1 -0
  136. package/dist/cli/file-processor.js +71 -0
  137. package/dist/cli/file-processor.js.map +1 -0
  138. package/dist/cli/initial-message.d.ts +18 -0
  139. package/dist/cli/initial-message.d.ts.map +1 -0
  140. package/dist/cli/initial-message.js +22 -0
  141. package/dist/cli/initial-message.js.map +1 -0
  142. package/dist/cli/list-models.d.ts +9 -0
  143. package/dist/cli/list-models.d.ts.map +1 -0
  144. package/dist/cli/list-models.js +98 -0
  145. package/dist/cli/list-models.js.map +1 -0
  146. package/dist/cli/plugin-command.d.ts +50 -0
  147. package/dist/cli/plugin-command.d.ts.map +1 -0
  148. package/dist/cli/plugin-command.js +85 -0
  149. package/dist/cli/plugin-command.js.map +1 -0
  150. package/dist/cli/plugin-manager-controller.d.ts +59 -0
  151. package/dist/cli/plugin-manager-controller.d.ts.map +1 -0
  152. package/dist/cli/plugin-manager-controller.js +183 -0
  153. package/dist/cli/plugin-manager-controller.js.map +1 -0
  154. package/dist/cli/plugin-selection-controller.d.ts +57 -0
  155. package/dist/cli/plugin-selection-controller.d.ts.map +1 -0
  156. package/dist/cli/plugin-selection-controller.js +159 -0
  157. package/dist/cli/plugin-selection-controller.js.map +1 -0
  158. package/dist/cli/serve.d.ts +39 -0
  159. package/dist/cli/serve.d.ts.map +1 -0
  160. package/dist/cli/serve.js +124 -0
  161. package/dist/cli/serve.js.map +1 -0
  162. package/dist/cli/session-picker.d.ts +30 -0
  163. package/dist/cli/session-picker.d.ts.map +1 -0
  164. package/dist/cli/session-picker.js +62 -0
  165. package/dist/cli/session-picker.js.map +1 -0
  166. package/dist/cli/startup-ui.d.ts +20 -0
  167. package/dist/cli/startup-ui.d.ts.map +1 -0
  168. package/dist/cli/startup-ui.js +185 -0
  169. package/dist/cli/startup-ui.js.map +1 -0
  170. package/dist/cli/trace-view.d.ts +86 -0
  171. package/dist/cli/trace-view.d.ts.map +1 -0
  172. package/dist/cli/trace-view.js +263 -0
  173. package/dist/cli/trace-view.js.map +1 -0
  174. package/dist/cli.d.ts +3 -0
  175. package/dist/cli.d.ts.map +1 -0
  176. package/dist/cli.js +19 -0
  177. package/dist/cli.js.map +1 -0
  178. package/dist/client/index.d.ts +3 -0
  179. package/dist/client/index.d.ts.map +1 -0
  180. package/dist/client/index.js +3 -0
  181. package/dist/client/index.js.map +1 -0
  182. package/dist/client/remote-session.d.ts +53 -0
  183. package/dist/client/remote-session.d.ts.map +1 -0
  184. package/dist/client/remote-session.js +340 -0
  185. package/dist/client/remote-session.js.map +1 -0
  186. package/dist/client/transcript.d.ts +12 -0
  187. package/dist/client/transcript.d.ts.map +1 -0
  188. package/dist/client/transcript.js +98 -0
  189. package/dist/client/transcript.js.map +1 -0
  190. package/dist/config.d.ts +95 -0
  191. package/dist/config.d.ts.map +1 -0
  192. package/dist/config.js +459 -0
  193. package/dist/config.js.map +1 -0
  194. package/dist/core/agent-capability-contract.d.ts +322 -0
  195. package/dist/core/agent-capability-contract.d.ts.map +1 -0
  196. package/dist/core/agent-capability-contract.js +1154 -0
  197. package/dist/core/agent-capability-contract.js.map +1 -0
  198. package/dist/core/agent-session-bash.d.ts +51 -0
  199. package/dist/core/agent-session-bash.d.ts.map +1 -0
  200. package/dist/core/agent-session-bash.js +138 -0
  201. package/dist/core/agent-session-bash.js.map +1 -0
  202. package/dist/core/agent-session-compaction.d.ts +188 -0
  203. package/dist/core/agent-session-compaction.d.ts.map +1 -0
  204. package/dist/core/agent-session-compaction.js +1071 -0
  205. package/dist/core/agent-session-compaction.js.map +1 -0
  206. package/dist/core/agent-session-context.d.ts +43 -0
  207. package/dist/core/agent-session-context.d.ts.map +1 -0
  208. package/dist/core/agent-session-context.js +170 -0
  209. package/dist/core/agent-session-context.js.map +1 -0
  210. package/dist/core/agent-session-extensions.d.ts +30 -0
  211. package/dist/core/agent-session-extensions.d.ts.map +1 -0
  212. package/dist/core/agent-session-extensions.js +74 -0
  213. package/dist/core/agent-session-extensions.js.map +1 -0
  214. package/dist/core/agent-session-internal.d.ts +290 -0
  215. package/dist/core/agent-session-internal.d.ts.map +1 -0
  216. package/dist/core/agent-session-internal.js +40 -0
  217. package/dist/core/agent-session-internal.js.map +1 -0
  218. package/dist/core/agent-session-lifecycle.d.ts +242 -0
  219. package/dist/core/agent-session-lifecycle.d.ts.map +1 -0
  220. package/dist/core/agent-session-lifecycle.js +699 -0
  221. package/dist/core/agent-session-lifecycle.js.map +1 -0
  222. package/dist/core/agent-session-loop-runner.d.ts +52 -0
  223. package/dist/core/agent-session-loop-runner.d.ts.map +1 -0
  224. package/dist/core/agent-session-loop-runner.js +168 -0
  225. package/dist/core/agent-session-loop-runner.js.map +1 -0
  226. package/dist/core/agent-session-loop.d.ts +39 -0
  227. package/dist/core/agent-session-loop.d.ts.map +1 -0
  228. package/dist/core/agent-session-loop.js +155 -0
  229. package/dist/core/agent-session-loop.js.map +1 -0
  230. package/dist/core/agent-session-model.d.ts +49 -0
  231. package/dist/core/agent-session-model.d.ts.map +1 -0
  232. package/dist/core/agent-session-model.js +155 -0
  233. package/dist/core/agent-session-model.js.map +1 -0
  234. package/dist/core/agent-session-paths.d.ts +3 -0
  235. package/dist/core/agent-session-paths.d.ts.map +1 -0
  236. package/dist/core/agent-session-paths.js +14 -0
  237. package/dist/core/agent-session-paths.js.map +1 -0
  238. package/dist/core/agent-session-projection.d.ts +53 -0
  239. package/dist/core/agent-session-projection.d.ts.map +1 -0
  240. package/dist/core/agent-session-projection.js +195 -0
  241. package/dist/core/agent-session-projection.js.map +1 -0
  242. package/dist/core/agent-session-retry.d.ts +28 -0
  243. package/dist/core/agent-session-retry.d.ts.map +1 -0
  244. package/dist/core/agent-session-retry.js +141 -0
  245. package/dist/core/agent-session-retry.js.map +1 -0
  246. package/dist/core/agent-session-runtime.d.ts +181 -0
  247. package/dist/core/agent-session-runtime.d.ts.map +1 -0
  248. package/dist/core/agent-session-runtime.js +297 -0
  249. package/dist/core/agent-session-runtime.js.map +1 -0
  250. package/dist/core/agent-session-services.d.ts +281 -0
  251. package/dist/core/agent-session-services.d.ts.map +1 -0
  252. package/dist/core/agent-session-services.js +680 -0
  253. package/dist/core/agent-session-services.js.map +1 -0
  254. package/dist/core/agent-session-store.d.ts +47 -0
  255. package/dist/core/agent-session-store.d.ts.map +1 -0
  256. package/dist/core/agent-session-store.js +155 -0
  257. package/dist/core/agent-session-store.js.map +1 -0
  258. package/dist/core/agent-session-tools.d.ts +36 -0
  259. package/dist/core/agent-session-tools.d.ts.map +1 -0
  260. package/dist/core/agent-session-tools.js +305 -0
  261. package/dist/core/agent-session-tools.js.map +1 -0
  262. package/dist/core/agent-session.d.ts +1156 -0
  263. package/dist/core/agent-session.d.ts.map +1 -0
  264. package/dist/core/agent-session.js +2550 -0
  265. package/dist/core/agent-session.js.map +1 -0
  266. package/dist/core/auth-guidance.d.ts +5 -0
  267. package/dist/core/auth-guidance.d.ts.map +1 -0
  268. package/dist/core/auth-guidance.js +21 -0
  269. package/dist/core/auth-guidance.js.map +1 -0
  270. package/dist/core/auth-storage.d.ts +72 -0
  271. package/dist/core/auth-storage.d.ts.map +1 -0
  272. package/dist/core/auth-storage.js +426 -0
  273. package/dist/core/auth-storage.js.map +1 -0
  274. package/dist/core/bash-executor.d.ts +32 -0
  275. package/dist/core/bash-executor.d.ts.map +1 -0
  276. package/dist/core/bash-executor.js +111 -0
  277. package/dist/core/bash-executor.js.map +1 -0
  278. package/dist/core/cache-stats.d.ts +49 -0
  279. package/dist/core/cache-stats.d.ts.map +1 -0
  280. package/dist/core/cache-stats.js +101 -0
  281. package/dist/core/cache-stats.js.map +1 -0
  282. package/dist/core/compaction/branch-summarization.d.ts +88 -0
  283. package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
  284. package/dist/core/compaction/branch-summarization.js +220 -0
  285. package/dist/core/compaction/branch-summarization.js.map +1 -0
  286. package/dist/core/compaction/compaction.d.ts +178 -0
  287. package/dist/core/compaction/compaction.d.ts.map +1 -0
  288. package/dist/core/compaction/compaction.js +608 -0
  289. package/dist/core/compaction/compaction.js.map +1 -0
  290. package/dist/core/compaction/index.d.ts +7 -0
  291. package/dist/core/compaction/index.d.ts.map +1 -0
  292. package/dist/core/compaction/index.js +7 -0
  293. package/dist/core/compaction/index.js.map +1 -0
  294. package/dist/core/compaction/utils.d.ts +49 -0
  295. package/dist/core/compaction/utils.d.ts.map +1 -0
  296. package/dist/core/compaction/utils.js +170 -0
  297. package/dist/core/compaction/utils.js.map +1 -0
  298. package/dist/core/defaults.d.ts +4 -0
  299. package/dist/core/defaults.d.ts.map +1 -0
  300. package/dist/core/defaults.js +11 -0
  301. package/dist/core/defaults.js.map +1 -0
  302. package/dist/core/diagnostics.d.ts +15 -0
  303. package/dist/core/diagnostics.d.ts.map +1 -0
  304. package/dist/core/diagnostics.js +2 -0
  305. package/dist/core/diagnostics.js.map +1 -0
  306. package/dist/core/embedded-sdk.d.ts +96 -0
  307. package/dist/core/embedded-sdk.d.ts.map +1 -0
  308. package/dist/core/embedded-sdk.js +395 -0
  309. package/dist/core/embedded-sdk.js.map +1 -0
  310. package/dist/core/event-bus.d.ts +9 -0
  311. package/dist/core/event-bus.d.ts.map +1 -0
  312. package/dist/core/event-bus.js +25 -0
  313. package/dist/core/event-bus.js.map +1 -0
  314. package/dist/core/exec.d.ts +29 -0
  315. package/dist/core/exec.d.ts.map +1 -0
  316. package/dist/core/exec.js +75 -0
  317. package/dist/core/exec.js.map +1 -0
  318. package/dist/core/experimental.d.ts +2 -0
  319. package/dist/core/experimental.d.ts.map +1 -0
  320. package/dist/core/experimental.js +6 -0
  321. package/dist/core/experimental.js.map +1 -0
  322. package/dist/core/export-html/ansi-to-html.d.ts +22 -0
  323. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  324. package/dist/core/export-html/ansi-to-html.js +249 -0
  325. package/dist/core/export-html/ansi-to-html.js.map +1 -0
  326. package/dist/core/export-html/index.d.ts +37 -0
  327. package/dist/core/export-html/index.d.ts.map +1 -0
  328. package/dist/core/export-html/index.js +226 -0
  329. package/dist/core/export-html/index.js.map +1 -0
  330. package/dist/core/export-html/template.css +1066 -0
  331. package/dist/core/export-html/template.html +55 -0
  332. package/dist/core/export-html/template.js +1864 -0
  333. package/dist/core/export-html/tool-renderer.d.ts +34 -0
  334. package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  335. package/dist/core/export-html/tool-renderer.js +108 -0
  336. package/dist/core/export-html/tool-renderer.js.map +1 -0
  337. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  338. package/dist/core/export-html/vendor/marked.min.js +78 -0
  339. package/dist/core/extensions/agent-composition.d.ts +67 -0
  340. package/dist/core/extensions/agent-composition.d.ts.map +1 -0
  341. package/dist/core/extensions/agent-composition.js +785 -0
  342. package/dist/core/extensions/agent-composition.js.map +1 -0
  343. package/dist/core/extensions/bootstrap-agent-loop.d.ts +203 -0
  344. package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -0
  345. package/dist/core/extensions/bootstrap-agent-loop.js +565 -0
  346. package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -0
  347. package/dist/core/extensions/bootstrap-branch-summary-policy.d.ts +7 -0
  348. package/dist/core/extensions/bootstrap-branch-summary-policy.d.ts.map +1 -0
  349. package/dist/core/extensions/bootstrap-branch-summary-policy.js +28 -0
  350. package/dist/core/extensions/bootstrap-branch-summary-policy.js.map +1 -0
  351. package/dist/core/extensions/bootstrap-compaction-policy.d.ts +7 -0
  352. package/dist/core/extensions/bootstrap-compaction-policy.d.ts.map +1 -0
  353. package/dist/core/extensions/bootstrap-compaction-policy.js +81 -0
  354. package/dist/core/extensions/bootstrap-compaction-policy.js.map +1 -0
  355. package/dist/core/extensions/bootstrap-lifecycle.d.ts +26 -0
  356. package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -0
  357. package/dist/core/extensions/bootstrap-lifecycle.js +181 -0
  358. package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -0
  359. package/dist/core/extensions/bootstrap-overflow-policy.d.ts +7 -0
  360. package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -0
  361. package/dist/core/extensions/bootstrap-overflow-policy.js +29 -0
  362. package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -0
  363. package/dist/core/extensions/bootstrap-retry-policy.d.ts +7 -0
  364. package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -0
  365. package/dist/core/extensions/bootstrap-retry-policy.js +28 -0
  366. package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -0
  367. package/dist/core/extensions/bootstrap-skills.d.ts +16 -0
  368. package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -0
  369. package/dist/core/extensions/bootstrap-skills.js +119 -0
  370. package/dist/core/extensions/bootstrap-skills.js.map +1 -0
  371. package/dist/core/extensions/bootstrap-tools.d.ts +20 -0
  372. package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -0
  373. package/dist/core/extensions/bootstrap-tools.js +35 -0
  374. package/dist/core/extensions/bootstrap-tools.js.map +1 -0
  375. package/dist/core/extensions/capability-exports.d.ts +5 -0
  376. package/dist/core/extensions/capability-exports.d.ts.map +1 -0
  377. package/dist/core/extensions/capability-exports.js +4 -0
  378. package/dist/core/extensions/capability-exports.js.map +1 -0
  379. package/dist/core/extensions/capability-plugin.d.ts +69 -0
  380. package/dist/core/extensions/capability-plugin.d.ts.map +1 -0
  381. package/dist/core/extensions/capability-plugin.js +485 -0
  382. package/dist/core/extensions/capability-plugin.js.map +1 -0
  383. package/dist/core/extensions/capability-runtime-events.d.ts +22 -0
  384. package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -0
  385. package/dist/core/extensions/capability-runtime-events.js +381 -0
  386. package/dist/core/extensions/capability-runtime-events.js.map +1 -0
  387. package/dist/core/extensions/capability-runtime-guards.d.ts +93 -0
  388. package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -0
  389. package/dist/core/extensions/capability-runtime-guards.js +800 -0
  390. package/dist/core/extensions/capability-runtime-guards.js.map +1 -0
  391. package/dist/core/extensions/capability-runtime-inspect.d.ts +12 -0
  392. package/dist/core/extensions/capability-runtime-inspect.d.ts.map +1 -0
  393. package/dist/core/extensions/capability-runtime-inspect.js +106 -0
  394. package/dist/core/extensions/capability-runtime-inspect.js.map +1 -0
  395. package/dist/core/extensions/capability-runtime-manifest.d.ts +19 -0
  396. package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -0
  397. package/dist/core/extensions/capability-runtime-manifest.js +218 -0
  398. package/dist/core/extensions/capability-runtime-manifest.js.map +1 -0
  399. package/dist/core/extensions/capability-runtime-operation.d.ts +26 -0
  400. package/dist/core/extensions/capability-runtime-operation.d.ts.map +1 -0
  401. package/dist/core/extensions/capability-runtime-operation.js +88 -0
  402. package/dist/core/extensions/capability-runtime-operation.js.map +1 -0
  403. package/dist/core/extensions/capability-runtime-snapshot.d.ts +11 -0
  404. package/dist/core/extensions/capability-runtime-snapshot.d.ts.map +1 -0
  405. package/dist/core/extensions/capability-runtime-snapshot.js +81 -0
  406. package/dist/core/extensions/capability-runtime-snapshot.js.map +1 -0
  407. package/dist/core/extensions/capability-runtime-store.d.ts +34 -0
  408. package/dist/core/extensions/capability-runtime-store.d.ts.map +1 -0
  409. package/dist/core/extensions/capability-runtime-store.js +153 -0
  410. package/dist/core/extensions/capability-runtime-store.js.map +1 -0
  411. package/dist/core/extensions/capability-runtime-tool.d.ts +10 -0
  412. package/dist/core/extensions/capability-runtime-tool.d.ts.map +1 -0
  413. package/dist/core/extensions/capability-runtime-tool.js +10 -0
  414. package/dist/core/extensions/capability-runtime-tool.js.map +1 -0
  415. package/dist/core/extensions/capability-runtime-types.d.ts +303 -0
  416. package/dist/core/extensions/capability-runtime-types.d.ts.map +1 -0
  417. package/dist/core/extensions/capability-runtime-types.js +2 -0
  418. package/dist/core/extensions/capability-runtime-types.js.map +1 -0
  419. package/dist/core/extensions/capability-runtime-validation.d.ts +35 -0
  420. package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -0
  421. package/dist/core/extensions/capability-runtime-validation.js +380 -0
  422. package/dist/core/extensions/capability-runtime-validation.js.map +1 -0
  423. package/dist/core/extensions/capability-runtime.d.ts +7 -0
  424. package/dist/core/extensions/capability-runtime.d.ts.map +1 -0
  425. package/dist/core/extensions/capability-runtime.js +2170 -0
  426. package/dist/core/extensions/capability-runtime.js.map +1 -0
  427. package/dist/core/extensions/compaction-memory-failure-mode.d.ts +43 -0
  428. package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -0
  429. package/dist/core/extensions/compaction-memory-failure-mode.js +31 -0
  430. package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -0
  431. package/dist/core/extensions/context-strategy-binding.d.ts +12 -0
  432. package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -0
  433. package/dist/core/extensions/context-strategy-binding.js +54 -0
  434. package/dist/core/extensions/context-strategy-binding.js.map +1 -0
  435. package/dist/core/extensions/index.d.ts +19 -0
  436. package/dist/core/extensions/index.d.ts.map +1 -0
  437. package/dist/core/extensions/index.js +18 -0
  438. package/dist/core/extensions/index.js.map +1 -0
  439. package/dist/core/extensions/lifecycle-catalog.d.ts +584 -0
  440. package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -0
  441. package/dist/core/extensions/lifecycle-catalog.js +1903 -0
  442. package/dist/core/extensions/lifecycle-catalog.js.map +1 -0
  443. package/dist/core/extensions/lifecycle-delivery-queue.d.ts +48 -0
  444. package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -0
  445. package/dist/core/extensions/lifecycle-delivery-queue.js +164 -0
  446. package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -0
  447. package/dist/core/extensions/microcompact.d.ts +71 -0
  448. package/dist/core/extensions/microcompact.d.ts.map +1 -0
  449. package/dist/core/extensions/microcompact.js +123 -0
  450. package/dist/core/extensions/microcompact.js.map +1 -0
  451. package/dist/core/extensions/public-api.d.ts +10 -0
  452. package/dist/core/extensions/public-api.d.ts.map +1 -0
  453. package/dist/core/extensions/public-api.js +9 -0
  454. package/dist/core/extensions/public-api.js.map +1 -0
  455. package/dist/core/facade/coding-agent-facade.d.ts +338 -0
  456. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -0
  457. package/dist/core/facade/coding-agent-facade.js +115 -0
  458. package/dist/core/facade/coding-agent-facade.js.map +1 -0
  459. package/dist/core/facade/coding-agent-runtime-facade.d.ts +115 -0
  460. package/dist/core/facade/coding-agent-runtime-facade.d.ts.map +1 -0
  461. package/dist/core/facade/coding-agent-runtime-facade.js +63 -0
  462. package/dist/core/facade/coding-agent-runtime-facade.js.map +1 -0
  463. package/dist/core/facade/index.d.ts +6 -0
  464. package/dist/core/facade/index.d.ts.map +1 -0
  465. package/dist/core/facade/index.js +3 -0
  466. package/dist/core/facade/index.js.map +1 -0
  467. package/dist/core/footer-data-provider.d.ts +57 -0
  468. package/dist/core/footer-data-provider.d.ts.map +1 -0
  469. package/dist/core/footer-data-provider.js +323 -0
  470. package/dist/core/footer-data-provider.js.map +1 -0
  471. package/dist/core/http-dispatcher.d.ts +22 -0
  472. package/dist/core/http-dispatcher.d.ts.map +1 -0
  473. package/dist/core/http-dispatcher.js +98 -0
  474. package/dist/core/http-dispatcher.js.map +1 -0
  475. package/dist/core/index.d.ts +19 -0
  476. package/dist/core/index.d.ts.map +1 -0
  477. package/dist/core/index.js +13 -0
  478. package/dist/core/index.js.map +1 -0
  479. package/dist/core/input-source.d.ts +9 -0
  480. package/dist/core/input-source.d.ts.map +1 -0
  481. package/dist/core/input-source.js +2 -0
  482. package/dist/core/input-source.js.map +1 -0
  483. package/dist/core/keybindings.d.ts +442 -0
  484. package/dist/core/keybindings.d.ts.map +1 -0
  485. package/dist/core/keybindings.js +329 -0
  486. package/dist/core/keybindings.js.map +1 -0
  487. package/dist/core/logger.d.ts +107 -0
  488. package/dist/core/logger.d.ts.map +1 -0
  489. package/dist/core/logger.js +246 -0
  490. package/dist/core/logger.js.map +1 -0
  491. package/dist/core/messages.d.ts +85 -0
  492. package/dist/core/messages.d.ts.map +1 -0
  493. package/dist/core/messages.js +146 -0
  494. package/dist/core/messages.js.map +1 -0
  495. package/dist/core/model-config.d.ts +586 -0
  496. package/dist/core/model-config.d.ts.map +1 -0
  497. package/dist/core/model-config.js +258 -0
  498. package/dist/core/model-config.js.map +1 -0
  499. package/dist/core/model-registry.d.ts +49 -0
  500. package/dist/core/model-registry.d.ts.map +1 -0
  501. package/dist/core/model-registry.js +115 -0
  502. package/dist/core/model-registry.js.map +1 -0
  503. package/dist/core/model-resolver.d.ts +124 -0
  504. package/dist/core/model-resolver.d.ts.map +1 -0
  505. package/dist/core/model-resolver.js +590 -0
  506. package/dist/core/model-resolver.js.map +1 -0
  507. package/dist/core/model-runtime.d.ts +100 -0
  508. package/dist/core/model-runtime.d.ts.map +1 -0
  509. package/dist/core/model-runtime.js +598 -0
  510. package/dist/core/model-runtime.js.map +1 -0
  511. package/dist/core/models-store.d.ts +22 -0
  512. package/dist/core/models-store.d.ts.map +1 -0
  513. package/dist/core/models-store.js +115 -0
  514. package/dist/core/models-store.js.map +1 -0
  515. package/dist/core/output-guard.d.ts +7 -0
  516. package/dist/core/output-guard.d.ts.map +1 -0
  517. package/dist/core/output-guard.js +90 -0
  518. package/dist/core/output-guard.js.map +1 -0
  519. package/dist/core/package-install-host.d.ts +23 -0
  520. package/dist/core/package-install-host.d.ts.map +1 -0
  521. package/dist/core/package-install-host.js +202 -0
  522. package/dist/core/package-install-host.js.map +1 -0
  523. package/dist/core/package-manager.d.ts +93 -0
  524. package/dist/core/package-manager.d.ts.map +1 -0
  525. package/dist/core/package-manager.js +947 -0
  526. package/dist/core/package-manager.js.map +1 -0
  527. package/dist/core/package-process-runner.d.ts +4 -0
  528. package/dist/core/package-process-runner.d.ts.map +1 -0
  529. package/dist/core/package-process-runner.js +47 -0
  530. package/dist/core/package-process-runner.js.map +1 -0
  531. package/dist/core/package-resource-collection.d.ts +16 -0
  532. package/dist/core/package-resource-collection.d.ts.map +1 -0
  533. package/dist/core/package-resource-collection.js +300 -0
  534. package/dist/core/package-resource-collection.js.map +1 -0
  535. package/dist/core/package-resource-discovery.d.ts +33 -0
  536. package/dist/core/package-resource-discovery.d.ts.map +1 -0
  537. package/dist/core/package-resource-discovery.js +449 -0
  538. package/dist/core/package-resource-discovery.js.map +1 -0
  539. package/dist/core/package-source.d.ts +157 -0
  540. package/dist/core/package-source.d.ts.map +1 -0
  541. package/dist/core/package-source.js +179 -0
  542. package/dist/core/package-source.js.map +1 -0
  543. package/dist/core/pi-manifest.d.ts +7 -0
  544. package/dist/core/pi-manifest.d.ts.map +1 -0
  545. package/dist/core/pi-manifest.js +26 -0
  546. package/dist/core/pi-manifest.js.map +1 -0
  547. package/dist/core/prompt-templates.d.ts +54 -0
  548. package/dist/core/prompt-templates.d.ts.map +1 -0
  549. package/dist/core/prompt-templates.js +236 -0
  550. package/dist/core/prompt-templates.js.map +1 -0
  551. package/dist/core/provider-composer.d.ts +58 -0
  552. package/dist/core/provider-composer.d.ts.map +1 -0
  553. package/dist/core/provider-composer.js +403 -0
  554. package/dist/core/provider-composer.js.map +1 -0
  555. package/dist/core/radius.d.ts +2 -0
  556. package/dist/core/radius.d.ts.map +1 -0
  557. package/dist/core/radius.js +2 -0
  558. package/dist/core/radius.js.map +1 -0
  559. package/dist/core/remote-catalog-provider.d.ts +5 -0
  560. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  561. package/dist/core/remote-catalog-provider.js +121 -0
  562. package/dist/core/remote-catalog-provider.js.map +1 -0
  563. package/dist/core/resolve-config-value.d.ts +30 -0
  564. package/dist/core/resolve-config-value.d.ts.map +1 -0
  565. package/dist/core/resolve-config-value.js +247 -0
  566. package/dist/core/resolve-config-value.js.map +1 -0
  567. package/dist/core/resource-loader.d.ts +211 -0
  568. package/dist/core/resource-loader.d.ts.map +1 -0
  569. package/dist/core/resource-loader.js +687 -0
  570. package/dist/core/resource-loader.js.map +1 -0
  571. package/dist/core/runtime-credentials.d.ts +15 -0
  572. package/dist/core/runtime-credentials.d.ts.map +1 -0
  573. package/dist/core/runtime-credentials.js +39 -0
  574. package/dist/core/runtime-credentials.js.map +1 -0
  575. package/dist/core/sdk.d.ts +395 -0
  576. package/dist/core/sdk.d.ts.map +1 -0
  577. package/dist/core/sdk.js +1112 -0
  578. package/dist/core/sdk.js.map +1 -0
  579. package/dist/core/session-cwd.d.ts +19 -0
  580. package/dist/core/session-cwd.d.ts.map +1 -0
  581. package/dist/core/session-cwd.js +38 -0
  582. package/dist/core/session-cwd.js.map +1 -0
  583. package/dist/core/session-export.d.ts +7 -0
  584. package/dist/core/session-export.d.ts.map +1 -0
  585. package/dist/core/session-export.js +48 -0
  586. package/dist/core/session-export.js.map +1 -0
  587. package/dist/core/session-manager.d.ts +463 -0
  588. package/dist/core/session-manager.d.ts.map +1 -0
  589. package/dist/core/session-manager.js +1583 -0
  590. package/dist/core/session-manager.js.map +1 -0
  591. package/dist/core/session-start.d.ts +12 -0
  592. package/dist/core/session-start.d.ts.map +1 -0
  593. package/dist/core/session-start.js +2 -0
  594. package/dist/core/session-start.js.map +1 -0
  595. package/dist/core/session-storage.d.ts +130 -0
  596. package/dist/core/session-storage.d.ts.map +1 -0
  597. package/dist/core/session-storage.js +386 -0
  598. package/dist/core/session-storage.js.map +1 -0
  599. package/dist/core/settings-diagnostics.d.ts +9 -0
  600. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  601. package/dist/core/settings-diagnostics.js +21 -0
  602. package/dist/core/settings-diagnostics.js.map +1 -0
  603. package/dist/core/settings-manager.d.ts +352 -0
  604. package/dist/core/settings-manager.d.ts.map +1 -0
  605. package/dist/core/settings-manager.js +987 -0
  606. package/dist/core/settings-manager.js.map +1 -0
  607. package/dist/core/skills.d.ts +60 -0
  608. package/dist/core/skills.d.ts.map +1 -0
  609. package/dist/core/skills.js +382 -0
  610. package/dist/core/skills.js.map +1 -0
  611. package/dist/core/slash-commands.d.ts +15 -0
  612. package/dist/core/slash-commands.d.ts.map +1 -0
  613. package/dist/core/slash-commands.js +33 -0
  614. package/dist/core/slash-commands.js.map +1 -0
  615. package/dist/core/source-info.d.ts +18 -0
  616. package/dist/core/source-info.d.ts.map +1 -0
  617. package/dist/core/source-info.js +19 -0
  618. package/dist/core/source-info.js.map +1 -0
  619. package/dist/core/system-prompt.d.ts +8 -0
  620. package/dist/core/system-prompt.d.ts.map +1 -0
  621. package/dist/core/system-prompt.js +137 -0
  622. package/dist/core/system-prompt.js.map +1 -0
  623. package/dist/core/timings.d.ts +11 -0
  624. package/dist/core/timings.d.ts.map +1 -0
  625. package/dist/core/timings.js +46 -0
  626. package/dist/core/timings.js.map +1 -0
  627. package/dist/core/tools/bash.d.ts +87 -0
  628. package/dist/core/tools/bash.d.ts.map +1 -0
  629. package/dist/core/tools/bash.js +409 -0
  630. package/dist/core/tools/bash.js.map +1 -0
  631. package/dist/core/tools/edit-diff.d.ts +110 -0
  632. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  633. package/dist/core/tools/edit-diff.js +425 -0
  634. package/dist/core/tools/edit-diff.js.map +1 -0
  635. package/dist/core/tools/edit.d.ts +55 -0
  636. package/dist/core/tools/edit.d.ts.map +1 -0
  637. package/dist/core/tools/edit.js +305 -0
  638. package/dist/core/tools/edit.js.map +1 -0
  639. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  640. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  641. package/dist/core/tools/file-mutation-queue.js +52 -0
  642. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  643. package/dist/core/tools/find.d.ts +42 -0
  644. package/dist/core/tools/find.d.ts.map +1 -0
  645. package/dist/core/tools/find.js +303 -0
  646. package/dist/core/tools/find.js.map +1 -0
  647. package/dist/core/tools/grep.d.ts +41 -0
  648. package/dist/core/tools/grep.d.ts.map +1 -0
  649. package/dist/core/tools/grep.js +309 -0
  650. package/dist/core/tools/grep.js.map +1 -0
  651. package/dist/core/tools/index.d.ts +44 -0
  652. package/dist/core/tools/index.d.ts.map +1 -0
  653. package/dist/core/tools/index.js +129 -0
  654. package/dist/core/tools/index.js.map +1 -0
  655. package/dist/core/tools/ls.d.ts +41 -0
  656. package/dist/core/tools/ls.d.ts.map +1 -0
  657. package/dist/core/tools/ls.js +173 -0
  658. package/dist/core/tools/ls.js.map +1 -0
  659. package/dist/core/tools/output-accumulator.d.ts +52 -0
  660. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  661. package/dist/core/tools/output-accumulator.js +184 -0
  662. package/dist/core/tools/output-accumulator.js.map +1 -0
  663. package/dist/core/tools/path-utils.d.ts +10 -0
  664. package/dist/core/tools/path-utils.d.ts.map +1 -0
  665. package/dist/core/tools/path-utils.js +99 -0
  666. package/dist/core/tools/path-utils.js.map +1 -0
  667. package/dist/core/tools/powershell.d.ts +16 -0
  668. package/dist/core/tools/powershell.d.ts.map +1 -0
  669. package/dist/core/tools/powershell.js +39 -0
  670. package/dist/core/tools/powershell.js.map +1 -0
  671. package/dist/core/tools/read.d.ts +39 -0
  672. package/dist/core/tools/read.d.ts.map +1 -0
  673. package/dist/core/tools/read.js +282 -0
  674. package/dist/core/tools/read.js.map +1 -0
  675. package/dist/core/tools/render-utils.d.ts +24 -0
  676. package/dist/core/tools/render-utils.d.ts.map +1 -0
  677. package/dist/core/tools/render-utils.js +65 -0
  678. package/dist/core/tools/render-utils.js.map +1 -0
  679. package/dist/core/tools/tool-definition-wrapper.d.ts +15 -0
  680. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  681. package/dist/core/tools/tool-definition-wrapper.js +36 -0
  682. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  683. package/dist/core/tools/tool-definition.d.ts +123 -0
  684. package/dist/core/tools/tool-definition.d.ts.map +1 -0
  685. package/dist/core/tools/tool-definition.js +20 -0
  686. package/dist/core/tools/tool-definition.js.map +1 -0
  687. package/dist/core/tools/tool-search.d.ts +30 -0
  688. package/dist/core/tools/tool-search.d.ts.map +1 -0
  689. package/dist/core/tools/tool-search.js +99 -0
  690. package/dist/core/tools/tool-search.js.map +1 -0
  691. package/dist/core/tools/truncate.d.ts +70 -0
  692. package/dist/core/tools/truncate.d.ts.map +1 -0
  693. package/dist/core/tools/truncate.js +215 -0
  694. package/dist/core/tools/truncate.js.map +1 -0
  695. package/dist/core/tools/write.d.ts +30 -0
  696. package/dist/core/tools/write.d.ts.map +1 -0
  697. package/dist/core/tools/write.js +202 -0
  698. package/dist/core/tools/write.js.map +1 -0
  699. package/dist/core/trace-retention.d.ts +19 -0
  700. package/dist/core/trace-retention.d.ts.map +1 -0
  701. package/dist/core/trace-retention.js +91 -0
  702. package/dist/core/trace-retention.js.map +1 -0
  703. package/dist/core/usage-totals.d.ts +21 -0
  704. package/dist/core/usage-totals.d.ts.map +1 -0
  705. package/dist/core/usage-totals.js +53 -0
  706. package/dist/core/usage-totals.js.map +1 -0
  707. package/dist/durable/durable-service.d.ts +136 -0
  708. package/dist/durable/durable-service.d.ts.map +1 -0
  709. package/dist/durable/durable-service.js +710 -0
  710. package/dist/durable/durable-service.js.map +1 -0
  711. package/dist/e2e/stdio-launcher.d.ts +25 -0
  712. package/dist/e2e/stdio-launcher.d.ts.map +1 -0
  713. package/dist/e2e/stdio-launcher.js +244 -0
  714. package/dist/e2e/stdio-launcher.js.map +1 -0
  715. package/dist/host/agent-retry-scheduler.d.ts +65 -0
  716. package/dist/host/agent-retry-scheduler.d.ts.map +1 -0
  717. package/dist/host/agent-retry-scheduler.js +52 -0
  718. package/dist/host/agent-retry-scheduler.js.map +1 -0
  719. package/dist/host/auto-compaction.d.ts +56 -0
  720. package/dist/host/auto-compaction.d.ts.map +1 -0
  721. package/dist/host/auto-compaction.js +62 -0
  722. package/dist/host/auto-compaction.js.map +1 -0
  723. package/dist/host/branch-reload.d.ts +56 -0
  724. package/dist/host/branch-reload.d.ts.map +1 -0
  725. package/dist/host/branch-reload.js +39 -0
  726. package/dist/host/branch-reload.js.map +1 -0
  727. package/dist/host/channel-adapter.d.ts +25 -0
  728. package/dist/host/channel-adapter.d.ts.map +1 -0
  729. package/dist/host/channel-adapter.js +45 -0
  730. package/dist/host/channel-adapter.js.map +1 -0
  731. package/dist/host/checkpoint-commit.d.ts +74 -0
  732. package/dist/host/checkpoint-commit.d.ts.map +1 -0
  733. package/dist/host/checkpoint-commit.js +76 -0
  734. package/dist/host/checkpoint-commit.js.map +1 -0
  735. package/dist/host/manual-compaction.d.ts +43 -0
  736. package/dist/host/manual-compaction.d.ts.map +1 -0
  737. package/dist/host/manual-compaction.js +63 -0
  738. package/dist/host/manual-compaction.js.map +1 -0
  739. package/dist/host/output-projection.d.ts +61 -0
  740. package/dist/host/output-projection.d.ts.map +1 -0
  741. package/dist/host/output-projection.js +74 -0
  742. package/dist/host/output-projection.js.map +1 -0
  743. package/dist/host/output-reducer.d.ts +43 -0
  744. package/dist/host/output-reducer.d.ts.map +1 -0
  745. package/dist/host/output-reducer.js +77 -0
  746. package/dist/host/output-reducer.js.map +1 -0
  747. package/dist/host/output-serializer.d.ts +31 -0
  748. package/dist/host/output-serializer.d.ts.map +1 -0
  749. package/dist/host/output-serializer.js +120 -0
  750. package/dist/host/output-serializer.js.map +1 -0
  751. package/dist/host/overflow-recovery.d.ts +55 -0
  752. package/dist/host/overflow-recovery.d.ts.map +1 -0
  753. package/dist/host/overflow-recovery.js +89 -0
  754. package/dist/host/overflow-recovery.js.map +1 -0
  755. package/dist/host/retry-common.d.ts +29 -0
  756. package/dist/host/retry-common.d.ts.map +1 -0
  757. package/dist/host/retry-common.js +12 -0
  758. package/dist/host/retry-common.js.map +1 -0
  759. package/dist/host/session-event-translation.d.ts +26 -0
  760. package/dist/host/session-event-translation.d.ts.map +1 -0
  761. package/dist/host/session-event-translation.js +61 -0
  762. package/dist/host/session-event-translation.js.map +1 -0
  763. package/dist/host/summary-retry.d.ts +54 -0
  764. package/dist/host/summary-retry.d.ts.map +1 -0
  765. package/dist/host/summary-retry.js +66 -0
  766. package/dist/host/summary-retry.js.map +1 -0
  767. package/dist/index.d.ts +105 -0
  768. package/dist/index.d.ts.map +1 -0
  769. package/dist/index.js +176 -0
  770. package/dist/index.js.map +1 -0
  771. package/dist/main.d.ts +36 -0
  772. package/dist/main.d.ts.map +1 -0
  773. package/dist/main.js +1630 -0
  774. package/dist/main.js.map +1 -0
  775. package/dist/migration/migration-tool.d.ts +56 -0
  776. package/dist/migration/migration-tool.d.ts.map +1 -0
  777. package/dist/migration/migration-tool.js +72 -0
  778. package/dist/migration/migration-tool.js.map +1 -0
  779. package/dist/migrations.d.ts +33 -0
  780. package/dist/migrations.d.ts.map +1 -0
  781. package/dist/migrations.js +272 -0
  782. package/dist/migrations.js.map +1 -0
  783. package/dist/modes/index.d.ts +10 -0
  784. package/dist/modes/index.d.ts.map +1 -0
  785. package/dist/modes/index.js +8 -0
  786. package/dist/modes/index.js.map +1 -0
  787. package/dist/modes/interactive/assets/clankolas.png +0 -0
  788. package/dist/modes/interactive/components/armin.d.ts +34 -0
  789. package/dist/modes/interactive/components/armin.d.ts.map +1 -0
  790. package/dist/modes/interactive/components/armin.js +336 -0
  791. package/dist/modes/interactive/components/armin.js.map +1 -0
  792. package/dist/modes/interactive/components/assistant-message.d.ts +25 -0
  793. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  794. package/dist/modes/interactive/components/assistant-message.js +151 -0
  795. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  796. package/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  797. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  798. package/dist/modes/interactive/components/bash-execution.js +176 -0
  799. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  800. package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  801. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
  802. package/dist/modes/interactive/components/bordered-loader.js +56 -0
  803. package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
  804. package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  805. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
  806. package/dist/modes/interactive/components/branch-summary-message.js +44 -0
  807. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
  808. package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  809. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
  810. package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
  811. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
  812. package/dist/modes/interactive/components/config-selector.d.ts +113 -0
  813. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  814. package/dist/modes/interactive/components/config-selector.js +857 -0
  815. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  816. package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  817. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
  818. package/dist/modes/interactive/components/countdown-timer.js +33 -0
  819. package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
  820. package/dist/modes/interactive/components/custom-editor.d.ts +19 -0
  821. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
  822. package/dist/modes/interactive/components/custom-editor.js +71 -0
  823. package/dist/modes/interactive/components/custom-editor.js.map +1 -0
  824. package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  825. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
  826. package/dist/modes/interactive/components/custom-entry.js +52 -0
  827. package/dist/modes/interactive/components/custom-entry.js.map +1 -0
  828. package/dist/modes/interactive/components/custom-message.d.ts +22 -0
  829. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  830. package/dist/modes/interactive/components/custom-message.js +87 -0
  831. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  832. package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  833. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
  834. package/dist/modes/interactive/components/daxnuts.js +141 -0
  835. package/dist/modes/interactive/components/daxnuts.js.map +1 -0
  836. package/dist/modes/interactive/components/dialog-editor.d.ts +21 -0
  837. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -0
  838. package/dist/modes/interactive/components/dialog-editor.js +98 -0
  839. package/dist/modes/interactive/components/dialog-editor.js.map +1 -0
  840. package/dist/modes/interactive/components/dialog-input.d.ts +23 -0
  841. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -0
  842. package/dist/modes/interactive/components/dialog-input.js +61 -0
  843. package/dist/modes/interactive/components/dialog-input.js.map +1 -0
  844. package/dist/modes/interactive/components/dialog-selector.d.ts +26 -0
  845. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -0
  846. package/dist/modes/interactive/components/dialog-selector.js +83 -0
  847. package/dist/modes/interactive/components/dialog-selector.js.map +1 -0
  848. package/dist/modes/interactive/components/diff.d.ts +12 -0
  849. package/dist/modes/interactive/components/diff.d.ts.map +1 -0
  850. package/dist/modes/interactive/components/diff.js +133 -0
  851. package/dist/modes/interactive/components/diff.js.map +1 -0
  852. package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  853. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
  854. package/dist/modes/interactive/components/dynamic-border.js +21 -0
  855. package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
  856. package/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  857. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -0
  858. package/dist/modes/interactive/components/first-time-setup.js +103 -0
  859. package/dist/modes/interactive/components/first-time-setup.js.map +1 -0
  860. package/dist/modes/interactive/components/footer.d.ts +33 -0
  861. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  862. package/dist/modes/interactive/components/footer.js +248 -0
  863. package/dist/modes/interactive/components/footer.js.map +1 -0
  864. package/dist/modes/interactive/components/index.d.ts +34 -0
  865. package/dist/modes/interactive/components/index.d.ts.map +1 -0
  866. package/dist/modes/interactive/components/index.js +35 -0
  867. package/dist/modes/interactive/components/index.js.map +1 -0
  868. package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  869. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
  870. package/dist/modes/interactive/components/keybinding-hints.js +36 -0
  871. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
  872. package/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  873. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
  874. package/dist/modes/interactive/components/login-dialog.js +188 -0
  875. package/dist/modes/interactive/components/login-dialog.js.map +1 -0
  876. package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
  877. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
  878. package/dist/modes/interactive/components/markdown-transform.js +19 -0
  879. package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
  880. package/dist/modes/interactive/components/mermaid.d.ts +11 -0
  881. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  882. package/dist/modes/interactive/components/mermaid.js +75 -0
  883. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  884. package/dist/modes/interactive/components/model-selector.d.ts +67 -0
  885. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
  886. package/dist/modes/interactive/components/model-selector.js +381 -0
  887. package/dist/modes/interactive/components/model-selector.js.map +1 -0
  888. package/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  889. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
  890. package/dist/modes/interactive/components/oauth-selector.js +165 -0
  891. package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
  892. package/dist/modes/interactive/components/plugin-manager-entry.d.ts +62 -0
  893. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -0
  894. package/dist/modes/interactive/components/plugin-manager-entry.js +294 -0
  895. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -0
  896. package/dist/modes/interactive/components/plugin-selection-entry.d.ts +82 -0
  897. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -0
  898. package/dist/modes/interactive/components/plugin-selection-entry.js +228 -0
  899. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -0
  900. package/dist/modes/interactive/components/render-types.d.ts +26 -0
  901. package/dist/modes/interactive/components/render-types.d.ts.map +1 -0
  902. package/dist/modes/interactive/components/render-types.js +7 -0
  903. package/dist/modes/interactive/components/render-types.js.map +1 -0
  904. package/dist/modes/interactive/components/scoped-models-selector.d.ts +46 -0
  905. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
  906. package/dist/modes/interactive/components/scoped-models-selector.js +328 -0
  907. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
  908. package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  909. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
  910. package/dist/modes/interactive/components/session-selector-search.js +158 -0
  911. package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
  912. package/dist/modes/interactive/components/session-selector.d.ts +143 -0
  913. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
  914. package/dist/modes/interactive/components/session-selector.js +1053 -0
  915. package/dist/modes/interactive/components/session-selector.js.map +1 -0
  916. package/dist/modes/interactive/components/settings-selector.d.ts +88 -0
  917. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
  918. package/dist/modes/interactive/components/settings-selector.js +677 -0
  919. package/dist/modes/interactive/components/settings-selector.js.map +1 -0
  920. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  921. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  922. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  923. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  924. package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  925. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
  926. package/dist/modes/interactive/components/show-images-selector.js +39 -0
  927. package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
  928. package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  929. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  930. package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
  931. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  932. package/dist/modes/interactive/components/status-indicator.d.ts +34 -0
  933. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
  934. package/dist/modes/interactive/components/status-indicator.js +60 -0
  935. package/dist/modes/interactive/components/status-indicator.js.map +1 -0
  936. package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  937. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
  938. package/dist/modes/interactive/components/theme-selector.js +50 -0
  939. package/dist/modes/interactive/components/theme-selector.js.map +1 -0
  940. package/dist/modes/interactive/components/thinking-selector.d.ts +23 -0
  941. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
  942. package/dist/modes/interactive/components/thinking-selector.js +109 -0
  943. package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
  944. package/dist/modes/interactive/components/tool-execution.d.ts +59 -0
  945. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  946. package/dist/modes/interactive/components/tool-execution.js +335 -0
  947. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  948. package/dist/modes/interactive/components/tree-list.d.ts +67 -0
  949. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -0
  950. package/dist/modes/interactive/components/tree-list.js +710 -0
  951. package/dist/modes/interactive/components/tree-list.js.map +1 -0
  952. package/dist/modes/interactive/components/tree-render.d.ts +17 -0
  953. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -0
  954. package/dist/modes/interactive/components/tree-render.js +316 -0
  955. package/dist/modes/interactive/components/tree-render.js.map +1 -0
  956. package/dist/modes/interactive/components/tree-selector.d.ts +25 -0
  957. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
  958. package/dist/modes/interactive/components/tree-selector.js +235 -0
  959. package/dist/modes/interactive/components/tree-selector.js.map +1 -0
  960. package/dist/modes/interactive/components/tree-types.d.ts +35 -0
  961. package/dist/modes/interactive/components/tree-types.d.ts.map +1 -0
  962. package/dist/modes/interactive/components/tree-types.js +2 -0
  963. package/dist/modes/interactive/components/tree-types.js.map +1 -0
  964. package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  965. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
  966. package/dist/modes/interactive/components/user-message-selector.js +114 -0
  967. package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
  968. package/dist/modes/interactive/components/user-message.d.ts +16 -0
  969. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  970. package/dist/modes/interactive/components/user-message.js +49 -0
  971. package/dist/modes/interactive/components/user-message.js.map +1 -0
  972. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  973. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  974. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  975. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  976. package/dist/modes/interactive/external-editor.d.ts +12 -0
  977. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  978. package/dist/modes/interactive/external-editor.js +38 -0
  979. package/dist/modes/interactive/external-editor.js.map +1 -0
  980. package/dist/modes/interactive/interactive-auth.d.ts +90 -0
  981. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -0
  982. package/dist/modes/interactive/interactive-auth.js +492 -0
  983. package/dist/modes/interactive/interactive-auth.js.map +1 -0
  984. package/dist/modes/interactive/interactive-commands.d.ts +68 -0
  985. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -0
  986. package/dist/modes/interactive/interactive-commands.js +157 -0
  987. package/dist/modes/interactive/interactive-commands.js.map +1 -0
  988. package/dist/modes/interactive/interactive-dialog-ui.d.ts +73 -0
  989. package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -0
  990. package/dist/modes/interactive/interactive-dialog-ui.js +189 -0
  991. package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -0
  992. package/dist/modes/interactive/interactive-format.d.ts +65 -0
  993. package/dist/modes/interactive/interactive-format.d.ts.map +1 -0
  994. package/dist/modes/interactive/interactive-format.js +268 -0
  995. package/dist/modes/interactive/interactive-format.js.map +1 -0
  996. package/dist/modes/interactive/interactive-helpers.d.ts +25 -0
  997. package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -0
  998. package/dist/modes/interactive/interactive-helpers.js +73 -0
  999. package/dist/modes/interactive/interactive-helpers.js.map +1 -0
  1000. package/dist/modes/interactive/interactive-mode.d.ts +640 -0
  1001. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  1002. package/dist/modes/interactive/interactive-mode.js +4107 -0
  1003. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  1004. package/dist/modes/interactive/interactive-selectors.d.ts +95 -0
  1005. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -0
  1006. package/dist/modes/interactive/interactive-selectors.js +356 -0
  1007. package/dist/modes/interactive/interactive-selectors.js.map +1 -0
  1008. package/dist/modes/interactive/model-catalog-refresh.d.ts +11 -0
  1009. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  1010. package/dist/modes/interactive/model-catalog-refresh.js +35 -0
  1011. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  1012. package/dist/modes/interactive/model-search.d.ts +12 -0
  1013. package/dist/modes/interactive/model-search.d.ts.map +1 -0
  1014. package/dist/modes/interactive/model-search.js +15 -0
  1015. package/dist/modes/interactive/model-search.js.map +1 -0
  1016. package/dist/modes/interactive/theme/dark.json +90 -0
  1017. package/dist/modes/interactive/theme/light.json +89 -0
  1018. package/dist/modes/interactive/theme/theme-controller.d.ts +40 -0
  1019. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
  1020. package/dist/modes/interactive/theme/theme-controller.js +126 -0
  1021. package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
  1022. package/dist/modes/interactive/theme/theme-schema.json +352 -0
  1023. package/dist/modes/interactive/theme/theme.d.ts +122 -0
  1024. package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
  1025. package/dist/modes/interactive/theme/theme.js +1093 -0
  1026. package/dist/modes/interactive/theme/theme.js.map +1 -0
  1027. package/dist/modes/json-event.d.ts +34 -0
  1028. package/dist/modes/json-event.d.ts.map +1 -0
  1029. package/dist/modes/json-event.js +29 -0
  1030. package/dist/modes/json-event.js.map +1 -0
  1031. package/dist/modes/print-mode.d.ts +32 -0
  1032. package/dist/modes/print-mode.d.ts.map +1 -0
  1033. package/dist/modes/print-mode.js +205 -0
  1034. package/dist/modes/print-mode.js.map +1 -0
  1035. package/dist/modes/rpc/jsonl.d.ts +17 -0
  1036. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  1037. package/dist/modes/rpc/jsonl.js +49 -0
  1038. package/dist/modes/rpc/jsonl.js.map +1 -0
  1039. package/dist/modes/rpc/rpc-client.d.ts +254 -0
  1040. package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
  1041. package/dist/modes/rpc/rpc-client.js +496 -0
  1042. package/dist/modes/rpc/rpc-client.js.map +1 -0
  1043. package/dist/modes/rpc/rpc-mode.d.ts +53 -0
  1044. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  1045. package/dist/modes/rpc/rpc-mode.js +540 -0
  1046. package/dist/modes/rpc/rpc-mode.js.map +1 -0
  1047. package/dist/modes/rpc/rpc-types.d.ts +486 -0
  1048. package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
  1049. package/dist/modes/rpc/rpc-types.js +8 -0
  1050. package/dist/modes/rpc/rpc-types.js.map +1 -0
  1051. package/dist/package-manager-cli.d.ts +18 -0
  1052. package/dist/package-manager-cli.d.ts.map +1 -0
  1053. package/dist/package-manager-cli.js +944 -0
  1054. package/dist/package-manager-cli.js.map +1 -0
  1055. package/dist/plugins/ecosystem/active-bindings.d.ts +92 -0
  1056. package/dist/plugins/ecosystem/active-bindings.d.ts.map +1 -0
  1057. package/dist/plugins/ecosystem/active-bindings.js +198 -0
  1058. package/dist/plugins/ecosystem/active-bindings.js.map +1 -0
  1059. package/dist/plugins/ecosystem/bootstrap-factory-manifest.d.ts +32 -0
  1060. package/dist/plugins/ecosystem/bootstrap-factory-manifest.d.ts.map +1 -0
  1061. package/dist/plugins/ecosystem/bootstrap-factory-manifest.js +32 -0
  1062. package/dist/plugins/ecosystem/bootstrap-factory-manifest.js.map +1 -0
  1063. package/dist/plugins/ecosystem/catalog.d.ts +38 -0
  1064. package/dist/plugins/ecosystem/catalog.d.ts.map +1 -0
  1065. package/dist/plugins/ecosystem/catalog.js +90 -0
  1066. package/dist/plugins/ecosystem/catalog.js.map +1 -0
  1067. package/dist/plugins/ecosystem/cli.d.ts +102 -0
  1068. package/dist/plugins/ecosystem/cli.d.ts.map +1 -0
  1069. package/dist/plugins/ecosystem/cli.js +970 -0
  1070. package/dist/plugins/ecosystem/cli.js.map +1 -0
  1071. package/dist/plugins/ecosystem/default-active-bindings.d.ts +33 -0
  1072. package/dist/plugins/ecosystem/default-active-bindings.d.ts.map +1 -0
  1073. package/dist/plugins/ecosystem/default-active-bindings.js +105 -0
  1074. package/dist/plugins/ecosystem/default-active-bindings.js.map +1 -0
  1075. package/dist/plugins/ecosystem/default-plugin-market.d.ts +68 -0
  1076. package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -0
  1077. package/dist/plugins/ecosystem/default-plugin-market.js +146 -0
  1078. package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -0
  1079. package/dist/plugins/ecosystem/distribution.d.ts +113 -0
  1080. package/dist/plugins/ecosystem/distribution.d.ts.map +1 -0
  1081. package/dist/plugins/ecosystem/distribution.js +371 -0
  1082. package/dist/plugins/ecosystem/distribution.js.map +1 -0
  1083. package/dist/plugins/ecosystem/index.d.ts +56 -0
  1084. package/dist/plugins/ecosystem/index.d.ts.map +1 -0
  1085. package/dist/plugins/ecosystem/index.js +31 -0
  1086. package/dist/plugins/ecosystem/index.js.map +1 -0
  1087. package/dist/plugins/ecosystem/installer.d.ts +130 -0
  1088. package/dist/plugins/ecosystem/installer.d.ts.map +1 -0
  1089. package/dist/plugins/ecosystem/installer.js +316 -0
  1090. package/dist/plugins/ecosystem/installer.js.map +1 -0
  1091. package/dist/plugins/ecosystem/node-disk-registry-source.d.ts +47 -0
  1092. package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -0
  1093. package/dist/plugins/ecosystem/node-disk-registry-source.js +208 -0
  1094. package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -0
  1095. package/dist/plugins/ecosystem/node-distribution-host.d.ts +55 -0
  1096. package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -0
  1097. package/dist/plugins/ecosystem/node-distribution-host.js +423 -0
  1098. package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -0
  1099. package/dist/plugins/ecosystem/node-local-package-source.d.ts +10 -0
  1100. package/dist/plugins/ecosystem/node-local-package-source.d.ts.map +1 -0
  1101. package/dist/plugins/ecosystem/node-local-package-source.js +97 -0
  1102. package/dist/plugins/ecosystem/node-local-package-source.js.map +1 -0
  1103. package/dist/plugins/ecosystem/node-npm-registry-source.d.ts +58 -0
  1104. package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -0
  1105. package/dist/plugins/ecosystem/node-npm-registry-source.js +326 -0
  1106. package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -0
  1107. package/dist/plugins/ecosystem/node-package-install-host.d.ts +91 -0
  1108. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -0
  1109. package/dist/plugins/ecosystem/node-package-install-host.js +857 -0
  1110. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -0
  1111. package/dist/plugins/ecosystem/node-package-install-persistence.d.ts +34 -0
  1112. package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -0
  1113. package/dist/plugins/ecosystem/node-package-install-persistence.js +221 -0
  1114. package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -0
  1115. package/dist/plugins/ecosystem/node-package-install-stack.d.ts +28 -0
  1116. package/dist/plugins/ecosystem/node-package-install-stack.d.ts.map +1 -0
  1117. package/dist/plugins/ecosystem/node-package-install-stack.js +65 -0
  1118. package/dist/plugins/ecosystem/node-package-install-stack.js.map +1 -0
  1119. package/dist/plugins/ecosystem/node-package-media.d.ts +14 -0
  1120. package/dist/plugins/ecosystem/node-package-media.d.ts.map +1 -0
  1121. package/dist/plugins/ecosystem/node-package-media.js +36 -0
  1122. package/dist/plugins/ecosystem/node-package-media.js.map +1 -0
  1123. package/dist/plugins/ecosystem/node-plugin-acquisition-host.d.ts +83 -0
  1124. package/dist/plugins/ecosystem/node-plugin-acquisition-host.d.ts.map +1 -0
  1125. package/dist/plugins/ecosystem/node-plugin-acquisition-host.js +423 -0
  1126. package/dist/plugins/ecosystem/node-plugin-acquisition-host.js.map +1 -0
  1127. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +48 -0
  1128. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -0
  1129. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +191 -0
  1130. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -0
  1131. package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts +26 -0
  1132. package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -0
  1133. package/dist/plugins/ecosystem/node-plugin-trust-root.js +120 -0
  1134. package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -0
  1135. package/dist/plugins/ecosystem/node-registry-source.d.ts +35 -0
  1136. package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -0
  1137. package/dist/plugins/ecosystem/node-registry-source.js +286 -0
  1138. package/dist/plugins/ecosystem/node-registry-source.js.map +1 -0
  1139. package/dist/plugins/ecosystem/node-release-package-source.d.ts +47 -0
  1140. package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -0
  1141. package/dist/plugins/ecosystem/node-release-package-source.js +336 -0
  1142. package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -0
  1143. package/dist/plugins/ecosystem/node-tar-package.d.ts +11 -0
  1144. package/dist/plugins/ecosystem/node-tar-package.d.ts.map +1 -0
  1145. package/dist/plugins/ecosystem/node-tar-package.js +294 -0
  1146. package/dist/plugins/ecosystem/node-tar-package.js.map +1 -0
  1147. package/dist/plugins/ecosystem/node-tar-writer.d.ts +16 -0
  1148. package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -0
  1149. package/dist/plugins/ecosystem/node-tar-writer.js +134 -0
  1150. package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -0
  1151. package/dist/plugins/ecosystem/node-url-package-source.d.ts +31 -0
  1152. package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -0
  1153. package/dist/plugins/ecosystem/node-url-package-source.js +159 -0
  1154. package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -0
  1155. package/dist/plugins/ecosystem/plugin-acquisition.d.ts +88 -0
  1156. package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -0
  1157. package/dist/plugins/ecosystem/plugin-acquisition.js +197 -0
  1158. package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -0
  1159. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +87 -0
  1160. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -0
  1161. package/dist/plugins/ecosystem/plugin-bootstrap.js +134 -0
  1162. package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -0
  1163. package/dist/plugins/ecosystem/registry-cli-adapter.d.ts +8 -0
  1164. package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -0
  1165. package/dist/plugins/ecosystem/registry-cli-adapter.js +16 -0
  1166. package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -0
  1167. package/dist/plugins/ecosystem/registry.d.ts +121 -0
  1168. package/dist/plugins/ecosystem/registry.d.ts.map +1 -0
  1169. package/dist/plugins/ecosystem/registry.js +324 -0
  1170. package/dist/plugins/ecosystem/registry.js.map +1 -0
  1171. package/dist/plugins/ecosystem/resolver.d.ts +32 -0
  1172. package/dist/plugins/ecosystem/resolver.d.ts.map +1 -0
  1173. package/dist/plugins/ecosystem/resolver.js +325 -0
  1174. package/dist/plugins/ecosystem/resolver.js.map +1 -0
  1175. package/dist/plugins/ecosystem/selection-store.d.ts +66 -0
  1176. package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -0
  1177. package/dist/plugins/ecosystem/selection-store.js +241 -0
  1178. package/dist/plugins/ecosystem/selection-store.js.map +1 -0
  1179. package/dist/plugins/ecosystem/selection.d.ts +54 -0
  1180. package/dist/plugins/ecosystem/selection.d.ts.map +1 -0
  1181. package/dist/plugins/ecosystem/selection.js +116 -0
  1182. package/dist/plugins/ecosystem/selection.js.map +1 -0
  1183. package/dist/plugins/ecosystem/state.d.ts +96 -0
  1184. package/dist/plugins/ecosystem/state.d.ts.map +1 -0
  1185. package/dist/plugins/ecosystem/state.js +346 -0
  1186. package/dist/plugins/ecosystem/state.js.map +1 -0
  1187. package/dist/plugins/ecosystem/types.d.ts +90 -0
  1188. package/dist/plugins/ecosystem/types.d.ts.map +1 -0
  1189. package/dist/plugins/ecosystem/types.js +8 -0
  1190. package/dist/plugins/ecosystem/types.js.map +1 -0
  1191. package/dist/plugins/ecosystem/updates.d.ts +30 -0
  1192. package/dist/plugins/ecosystem/updates.d.ts.map +1 -0
  1193. package/dist/plugins/ecosystem/updates.js +148 -0
  1194. package/dist/plugins/ecosystem/updates.js.map +1 -0
  1195. package/dist/plugins/integrity-adapter.d.ts +58 -0
  1196. package/dist/plugins/integrity-adapter.d.ts.map +1 -0
  1197. package/dist/plugins/integrity-adapter.js +70 -0
  1198. package/dist/plugins/integrity-adapter.js.map +1 -0
  1199. package/dist/plugins/mcp-http.d.ts +78 -0
  1200. package/dist/plugins/mcp-http.d.ts.map +1 -0
  1201. package/dist/plugins/mcp-http.js +176 -0
  1202. package/dist/plugins/mcp-http.js.map +1 -0
  1203. package/dist/plugins/observability-types.d.ts +9 -0
  1204. package/dist/plugins/observability-types.d.ts.map +1 -0
  1205. package/dist/plugins/observability-types.js +9 -0
  1206. package/dist/plugins/observability-types.js.map +1 -0
  1207. package/dist/plugins/plugin-host.d.ts +46 -0
  1208. package/dist/plugins/plugin-host.d.ts.map +1 -0
  1209. package/dist/plugins/plugin-host.js +80 -0
  1210. package/dist/plugins/plugin-host.js.map +1 -0
  1211. package/dist/plugins/plugin-supervisor.d.ts +77 -0
  1212. package/dist/plugins/plugin-supervisor.d.ts.map +1 -0
  1213. package/dist/plugins/plugin-supervisor.js +82 -0
  1214. package/dist/plugins/plugin-supervisor.js.map +1 -0
  1215. package/dist/plugins/subagent-task/runner-entry.d.ts +35 -0
  1216. package/dist/plugins/subagent-task/runner-entry.d.ts.map +1 -0
  1217. package/dist/plugins/subagent-task/runner-entry.js +39 -0
  1218. package/dist/plugins/subagent-task/runner-entry.js.map +1 -0
  1219. package/dist/plugins/subagent-task/session-factory.d.ts +57 -0
  1220. package/dist/plugins/subagent-task/session-factory.d.ts.map +1 -0
  1221. package/dist/plugins/subagent-task/session-factory.js +51 -0
  1222. package/dist/plugins/subagent-task/session-factory.js.map +1 -0
  1223. package/dist/profile/child-facade.d.ts +44 -0
  1224. package/dist/profile/child-facade.d.ts.map +1 -0
  1225. package/dist/profile/child-facade.js +56 -0
  1226. package/dist/profile/child-facade.js.map +1 -0
  1227. package/dist/profile/dependency-wiring.d.ts +48 -0
  1228. package/dist/profile/dependency-wiring.d.ts.map +1 -0
  1229. package/dist/profile/dependency-wiring.js +56 -0
  1230. package/dist/profile/dependency-wiring.js.map +1 -0
  1231. package/dist/profile/domain-recovery.d.ts +60 -0
  1232. package/dist/profile/domain-recovery.d.ts.map +1 -0
  1233. package/dist/profile/domain-recovery.js +94 -0
  1234. package/dist/profile/domain-recovery.js.map +1 -0
  1235. package/dist/profile/first-roles.d.ts +30 -0
  1236. package/dist/profile/first-roles.d.ts.map +1 -0
  1237. package/dist/profile/first-roles.js +74 -0
  1238. package/dist/profile/first-roles.js.map +1 -0
  1239. package/dist/profile/goal-plugin.d.ts +38 -0
  1240. package/dist/profile/goal-plugin.d.ts.map +1 -0
  1241. package/dist/profile/goal-plugin.js +113 -0
  1242. package/dist/profile/goal-plugin.js.map +1 -0
  1243. package/dist/profile/identity.d.ts +58 -0
  1244. package/dist/profile/identity.d.ts.map +1 -0
  1245. package/dist/profile/identity.js +100 -0
  1246. package/dist/profile/identity.js.map +1 -0
  1247. package/dist/profile/lock.d.ts +59 -0
  1248. package/dist/profile/lock.d.ts.map +1 -0
  1249. package/dist/profile/lock.js +59 -0
  1250. package/dist/profile/lock.js.map +1 -0
  1251. package/dist/profile/plan-plugin.d.ts +44 -0
  1252. package/dist/profile/plan-plugin.d.ts.map +1 -0
  1253. package/dist/profile/plan-plugin.js +144 -0
  1254. package/dist/profile/plan-plugin.js.map +1 -0
  1255. package/dist/profile/plugin-profiles.d.ts +56 -0
  1256. package/dist/profile/plugin-profiles.d.ts.map +1 -0
  1257. package/dist/profile/plugin-profiles.js +192 -0
  1258. package/dist/profile/plugin-profiles.js.map +1 -0
  1259. package/dist/profile/policy-manifest.d.ts +53 -0
  1260. package/dist/profile/policy-manifest.d.ts.map +1 -0
  1261. package/dist/profile/policy-manifest.js +52 -0
  1262. package/dist/profile/policy-manifest.js.map +1 -0
  1263. package/dist/profile/profile-assembly.d.ts +74 -0
  1264. package/dist/profile/profile-assembly.d.ts.map +1 -0
  1265. package/dist/profile/profile-assembly.js +90 -0
  1266. package/dist/profile/profile-assembly.js.map +1 -0
  1267. package/dist/profile/profile-migration.d.ts +56 -0
  1268. package/dist/profile/profile-migration.d.ts.map +1 -0
  1269. package/dist/profile/profile-migration.js +60 -0
  1270. package/dist/profile/profile-migration.js.map +1 -0
  1271. package/dist/profile/profile-registry.d.ts +58 -0
  1272. package/dist/profile/profile-registry.d.ts.map +1 -0
  1273. package/dist/profile/profile-registry.js +74 -0
  1274. package/dist/profile/profile-registry.js.map +1 -0
  1275. package/dist/profile/role-assembly.d.ts +47 -0
  1276. package/dist/profile/role-assembly.d.ts.map +1 -0
  1277. package/dist/profile/role-assembly.js +31 -0
  1278. package/dist/profile/role-assembly.js.map +1 -0
  1279. package/dist/profile/role-catalog.d.ts +44 -0
  1280. package/dist/profile/role-catalog.d.ts.map +1 -0
  1281. package/dist/profile/role-catalog.js +130 -0
  1282. package/dist/profile/role-catalog.js.map +1 -0
  1283. package/dist/profile/role-orchestrator.d.ts +123 -0
  1284. package/dist/profile/role-orchestrator.d.ts.map +1 -0
  1285. package/dist/profile/role-orchestrator.js +194 -0
  1286. package/dist/profile/role-orchestrator.js.map +1 -0
  1287. package/dist/profile/role-runner.d.ts +99 -0
  1288. package/dist/profile/role-runner.d.ts.map +1 -0
  1289. package/dist/profile/role-runner.js +78 -0
  1290. package/dist/profile/role-runner.js.map +1 -0
  1291. package/dist/profile/root-facade.d.ts +36 -0
  1292. package/dist/profile/root-facade.d.ts.map +1 -0
  1293. package/dist/profile/root-facade.js +48 -0
  1294. package/dist/profile/root-facade.js.map +1 -0
  1295. package/dist/profile/skill-discovery-wiring.d.ts +58 -0
  1296. package/dist/profile/skill-discovery-wiring.d.ts.map +1 -0
  1297. package/dist/profile/skill-discovery-wiring.js +75 -0
  1298. package/dist/profile/skill-discovery-wiring.js.map +1 -0
  1299. package/dist/profile/state-store.d.ts +62 -0
  1300. package/dist/profile/state-store.d.ts.map +1 -0
  1301. package/dist/profile/state-store.js +140 -0
  1302. package/dist/profile/state-store.js.map +1 -0
  1303. package/dist/profile/todo-plugin.d.ts +37 -0
  1304. package/dist/profile/todo-plugin.d.ts.map +1 -0
  1305. package/dist/profile/todo-plugin.js +132 -0
  1306. package/dist/profile/todo-plugin.js.map +1 -0
  1307. package/dist/profiles/builtin-suites.d.ts +142 -0
  1308. package/dist/profiles/builtin-suites.d.ts.map +1 -0
  1309. package/dist/profiles/builtin-suites.js +395 -0
  1310. package/dist/profiles/builtin-suites.js.map +1 -0
  1311. package/dist/profiles/resolved-agent-profile.d.ts +83 -0
  1312. package/dist/profiles/resolved-agent-profile.d.ts.map +1 -0
  1313. package/dist/profiles/resolved-agent-profile.js +75 -0
  1314. package/dist/profiles/resolved-agent-profile.js.map +1 -0
  1315. package/dist/profiles/suite-lifecycle.d.ts +158 -0
  1316. package/dist/profiles/suite-lifecycle.d.ts.map +1 -0
  1317. package/dist/profiles/suite-lifecycle.js +447 -0
  1318. package/dist/profiles/suite-lifecycle.js.map +1 -0
  1319. package/dist/profiles/suite-loader.d.ts +410 -0
  1320. package/dist/profiles/suite-loader.d.ts.map +1 -0
  1321. package/dist/profiles/suite-loader.js +823 -0
  1322. package/dist/profiles/suite-loader.js.map +1 -0
  1323. package/dist/remote/server-assembly.d.ts +230 -0
  1324. package/dist/remote/server-assembly.d.ts.map +1 -0
  1325. package/dist/remote/server-assembly.js +1189 -0
  1326. package/dist/remote/server-assembly.js.map +1 -0
  1327. package/dist/remote/server-entry.d.ts +112 -0
  1328. package/dist/remote/server-entry.d.ts.map +1 -0
  1329. package/dist/remote/server-entry.js +239 -0
  1330. package/dist/remote/server-entry.js.map +1 -0
  1331. package/dist/remote/session-source.d.ts +101 -0
  1332. package/dist/remote/session-source.d.ts.map +1 -0
  1333. package/dist/remote/session-source.js +173 -0
  1334. package/dist/remote/session-source.js.map +1 -0
  1335. package/dist/rpc-entry.d.ts +3 -0
  1336. package/dist/rpc-entry.d.ts.map +1 -0
  1337. package/dist/rpc-entry.js +11 -0
  1338. package/dist/rpc-entry.js.map +1 -0
  1339. package/dist/server/create-harness.d.ts +26 -0
  1340. package/dist/server/create-harness.d.ts.map +1 -0
  1341. package/dist/server/create-harness.js +106 -0
  1342. package/dist/server/create-harness.js.map +1 -0
  1343. package/dist/share/session-share.d.ts +98 -0
  1344. package/dist/share/session-share.d.ts.map +1 -0
  1345. package/dist/share/session-share.js +89 -0
  1346. package/dist/share/session-share.js.map +1 -0
  1347. package/dist/share/share-viewer.d.ts +43 -0
  1348. package/dist/share/share-viewer.d.ts.map +1 -0
  1349. package/dist/share/share-viewer.js +103 -0
  1350. package/dist/share/share-viewer.js.map +1 -0
  1351. package/dist/testing/index.d.ts +4 -0
  1352. package/dist/testing/index.d.ts.map +1 -0
  1353. package/dist/testing/index.js +6 -0
  1354. package/dist/testing/index.js.map +1 -0
  1355. package/dist/testing/mock-ai-server.d.ts +77 -0
  1356. package/dist/testing/mock-ai-server.d.ts.map +1 -0
  1357. package/dist/testing/mock-ai-server.js +69 -0
  1358. package/dist/testing/mock-ai-server.js.map +1 -0
  1359. package/dist/testing/plugin-testkit.d.ts +148 -0
  1360. package/dist/testing/plugin-testkit.d.ts.map +1 -0
  1361. package/dist/testing/plugin-testkit.js +493 -0
  1362. package/dist/testing/plugin-testkit.js.map +1 -0
  1363. package/dist/testing/runtime-delivery-queue.d.ts +47 -0
  1364. package/dist/testing/runtime-delivery-queue.d.ts.map +1 -0
  1365. package/dist/testing/runtime-delivery-queue.js +158 -0
  1366. package/dist/testing/runtime-delivery-queue.js.map +1 -0
  1367. package/dist/testing/session-plugin-testkit.d.ts +144 -0
  1368. package/dist/testing/session-plugin-testkit.d.ts.map +1 -0
  1369. package/dist/testing/session-plugin-testkit.js +444 -0
  1370. package/dist/testing/session-plugin-testkit.js.map +1 -0
  1371. package/dist/utils/abort.d.ts +5 -0
  1372. package/dist/utils/abort.d.ts.map +1 -0
  1373. package/dist/utils/abort.js +53 -0
  1374. package/dist/utils/abort.js.map +1 -0
  1375. package/dist/utils/agent-forge-user-agent.d.ts +2 -0
  1376. package/dist/utils/agent-forge-user-agent.d.ts.map +1 -0
  1377. package/dist/utils/agent-forge-user-agent.js +5 -0
  1378. package/dist/utils/agent-forge-user-agent.js.map +1 -0
  1379. package/dist/utils/ansi.d.ts +2 -0
  1380. package/dist/utils/ansi.d.ts.map +1 -0
  1381. package/dist/utils/ansi.js +53 -0
  1382. package/dist/utils/ansi.js.map +1 -0
  1383. package/dist/utils/changelog.d.ts +22 -0
  1384. package/dist/utils/changelog.d.ts.map +1 -0
  1385. package/dist/utils/changelog.js +165 -0
  1386. package/dist/utils/changelog.js.map +1 -0
  1387. package/dist/utils/child-process.d.ts +18 -0
  1388. package/dist/utils/child-process.d.ts.map +1 -0
  1389. package/dist/utils/child-process.js +107 -0
  1390. package/dist/utils/child-process.js.map +1 -0
  1391. package/dist/utils/clipboard-image.d.ts +11 -0
  1392. package/dist/utils/clipboard-image.d.ts.map +1 -0
  1393. package/dist/utils/clipboard-image.js +246 -0
  1394. package/dist/utils/clipboard-image.js.map +1 -0
  1395. package/dist/utils/clipboard-native.d.ts +11 -0
  1396. package/dist/utils/clipboard-native.d.ts.map +1 -0
  1397. package/dist/utils/clipboard-native.js +22 -0
  1398. package/dist/utils/clipboard-native.js.map +1 -0
  1399. package/dist/utils/clipboard.d.ts +4 -0
  1400. package/dist/utils/clipboard.d.ts.map +1 -0
  1401. package/dist/utils/clipboard.js +161 -0
  1402. package/dist/utils/clipboard.js.map +1 -0
  1403. package/dist/utils/deprecation.d.ts +4 -0
  1404. package/dist/utils/deprecation.d.ts.map +1 -0
  1405. package/dist/utils/deprecation.js +13 -0
  1406. package/dist/utils/deprecation.js.map +1 -0
  1407. package/dist/utils/exif-orientation.d.ts +5 -0
  1408. package/dist/utils/exif-orientation.d.ts.map +1 -0
  1409. package/dist/utils/exif-orientation.js +158 -0
  1410. package/dist/utils/exif-orientation.js.map +1 -0
  1411. package/dist/utils/frontmatter.d.ts +8 -0
  1412. package/dist/utils/frontmatter.d.ts.map +1 -0
  1413. package/dist/utils/frontmatter.js +27 -0
  1414. package/dist/utils/frontmatter.js.map +1 -0
  1415. package/dist/utils/fs-watch.d.ts +5 -0
  1416. package/dist/utils/fs-watch.d.ts.map +1 -0
  1417. package/dist/utils/fs-watch.js +25 -0
  1418. package/dist/utils/fs-watch.js.map +1 -0
  1419. package/dist/utils/git.d.ts +26 -0
  1420. package/dist/utils/git.d.ts.map +1 -0
  1421. package/dist/utils/git.js +201 -0
  1422. package/dist/utils/git.js.map +1 -0
  1423. package/dist/utils/html.d.ts +7 -0
  1424. package/dist/utils/html.d.ts.map +1 -0
  1425. package/dist/utils/html.js +40 -0
  1426. package/dist/utils/html.js.map +1 -0
  1427. package/dist/utils/image-convert.d.ts +10 -0
  1428. package/dist/utils/image-convert.d.ts.map +1 -0
  1429. package/dist/utils/image-convert.js +45 -0
  1430. package/dist/utils/image-convert.js.map +1 -0
  1431. package/dist/utils/image-process.d.ts +18 -0
  1432. package/dist/utils/image-process.d.ts.map +1 -0
  1433. package/dist/utils/image-process.js +84 -0
  1434. package/dist/utils/image-process.js.map +1 -0
  1435. package/dist/utils/image-resize-core.d.ts +30 -0
  1436. package/dist/utils/image-resize-core.d.ts.map +1 -0
  1437. package/dist/utils/image-resize-core.js +125 -0
  1438. package/dist/utils/image-resize-core.js.map +1 -0
  1439. package/dist/utils/image-resize-worker.d.ts +2 -0
  1440. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  1441. package/dist/utils/image-resize-worker.js +31 -0
  1442. package/dist/utils/image-resize-worker.js.map +1 -0
  1443. package/dist/utils/image-resize.d.ts +16 -0
  1444. package/dist/utils/image-resize.d.ts.map +1 -0
  1445. package/dist/utils/image-resize.js +100 -0
  1446. package/dist/utils/image-resize.js.map +1 -0
  1447. package/dist/utils/json.d.ts +3 -0
  1448. package/dist/utils/json.d.ts.map +1 -0
  1449. package/dist/utils/json.js +8 -0
  1450. package/dist/utils/json.js.map +1 -0
  1451. package/dist/utils/management-http.d.ts +25 -0
  1452. package/dist/utils/management-http.d.ts.map +1 -0
  1453. package/dist/utils/management-http.js +54 -0
  1454. package/dist/utils/management-http.js.map +1 -0
  1455. package/dist/utils/mime.d.ts +3 -0
  1456. package/dist/utils/mime.d.ts.map +1 -0
  1457. package/dist/utils/mime.js +115 -0
  1458. package/dist/utils/mime.js.map +1 -0
  1459. package/dist/utils/open-browser.d.ts +9 -0
  1460. package/dist/utils/open-browser.d.ts.map +1 -0
  1461. package/dist/utils/open-browser.js +22 -0
  1462. package/dist/utils/open-browser.js.map +1 -0
  1463. package/dist/utils/paths.d.ts +34 -0
  1464. package/dist/utils/paths.d.ts.map +1 -0
  1465. package/dist/utils/paths.js +114 -0
  1466. package/dist/utils/paths.js.map +1 -0
  1467. package/dist/utils/photon.d.ts +21 -0
  1468. package/dist/utils/photon.d.ts.map +1 -0
  1469. package/dist/utils/photon.js +124 -0
  1470. package/dist/utils/photon.js.map +1 -0
  1471. package/dist/utils/shell.d.ts +34 -0
  1472. package/dist/utils/shell.d.ts.map +1 -0
  1473. package/dist/utils/shell.js +216 -0
  1474. package/dist/utils/shell.js.map +1 -0
  1475. package/dist/utils/sleep.d.ts +5 -0
  1476. package/dist/utils/sleep.d.ts.map +1 -0
  1477. package/dist/utils/sleep.js +17 -0
  1478. package/dist/utils/sleep.js.map +1 -0
  1479. package/dist/utils/sync-sleep.d.ts +2 -0
  1480. package/dist/utils/sync-sleep.d.ts.map +1 -0
  1481. package/dist/utils/sync-sleep.js +11 -0
  1482. package/dist/utils/sync-sleep.js.map +1 -0
  1483. package/dist/utils/syntax-highlight.d.ts +13 -0
  1484. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  1485. package/dist/utils/syntax-highlight.js +177 -0
  1486. package/dist/utils/syntax-highlight.js.map +1 -0
  1487. package/dist/utils/text.d.ts +8 -0
  1488. package/dist/utils/text.d.ts.map +1 -0
  1489. package/dist/utils/text.js +9 -0
  1490. package/dist/utils/text.js.map +1 -0
  1491. package/dist/utils/tool-result-images.d.ts +19 -0
  1492. package/dist/utils/tool-result-images.d.ts.map +1 -0
  1493. package/dist/utils/tool-result-images.js +45 -0
  1494. package/dist/utils/tool-result-images.js.map +1 -0
  1495. package/dist/utils/tools-manager.d.ts +24 -0
  1496. package/dist/utils/tools-manager.d.ts.map +1 -0
  1497. package/dist/utils/tools-manager.js +437 -0
  1498. package/dist/utils/tools-manager.js.map +1 -0
  1499. package/dist/utils/version-check.d.ts +21 -0
  1500. package/dist/utils/version-check.d.ts.map +1 -0
  1501. package/dist/utils/version-check.js +86 -0
  1502. package/dist/utils/version-check.js.map +1 -0
  1503. package/dist/utils/windows-self-update.d.ts +3 -0
  1504. package/dist/utils/windows-self-update.d.ts.map +1 -0
  1505. package/dist/utils/windows-self-update.js +77 -0
  1506. package/dist/utils/windows-self-update.js.map +1 -0
  1507. package/docs/compaction.md +348 -0
  1508. package/docs/containerization.md +114 -0
  1509. package/docs/development.md +71 -0
  1510. package/docs/docs.json +148 -0
  1511. package/docs/environment-variables.md +96 -0
  1512. package/docs/images/exy.png +0 -0
  1513. package/docs/images/interactive-mode.png +0 -0
  1514. package/docs/images/tree-view.png +0 -0
  1515. package/docs/index.md +76 -0
  1516. package/docs/json.md +98 -0
  1517. package/docs/keybindings.md +245 -0
  1518. package/docs/llama-cpp.md +101 -0
  1519. package/docs/models.md +576 -0
  1520. package/docs/packages.md +205 -0
  1521. package/docs/prompt-templates.md +96 -0
  1522. package/docs/providers.md +317 -0
  1523. package/docs/quickstart.md +167 -0
  1524. package/docs/rpc.md +1487 -0
  1525. package/docs/sdk.md +1146 -0
  1526. package/docs/security.md +24 -0
  1527. package/docs/session-format.md +438 -0
  1528. package/docs/sessions.md +145 -0
  1529. package/docs/settings.md +355 -0
  1530. package/docs/shell-aliases.md +13 -0
  1531. package/docs/skills.md +231 -0
  1532. package/docs/terminal-setup.md +192 -0
  1533. package/docs/termux.md +127 -0
  1534. package/docs/themes.md +320 -0
  1535. package/docs/tmux.md +63 -0
  1536. package/docs/tui.md +478 -0
  1537. package/docs/usage.md +291 -0
  1538. package/docs/windows.md +39 -0
  1539. package/examples/README.md +21 -0
  1540. package/examples/extensions/README.md +163 -0
  1541. package/examples/extensions/bash-spawn-hook/index.ts +37 -0
  1542. package/examples/extensions/bash-spawn-hook/plugin.json +10 -0
  1543. package/examples/extensions/bookmark/index.ts +67 -0
  1544. package/examples/extensions/bookmark/plugin.json +11 -0
  1545. package/examples/extensions/built-in-tool-renderer/index.ts +262 -0
  1546. package/examples/extensions/built-in-tool-renderer/plugin.json +10 -0
  1547. package/examples/extensions/claude-rules/index.ts +119 -0
  1548. package/examples/extensions/claude-rules/plugin.json +8 -0
  1549. package/examples/extensions/cli-bridge/README.md +27 -0
  1550. package/examples/extensions/cli-bridge/index.ts +320 -0
  1551. package/examples/extensions/cli-bridge/plugin.json +10 -0
  1552. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  1553. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  1554. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  1555. package/examples/extensions/dynamic-resources/index.ts +53 -0
  1556. package/examples/extensions/dynamic-resources/plugin.json +8 -0
  1557. package/examples/extensions/dynamic-tools/index.ts +102 -0
  1558. package/examples/extensions/dynamic-tools/plugin.json +14 -0
  1559. package/examples/extensions/event-bus/index.ts +75 -0
  1560. package/examples/extensions/event-bus/plugin.json +13 -0
  1561. package/examples/extensions/file-trigger/index.ts +65 -0
  1562. package/examples/extensions/file-trigger/plugin.json +13 -0
  1563. package/examples/extensions/goal/README.md +16 -0
  1564. package/examples/extensions/goal/index.ts +134 -0
  1565. package/examples/extensions/goal/plugin.json +12 -0
  1566. package/examples/extensions/hello/index.ts +29 -0
  1567. package/examples/extensions/hello/plugin.json +10 -0
  1568. package/examples/extensions/kimi-deferred-tools/index.ts +93 -0
  1569. package/examples/extensions/kimi-deferred-tools/plugin.json +11 -0
  1570. package/examples/extensions/mcp-stdio/README.md +19 -0
  1571. package/examples/extensions/mcp-stdio/index.d.ts +64 -0
  1572. package/examples/extensions/mcp-stdio/index.d.ts.map +1 -0
  1573. package/examples/extensions/mcp-stdio/index.js +292 -0
  1574. package/examples/extensions/mcp-stdio/index.js.map +1 -0
  1575. package/examples/extensions/mcp-stdio/index.ts +381 -0
  1576. package/examples/extensions/mcp-stdio/plugin.json +10 -0
  1577. package/examples/extensions/memory-backend/index.ts +120 -0
  1578. package/examples/extensions/memory-backend/plugin.json +10 -0
  1579. package/examples/extensions/minimal-mode/index.ts +447 -0
  1580. package/examples/extensions/minimal-mode/plugin.json +10 -0
  1581. package/examples/extensions/multi-agent/README.md +7 -0
  1582. package/examples/extensions/multi-agent/index.ts +592 -0
  1583. package/examples/extensions/multi-agent/plugin.json +13 -0
  1584. package/examples/extensions/notify/index.ts +70 -0
  1585. package/examples/extensions/notify/plugin.json +8 -0
  1586. package/examples/extensions/permission-gate/index.ts +55 -0
  1587. package/examples/extensions/permission-gate/plugin.json +11 -0
  1588. package/examples/extensions/pirate/index.ts +75 -0
  1589. package/examples/extensions/pirate/plugin.json +8 -0
  1590. package/examples/extensions/plan/README.md +16 -0
  1591. package/examples/extensions/plan/index.ts +136 -0
  1592. package/examples/extensions/plan/plugin.json +12 -0
  1593. package/examples/extensions/prompt-customizer/index.ts +117 -0
  1594. package/examples/extensions/prompt-customizer/plugin.json +8 -0
  1595. package/examples/extensions/protected-paths/index.ts +44 -0
  1596. package/examples/extensions/protected-paths/plugin.json +11 -0
  1597. package/examples/extensions/provider-attribution/README.md +12 -0
  1598. package/examples/extensions/provider-attribution/index.ts +86 -0
  1599. package/examples/extensions/provider-attribution/plugin.json +10 -0
  1600. package/examples/extensions/send-user-message/index.ts +118 -0
  1601. package/examples/extensions/send-user-message/plugin.json +11 -0
  1602. package/examples/extensions/session-name/index.ts +31 -0
  1603. package/examples/extensions/session-name/plugin.json +11 -0
  1604. package/examples/extensions/session-share/README.md +15 -0
  1605. package/examples/extensions/session-share/index.ts +170 -0
  1606. package/examples/extensions/session-share/plugin.json +15 -0
  1607. package/examples/extensions/structured-output/index.ts +68 -0
  1608. package/examples/extensions/structured-output/plugin.json +10 -0
  1609. package/examples/extensions/subagent/README.md +177 -0
  1610. package/examples/extensions/subagent/agents/planner.md +37 -0
  1611. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  1612. package/examples/extensions/subagent/agents/scout.md +50 -0
  1613. package/examples/extensions/subagent/agents/worker.md +24 -0
  1614. package/examples/extensions/subagent/agents.ts +157 -0
  1615. package/examples/extensions/subagent/index.ts +1057 -0
  1616. package/examples/extensions/subagent/plugin.json +13 -0
  1617. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  1618. package/examples/extensions/subagent/prompts/implement.md +10 -0
  1619. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  1620. package/examples/extensions/suite-manager/README.md +45 -0
  1621. package/examples/extensions/suite-manager/index.ts +182 -0
  1622. package/examples/extensions/suite-manager/plugin.json +13 -0
  1623. package/examples/extensions/timed-confirm/index.ts +93 -0
  1624. package/examples/extensions/timed-confirm/plugin.json +13 -0
  1625. package/examples/extensions/todo-set/README.md +18 -0
  1626. package/examples/extensions/todo-set/index.ts +133 -0
  1627. package/examples/extensions/todo-set/plugin.json +12 -0
  1628. package/examples/extensions/tool-override/index.ts +159 -0
  1629. package/examples/extensions/tool-override/plugin.json +11 -0
  1630. package/examples/extensions/trigger-compact/index.ts +76 -0
  1631. package/examples/extensions/trigger-compact/plugin.json +14 -0
  1632. package/examples/extensions/truncated-tool/index.ts +204 -0
  1633. package/examples/extensions/truncated-tool/plugin.json +10 -0
  1634. package/examples/extensions/with-deps/index.ts +42 -0
  1635. package/examples/extensions/with-deps/package-lock.json +31 -0
  1636. package/examples/extensions/with-deps/package.json +22 -0
  1637. package/examples/extensions/with-deps/plugin.json +10 -0
  1638. package/examples/remote-client.ts +66 -0
  1639. package/examples/rpc-extension-ui.ts +641 -0
  1640. package/examples/sdk/01-minimal.ts +26 -0
  1641. package/examples/sdk/02-custom-model.ts +49 -0
  1642. package/examples/sdk/03-custom-prompt.ts +70 -0
  1643. package/examples/sdk/04-skills.ts +55 -0
  1644. package/examples/sdk/05-tools.ts +48 -0
  1645. package/examples/sdk/07-context-files.ts +42 -0
  1646. package/examples/sdk/08-prompt-templates.ts +51 -0
  1647. package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
  1648. package/examples/sdk/10-settings.ts +53 -0
  1649. package/examples/sdk/11-sessions.ts +52 -0
  1650. package/examples/sdk/12-full-control.ts +72 -0
  1651. package/examples/sdk/13-session-runtime.ts +71 -0
  1652. package/examples/sdk/14-custom-session-storage.ts +132 -0
  1653. package/examples/sdk/README.md +139 -0
  1654. package/package.json +111 -0
@@ -0,0 +1,4107 @@
1
+ /**
2
+ * Interactive mode for the coding agent.
3
+ * Handles TUI rendering and user interaction, delegating business logic to AgentSession.
4
+ */
5
+ import * as crypto from "node:crypto";
6
+ import * as fs from "node:fs";
7
+ import * as os from "node:os";
8
+ import * as path from "node:path";
9
+ import { contentText } from "@agent-forge/ai";
10
+ import * as TuiLayouts from "@agent-forge/tui";
11
+ import { CombinedAutocompleteProvider, Container, getCapabilities, hyperlink, Markdown, ProcessTerminal, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@agent-forge/tui";
12
+ import chalk from "chalk";
13
+ import { spawn } from "child_process";
14
+ import { APP_NAME, APP_TITLE, getAgentDir, getDebugLogPath, VERSION } from "../../config.js";
15
+ import { parseSkillBlock } from "../../core/agent-session.js";
16
+ import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
17
+ import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
18
+ import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defaults.js";
19
+ import { createCodingAgentFacade, createCodingAgentRuntimeFacade, } from "../../core/facade/index.js";
20
+ import { FooterDataProvider } from "../../core/footer-data-provider.js";
21
+ import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
22
+ import { KeybindingsManager } from "../../core/keybindings.js";
23
+ import { createCompactionSummaryMessage } from "../../core/messages.js";
24
+ import { DefaultPackageManager } from "../../core/package-manager.js";
25
+ import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
26
+ import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
27
+ import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
28
+ import { getUsageCostBreakdown } from "../../core/usage-totals.js";
29
+ import { listSuiteIds, resolveSuiteId, SUITE_ENV_VAR, SUITE_SESSION_ENTRY_TYPE } from "../../profiles/suite-loader.js";
30
+ import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
31
+ import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
32
+ import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
33
+ import { parseGitUrl } from "../../utils/git.js";
34
+ import { openBrowser } from "../../utils/open-browser.js";
35
+ import { killTrackedDetachedChildren } from "../../utils/shell.js";
36
+ import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
37
+ import { ensureTool } from "../../utils/tools-manager.js";
38
+ import { checkForNewVersion } from "../../utils/version-check.js";
39
+ import { ArminComponent } from "./components/armin.js";
40
+ import { AssistantMessageComponent } from "./components/assistant-message.js";
41
+ import { BashExecutionComponent } from "./components/bash-execution.js";
42
+ import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
43
+ import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
44
+ import { CustomEditor } from "./components/custom-editor.js";
45
+ import { CustomMessageComponent } from "./components/custom-message.js";
46
+ import { DaxnutsComponent } from "./components/daxnuts.js";
47
+ import { DynamicBorder } from "./components/dynamic-border.js";
48
+ import { FooterComponent, formatTokens } from "./components/footer.js";
49
+ import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
50
+ import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
51
+ import { readSessionSuiteIdFromFile, SessionSelectorComponent } from "./components/session-selector.js";
52
+ import { SettingsSelectorComponent } from "./components/settings-selector.js";
53
+ import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
54
+ import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
55
+ import { ToolExecutionComponent } from "./components/tool-execution.js";
56
+ import { TreeSelectorComponent } from "./components/tree-selector.js";
57
+ import { UserMessageComponent } from "./components/user-message.js";
58
+ import { editInExternalEditor } from "./external-editor.js";
59
+ import * as authFlow from "./interactive-auth.js";
60
+ import { COMMAND_DISPATCH_ENTRIES, matchCommandDispatchEntry } from "./interactive-commands.js";
61
+ import { createInteractionHostV1, hideDialogEditor, hideDialogInput, hideDialogSelector, isExpandable, showDialogConfirm, showDialogEditor, showDialogInput, showDialogNotify, showDialogSelector, } from "./interactive-dialog-ui.js";
62
+ import { buildScopeGroups, findSourceInfoForPath, formatContextPath, formatDiagnostics, formatDisplayPath, formatMetricsSnapshot, formatPathWithSource, formatScopeGroups, getCompactPackageSourceLabel, getCompactPathLabel, getDisplaySourceInfo, getScopeGroup, getShortPath, isPackageSource, } from "./interactive-format.js";
63
+ import { createFuzzyAutocompleteItems, formatLoginProviderCompletionDescription, getLoginProviderCompletionOptions, getLoginProviderSearchText, isAnthropicSubscriptionAuthKey, isDeadTerminalError, quoteIfNeeded, } from "./interactive-helpers.js";
64
+ import * as selectorsFlow from "./interactive-selectors.js";
65
+ import { refreshModelCatalogs } from "./model-catalog-refresh.js";
66
+ import { getModelSearchText } from "./model-search.js";
67
+ import { getAvailableThemes, getEditorTheme, getMarkdownTheme, loadThemeFromPath, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
68
+ import { InteractiveThemeController } from "./theme/theme-controller.js";
69
+ // Re-exported for existing consumers of the interactive mode module; the
70
+ // implementation moved to ./interactive-dialog-ui.ts with the extension UI block.
71
+ export { mapLegacyDialogResultToOutcome } from "./interactive-dialog-ui.js";
72
+ /**
73
+ * Rebuilds real Theme instances from the resource loader's ThemeMetaV1
74
+ * projection for the theme registry (B-S2b v1). Registration points
75
+ * (constructor, runtime session start, reload) need loadable instances —
76
+ * setRegisteredThemes stores what it is given and getThemeByName returns the
77
+ * registered instance first — while the loader surface now projects only
78
+ * metadata. Re-loading is synchronous and deterministic per sourcePath;
79
+ * theme names come from the same JSON the loader parsed, so meta.name ===
80
+ * Theme.name and the registry keeps its own name-filter/dedupe semantics.
81
+ *
82
+ * Contract: a meta without a sourcePath (or one whose file no longer parses)
83
+ * throws — themesOverride host inputs must always carry a loadable
84
+ * sourcePath. This adds one extra parse per theme at registration time
85
+ * (constructor / session start / reload, not per turn).
86
+ */
87
+ export function buildRegisteredThemes(themes) {
88
+ return themes.map((meta) => loadThemeFromPath(meta.sourcePath));
89
+ }
90
+ class ExpandableText extends Text {
91
+ getCollapsedText;
92
+ getExpandedText;
93
+ constructor(getCollapsedText, getExpandedText, expanded = false, paddingX = 0, paddingY = 0) {
94
+ super(expanded ? getExpandedText() : getCollapsedText(), paddingX, paddingY);
95
+ this.getCollapsedText = getCollapsedText;
96
+ this.getExpandedText = getExpandedText;
97
+ }
98
+ setExpanded(expanded) {
99
+ this.setText(expanded ? this.getExpandedText() : this.getCollapsedText());
100
+ }
101
+ }
102
+ function isCustomSessionEntry(item) {
103
+ return "type" in item && item.type === "custom";
104
+ }
105
+ function isCompactionCostNotice(item) {
106
+ return "type" in item && item.type === "compaction_cost";
107
+ }
108
+ // Empty-reply auto-continuation (#5, print-mode parity): sent at most once per
109
+ // submitted turn when the turn ends with an empty assistant reply and the
110
+ // model was neither aborted nor errored. The one-shot budget prevents loops.
111
+ const EMPTY_REPLY_RETRY_PROMPT = "Your previous reply was empty. Continue the user's task now.";
112
+ const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";
113
+ export function formatResumeCommand(session) {
114
+ if (!process.stdout.isTTY)
115
+ return undefined;
116
+ if (!session.isPersisted())
117
+ return undefined;
118
+ const sessionFile = session.getSessionFile();
119
+ if (!sessionFile || !fs.existsSync(sessionFile))
120
+ return undefined;
121
+ const args = [APP_NAME];
122
+ if (!session.usesDefaultSessionDir()) {
123
+ args.push("--session-dir", quoteIfNeeded(session.getSessionDir()));
124
+ }
125
+ args.push("--session", session.getSessionId());
126
+ return args.join(" ");
127
+ }
128
+ /** Composition root for selecting the interactive terminal renderer. */
129
+ export function createInteractiveTui(options) {
130
+ const terminal = options.terminal ?? new ProcessTerminal();
131
+ if (options.tuiMode === "fullscreen") {
132
+ const styleSearchMatch = (text) => theme.bg("searchMatchBg", theme.fg("searchMatchText", text));
133
+ return new TuiAltScreen(terminal, options.showHardwareCursor, options.logDirectory, {
134
+ searchMatchStyle: (text) => theme.underline(styleSearchMatch(text)),
135
+ searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
136
+ openUrl: openBrowser,
137
+ onRightClickPaste: options.onRightClickPaste,
138
+ copyOnSelect: options.fullscreenCopyOnSelect,
139
+ copySelection: async (text) => {
140
+ try {
141
+ await copyToClipboard(text);
142
+ return true;
143
+ }
144
+ catch {
145
+ return false;
146
+ }
147
+ },
148
+ });
149
+ }
150
+ return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
151
+ }
152
+ /** Stable reference for components while InteractiveMode replaces the active renderer. */
153
+ export function createInteractiveTuiReference(getTui) {
154
+ return new Proxy({}, {
155
+ get: (_target, property) => {
156
+ const tui = getTui();
157
+ const value = Reflect.get(tui, property, tui);
158
+ if (typeof value !== "function")
159
+ return value;
160
+ let methodTui = tui;
161
+ let method = value;
162
+ return (...args) => {
163
+ const currentTui = getTui();
164
+ if (currentTui !== methodTui) {
165
+ const currentMethod = Reflect.get(currentTui, property, currentTui);
166
+ if (typeof currentMethod !== "function") {
167
+ throw new TypeError(`TUI property ${String(property)} is not callable`);
168
+ }
169
+ methodTui = currentTui;
170
+ method = currentMethod;
171
+ }
172
+ return Reflect.apply(method, methodTui, args);
173
+ };
174
+ },
175
+ set: (_target, property, value) => {
176
+ const tui = getTui();
177
+ return Reflect.set(tui, property, value, tui);
178
+ },
179
+ has: (_target, property) => Reflect.has(getTui(), property),
180
+ getPrototypeOf: () => Reflect.getPrototypeOf(getTui()),
181
+ });
182
+ }
183
+ export class InteractiveMode {
184
+ runtimeHost;
185
+ renderer;
186
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
187
+ ui;
188
+ mainScreenRenderState;
189
+ loadedResourcesContainer;
190
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
191
+ chatContainer;
192
+ documentContainer;
193
+ transcriptScrollView;
194
+ fullscreenLayoutRoot;
195
+ pendingMessagesContainer;
196
+ statusContainer;
197
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
198
+ defaultEditor;
199
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
200
+ editor;
201
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
202
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
203
+ autocompleteProvider;
204
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
205
+ fdPath;
206
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
207
+ editorContainer;
208
+ activeSelectorToken;
209
+ activeSelectorDispose;
210
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
211
+ footer;
212
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
213
+ footerContainer;
214
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
215
+ footerDataProvider;
216
+ // Stored so the same manager can be injected into custom editors, selectors, and extension UI.
217
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
218
+ keybindings;
219
+ version;
220
+ isInitialized = false;
221
+ onInputCallback;
222
+ pendingUserInputs = [];
223
+ activeStatusIndicator = undefined;
224
+ idleStatus = new IdleStatus();
225
+ workingMessage = undefined;
226
+ workingVisible = true;
227
+ workingIndicatorOptions = undefined;
228
+ defaultWorkingMessage = "Working...";
229
+ defaultHiddenThinkingLabel = "Thinking...";
230
+ hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
231
+ lastSigintTime = 0;
232
+ lastEscapeTime = 0;
233
+ changelogMarkdown = undefined;
234
+ startupNoticesShown = false;
235
+ anthropicSubscriptionWarningShown = false;
236
+ // Status line tracking (for mutating immediately-sequential status updates)
237
+ lastStatusSpacer = undefined;
238
+ lastStatusText = undefined;
239
+ managedToolStatusStarted = false;
240
+ // Streaming message tracking
241
+ streamingComponent = undefined;
242
+ streamingMessage = undefined;
243
+ // Tool execution tracking: toolCallId -> component
244
+ pendingTools = new Map();
245
+ // Tool output expansion state
246
+ /** Host-visible for ./interactive-dialog-ui.ts (S5 slice 2). */
247
+ toolOutputExpanded = false;
248
+ // Thinking block visibility state
249
+ hideThinkingBlock = false;
250
+ outputPad = 1;
251
+ mermaidMarkdownTransformer = createMermaidMarkdownTransformer({
252
+ getMode: () => this.settingsManager.getMermaidRenderingMode(),
253
+ theme,
254
+ });
255
+ // Skill commands: command name -> skill file path
256
+ skillCommands = new Map();
257
+ // Agent subscription unsubscribe function
258
+ unsubscribe;
259
+ signalCleanupHandlers = [];
260
+ // Track if editor is in bash mode (text starts with !)
261
+ isBashMode = false;
262
+ // Track current bash execution component
263
+ bashComponent = undefined;
264
+ // Track pending bash components (shown in pending area, moved to chat on submit)
265
+ pendingBashComponents = [];
266
+ // Auto-compaction state
267
+ autoCompactionEscapeHandler;
268
+ // Auto-retry state
269
+ retryEscapeHandler;
270
+ // Messages queued while compaction is running
271
+ compactionQueuedMessages = [];
272
+ // Shutdown state
273
+ shutdownRequested = false;
274
+ // Extension UI state: host-visible for ./interactive-dialog-ui.ts (S5 slice 2).
275
+ dialogSelector = undefined;
276
+ dialogInput = undefined;
277
+ // Settles the replaced dialog's still-pending promise when a concurrent
278
+ // request mounts a new dialog in the same slot (1A.8: request() settles).
279
+ dialogSelectorReplaced = undefined;
280
+ dialogInputReplaced = undefined;
281
+ dialogEditor = undefined;
282
+ // Layout spacer slots above/below the editor (fixed empty chrome; the legacy extension widget producer is retired).
283
+ widgetContainerAbove;
284
+ widgetContainerBelow;
285
+ // Header container that holds the built-in or custom header
286
+ headerContainer;
287
+ // Built-in header (logo + keybinding hints + changelog)
288
+ builtInHeader = undefined;
289
+ options;
290
+ onRightClickPaste = () => {
291
+ void this.handleRightClickPaste();
292
+ };
293
+ themeController;
294
+ // Convenience accessors
295
+ get session() {
296
+ return this.runtimeHost.session;
297
+ }
298
+ get agent() {
299
+ // 1B.7c: agent-loop control goes through the curated host surface.
300
+ return {
301
+ abort: () => this.session.host.abortAgent(),
302
+ signal: this.session.host.abortSignal,
303
+ };
304
+ }
305
+ /**
306
+ * Constructor-injected settings (D-047): the TUI reads settings from the
307
+ * host-provided manager, never from AgentSession. Internal collaboration
308
+ * surface; exposed for ./interactive-selectors.ts (S5 slice 5).
309
+ */
310
+ get settingsManager() {
311
+ return this.options.settingsManager;
312
+ }
313
+ // Stable facade (阶段 1 slice 1): derived on each access; the facade and
314
+ // `this.session` always resolve to the same AgentSession, so session rebind
315
+ // needs no separate handling.
316
+ /** Internal collaboration surface; exposed for ./interactive-selectors.ts (S5 slice 5). */
317
+ get facade() {
318
+ return createCodingAgentFacade(this.session);
319
+ }
320
+ // Stable runtime facade (阶段 4 slice 3): derived on each access, same
321
+ // pattern as `facade`; runtime session rebinds are picked up automatically.
322
+ /** Internal collaboration surface; exposed for ./interactive-selectors.ts (S5 slice 5). */
323
+ get runtimeFacade() {
324
+ return createCodingAgentRuntimeFacade(this.runtimeHost);
325
+ }
326
+ constructor(runtimeHost, options) {
327
+ // Assign options first: the settingsManager getter reads the injected
328
+ // manager (D-047) and the constructor uses it before anything else.
329
+ this.options = { ...options };
330
+ this.runtimeHost = runtimeHost;
331
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
332
+ const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
333
+ this.options.tuiMode = tuiMode;
334
+ this.runtimeFacade.setBeforeSessionInvalidate(() => {
335
+ this.resetDialogUI();
336
+ });
337
+ this.runtimeFacade.setRebindSession(async () => {
338
+ await this.rebindCurrentSession({ renderBeforeBind: true });
339
+ await this.themeController.applyFromSettings();
340
+ });
341
+ this.version = VERSION;
342
+ this.renderer = createInteractiveTui({
343
+ tuiMode,
344
+ showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
345
+ logDirectory: getAgentDir(),
346
+ onRightClickPaste: this.onRightClickPaste,
347
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
348
+ });
349
+ this.ui = createInteractiveTuiReference(() => this.renderer);
350
+ this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
351
+ this.headerContainer = new Container();
352
+ this.loadedResourcesContainer = new Container();
353
+ this.chatContainer = new Container();
354
+ this.documentContainer = new Container();
355
+ this.documentContainer.addChild(this.headerContainer);
356
+ this.documentContainer.addChild(this.loadedResourcesContainer);
357
+ this.documentContainer.addChild(this.chatContainer);
358
+ this.pendingMessagesContainer = new Container();
359
+ this.statusContainer = new Container();
360
+ this.widgetContainerAbove = new Container();
361
+ // Fixed empty state (single spacer): matches the retired widget renderer's empty layout.
362
+ this.widgetContainerAbove.addChild(new Spacer(1));
363
+ this.widgetContainerBelow = new Container();
364
+ this.keybindings = KeybindingsManager.create();
365
+ setKeybindings(this.keybindings);
366
+ const editorPaddingX = this.settingsManager.getEditorPaddingX();
367
+ const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
368
+ this.defaultEditor = new CustomEditor(this.ui, getEditorTheme(), this.keybindings, {
369
+ paddingX: editorPaddingX,
370
+ autocompleteMaxVisible,
371
+ });
372
+ this.editor = this.defaultEditor;
373
+ this.editorContainer = new Container();
374
+ this.editorContainer.addChild(this.editor);
375
+ this.footerDataProvider = new FooterDataProvider(this.facade.getCwd());
376
+ this.footer = new FooterComponent(this.session, this.footerDataProvider);
377
+ this.footer.setAutoCompactEnabled(this.facade.isAutoCompactionEnabled());
378
+ this.footerContainer = new Container();
379
+ this.footerContainer.addChild(this.footer);
380
+ // Load hide thinking block setting
381
+ this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
382
+ this.outputPad = this.settingsManager.getOutputPad();
383
+ // Register themes from resource loader and initialize
384
+ setRegisteredThemes(buildRegisteredThemes(this.facade.getThemes().themes));
385
+ this.themeController = new InteractiveThemeController(this.ui, {
386
+ getSettingsManager: () => this.settingsManager,
387
+ showError: (message) => this.showError(message),
388
+ onChanged: () => this.updateEditorBorderColor(),
389
+ initialThemeSetting: options.initialThemeSetting,
390
+ });
391
+ }
392
+ getAutocompleteSourceTag(sourceInfo) {
393
+ if (!sourceInfo) {
394
+ return undefined;
395
+ }
396
+ const scopePrefix = sourceInfo.scope === "user" ? "u" : sourceInfo.scope === "project" ? "p" : "t";
397
+ const source = sourceInfo.source.trim();
398
+ if (source === "auto" || source === "local" || source === "cli") {
399
+ return scopePrefix;
400
+ }
401
+ if (source.startsWith("npm:")) {
402
+ return `${scopePrefix}:${source}`;
403
+ }
404
+ const gitSource = parseGitUrl(source);
405
+ if (gitSource) {
406
+ const ref = gitSource.ref ? `@${gitSource.ref}` : "";
407
+ return `${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`;
408
+ }
409
+ return scopePrefix;
410
+ }
411
+ prefixAutocompleteDescription(description, sourceInfo) {
412
+ const sourceTag = this.getAutocompleteSourceTag(sourceInfo);
413
+ if (!sourceTag) {
414
+ return description;
415
+ }
416
+ return description ? `[${sourceTag}] ${description}` : `[${sourceTag}]`;
417
+ }
418
+ createBaseAutocompleteProvider() {
419
+ // Define commands for autocomplete
420
+ const slashCommands = BUILTIN_SLASH_COMMANDS.map((command) => ({
421
+ name: command.name,
422
+ description: command.description,
423
+ ...(command.argumentHint && { argumentHint: command.argumentHint }),
424
+ }));
425
+ const modelCommand = slashCommands.find((command) => command.name === "model");
426
+ // v8 ignore next -- BUILTIN_SLASH_COMMANDS 恒含 model,find 必命中
427
+ if (modelCommand) {
428
+ modelCommand.getArgumentCompletions = (prefix) => {
429
+ const models = this.facade.getScopedModels().length > 0
430
+ ? this.facade.getScopedModels().map((s) => s.model)
431
+ : this.facade.getAvailableModels();
432
+ if (models.length === 0)
433
+ return null;
434
+ // Create items with provider/id format
435
+ const items = models.map((m) => ({
436
+ id: m.id,
437
+ provider: m.provider,
438
+ name: m.name,
439
+ label: `${m.provider}/${m.id}`,
440
+ }));
441
+ return createFuzzyAutocompleteItems(items, prefix, getModelSearchText, (item) => ({
442
+ value: item.label,
443
+ label: item.id,
444
+ description: item.provider,
445
+ }));
446
+ };
447
+ }
448
+ const thinkingCommand = slashCommands.find((command) => command.name === "thinking");
449
+ // v8 ignore next -- BUILTIN_SLASH_COMMANDS 恒含 thinking,find 必命中
450
+ if (thinkingCommand) {
451
+ thinkingCommand.getArgumentCompletions = (prefix) => {
452
+ return createFuzzyAutocompleteItems(this.facade.getAvailableThinkingLevels(), prefix, (level) => level, (level) => ({
453
+ value: level,
454
+ label: level,
455
+ }));
456
+ };
457
+ }
458
+ const suiteCommand = slashCommands.find((command) => command.name === "suite");
459
+ // v8 ignore next -- BUILTIN_SLASH_COMMANDS 恒含 suite,find 必命中
460
+ if (suiteCommand) {
461
+ suiteCommand.getArgumentCompletions = (prefix) => {
462
+ return createFuzzyAutocompleteItems(listSuiteIds(getAgentDir()), prefix, (id) => id, (id) => ({
463
+ value: id,
464
+ label: id,
465
+ }));
466
+ };
467
+ }
468
+ const loginCommand = slashCommands.find((command) => command.name === "login");
469
+ // v8 ignore next -- BUILTIN_SLASH_COMMANDS 恒含 login,find 必命中
470
+ if (loginCommand) {
471
+ loginCommand.getArgumentCompletions = (prefix) => {
472
+ const providers = getLoginProviderCompletionOptions(this.getLoginProviderOptions());
473
+ return createFuzzyAutocompleteItems(providers, prefix, getLoginProviderSearchText, (provider) => ({
474
+ value: provider.id,
475
+ label: provider.id,
476
+ description: formatLoginProviderCompletionDescription(provider),
477
+ }));
478
+ };
479
+ }
480
+ const capabilityRegistrations = this.session.getCapabilityRuntime().listCommands();
481
+ const capabilityCommandNames = new Set(capabilityRegistrations.map(({ definition }) => definition.name));
482
+ // Conflicting command names are rejected by AgentSession rather than silently
483
+ // selecting a source, so do not offer either side as an executable completion.
484
+ const templateCommands = this.facade
485
+ .getPromptTemplates()
486
+ .filter((cmd) => !capabilityCommandNames.has(cmd.name))
487
+ .map((cmd) => ({
488
+ name: cmd.name,
489
+ description: this.prefixAutocompleteDescription(cmd.description, cmd.sourceInfo),
490
+ ...(cmd.argumentHint && { argumentHint: cmd.argumentHint }),
491
+ }));
492
+ const builtinCommandNames = new Set(slashCommands.map((c) => c.name));
493
+ const resourceSkillCommandNames = new Set(this.facade.getSkills().skills.map((skill) => `skill:${skill.name}`));
494
+ const capabilityCommands = capabilityRegistrations
495
+ .filter(({ definition }) => !builtinCommandNames.has(definition.name) &&
496
+ !this.facade.getPromptTemplates().some((template) => template.name === definition.name) &&
497
+ !resourceSkillCommandNames.has(definition.name))
498
+ .map(({ definition }) => ({
499
+ name: definition.name,
500
+ description: definition.description,
501
+ ...(definition.argumentHint && { argumentHint: definition.argumentHint }),
502
+ }));
503
+ // Build skill commands from session.skills (if enabled)
504
+ this.skillCommands.clear();
505
+ const skillCommandList = [];
506
+ if (this.settingsManager.getEnableSkillCommands()) {
507
+ for (const skill of this.facade.getSkills().skills) {
508
+ const commandName = `skill:${skill.name}`;
509
+ if (capabilityCommandNames.has(commandName))
510
+ continue;
511
+ this.skillCommands.set(commandName, skill.filePath);
512
+ skillCommandList.push({
513
+ name: commandName,
514
+ description: this.prefixAutocompleteDescription(skill.description, skill.sourceInfo),
515
+ });
516
+ }
517
+ }
518
+ return new CombinedAutocompleteProvider([...slashCommands, ...templateCommands, ...capabilityCommands, ...skillCommandList], this.facade.getCwd(), this.fdPath);
519
+ }
520
+ setupAutocompleteProvider() {
521
+ const provider = this.createBaseAutocompleteProvider();
522
+ this.autocompleteProvider = provider;
523
+ this.defaultEditor.setAutocompleteProvider(provider);
524
+ if (this.editor !== this.defaultEditor) {
525
+ this.editor.setAutocompleteProvider?.(provider);
526
+ }
527
+ }
528
+ showStartupNoticesIfNeeded() {
529
+ if (this.startupNoticesShown) {
530
+ return;
531
+ }
532
+ this.startupNoticesShown = true;
533
+ if (!this.changelogMarkdown) {
534
+ return;
535
+ }
536
+ if (this.chatContainer.children.length > 0) {
537
+ this.chatContainer.addChild(new Spacer(1));
538
+ }
539
+ this.chatContainer.addChild(new DynamicBorder());
540
+ if (this.settingsManager.getCollapseChangelog()) {
541
+ const versionMatch = this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/);
542
+ const latestVersion = versionMatch ? versionMatch[1] : this.version;
543
+ const condensedText = `Updated to v${latestVersion}. Use ${theme.bold("/changelog")} to view full changelog.`;
544
+ this.chatContainer.addChild(new Text(condensedText, 1, 0));
545
+ }
546
+ else {
547
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
548
+ this.chatContainer.addChild(new Spacer(1));
549
+ this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
550
+ this.chatContainer.addChild(new Spacer(1));
551
+ }
552
+ this.chatContainer.addChild(new DynamicBorder());
553
+ }
554
+ mountInteractiveTui(tui, components) {
555
+ for (const component of components)
556
+ tui.addChild(component);
557
+ if (TuiLayouts.isViewportTUI(tui)) {
558
+ if (!this.fullscreenLayoutRoot)
559
+ throw new Error("Fullscreen layout is not initialized");
560
+ tui.setLayoutRoot(this.fullscreenLayoutRoot);
561
+ }
562
+ }
563
+ stopInteractiveTui(fullscreenExitOutput) {
564
+ if (this.renderer.mode === "fullscreen" && fullscreenExitOutput === "transcript") {
565
+ while (this.renderer.hasOverlayEntries)
566
+ this.renderer.hideOverlay();
567
+ this.switchTuiMode("regular", false, false);
568
+ this.renderer.renderNow();
569
+ }
570
+ this.ui.stop({ preserveScreen: this.renderer.mode === "fullscreen" });
571
+ }
572
+ switchTuiMode(mode, restoreProgress = true, startRenderer = true) {
573
+ const previousUi = this.renderer;
574
+ if (mode === previousUi.mode)
575
+ return true;
576
+ if (previousUi.hasOverlayEntries)
577
+ return false;
578
+ const components = [...previousUi.children];
579
+ const focus = previousUi.getFocusedComponent();
580
+ const terminal = previousUi.terminal;
581
+ const showHardwareCursor = previousUi.getShowHardwareCursor();
582
+ const clearOnShrink = previousUi.getClearOnShrink();
583
+ const onDebug = previousUi.onDebug;
584
+ if (previousUi instanceof TuiMainScreen) {
585
+ this.mainScreenRenderState = previousUi.captureRenderState();
586
+ }
587
+ previousUi.stop({ preserveScreen: true });
588
+ previousUi.setFocus(null);
589
+ previousUi.clear();
590
+ if (TuiLayouts.isViewportTUI(previousUi))
591
+ previousUi.setLayoutRoot(undefined);
592
+ const nextUi = createInteractiveTui({
593
+ tuiMode: mode,
594
+ showHardwareCursor,
595
+ logDirectory: getAgentDir(),
596
+ terminal,
597
+ onRightClickPaste: this.onRightClickPaste,
598
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
599
+ });
600
+ nextUi.setClearOnShrink(clearOnShrink);
601
+ nextUi.onDebug = onDebug;
602
+ if (nextUi instanceof TuiMainScreen && this.mainScreenRenderState) {
603
+ nextUi.restoreRenderState(this.mainScreenRenderState);
604
+ }
605
+ this.renderer = nextUi;
606
+ this.options.tuiMode = mode;
607
+ this.mountInteractiveTui(nextUi, components);
608
+ nextUi.invalidate();
609
+ nextUi.setFocus(focus);
610
+ if (!startRenderer)
611
+ return true;
612
+ nextUi.start();
613
+ this.themeController.rebindTui();
614
+ if (restoreProgress &&
615
+ this.settingsManager.getShowTerminalProgress() &&
616
+ (this.facade.isStreaming() || this.facade.isCompacting())) {
617
+ terminal.setProgress(true);
618
+ }
619
+ return true;
620
+ }
621
+ async init() {
622
+ if (this.isInitialized)
623
+ return;
624
+ this.registerSignalHandlers();
625
+ // Load changelog (only show new entries, skip for resumed sessions)
626
+ this.changelogMarkdown = this.getChangelogForDisplay();
627
+ if (this.facade.getScopedModels().length > 0 &&
628
+ (this.options.verbose || !this.settingsManager.getQuietStartup())) {
629
+ const modelList = this.facade
630
+ .getScopedModels()
631
+ .map((sm) => {
632
+ const thinkingStr = sm.thinkingLevel ? `:${sm.thinkingLevel}` : "";
633
+ return `${sm.model.id}${thinkingStr}`;
634
+ })
635
+ .join(", ");
636
+ const cycleKeys = this.keybindings.getKeys("app.model.cycleForward");
637
+ const cycleHint = cycleKeys.length > 0
638
+ ? theme.fg("muted", ` (${formatKeyText(cycleKeys.join("/"), { capitalize: true })} to cycle)`)
639
+ : "";
640
+ console.log(theme.fg("dim", `Model scope: ${modelList}${cycleHint}`));
641
+ }
642
+ // Keep one component tree and remount it when changing renderers.
643
+ // Widget chrome is fixed empty; no initialization render needed.
644
+ this.transcriptScrollView = new TuiLayouts.ScrollView(this.documentContainer, {
645
+ follow: "end",
646
+ primary: true,
647
+ overscroll: "chain",
648
+ scrollbar: this.settingsManager.getFullscreenScrollbar(),
649
+ scrollbarStyle: (text) => theme.bg("scrollbarThumb", text),
650
+ });
651
+ const dock = new TuiLayouts.VStack([
652
+ { component: this.pendingMessagesContainer, shrink: 1, minSize: 0 },
653
+ { component: this.statusContainer, shrink: 1, minSize: 0 },
654
+ { component: this.widgetContainerAbove, shrink: 1, minSize: 0 },
655
+ { component: this.editorContainer, shrink: 1, minSize: 3 },
656
+ { component: this.widgetContainerBelow, shrink: 1, minSize: 0 },
657
+ { component: this.footerContainer, shrink: 1, minSize: 1 },
658
+ ]);
659
+ this.fullscreenLayoutRoot = new TuiLayouts.VStack([
660
+ { component: this.transcriptScrollView, basis: 0, grow: 1, shrink: 1, minSize: 1 },
661
+ { component: dock, basis: "auto", grow: 0, shrink: 1, minSize: 1 },
662
+ ]);
663
+ this.mountInteractiveTui(this.renderer, [
664
+ this.documentContainer,
665
+ this.pendingMessagesContainer,
666
+ this.statusContainer,
667
+ this.widgetContainerAbove,
668
+ this.editorContainer,
669
+ this.widgetContainerBelow,
670
+ this.footerContainer,
671
+ ]);
672
+ // Accept text while startup completes, but only enable interrupt, exit, and submission feedback.
673
+ this.defaultEditor.onAction("app.clear", () => this.handleCtrlC());
674
+ this.defaultEditor.onCtrlD = () => this.handleCtrlD();
675
+ this.defaultEditor.onSubmit = (text) => this.handleStartupSubmit(text);
676
+ this.ui.setFocus(this.editor);
677
+ // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
678
+ this.ui.start();
679
+ this.isInitialized = true;
680
+ await this.themeController.applyFromSettings();
681
+ // Add header with keybindings from config (unless silenced)
682
+ if (this.options.verbose || !this.settingsManager.getQuietStartup()) {
683
+ const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
684
+ // Build startup instructions using keybinding hint helpers
685
+ const hint = (keybinding, description) => keyHint(keybinding, description);
686
+ const expandedInstructions = [
687
+ hint("app.interrupt", "to interrupt"),
688
+ hint("app.clear", "to clear"),
689
+ rawKeyHint(`${keyText("app.clear")} twice`, "to exit"),
690
+ hint("app.exit", "to exit (empty)"),
691
+ hint("app.suspend", "to suspend"),
692
+ keyHint("tui.editor.deleteToLineEnd", "to delete to end"),
693
+ hint("app.thinking.cycle", "to cycle thinking level"),
694
+ rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`, "to cycle models"),
695
+ hint("app.model.select", "to select model"),
696
+ hint("app.tools.expand", "to expand tools"),
697
+ hint("app.thinking.toggle", "to expand thinking"),
698
+ hint("app.editor.external", "for external editor"),
699
+ rawKeyHint("/", "for commands"),
700
+ rawKeyHint("!", "to run bash"),
701
+ rawKeyHint("!!", "to run bash (no context)"),
702
+ hint("app.message.followUp", "to queue follow-up"),
703
+ hint("app.message.dequeue", "to edit all queued messages"),
704
+ hint("app.clipboard.pasteImage", "to paste image (with text fallback)"),
705
+ rawKeyHint("drop files", "to attach"),
706
+ ].join("\n");
707
+ const compactInstructions = [
708
+ hint("app.interrupt", "interrupt"),
709
+ rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`, "clear/exit"),
710
+ rawKeyHint("/", "commands"),
711
+ rawKeyHint("!", "bash"),
712
+ hint("app.tools.expand", "more"),
713
+ ].join(theme.fg("muted", " · "));
714
+ const compactOnboarding = theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help and loaded resources.`);
715
+ const onboarding = theme.fg("dim", `Agent Forge can explain its own features and look up its docs. Ask it how to use or extend Agent Forge.`);
716
+ this.builtInHeader = new ExpandableText(() => `${logo}\n${compactInstructions}\n${compactOnboarding}\n\n${onboarding}`, () => `${logo}\n${expandedInstructions}\n\n${onboarding}`, this.getStartupExpansionState(), 1, 0);
717
+ // Setup UI layout
718
+ this.headerContainer.addChild(new Spacer(1));
719
+ this.headerContainer.addChild(this.builtInHeader);
720
+ this.headerContainer.addChild(new Spacer(1));
721
+ }
722
+ else {
723
+ // Minimal header when silenced
724
+ this.builtInHeader = new Text("", 0, 0);
725
+ this.headerContainer.addChild(this.builtInHeader);
726
+ }
727
+ this.ui.requestRender();
728
+ // Ensure fd and rg are available after mounting the TUI (downloads if missing, adds to PATH via getBinDir)
729
+ // so slow downloads do not make startup appear frozen.
730
+ // Both are needed: fd for autocomplete, rg for grep tool and bash commands.
731
+ const [fdPath] = await Promise.all([
732
+ ensureTool("fd", (status) => this.showManagedToolStatus(status)),
733
+ ensureTool("rg", (status) => this.showManagedToolStatus(status)),
734
+ ]);
735
+ this.fdPath = fdPath;
736
+ // Enable the remaining input handlers only after managed-tool setup completes.
737
+ this.setupKeyHandlers();
738
+ this.setupEditorSubmitHandler();
739
+ this.ui.requestRender();
740
+ // Initialize extensions first so resources are shown before messages
741
+ await this.rebindCurrentSession();
742
+ // Render initial messages AFTER showing loaded resources
743
+ this.renderInitialMessages();
744
+ // Cross-suite resume detection (设计 §10.1 最小可用版): a `-c`/resumed
745
+ // session may carry a binding from a different suite than the one the
746
+ // runtime just assembled it with. Record the fact; conversion is out of
747
+ // scope.
748
+ this.detectCrossSuiteResume();
749
+ // Set up theme file watcher
750
+ onThemeChange(() => {
751
+ this.ui.invalidate();
752
+ this.updateEditorBorderColor();
753
+ this.ui.requestRender();
754
+ });
755
+ // Set up git branch watcher (uses provider instead of footer)
756
+ this.footerDataProvider.onBranchChange(() => {
757
+ this.ui.requestRender();
758
+ });
759
+ // Initialize available provider count for footer display
760
+ await this.updateAvailableProviderCount();
761
+ // Unresolved startup suite id (设计 §9): with the TUI ready, let the user
762
+ // pick a suite before the first prompt; the session is then rebuilt with
763
+ // the selected suite. print/RPC never reach here (structured exit in main.ts).
764
+ if (this.options.pendingSuiteSelector) {
765
+ await this.showStartupSuiteSelector(this.options.pendingSuiteSelector);
766
+ }
767
+ // Flush the completed startup state before loading the remaining syntax grammars.
768
+ this.ui.renderNow();
769
+ void loadAllHighlightLanguages().then(() => {
770
+ if (!this.isInitialized)
771
+ return;
772
+ this.ui.invalidate();
773
+ this.ui.requestRender();
774
+ });
775
+ }
776
+ /**
777
+ * Update terminal title with session name and cwd.
778
+ */
779
+ updateTerminalTitle() {
780
+ const cwdBasename = path.basename(this.facade.getCwd());
781
+ const sessionName = this.facade.getSessionName();
782
+ if (sessionName) {
783
+ this.ui.terminal.setTitle(`${APP_TITLE} - ${sessionName} - ${cwdBasename}`);
784
+ }
785
+ else {
786
+ this.ui.terminal.setTitle(`${APP_TITLE} - ${cwdBasename}`);
787
+ }
788
+ }
789
+ /**
790
+ * Run the interactive mode. This is the main entry point.
791
+ * Initializes the UI, shows warnings, processes initial messages, and starts the interactive loop.
792
+ */
793
+ async run() {
794
+ await this.init();
795
+ if (!process.env.AGENT_FORGE_OFFLINE) {
796
+ const controller = new AbortController();
797
+ const timeout = setTimeout(() => controller.abort(), 15_000);
798
+ void refreshModelCatalogs(this.facade.getModelCatalog(), controller.signal)
799
+ .then(() => this.updateAvailableProviderCount())
800
+ .catch(() => { })
801
+ .finally(() => clearTimeout(timeout));
802
+ }
803
+ // Start version check asynchronously
804
+ checkForNewVersion(this.version).then((newRelease) => {
805
+ if (newRelease) {
806
+ this.showNewVersionNotification(newRelease);
807
+ }
808
+ });
809
+ // Start package update check asynchronously
810
+ this.checkForPackageUpdates()
811
+ .then((updates) => {
812
+ if (updates.length > 0) {
813
+ this.showPackageUpdateNotification(updates);
814
+ }
815
+ })
816
+ .finally(() => {
817
+ // On Windows, npm can overwrite the shared console title while checking
818
+ // extension package versions. Restore the product title after the startup check.
819
+ if (process.platform === "win32" && this.isInitialized) {
820
+ this.updateTerminalTitle();
821
+ }
822
+ });
823
+ // Check tmux keyboard setup asynchronously
824
+ this.checkTmuxKeyboardSetup().then((warning) => {
825
+ if (warning) {
826
+ this.showWarning(warning);
827
+ }
828
+ });
829
+ // Show startup warnings
830
+ const { migratedProviders, startupDiagnostics, modelFallbackMessage, initialMessage, initialImages, initialMessages, } = this.options;
831
+ for (const diagnostic of startupDiagnostics ?? []) {
832
+ if (diagnostic.type === "error") {
833
+ this.showError(diagnostic.message);
834
+ }
835
+ else if (diagnostic.type === "warning") {
836
+ this.showWarning(diagnostic.message);
837
+ }
838
+ else {
839
+ this.showStatus(diagnostic.message);
840
+ }
841
+ }
842
+ if (migratedProviders && migratedProviders.length > 0) {
843
+ this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
844
+ }
845
+ const modelsJsonError = this.facade.getModelsError();
846
+ if (modelsJsonError) {
847
+ this.showError(`models.json error: ${modelsJsonError}`);
848
+ }
849
+ if (modelFallbackMessage) {
850
+ this.showWarning(modelFallbackMessage);
851
+ }
852
+ void this.maybeWarnAboutAnthropicSubscriptionAuth();
853
+ // Process initial messages
854
+ if (initialMessage) {
855
+ try {
856
+ await this.facade.prompt(initialMessage, { images: initialImages });
857
+ }
858
+ catch (error) {
859
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
860
+ this.showError(errorMessage);
861
+ }
862
+ }
863
+ if (initialMessages) {
864
+ for (const message of initialMessages) {
865
+ try {
866
+ await this.facade.prompt(message);
867
+ }
868
+ catch (error) {
869
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
870
+ this.showError(errorMessage);
871
+ }
872
+ }
873
+ }
874
+ // Main interactive loop
875
+ while (true) {
876
+ const userInput = await this.getUserInput();
877
+ try {
878
+ await this.promptWithEmptyReplyRetry(userInput);
879
+ }
880
+ catch (error) {
881
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
882
+ this.showError(errorMessage);
883
+ }
884
+ }
885
+ }
886
+ /**
887
+ * One-shot empty-reply auto-continuation (#5, print-mode parity): when a
888
+ * submitted turn finishes with an empty assistant text — and the model was
889
+ * neither aborted nor errored — nudge the model once to continue the task.
890
+ * The retry itself is never retried, so the budget is capped at one
891
+ * continuation per submission and this cannot loop.
892
+ */
893
+ async promptWithEmptyReplyRetry(text) {
894
+ const seen = this.facade.getState().messages.length;
895
+ await this.facade.prompt(text);
896
+ const lastAssistant = [...this.facade.getState().messages.slice(seen)]
897
+ .reverse()
898
+ .find((m) => m.role === "assistant");
899
+ if (lastAssistant === undefined)
900
+ return;
901
+ if (lastAssistant.stopReason === "error" || lastAssistant.stopReason === "aborted")
902
+ return;
903
+ if (contentText(lastAssistant.content).trim().length > 0)
904
+ return;
905
+ this.showStatus("Previous reply was empty, retrying...");
906
+ await this.facade.prompt(EMPTY_REPLY_RETRY_PROMPT);
907
+ }
908
+ async checkForPackageUpdates() {
909
+ if (process.env.AGENT_FORGE_OFFLINE) {
910
+ return [];
911
+ }
912
+ try {
913
+ const packageManager = new DefaultPackageManager({
914
+ cwd: this.facade.getCwd(),
915
+ agentDir: getAgentDir(),
916
+ settingsManager: this.settingsManager,
917
+ });
918
+ const updates = await packageManager.checkForAvailableUpdates();
919
+ return updates.map((update) => update.displayName);
920
+ }
921
+ catch {
922
+ return [];
923
+ }
924
+ }
925
+ async checkTmuxKeyboardSetup() {
926
+ if (!process.env.TMUX)
927
+ return undefined;
928
+ const runTmuxShow = (option) => {
929
+ return new Promise((resolve) => {
930
+ const proc = spawn("tmux", ["show", "-gv", option], {
931
+ stdio: ["ignore", "pipe", "ignore"],
932
+ });
933
+ let stdout = "";
934
+ const timer = setTimeout(() => {
935
+ proc.kill();
936
+ resolve(undefined);
937
+ }, 2000);
938
+ proc.stdout?.on("data", (data) => {
939
+ stdout += data.toString();
940
+ });
941
+ proc.on("error", () => {
942
+ clearTimeout(timer);
943
+ resolve(undefined);
944
+ });
945
+ proc.on("close", (code) => {
946
+ clearTimeout(timer);
947
+ resolve(code === 0 ? stdout.trim() : undefined);
948
+ });
949
+ });
950
+ };
951
+ const [extendedKeys, extendedKeysFormat] = await Promise.all([
952
+ runTmuxShow("extended-keys"),
953
+ runTmuxShow("extended-keys-format"),
954
+ ]);
955
+ // If we couldn't query tmux (timeout, sandbox, etc.), don't warn
956
+ if (extendedKeys === undefined)
957
+ return undefined;
958
+ if (extendedKeys !== "on" && extendedKeys !== "always") {
959
+ return "tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.";
960
+ }
961
+ if (extendedKeysFormat === "xterm") {
962
+ return "tmux extended-keys-format is xterm. Agent Forge works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.";
963
+ }
964
+ return undefined;
965
+ }
966
+ /**
967
+ * Get changelog entries to display on startup.
968
+ * Only shows new entries since last seen version, skips for resumed sessions.
969
+ */
970
+ getChangelogForDisplay() {
971
+ // Skip changelog for resumed/continued sessions (already have messages)
972
+ if (this.facade.getState().messages.length > 0) {
973
+ return undefined;
974
+ }
975
+ const lastVersion = this.settingsManager.getLastChangelogVersion();
976
+ const changelogPath = getChangelogPath();
977
+ const entries = parseChangelog(changelogPath);
978
+ if (!lastVersion) {
979
+ // Fresh install - record the version, don't show changelog
980
+ this.settingsManager.setLastChangelogVersion(VERSION);
981
+ return undefined;
982
+ }
983
+ const newEntries = getNewEntries(entries, lastVersion);
984
+ if (newEntries.length > 0) {
985
+ this.settingsManager.setLastChangelogVersion(VERSION);
986
+ return newEntries.map((e) => normalizeChangelogLinks(e.content, e)).join("\n\n");
987
+ }
988
+ return undefined;
989
+ }
990
+ getMarkdownThemeWithSettings() {
991
+ return {
992
+ ...getMarkdownTheme(),
993
+ codeBlockIndent: this.settingsManager.getCodeBlockIndent(),
994
+ };
995
+ }
996
+ // =========================================================================
997
+ // Extension System
998
+ // =========================================================================
999
+ formatDisplayPath(p) {
1000
+ return formatDisplayPath(p);
1001
+ }
1002
+ formatContextPath(p) {
1003
+ return formatContextPath(p, this.facade.getCwd());
1004
+ }
1005
+ getStartupExpansionState() {
1006
+ return this.options.verbose || this.toolOutputExpanded;
1007
+ }
1008
+ /**
1009
+ * Get a short path relative to the package root for display.
1010
+ */
1011
+ getShortPath(fullPath, sourceInfo) {
1012
+ return getShortPath(fullPath, sourceInfo);
1013
+ }
1014
+ getCompactPathLabel(resourcePath, sourceInfo) {
1015
+ return getCompactPathLabel(resourcePath, sourceInfo);
1016
+ }
1017
+ // The following formatting delegates have no in-class call sites (their
1018
+ // implementations moved to interactive-format.ts) but remain part of the
1019
+ // prototype contract, so they stay public instead of private.
1020
+ getCompactPackageSourceLabel(sourceInfo) {
1021
+ return getCompactPackageSourceLabel(sourceInfo);
1022
+ }
1023
+ getDisplaySourceInfo(sourceInfo) {
1024
+ return getDisplaySourceInfo(sourceInfo);
1025
+ }
1026
+ getScopeGroup(sourceInfo) {
1027
+ return getScopeGroup(sourceInfo);
1028
+ }
1029
+ isPackageSource(sourceInfo) {
1030
+ return isPackageSource(sourceInfo);
1031
+ }
1032
+ buildScopeGroups(items) {
1033
+ return buildScopeGroups(items);
1034
+ }
1035
+ formatScopeGroups(groups, options) {
1036
+ return formatScopeGroups(groups, options);
1037
+ }
1038
+ findSourceInfoForPath(p, sourceInfos) {
1039
+ return findSourceInfoForPath(p, sourceInfos);
1040
+ }
1041
+ formatPathWithSource(p, sourceInfo) {
1042
+ return formatPathWithSource(p, sourceInfo);
1043
+ }
1044
+ formatDiagnostics(diagnostics, sourceInfos) {
1045
+ return formatDiagnostics(diagnostics, sourceInfos);
1046
+ }
1047
+ showLoadedResources(options) {
1048
+ // Resource rendering is idempotent; chat clears no longer clear this separate container.
1049
+ this.loadedResourcesContainer.clear();
1050
+ const showListing = options?.force || this.options.verbose || !this.settingsManager.getQuietStartup();
1051
+ const showDiagnostics = showListing || options?.showDiagnosticsWhenQuiet === true;
1052
+ if (!showListing && !showDiagnostics) {
1053
+ return;
1054
+ }
1055
+ const sectionHeader = (name, color = "mdHeading") => theme.fg(color, `[${name}]`);
1056
+ const formatCompactList = (items, options) => {
1057
+ const labels = items.map((item) => item.trim()).filter((item) => item.length > 0);
1058
+ if (options?.sort !== false) {
1059
+ labels.sort((a, b) => a.localeCompare(b));
1060
+ }
1061
+ return theme.fg("dim", ` ${labels.join(", ")}`);
1062
+ };
1063
+ const addLoadedSection = (name, collapsedBody, expandedBody = collapsedBody, color = "mdHeading") => {
1064
+ const section = new ExpandableText(() => `${sectionHeader(name, color)}\n${collapsedBody}`, () => `${sectionHeader(name, color)}\n${expandedBody}`, this.getStartupExpansionState(), 0, 0);
1065
+ this.loadedResourcesContainer.addChild(section);
1066
+ this.loadedResourcesContainer.addChild(new Spacer(1));
1067
+ };
1068
+ const skillsResult = this.facade.getSkills();
1069
+ const promptsResult = this.facade.getPrompts();
1070
+ const themesResult = this.facade.getThemes();
1071
+ const sourceInfos = new Map();
1072
+ for (const skill of skillsResult.skills) {
1073
+ if (skill.sourceInfo) {
1074
+ sourceInfos.set(skill.filePath, skill.sourceInfo);
1075
+ }
1076
+ }
1077
+ for (const prompt of promptsResult.prompts) {
1078
+ if (prompt.sourceInfo) {
1079
+ sourceInfos.set(prompt.filePath, prompt.sourceInfo);
1080
+ }
1081
+ }
1082
+ for (const loadedTheme of themesResult.themes) {
1083
+ if (loadedTheme.sourcePath && loadedTheme.sourceInfo) {
1084
+ sourceInfos.set(loadedTheme.sourcePath, loadedTheme.sourceInfo);
1085
+ }
1086
+ }
1087
+ if (showListing) {
1088
+ const systemPromptSource = this.facade.getSystemPromptSource();
1089
+ const contextFiles = [
1090
+ ...(systemPromptSource ? [systemPromptSource] : []),
1091
+ ...this.facade.getAppendSystemPromptSources(),
1092
+ ...this.facade.getAgentsFiles().agentsFiles,
1093
+ ];
1094
+ if (contextFiles.length > 0) {
1095
+ this.loadedResourcesContainer.addChild(new Spacer(1));
1096
+ const contextList = contextFiles
1097
+ .map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`))
1098
+ .join("\n");
1099
+ const contextCompactList = formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
1100
+ addLoadedSection("Context", contextCompactList, contextList);
1101
+ }
1102
+ const skills = skillsResult.skills;
1103
+ if (skills.length > 0) {
1104
+ const groups = this.buildScopeGroups(skills.map((skill) => ({ path: skill.filePath, sourceInfo: skill.sourceInfo })));
1105
+ const skillList = this.formatScopeGroups(groups, {
1106
+ formatPath: (item) => this.formatDisplayPath(item.path),
1107
+ formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1108
+ });
1109
+ const skillCompactList = formatCompactList(skills.map((skill) => skill.name));
1110
+ addLoadedSection("Skills", skillCompactList, skillList);
1111
+ }
1112
+ const templates = this.facade.getPromptTemplates();
1113
+ if (templates.length > 0) {
1114
+ const groups = this.buildScopeGroups(templates.map((template) => ({ path: template.filePath, sourceInfo: template.sourceInfo })));
1115
+ const templateByPath = new Map(templates.map((t) => [t.filePath, t]));
1116
+ const templateList = this.formatScopeGroups(groups, {
1117
+ formatPath: (item) => {
1118
+ const template = templateByPath.get(item.path);
1119
+ // v8 ignore next -- templateByPath is built from the same templates as the groups
1120
+ return template ? `/${template.name}` : this.formatDisplayPath(item.path);
1121
+ },
1122
+ formatPackagePath: (item) => {
1123
+ const template = templateByPath.get(item.path);
1124
+ // v8 ignore next -- templateByPath is built from the same templates as the groups
1125
+ return template ? `/${template.name}` : this.formatDisplayPath(item.path);
1126
+ },
1127
+ });
1128
+ const promptCompactList = formatCompactList(templates.map((template) => `/${template.name}`));
1129
+ addLoadedSection("Prompts", promptCompactList, templateList);
1130
+ }
1131
+ // Show loaded themes (excluding built-in)
1132
+ const loadedThemes = themesResult.themes;
1133
+ const customThemes = loadedThemes.filter((t) => t.sourcePath);
1134
+ if (customThemes.length > 0) {
1135
+ const groups = this.buildScopeGroups(customThemes.map((loadedTheme) => ({
1136
+ path: loadedTheme.sourcePath,
1137
+ sourceInfo: loadedTheme.sourceInfo,
1138
+ })));
1139
+ const themeList = this.formatScopeGroups(groups, {
1140
+ formatPath: (item) => this.formatDisplayPath(item.path),
1141
+ formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1142
+ });
1143
+ const themeCompactList = formatCompactList(customThemes.map((loadedTheme) => loadedTheme.name ?? this.getCompactPathLabel(loadedTheme.sourcePath, loadedTheme.sourceInfo)));
1144
+ addLoadedSection("Themes", themeCompactList, themeList);
1145
+ }
1146
+ }
1147
+ // v8 ignore next -- showDiagnostics 为假时上方已提前返回,此处恒为真
1148
+ if (showDiagnostics) {
1149
+ const skillDiagnostics = skillsResult.diagnostics;
1150
+ if (skillDiagnostics.length > 0) {
1151
+ const warningLines = this.formatDiagnostics(skillDiagnostics, sourceInfos);
1152
+ this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Skill conflicts]")}\n${warningLines}`, 0, 0));
1153
+ this.loadedResourcesContainer.addChild(new Spacer(1));
1154
+ }
1155
+ const promptDiagnostics = promptsResult.diagnostics;
1156
+ if (promptDiagnostics.length > 0) {
1157
+ const warningLines = this.formatDiagnostics(promptDiagnostics, sourceInfos);
1158
+ this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines}`, 0, 0));
1159
+ this.loadedResourcesContainer.addChild(new Spacer(1));
1160
+ }
1161
+ const themeDiagnostics = themesResult.diagnostics;
1162
+ if (themeDiagnostics.length > 0) {
1163
+ const warningLines = this.formatDiagnostics(themeDiagnostics, sourceInfos);
1164
+ this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Theme conflicts]")}\n${warningLines}`, 0, 0));
1165
+ this.loadedResourcesContainer.addChild(new Spacer(1));
1166
+ }
1167
+ }
1168
+ }
1169
+ /**
1170
+ * Run the session-start boundary for the current session (capability
1171
+ * session.start@1 dispatch + resource discovery pass) and refresh the
1172
+ * startup surfaces that read session resources.
1173
+ */
1174
+ async bindCurrentSessionExtensions() {
1175
+ await this.session.startSession();
1176
+ setRegisteredThemes(buildRegisteredThemes(this.facade.getThemes().themes));
1177
+ this.setupAutocompleteProvider();
1178
+ this.showLoadedResources({ force: false, showDiagnosticsWhenQuiet: true });
1179
+ this.showStartupNoticesIfNeeded();
1180
+ }
1181
+ applyFullscreenScrollbarSetting() {
1182
+ this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
1183
+ }
1184
+ applyRuntimeSettings() {
1185
+ setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
1186
+ configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
1187
+ this.applyFullscreenScrollbarSetting();
1188
+ if (this.renderer instanceof TuiAltScreen) {
1189
+ this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
1190
+ }
1191
+ this.footer.setSession(this.session);
1192
+ this.footer.setAutoCompactEnabled(this.facade.isAutoCompactionEnabled());
1193
+ this.footerDataProvider.setCwd(this.facade.getCwd());
1194
+ this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
1195
+ this.outputPad = this.settingsManager.getOutputPad();
1196
+ this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
1197
+ const clearOnShrink = this.settingsManager.getClearOnShrink();
1198
+ this.ui.setClearOnShrink(clearOnShrink);
1199
+ if (!clearOnShrink && !this.activeStatusIndicator) {
1200
+ this.statusContainer.clear();
1201
+ }
1202
+ const editorPaddingX = this.settingsManager.getEditorPaddingX();
1203
+ const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
1204
+ this.defaultEditor.setPaddingX(editorPaddingX);
1205
+ this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible);
1206
+ if (this.editor !== this.defaultEditor) {
1207
+ this.editor.setPaddingX?.(editorPaddingX);
1208
+ this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
1209
+ }
1210
+ }
1211
+ async rebindCurrentSession(options = {}) {
1212
+ const session = this.session;
1213
+ this.unsubscribe?.();
1214
+ this.unsubscribe = undefined;
1215
+ this.applyRuntimeSettings();
1216
+ if (options.renderBeforeBind) {
1217
+ this.renderCurrentSessionState();
1218
+ this.subscribeToAgent();
1219
+ }
1220
+ await this.bindCurrentSessionExtensions();
1221
+ if (this.session !== session) {
1222
+ return;
1223
+ }
1224
+ if (!options.renderBeforeBind) {
1225
+ this.subscribeToAgent();
1226
+ }
1227
+ await this.updateAvailableProviderCount();
1228
+ this.updateEditorBorderColor();
1229
+ this.updateTerminalTitle();
1230
+ }
1231
+ async handleFatalRuntimeError(prefix, error) {
1232
+ const message = error instanceof Error ? error.message : String(error);
1233
+ this.showError(`${prefix}: ${message}`);
1234
+ stopThemeWatcher();
1235
+ this.stop("transcript");
1236
+ process.exit(1);
1237
+ }
1238
+ renderCurrentSessionState() {
1239
+ this.loadedResourcesContainer.clear();
1240
+ this.chatContainer.clear();
1241
+ this.pendingMessagesContainer.clear();
1242
+ this.compactionQueuedMessages = [];
1243
+ this.streamingComponent = undefined;
1244
+ this.streamingMessage = undefined;
1245
+ this.pendingTools.clear();
1246
+ this.renderInitialMessages();
1247
+ }
1248
+ /**
1249
+ * Get a registered tool definition by name (for custom rendering).
1250
+ */
1251
+ getRegisteredToolDefinition(toolName) {
1252
+ return this.facade.getToolDefinition(toolName);
1253
+ }
1254
+ getMarkdownTransformers() {
1255
+ return [this.mermaidMarkdownTransformer];
1256
+ }
1257
+ showStatusIndicator(indicator) {
1258
+ this.activeStatusIndicator?.dispose();
1259
+ this.activeStatusIndicator = indicator;
1260
+ this.statusContainer.clear();
1261
+ this.statusContainer.addChild(indicator);
1262
+ }
1263
+ clearStatusIndicator(kind) {
1264
+ if (kind && this.activeStatusIndicator?.kind !== kind) {
1265
+ return;
1266
+ }
1267
+ const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
1268
+ this.activeStatusIndicator?.dispose();
1269
+ this.activeStatusIndicator = undefined;
1270
+ this.statusContainer.clear();
1271
+ if (hadActiveStatusIndicator && this.options.tuiMode === "regular" && this.ui.getClearOnShrink()) {
1272
+ this.statusContainer.addChild(this.idleStatus);
1273
+ }
1274
+ }
1275
+ showWorkingStatusIndicator() {
1276
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1277
+ }
1278
+ setWorkingVisible(visible) {
1279
+ this.workingVisible = visible;
1280
+ if (!visible) {
1281
+ this.clearStatusIndicator("working");
1282
+ this.ui.requestRender();
1283
+ return;
1284
+ }
1285
+ if (this.facade.isStreaming() && this.activeStatusIndicator?.kind !== "working") {
1286
+ this.showWorkingStatusIndicator();
1287
+ }
1288
+ this.ui.requestRender();
1289
+ }
1290
+ setWorkingIndicator(options) {
1291
+ this.workingIndicatorOptions = options;
1292
+ if (this.activeStatusIndicator?.kind === "working") {
1293
+ this.activeStatusIndicator.setIndicator(options);
1294
+ }
1295
+ this.ui.requestRender();
1296
+ }
1297
+ setHiddenThinkingLabel(label) {
1298
+ this.hiddenThinkingLabel = label ?? this.defaultHiddenThinkingLabel;
1299
+ for (const child of this.chatContainer.children) {
1300
+ if (child instanceof AssistantMessageComponent) {
1301
+ child.setHiddenThinkingLabel(this.hiddenThinkingLabel);
1302
+ }
1303
+ }
1304
+ if (this.streamingComponent) {
1305
+ this.streamingComponent.setHiddenThinkingLabel(this.hiddenThinkingLabel);
1306
+ }
1307
+ this.ui.requestRender();
1308
+ }
1309
+ /**
1310
+ * Set the working/loading message shown during streaming. Host entry wired
1311
+ * through ./interactive-dialog-ui.ts; restores the default when undefined.
1312
+ */
1313
+ setWorkingMessage(message) {
1314
+ this.workingMessage = message;
1315
+ if (this.activeStatusIndicator?.kind === "working") {
1316
+ this.activeStatusIndicator.setMessage(message ?? this.defaultWorkingMessage);
1317
+ }
1318
+ }
1319
+ resetDialogUI() {
1320
+ if (this.dialogSelector) {
1321
+ this.hideDialogSelector();
1322
+ }
1323
+ if (this.dialogInput) {
1324
+ this.hideDialogInput();
1325
+ }
1326
+ if (this.dialogEditor) {
1327
+ this.hideDialogEditor();
1328
+ }
1329
+ this.ui.hideOverlay();
1330
+ this.footer.invalidate();
1331
+ this.setupAutocompleteProvider();
1332
+ this.updateTerminalTitle();
1333
+ this.workingMessage = undefined;
1334
+ this.workingVisible = true;
1335
+ this.setWorkingIndicator();
1336
+ if (this.activeStatusIndicator?.kind === "working") {
1337
+ this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
1338
+ }
1339
+ this.setHiddenThinkingLabel();
1340
+ }
1341
+ /**
1342
+ * Apply a theme request from the extension UI host (implemented by
1343
+ * ./interactive-dialog-ui.ts), keeping the theme controller and settings
1344
+ * persistence on the mode.
1345
+ */
1346
+ applyExtensionTheme(themeOrName) {
1347
+ if (themeOrName instanceof Theme) {
1348
+ return this.themeController.setThemeInstance(themeOrName);
1349
+ }
1350
+ const result = this.themeController.setThemeName(themeOrName);
1351
+ if (result.success) {
1352
+ if (this.settingsManager.getTheme() !== themeOrName) {
1353
+ this.settingsManager.setTheme(themeOrName);
1354
+ }
1355
+ }
1356
+ return result;
1357
+ }
1358
+ /**
1359
+ * Interaction host for the versioned capability surface (1A.8): maps the
1360
+ * frozen InteractionHostV1 contract onto the legacy TUI dialogs. Cancellation
1361
+ * rides the existing dialog signal support; notify reuses the notify channel.
1362
+ */
1363
+ createInteractionHostV1() {
1364
+ return createInteractionHostV1(this);
1365
+ }
1366
+ /**
1367
+ * Show a selector for extensions.
1368
+ */
1369
+ showDialogSelector(title, options, opts) {
1370
+ return showDialogSelector(this, title, options, opts);
1371
+ }
1372
+ /**
1373
+ * Hide the extension selector.
1374
+ */
1375
+ hideDialogSelector() {
1376
+ hideDialogSelector(this);
1377
+ }
1378
+ /**
1379
+ * Show a confirmation dialog for extensions.
1380
+ */
1381
+ async showDialogConfirm(title, message, opts) {
1382
+ return showDialogConfirm(this, title, message, opts);
1383
+ }
1384
+ async promptForMissingSessionCwd(error) {
1385
+ const confirmed = await this.showDialogConfirm("Session cwd not found", formatMissingSessionCwdPrompt(error.issue));
1386
+ return confirmed ? error.issue.fallbackCwd : undefined;
1387
+ }
1388
+ /**
1389
+ * Show a text input for extensions.
1390
+ */
1391
+ showDialogInput(title, placeholder, opts) {
1392
+ return showDialogInput(this, title, placeholder, opts);
1393
+ }
1394
+ /**
1395
+ * Hide the extension input.
1396
+ */
1397
+ hideDialogInput() {
1398
+ hideDialogInput(this);
1399
+ }
1400
+ /**
1401
+ * Show a multi-line editor for extensions (with Ctrl+G support).
1402
+ */
1403
+ showDialogEditor(title, prefill) {
1404
+ return showDialogEditor(this, title, prefill);
1405
+ }
1406
+ /**
1407
+ * External editor command for extension editors. Host entry for
1408
+ * ./interactive-dialog-ui.ts, keeping settings access on the mode.
1409
+ */
1410
+ getExternalEditorCommand() {
1411
+ return this.settingsManager.getExternalEditorCommand();
1412
+ }
1413
+ /**
1414
+ * Hide the extension editor.
1415
+ */
1416
+ hideDialogEditor() {
1417
+ hideDialogEditor(this);
1418
+ }
1419
+ /**
1420
+ * Show a notification for extensions.
1421
+ */
1422
+ showDialogNotify(message, type) {
1423
+ showDialogNotify(this, message, type);
1424
+ }
1425
+ // =========================================================================
1426
+ // Key Handlers
1427
+ // =========================================================================
1428
+ setupKeyHandlers() {
1429
+ // Set up handlers on defaultEditor - they use this.editor for text access
1430
+ // so they work correctly regardless of which editor is active
1431
+ this.defaultEditor.onEscape = () => {
1432
+ if (this.facade.isStreaming()) {
1433
+ this.restoreQueuedMessagesToEditor({ abort: true });
1434
+ }
1435
+ else if (this.facade.isBashRunning()) {
1436
+ this.facade.abortBash();
1437
+ }
1438
+ else if (this.isBashMode) {
1439
+ this.editor.setText("");
1440
+ this.isBashMode = false;
1441
+ this.updateEditorBorderColor();
1442
+ }
1443
+ else if (!this.editor.getText().trim()) {
1444
+ // Double-escape with empty editor triggers /tree, /fork, or nothing based on setting
1445
+ const action = this.settingsManager.getDoubleEscapeAction();
1446
+ if (action !== "none") {
1447
+ const now = Date.now();
1448
+ if (now - this.lastEscapeTime < 500) {
1449
+ if (action === "tree") {
1450
+ this.showTreeSelector();
1451
+ }
1452
+ else {
1453
+ this.showUserMessageSelector();
1454
+ }
1455
+ this.lastEscapeTime = 0;
1456
+ }
1457
+ else {
1458
+ this.lastEscapeTime = now;
1459
+ }
1460
+ }
1461
+ }
1462
+ };
1463
+ // Register app action handlers
1464
+ this.defaultEditor.onAction("app.clear", () => this.handleCtrlC());
1465
+ this.defaultEditor.onCtrlD = () => this.handleCtrlD();
1466
+ this.defaultEditor.onAction("app.suspend", () => this.handleCtrlZ());
1467
+ this.defaultEditor.onAction("app.thinking.cycle", () => this.cycleThinkingLevel());
1468
+ this.defaultEditor.onAction("app.model.cycleForward", () => this.cycleModel("forward"));
1469
+ this.defaultEditor.onAction("app.model.cycleBackward", () => this.cycleModel("backward"));
1470
+ // Global debug handler on TUI (works regardless of focus)
1471
+ this.ui.onDebug = () => this.handleDebugCommand();
1472
+ this.defaultEditor.onAction("app.model.select", () => this.showModelSelector());
1473
+ this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
1474
+ this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
1475
+ this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
1476
+ this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true, preferSelection: true }));
1477
+ this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
1478
+ this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
1479
+ this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
1480
+ this.defaultEditor.onAction("app.session.tree", () => this.showTreeSelector());
1481
+ this.defaultEditor.onAction("app.session.fork", () => this.showUserMessageSelector());
1482
+ this.defaultEditor.onAction("app.session.resume", () => this.showSessionSelector());
1483
+ this.defaultEditor.onChange = (text) => {
1484
+ const wasBashMode = this.isBashMode;
1485
+ this.isBashMode = text.trimStart().startsWith("!");
1486
+ if (wasBashMode !== this.isBashMode) {
1487
+ this.updateEditorBorderColor();
1488
+ }
1489
+ };
1490
+ // Handle clipboard paste (triggered on Ctrl+V). Images are attached by path;
1491
+ // otherwise, paste plain text from the system clipboard.
1492
+ this.defaultEditor.onPasteImage = () => {
1493
+ void this.handleClipboardPaste();
1494
+ };
1495
+ }
1496
+ async handleRightClickPaste() {
1497
+ const target = this.renderer.getFocusedComponent();
1498
+ const handleInput = target?.handleInput;
1499
+ if (!target || !handleInput)
1500
+ return;
1501
+ try {
1502
+ const text = await readClipboardText();
1503
+ if (!text || this.renderer.getFocusedComponent() !== target)
1504
+ return;
1505
+ handleInput.call(target, `\x1b[200~${text}\x1b[201~`);
1506
+ this.ui.requestRender();
1507
+ }
1508
+ catch {
1509
+ // Silently ignore clipboard errors (may not have permission, etc.)
1510
+ }
1511
+ }
1512
+ async handleClipboardPaste() {
1513
+ try {
1514
+ const image = await readClipboardImage();
1515
+ if (image) {
1516
+ const tmpDir = os.tmpdir();
1517
+ const ext = extensionForImageMimeType(image.mimeType) ?? "png";
1518
+ const fileName = `agent-forge-clipboard-${crypto.randomUUID()}.${ext}`;
1519
+ const filePath = path.join(tmpDir, fileName);
1520
+ fs.writeFileSync(filePath, Buffer.from(image.bytes));
1521
+ this.editor.insertTextAtCursor?.(filePath);
1522
+ this.ui.requestRender();
1523
+ return;
1524
+ }
1525
+ const text = await readClipboardText();
1526
+ if (text) {
1527
+ this.editor.insertTextAtCursor?.(text);
1528
+ this.ui.requestRender();
1529
+ }
1530
+ }
1531
+ catch {
1532
+ // Silently ignore clipboard errors (may not have permission, etc.)
1533
+ }
1534
+ }
1535
+ // Startup-time submissions of plain prompts are queued; the main loop
1536
+ // dequeues and submits them automatically once startup completes.
1537
+ // Commands ("/", "!") and empty input keep the pre-existing behavior:
1538
+ // commands need the post-startup dispatch context, so they are restored
1539
+ // into the editor for the user to submit again after startup.
1540
+ handleStartupSubmit(text) {
1541
+ if (!text.trim())
1542
+ return;
1543
+ if (text.startsWith("/") || text.startsWith("!")) {
1544
+ this.editor.setText(text);
1545
+ this.showStatus("Startup in progress — command restored to the editor, submit again once startup completes");
1546
+ return;
1547
+ }
1548
+ this.pendingUserInputs.push(text);
1549
+ this.showStatus("Startup in progress — input queued and will run when startup completes");
1550
+ }
1551
+ setupEditorSubmitHandler() {
1552
+ this.defaultEditor.onSubmit = async (text) => {
1553
+ text = text.trim();
1554
+ if (!text)
1555
+ return;
1556
+ // Handle /commands through the dispatch table (interactive-commands.ts)
1557
+ const dispatched = this.dispatchEditorCommand(text);
1558
+ if (dispatched) {
1559
+ if (dispatched.pending)
1560
+ await dispatched.pending;
1561
+ return;
1562
+ }
1563
+ // Handle bash command (! for normal, !! for excluded from context)
1564
+ if (text.startsWith("!")) {
1565
+ const isExcluded = text.startsWith("!!");
1566
+ const command = isExcluded ? text.slice(2).trim() : text.slice(1).trim();
1567
+ if (command) {
1568
+ if (this.facade.isBashRunning()) {
1569
+ this.showWarning("A bash command is already running. Press Esc to cancel it first.");
1570
+ this.editor.setText(text);
1571
+ return;
1572
+ }
1573
+ this.editor.addToHistory?.(text);
1574
+ await this.handleBashCommand(command, isExcluded);
1575
+ this.isBashMode = false;
1576
+ this.updateEditorBorderColor();
1577
+ return;
1578
+ }
1579
+ }
1580
+ // Queue input during compaction
1581
+ if (this.facade.isCompacting()) {
1582
+ this.queueCompactionMessage(text, "steer");
1583
+ return;
1584
+ }
1585
+ // If streaming, use prompt() with steer behavior
1586
+ // This handles extension commands (execute immediately), prompt template expansion, and queueing
1587
+ if (this.facade.isStreaming()) {
1588
+ this.editor.addToHistory?.(text);
1589
+ this.editor.setText("");
1590
+ await this.facade.prompt(text, { streamingBehavior: "steer" });
1591
+ this.updatePendingMessagesDisplay();
1592
+ this.ui.requestRender();
1593
+ return;
1594
+ }
1595
+ // Normal message submission
1596
+ // First, move any pending bash components to chat
1597
+ this.flushPendingBashComponents();
1598
+ if (this.onInputCallback) {
1599
+ this.onInputCallback(text);
1600
+ }
1601
+ else {
1602
+ this.pendingUserInputs.push(text);
1603
+ }
1604
+ this.editor.addToHistory?.(text);
1605
+ };
1606
+ }
1607
+ /**
1608
+ * Run a /command through COMMAND_DISPATCH_ENTRIES. Returns undefined when
1609
+ * text is not a registered command; otherwise the command has been fully
1610
+ * dispatched (handler invoked, editor cleared in the original order) and
1611
+ * pending carries the async completion, if any.
1612
+ */
1613
+ dispatchEditorCommand(text) {
1614
+ const match = matchCommandDispatchEntry(COMMAND_DISPATCH_ENTRIES, text);
1615
+ if (!match)
1616
+ return undefined;
1617
+ const { entry, arg } = match;
1618
+ if (entry.clearEditorBeforeRun)
1619
+ this.setEditorText("");
1620
+ const result = entry.run(this, text, arg);
1621
+ if (!(result instanceof Promise)) {
1622
+ if (!entry.clearEditorBeforeRun)
1623
+ this.setEditorText("");
1624
+ return { pending: undefined };
1625
+ }
1626
+ return {
1627
+ pending: entry.clearEditorBeforeRun ? result : result.then(() => this.setEditorText("")),
1628
+ };
1629
+ }
1630
+ setEditorText(text) {
1631
+ this.editor.setText(text);
1632
+ }
1633
+ subscribeToAgent() {
1634
+ this.unsubscribe = this.facade.subscribe(async (event) => {
1635
+ await this.handleEvent(event);
1636
+ });
1637
+ }
1638
+ async handleEvent(event) {
1639
+ if (!this.isInitialized) {
1640
+ await this.init();
1641
+ }
1642
+ this.footer.invalidate();
1643
+ switch (event.type) {
1644
+ case "agent_start":
1645
+ this.pendingTools.clear();
1646
+ // Restore main escape handler if retry handler is still active
1647
+ // (retry success event fires later, but we need main handler now)
1648
+ if (this.retryEscapeHandler) {
1649
+ this.defaultEditor.onEscape = this.retryEscapeHandler;
1650
+ this.retryEscapeHandler = undefined;
1651
+ }
1652
+ break;
1653
+ case "turn_start":
1654
+ if (this.settingsManager.getShowTerminalProgress()) {
1655
+ this.ui.terminal.setProgress(true);
1656
+ }
1657
+ if (this.workingVisible) {
1658
+ if (this.activeStatusIndicator?.kind !== "working") {
1659
+ this.showWorkingStatusIndicator();
1660
+ }
1661
+ }
1662
+ else {
1663
+ this.clearStatusIndicator();
1664
+ }
1665
+ this.ui.requestRender();
1666
+ break;
1667
+ case "queue_update":
1668
+ this.updatePendingMessagesDisplay();
1669
+ this.ui.requestRender();
1670
+ break;
1671
+ case "entry_appended":
1672
+ // Custom entries have no renderer source since the legacy extension
1673
+ // surface was removed; nothing to append to the chat.
1674
+ break;
1675
+ case "session_info_changed":
1676
+ this.updateTerminalTitle();
1677
+ this.footer.invalidate();
1678
+ this.ui.requestRender();
1679
+ break;
1680
+ case "thinking_level_changed":
1681
+ this.footer.invalidate();
1682
+ this.updateEditorBorderColor();
1683
+ break;
1684
+ case "message_start":
1685
+ if (event.message.role === "custom") {
1686
+ this.addMessageToChat(event.message);
1687
+ this.ui.requestRender();
1688
+ }
1689
+ else if (event.message.role === "user") {
1690
+ this.addMessageToChat(event.message);
1691
+ this.updatePendingMessagesDisplay();
1692
+ this.ui.requestRender();
1693
+ }
1694
+ else if (event.message.role === "assistant") {
1695
+ this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
1696
+ this.streamingMessage = event.message;
1697
+ this.chatContainer.addChild(this.streamingComponent);
1698
+ this.streamingComponent.updateContent(this.streamingMessage, true);
1699
+ this.ui.requestRender();
1700
+ }
1701
+ break;
1702
+ case "message_update":
1703
+ if (this.streamingComponent && event.message.role === "assistant") {
1704
+ this.streamingMessage = event.message;
1705
+ this.streamingComponent.updateContent(this.streamingMessage, true);
1706
+ for (const content of this.streamingMessage.content) {
1707
+ if (content.type === "toolCall") {
1708
+ if (!this.pendingTools.has(content.id)) {
1709
+ const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
1710
+ showImages: this.settingsManager.getShowImages(),
1711
+ imageWidthCells: this.settingsManager.getImageWidthCells(),
1712
+ }, this.getRegisteredToolDefinition(content.name), this.ui, this.facade.getCwd());
1713
+ component.setExpanded(this.toolOutputExpanded);
1714
+ this.chatContainer.addChild(component);
1715
+ this.pendingTools.set(content.id, component);
1716
+ }
1717
+ else {
1718
+ const component = this.pendingTools.get(content.id);
1719
+ // v8 ignore next -- has() 已确认键存在,get() 恒返回组件
1720
+ if (component) {
1721
+ component.updateArgs(content.arguments);
1722
+ }
1723
+ }
1724
+ }
1725
+ }
1726
+ this.ui.requestRender();
1727
+ }
1728
+ break;
1729
+ case "message_end":
1730
+ if (event.message.role === "user")
1731
+ break;
1732
+ if (this.streamingComponent && event.message.role === "assistant") {
1733
+ this.streamingMessage = event.message;
1734
+ let errorMessage;
1735
+ if (this.streamingMessage.stopReason === "aborted") {
1736
+ const retryAttempt = this.facade.getRetryAttempt();
1737
+ errorMessage =
1738
+ retryAttempt > 0
1739
+ ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
1740
+ : "Operation aborted";
1741
+ this.streamingMessage.errorMessage = errorMessage;
1742
+ }
1743
+ this.streamingComponent.updateContent(this.streamingMessage, false);
1744
+ if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
1745
+ if (!errorMessage) {
1746
+ errorMessage = this.streamingMessage.errorMessage || "Error";
1747
+ }
1748
+ for (const [, component] of this.pendingTools.entries()) {
1749
+ component.updateResult({
1750
+ content: [{ type: "text", text: errorMessage }],
1751
+ isError: true,
1752
+ });
1753
+ }
1754
+ this.pendingTools.clear();
1755
+ }
1756
+ else {
1757
+ // Args are now complete - trigger diff computation for edit tools
1758
+ for (const [, component] of this.pendingTools.entries()) {
1759
+ component.setArgsComplete();
1760
+ }
1761
+ this.maybeShowAssistantDiagnostics(this.streamingMessage);
1762
+ this.maybeShowCacheMissNotice(this.streamingMessage);
1763
+ }
1764
+ this.streamingComponent = undefined;
1765
+ this.streamingMessage = undefined;
1766
+ this.footer.invalidate();
1767
+ }
1768
+ this.ui.requestRender();
1769
+ break;
1770
+ case "bash_execution_update":
1771
+ // The bash execution callback handles TUI output rendering.
1772
+ break;
1773
+ case "tool_execution_start": {
1774
+ let component = this.pendingTools.get(event.toolCallId);
1775
+ if (!component) {
1776
+ component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
1777
+ showImages: this.settingsManager.getShowImages(),
1778
+ imageWidthCells: this.settingsManager.getImageWidthCells(),
1779
+ }, this.getRegisteredToolDefinition(event.toolName), this.ui, this.facade.getCwd());
1780
+ component.setExpanded(this.toolOutputExpanded);
1781
+ this.chatContainer.addChild(component);
1782
+ this.pendingTools.set(event.toolCallId, component);
1783
+ }
1784
+ component.markExecutionStarted();
1785
+ this.ui.requestRender();
1786
+ break;
1787
+ }
1788
+ case "tool_execution_update": {
1789
+ const component = this.pendingTools.get(event.toolCallId);
1790
+ if (component) {
1791
+ component.updateResult({ ...event.partialResult, isError: false }, true);
1792
+ this.ui.requestRender();
1793
+ }
1794
+ break;
1795
+ }
1796
+ case "tool_execution_end": {
1797
+ const component = this.pendingTools.get(event.toolCallId);
1798
+ if (component) {
1799
+ component.updateResult({ ...event.result, isError: event.isError });
1800
+ this.pendingTools.delete(event.toolCallId);
1801
+ this.ui.requestRender();
1802
+ }
1803
+ break;
1804
+ }
1805
+ case "capability_command_result": {
1806
+ const links = event.result.links?.map((link) => `${link.label}: ${link.url}`) ?? [];
1807
+ const message = [event.result.message, ...links].filter(Boolean).join("\n");
1808
+ if (event.result.status === "error")
1809
+ this.showError(message);
1810
+ else
1811
+ this.showStatus(message);
1812
+ this.ui.requestRender();
1813
+ break;
1814
+ }
1815
+ case "agent_end":
1816
+ if (this.settingsManager.getShowTerminalProgress()) {
1817
+ this.ui.terminal.setProgress(false);
1818
+ }
1819
+ this.clearStatusIndicator("working");
1820
+ if (this.streamingComponent) {
1821
+ this.chatContainer.removeChild(this.streamingComponent);
1822
+ this.streamingComponent = undefined;
1823
+ this.streamingMessage = undefined;
1824
+ }
1825
+ this.pendingTools.clear();
1826
+ this.ui.requestRender();
1827
+ break;
1828
+ case "agent_settled":
1829
+ await this.checkShutdownRequested();
1830
+ break;
1831
+ case "compaction_start": {
1832
+ if (this.settingsManager.getShowTerminalProgress()) {
1833
+ this.ui.terminal.setProgress(true);
1834
+ }
1835
+ // Keep editor active; submissions are queued during compaction.
1836
+ this.autoCompactionEscapeHandler = this.defaultEditor.onEscape;
1837
+ this.defaultEditor.onEscape = () => {
1838
+ this.facade.abortCompaction();
1839
+ };
1840
+ this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
1841
+ this.ui.requestRender();
1842
+ break;
1843
+ }
1844
+ case "compaction_end": {
1845
+ if (this.settingsManager.getShowTerminalProgress()) {
1846
+ this.ui.terminal.setProgress(false);
1847
+ }
1848
+ if (this.autoCompactionEscapeHandler) {
1849
+ this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
1850
+ this.autoCompactionEscapeHandler = undefined;
1851
+ }
1852
+ this.clearStatusIndicator("compaction");
1853
+ if (event.aborted) {
1854
+ if (event.reason === "manual") {
1855
+ this.showError("Compaction cancelled");
1856
+ }
1857
+ else {
1858
+ this.showStatus("Auto-compaction cancelled");
1859
+ }
1860
+ }
1861
+ else if (event.result) {
1862
+ const entries = this.facade.getContextEntries();
1863
+ if (entries[0]?.type !== "compaction") {
1864
+ throw new Error("Completed compaction is missing from the session context");
1865
+ }
1866
+ this.chatContainer.clear();
1867
+ // The latest compaction is prepended for model context; append it below at its chronological position.
1868
+ this.renderSessionEntries(entries.slice(1));
1869
+ this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
1870
+ if (event.result.usage) {
1871
+ this.addCompactionCostNotice({
1872
+ type: "compaction_cost",
1873
+ kind: "compaction",
1874
+ usage: event.result.usage,
1875
+ });
1876
+ }
1877
+ this.footer.invalidate();
1878
+ }
1879
+ else if (event.errorMessage) {
1880
+ if (event.reason === "manual") {
1881
+ this.showError(event.errorMessage);
1882
+ }
1883
+ else {
1884
+ this.chatContainer.addChild(new Spacer(1));
1885
+ this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
1886
+ }
1887
+ }
1888
+ void this.flushCompactionQueue({ willRetry: event.willRetry });
1889
+ this.ui.requestRender();
1890
+ break;
1891
+ }
1892
+ case "auto_retry_start": {
1893
+ // Set up escape to abort retry
1894
+ this.retryEscapeHandler = this.defaultEditor.onEscape;
1895
+ this.defaultEditor.onEscape = () => {
1896
+ this.facade.abortRetry();
1897
+ };
1898
+ this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
1899
+ this.ui.requestRender();
1900
+ break;
1901
+ }
1902
+ case "auto_retry_end": {
1903
+ // Restore escape handler
1904
+ if (this.retryEscapeHandler) {
1905
+ this.defaultEditor.onEscape = this.retryEscapeHandler;
1906
+ this.retryEscapeHandler = undefined;
1907
+ }
1908
+ this.clearStatusIndicator("retry");
1909
+ // Show error only on final failure (success shows normal response)
1910
+ if (!event.success) {
1911
+ this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
1912
+ }
1913
+ this.ui.requestRender();
1914
+ break;
1915
+ }
1916
+ case "summarization_retry_scheduled": {
1917
+ this.showError(event.errorMessage);
1918
+ this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
1919
+ this.ui.requestRender();
1920
+ break;
1921
+ }
1922
+ case "summarization_retry_attempt_start": {
1923
+ this.clearStatusIndicator("retry");
1924
+ if (event.source === "branchSummary") {
1925
+ this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
1926
+ }
1927
+ else {
1928
+ this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
1929
+ }
1930
+ this.ui.requestRender();
1931
+ break;
1932
+ }
1933
+ case "summarization_retry_finished": {
1934
+ this.clearStatusIndicator("retry");
1935
+ this.ui.requestRender();
1936
+ break;
1937
+ }
1938
+ }
1939
+ }
1940
+ /** Extract text content from a user message */
1941
+ getUserMessageText(message) {
1942
+ if (message.role !== "user")
1943
+ return "";
1944
+ const textBlocks = typeof message.content === "string"
1945
+ ? [{ type: "text", text: message.content }]
1946
+ : message.content.filter((c) => c.type === "text");
1947
+ return textBlocks.map((c) => c.text).join("");
1948
+ }
1949
+ /** Show a managed-tool status update in the chat. */
1950
+ showManagedToolStatus(status) {
1951
+ if (!this.managedToolStatusStarted) {
1952
+ this.chatContainer.addChild(new Spacer(1));
1953
+ this.managedToolStatusStarted = true;
1954
+ }
1955
+ const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
1956
+ const color = status.type === "warning" ? "warning" : "dim";
1957
+ this.chatContainer.addChild(new Text(theme.fg(color, message), 1, 0));
1958
+ this.lastStatusSpacer = undefined;
1959
+ this.lastStatusText = undefined;
1960
+ this.ui.requestRender();
1961
+ }
1962
+ /**
1963
+ * Show a status message in the chat.
1964
+ *
1965
+ * If multiple status messages are emitted back-to-back (without anything else being added to the chat),
1966
+ * we update the previous status line instead of appending new ones to avoid log spam.
1967
+ */
1968
+ showStatus(message) {
1969
+ const children = this.chatContainer.children;
1970
+ const last = children.length > 0 ? children[children.length - 1] : undefined;
1971
+ const secondLast = children.length > 1 ? children[children.length - 2] : undefined;
1972
+ if (last && secondLast && last === this.lastStatusText && secondLast === this.lastStatusSpacer) {
1973
+ this.lastStatusText.setText(theme.fg("dim", message));
1974
+ this.ui.requestRender();
1975
+ return;
1976
+ }
1977
+ const spacer = new Spacer(1);
1978
+ const text = new Text(theme.fg("dim", message), 1, 0);
1979
+ this.chatContainer.addChild(spacer);
1980
+ this.chatContainer.addChild(text);
1981
+ this.lastStatusSpacer = spacer;
1982
+ this.lastStatusText = text;
1983
+ this.ui.requestRender();
1984
+ }
1985
+ addMessageToChat(message, options) {
1986
+ switch (message.role) {
1987
+ case "bashExecution": {
1988
+ const component = new BashExecutionComponent(message.command, this.ui, message.excludeFromContext);
1989
+ if (message.output) {
1990
+ component.appendOutput(message.output);
1991
+ }
1992
+ component.setComplete(message.exitCode, message.cancelled, message.truncated ? { truncated: true } : undefined, message.fullOutputPath);
1993
+ this.chatContainer.addChild(component);
1994
+ break;
1995
+ }
1996
+ case "custom": {
1997
+ if (message.display) {
1998
+ const renderer = undefined;
1999
+ const component = new CustomMessageComponent(message, renderer, this.getMarkdownThemeWithSettings(), this.outputPad);
2000
+ component.setExpanded(this.toolOutputExpanded);
2001
+ this.chatContainer.addChild(component);
2002
+ }
2003
+ break;
2004
+ }
2005
+ case "compactionSummary": {
2006
+ this.chatContainer.addChild(new Spacer(1));
2007
+ const component = new CompactionSummaryMessageComponent(message, this.getMarkdownThemeWithSettings());
2008
+ component.setExpanded(this.toolOutputExpanded);
2009
+ this.chatContainer.addChild(component);
2010
+ break;
2011
+ }
2012
+ case "branchSummary": {
2013
+ this.chatContainer.addChild(new Spacer(1));
2014
+ const component = new BranchSummaryMessageComponent(message, this.getMarkdownThemeWithSettings());
2015
+ component.setExpanded(this.toolOutputExpanded);
2016
+ this.chatContainer.addChild(component);
2017
+ break;
2018
+ }
2019
+ case "user": {
2020
+ const textContent = this.getUserMessageText(message);
2021
+ if (textContent) {
2022
+ if (this.chatContainer.children.length > 0) {
2023
+ this.chatContainer.addChild(new Spacer(1));
2024
+ }
2025
+ const skillBlock = parseSkillBlock(textContent);
2026
+ if (skillBlock) {
2027
+ // Render skill block (collapsible)
2028
+ const component = new SkillInvocationMessageComponent(skillBlock, this.getMarkdownThemeWithSettings());
2029
+ component.setExpanded(this.toolOutputExpanded);
2030
+ this.chatContainer.addChild(component);
2031
+ // Render user message separately if present
2032
+ if (skillBlock.userMessage) {
2033
+ this.chatContainer.addChild(new Spacer(1));
2034
+ const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
2035
+ this.chatContainer.addChild(userComponent);
2036
+ }
2037
+ }
2038
+ else {
2039
+ const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
2040
+ this.chatContainer.addChild(userComponent);
2041
+ }
2042
+ if (options?.populateHistory) {
2043
+ this.editor.addToHistory?.(textContent);
2044
+ }
2045
+ }
2046
+ break;
2047
+ }
2048
+ case "assistant": {
2049
+ const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
2050
+ this.chatContainer.addChild(assistantComponent);
2051
+ break;
2052
+ }
2053
+ case "toolResult": {
2054
+ // Tool results are rendered inline with tool calls, handled separately
2055
+ break;
2056
+ }
2057
+ default: {
2058
+ // v8 ignore next -- exhaustive over AgentMessage roles
2059
+ const _exhaustive = message;
2060
+ }
2061
+ }
2062
+ }
2063
+ renderSessionItems(items, options = {}) {
2064
+ this.pendingTools.clear();
2065
+ const renderedPendingTools = new Map();
2066
+ // Cache-miss notices are not persisted; re-derive them from the full entry
2067
+ // list and re-inject them after the assistant messages that paid for them.
2068
+ const cacheMisses = this.settingsManager.getShowCacheMissNotices()
2069
+ ? collectCacheMisses(this.facade.getEntries(), this.facade.getModelPriceSource())
2070
+ : new Map();
2071
+ if (options.updateFooter) {
2072
+ this.footer.invalidate();
2073
+ this.updateEditorBorderColor();
2074
+ }
2075
+ for (const item of items) {
2076
+ if (isCustomSessionEntry(item)) {
2077
+ // No entry renderer source since the legacy extension surface was
2078
+ // removed; previously renderer-less entries were skipped as well.
2079
+ continue;
2080
+ }
2081
+ if (isCompactionCostNotice(item)) {
2082
+ this.addCompactionCostNotice(item);
2083
+ continue;
2084
+ }
2085
+ const message = item;
2086
+ // Assistant messages need special handling for tool calls
2087
+ if (message.role === "assistant") {
2088
+ this.addMessageToChat(message);
2089
+ // Render tool call components
2090
+ for (const content of message.content) {
2091
+ if (content.type === "toolCall") {
2092
+ const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
2093
+ showImages: this.settingsManager.getShowImages(),
2094
+ imageWidthCells: this.settingsManager.getImageWidthCells(),
2095
+ }, this.getRegisteredToolDefinition(content.name), this.ui, this.facade.getCwd());
2096
+ component.setExpanded(this.toolOutputExpanded);
2097
+ this.chatContainer.addChild(component);
2098
+ if (message.stopReason === "aborted" || message.stopReason === "error") {
2099
+ let errorMessage;
2100
+ if (message.stopReason === "aborted") {
2101
+ const retryAttempt = this.facade.getRetryAttempt();
2102
+ errorMessage =
2103
+ retryAttempt > 0
2104
+ ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
2105
+ : "Operation aborted";
2106
+ }
2107
+ else {
2108
+ errorMessage = message.errorMessage || "Error";
2109
+ }
2110
+ component.updateResult({ content: [{ type: "text", text: errorMessage }], isError: true });
2111
+ }
2112
+ else {
2113
+ renderedPendingTools.set(content.id, component);
2114
+ }
2115
+ }
2116
+ }
2117
+ if (message.stopReason !== "aborted" && message.stopReason !== "error") {
2118
+ this.maybeShowAssistantDiagnostics(message);
2119
+ const miss = cacheMisses.get(message);
2120
+ if (miss)
2121
+ this.addCacheMissNotice(miss);
2122
+ }
2123
+ }
2124
+ else if (message.role === "toolResult") {
2125
+ // Match tool results to pending tool components
2126
+ const component = renderedPendingTools.get(message.toolCallId);
2127
+ if (component) {
2128
+ component.updateResult(message);
2129
+ renderedPendingTools.delete(message.toolCallId);
2130
+ }
2131
+ }
2132
+ else {
2133
+ // All other messages use standard rendering
2134
+ this.addMessageToChat(message, options);
2135
+ }
2136
+ }
2137
+ for (const [toolCallId, component] of renderedPendingTools) {
2138
+ this.pendingTools.set(toolCallId, component);
2139
+ }
2140
+ this.ui.requestRender();
2141
+ }
2142
+ /**
2143
+ * Render session entries to chat. Used for initial load and rebuild after compaction.
2144
+ * @param entries Compaction-aware session entries to render
2145
+ * @param options.updateFooter Update footer state
2146
+ * @param options.populateHistory Add user messages to editor history
2147
+ */
2148
+ renderSessionEntries(entries, options = {}) {
2149
+ const items = entries.flatMap((entry) => {
2150
+ if (entry.type === "custom") {
2151
+ return [entry];
2152
+ }
2153
+ const messages = sessionEntryToContextMessages(entry);
2154
+ if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage && messages.length > 0) {
2155
+ return [...messages, { type: "compaction_cost", kind: entry.type, usage: entry.usage }];
2156
+ }
2157
+ return messages;
2158
+ });
2159
+ this.renderSessionItems(items, options);
2160
+ }
2161
+ /**
2162
+ * Render billing usage for a compaction or branch summary. The notice is derived
2163
+ * from persisted summary usage and is not stored as a separate session entry.
2164
+ */
2165
+ addCompactionCostNotice(notice) {
2166
+ if (!this.settingsManager.getShowCacheMissNotices())
2167
+ return;
2168
+ const { usage } = notice;
2169
+ const tokens = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
2170
+ const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
2171
+ const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
2172
+ this.chatContainer.addChild(new Spacer(1));
2173
+ this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
2174
+ }
2175
+ maybeShowAssistantDiagnostics(message) {
2176
+ if (!this.settingsManager.getShowCacheMissNotices())
2177
+ return;
2178
+ for (const diagnostic of message.diagnostics ?? []) {
2179
+ if (diagnostic.type !== "anthropic_input_transformations")
2180
+ continue;
2181
+ const transformations = diagnostic.details?.transformations;
2182
+ if (!Array.isArray(transformations))
2183
+ continue;
2184
+ const dropped = transformations.flatMap((transformation) => {
2185
+ if (typeof transformation !== "object" || transformation === null)
2186
+ return [];
2187
+ const details = transformation;
2188
+ if (details.type !== "thinking_dropped")
2189
+ return [];
2190
+ const reason = typeof details.reason === "string" ? details.reason : "unknown reason";
2191
+ const location = typeof details.path === "string" ? ` at ${details.path}` : "";
2192
+ return [`${reason}${location}`];
2193
+ });
2194
+ if (dropped.length === 0)
2195
+ continue;
2196
+ const noun = dropped.length === 1 ? "thinking block" : `${dropped.length} thinking blocks`;
2197
+ this.chatContainer.addChild(new Spacer(1));
2198
+ this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${noun}: ${dropped.join("; ")}`), 1, 0));
2199
+ }
2200
+ }
2201
+ /**
2202
+ * Show a transcript notice when a completed assistant message paid for a
2203
+ * significant cache miss. Only states observable facts: the miss itself,
2204
+ * a model switch, or an idle gap past the cache TTL.
2205
+ */
2206
+ maybeShowCacheMissNotice(message) {
2207
+ if (!this.settingsManager.getShowCacheMissNotices())
2208
+ return;
2209
+ // Entries don't contain `message` yet: message_end fires before persistence.
2210
+ const miss = detectCacheMiss(this.facade.getEntries(), message, this.facade.getModelPriceSource());
2211
+ if (miss)
2212
+ this.addCacheMissNotice(miss);
2213
+ }
2214
+ addCacheMissNotice(miss) {
2215
+ if (miss.missedTokens < 20_000 && miss.missedCost < 0.1)
2216
+ return;
2217
+ const cost = miss.missedCost >= 0.01 ? ` (~$${miss.missedCost.toFixed(2)})` : "";
2218
+ const reBilled = `${formatTokens(miss.missedTokens)} tokens re-billed${cost}`;
2219
+ let label = "Cache miss";
2220
+ if (miss.modelChanged) {
2221
+ label = "Cache miss after model switch";
2222
+ }
2223
+ else if (miss.idleMs >= CACHE_TTL_MS) {
2224
+ label = `Cache miss after ${Math.round(miss.idleMs / 60_000)}m idle`;
2225
+ }
2226
+ const text = theme.fg("warning", `${label}: ${reBilled}`);
2227
+ this.chatContainer.addChild(new Spacer(1));
2228
+ this.chatContainer.addChild(new Text(text, 1, 0));
2229
+ }
2230
+ renderInitialMessages() {
2231
+ const entries = this.facade.getContextEntries();
2232
+ this.renderSessionEntries(entries, {
2233
+ updateFooter: true,
2234
+ populateHistory: true,
2235
+ });
2236
+ // Show compaction info if session was compacted
2237
+ const allEntries = this.facade.getEntries();
2238
+ const compactionCount = allEntries.filter((e) => e.type === "compaction").length;
2239
+ if (compactionCount > 0) {
2240
+ const times = compactionCount === 1 ? "1 time" : `${compactionCount} times`;
2241
+ this.showStatus(`Session compacted ${times}`);
2242
+ }
2243
+ }
2244
+ async getUserInput() {
2245
+ const queuedInput = this.pendingUserInputs.shift();
2246
+ if (queuedInput !== undefined) {
2247
+ return queuedInput;
2248
+ }
2249
+ return new Promise((resolve) => {
2250
+ this.onInputCallback = (text) => {
2251
+ this.onInputCallback = undefined;
2252
+ resolve(text);
2253
+ };
2254
+ });
2255
+ }
2256
+ rebuildChatFromMessages() {
2257
+ this.chatContainer.clear();
2258
+ this.renderSessionEntries(this.facade.getContextEntries());
2259
+ }
2260
+ // =========================================================================
2261
+ // Key handlers
2262
+ // =========================================================================
2263
+ handleCtrlC() {
2264
+ const now = Date.now();
2265
+ if (now - this.lastSigintTime < 500) {
2266
+ void this.shutdown();
2267
+ }
2268
+ else {
2269
+ this.clearEditor();
2270
+ this.lastSigintTime = now;
2271
+ }
2272
+ }
2273
+ handleCtrlD() {
2274
+ // Only called when editor is empty (enforced by CustomEditor)
2275
+ void this.shutdown();
2276
+ }
2277
+ /**
2278
+ * Gracefully shutdown the agent.
2279
+ * Stops the TUI before emitting shutdown events so extension UI cleanup cannot
2280
+ * repaint the final frame while the process is exiting.
2281
+ */
2282
+ isShuttingDown = false;
2283
+ async shutdown(options) {
2284
+ if (this.isShuttingDown)
2285
+ return;
2286
+ this.isShuttingDown = true;
2287
+ // Keep signal handlers registered until terminal cleanup has completed.
2288
+ // `signal-exit` checks the listener list during the same SIGTERM/SIGHUP
2289
+ // dispatch and re-sends the signal if only its own listeners remain.
2290
+ if (options?.fromSignal) {
2291
+ // Signal-triggered shutdown (SIGTERM/SIGHUP). Emit extension cleanup
2292
+ // (session_shutdown) BEFORE touching the terminal. Extension teardown
2293
+ // such as removing sockets does not write to the tty, so it must not be
2294
+ // skipped if a later terminal-restore write fails on a dead or stalled
2295
+ // terminal. If the terminal is gone, the restore writes below emit EIO,
2296
+ // which the stdout/stderr error handler turns into emergencyTerminalExit;
2297
+ // the render loop is already idle, so this cannot hot-spin (see #4144).
2298
+ await this.runtimeFacade.dispose();
2299
+ this.themeController.disableAutoSync();
2300
+ await this.ui.terminal.drainInput(1000);
2301
+ this.stop();
2302
+ process.exit(0);
2303
+ }
2304
+ // Interactive quit (Ctrl+D, Ctrl+C, /quit, extension shutdown()). Stop the
2305
+ // TUI before emitting shutdown events so extension UI cleanup cannot repaint
2306
+ // the final frame while the process is exiting.
2307
+ // Drain any in-flight Kitty key release events before stopping.
2308
+ // This prevents escape sequences from leaking to the parent shell over slow SSH.
2309
+ this.themeController.disableAutoSync();
2310
+ await this.ui.terminal.drainInput(1000);
2311
+ this.stop();
2312
+ await this.runtimeFacade.dispose();
2313
+ const resumeCommand = formatResumeCommand(this.runtimeFacade);
2314
+ if (resumeCommand) {
2315
+ process.stdout.write(`${chalk.dim("To resume this session:")} ${resumeCommand}\n`);
2316
+ }
2317
+ process.exit(0);
2318
+ }
2319
+ emergencyTerminalExit() {
2320
+ this.isShuttingDown = true;
2321
+ this.unregisterSignalHandlers();
2322
+ killTrackedDetachedChildren();
2323
+ // The terminal is gone. Do not run normal shutdown because TUI and
2324
+ // extension cleanup can write restore sequences and re-trigger EIO.
2325
+ process.exit(129);
2326
+ }
2327
+ /**
2328
+ * Last-resort handler for uncaught exceptions. The TUI puts stdin into raw
2329
+ * mode and hides the cursor; without this handler, an uncaught throw from
2330
+ * anywhere (e.g. an extension's async `ChildProcess.on("exit")` callback)
2331
+ * tears down the process while leaving the terminal in raw mode with no
2332
+ * cursor, requiring `stty sane && reset` to recover.
2333
+ *
2334
+ * Unlike emergencyTerminalExit, the terminal is still alive here, so we
2335
+ * call ui.stop() to restore cooked mode, the cursor, and disable bracketed
2336
+ * paste / Kitty / modifyOtherKeys sequences.
2337
+ */
2338
+ uncaughtCrash(error) {
2339
+ if (this.isShuttingDown) {
2340
+ process.exit(1);
2341
+ }
2342
+ this.isShuttingDown = true;
2343
+ try {
2344
+ this.unregisterSignalHandlers();
2345
+ }
2346
+ catch { }
2347
+ try {
2348
+ killTrackedDetachedChildren();
2349
+ }
2350
+ catch { }
2351
+ try {
2352
+ this.ui.stop();
2353
+ }
2354
+ catch { }
2355
+ console.error(`${APP_NAME} exiting due to uncaughtException:`);
2356
+ console.error(error);
2357
+ process.exit(1);
2358
+ }
2359
+ /**
2360
+ * Check if shutdown was requested and perform shutdown if so.
2361
+ */
2362
+ async checkShutdownRequested() {
2363
+ if (!this.shutdownRequested)
2364
+ return;
2365
+ await this.shutdown();
2366
+ }
2367
+ registerSignalHandlers() {
2368
+ this.unregisterSignalHandlers();
2369
+ const signals = ["SIGTERM"];
2370
+ if (process.platform !== "win32") {
2371
+ signals.push("SIGHUP");
2372
+ }
2373
+ for (const signal of signals) {
2374
+ const handler = () => {
2375
+ // SIGHUP no longer hard-exits: graceful shutdown emits session_shutdown
2376
+ // first, then attempts terminal restore. A genuinely dead terminal
2377
+ // surfaces as an EIO on the restore writes, which the stdout/stderr
2378
+ // error handler converts into emergencyTerminalExit (see #4144, #5080).
2379
+ killTrackedDetachedChildren();
2380
+ void this.shutdown({ fromSignal: true });
2381
+ };
2382
+ process.prependListener(signal, handler);
2383
+ this.signalCleanupHandlers.push(() => process.off(signal, handler));
2384
+ }
2385
+ const terminalErrorHandler = (error) => {
2386
+ if (isDeadTerminalError(error)) {
2387
+ this.emergencyTerminalExit();
2388
+ }
2389
+ throw error;
2390
+ };
2391
+ process.stdout.on("error", terminalErrorHandler);
2392
+ process.stderr.on("error", terminalErrorHandler);
2393
+ this.signalCleanupHandlers.push(() => process.stdout.off("error", terminalErrorHandler));
2394
+ this.signalCleanupHandlers.push(() => process.stderr.off("error", terminalErrorHandler));
2395
+ // Restore the terminal before the process dies on any uncaught throw.
2396
+ // Without this, an unhandled exception from extension code (or anywhere
2397
+ // in the application) leaves the terminal in raw mode with no cursor.
2398
+ const uncaughtExceptionHandler = (error) => this.uncaughtCrash(error);
2399
+ process.prependListener("uncaughtException", uncaughtExceptionHandler);
2400
+ this.signalCleanupHandlers.push(() => process.off("uncaughtException", uncaughtExceptionHandler));
2401
+ }
2402
+ unregisterSignalHandlers() {
2403
+ for (const cleanup of this.signalCleanupHandlers) {
2404
+ cleanup();
2405
+ }
2406
+ this.signalCleanupHandlers = [];
2407
+ }
2408
+ handleCtrlZ() {
2409
+ if (process.platform === "win32") {
2410
+ this.showStatus("Suspend to background is not supported on Windows");
2411
+ return;
2412
+ }
2413
+ // Keep the event loop alive while suspended. Without this, stopping the TUI
2414
+ // can leave Node with no ref'ed handles, causing the process to exit on fg
2415
+ // before the SIGCONT handler gets a chance to restore the terminal.
2416
+ const suspendKeepAlive = setInterval(() => { }, 2 ** 30);
2417
+ // Ignore SIGINT while suspended so Ctrl+C in the terminal does not
2418
+ // kill the backgrounded process. The handler is removed on resume.
2419
+ const ignoreSigint = () => { };
2420
+ process.on("SIGINT", ignoreSigint);
2421
+ // Set up handler to restore TUI when resumed
2422
+ process.once("SIGCONT", () => {
2423
+ clearInterval(suspendKeepAlive);
2424
+ process.removeListener("SIGINT", ignoreSigint);
2425
+ this.ui.start();
2426
+ this.ui.requestRender(true);
2427
+ });
2428
+ try {
2429
+ // Stop the TUI (restore terminal to normal mode)
2430
+ this.ui.stop();
2431
+ // Send SIGTSTP to process group (pid=0 means all processes in group)
2432
+ process.kill(0, "SIGTSTP");
2433
+ }
2434
+ catch (error) {
2435
+ clearInterval(suspendKeepAlive);
2436
+ process.removeListener("SIGINT", ignoreSigint);
2437
+ throw error;
2438
+ }
2439
+ }
2440
+ async handleFollowUp() {
2441
+ const text = (this.editor.getExpandedText?.() ?? this.editor.getText()).trim();
2442
+ if (!text)
2443
+ return;
2444
+ // Queue input during compaction (extension commands execute immediately)
2445
+ if (this.facade.isCompacting()) {
2446
+ this.queueCompactionMessage(text, "followUp");
2447
+ return;
2448
+ }
2449
+ // Alt+Enter queues a follow-up message (waits until agent finishes)
2450
+ // This handles extension commands (execute immediately), prompt template expansion, and queueing
2451
+ if (this.facade.isStreaming()) {
2452
+ this.editor.addToHistory?.(text);
2453
+ this.editor.setText("");
2454
+ await this.facade.prompt(text, { streamingBehavior: "followUp" });
2455
+ this.updatePendingMessagesDisplay();
2456
+ this.ui.requestRender();
2457
+ }
2458
+ // If not streaming, Alt+Enter acts like regular Enter (trigger onSubmit)
2459
+ else if (this.editor.onSubmit) {
2460
+ this.editor.setText("");
2461
+ this.editor.onSubmit(text);
2462
+ }
2463
+ }
2464
+ handleDequeue() {
2465
+ const restored = this.restoreQueuedMessagesToEditor();
2466
+ if (restored === 0) {
2467
+ this.showStatus("No queued messages to restore");
2468
+ }
2469
+ else {
2470
+ this.showStatus(`Restored ${restored} queued message${restored > 1 ? "s" : ""} to editor`);
2471
+ }
2472
+ }
2473
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3). */
2474
+ updateEditorBorderColor() {
2475
+ if (this.isBashMode) {
2476
+ this.editor.borderColor = theme.getBashModeBorderColor();
2477
+ }
2478
+ else {
2479
+ const level = this.facade.getState().thinkingLevel || "off";
2480
+ this.editor.borderColor = theme.getThinkingBorderColor(level);
2481
+ }
2482
+ this.ui.requestRender();
2483
+ }
2484
+ cycleThinkingLevel() {
2485
+ const newLevel = this.facade.cycleThinkingLevel();
2486
+ if (newLevel === undefined) {
2487
+ this.showStatus("Current model does not support thinking");
2488
+ }
2489
+ else {
2490
+ this.footer.invalidate();
2491
+ this.updateEditorBorderColor();
2492
+ this.showStatus(`Thinking level: ${newLevel}`);
2493
+ }
2494
+ }
2495
+ async cycleModel(direction) {
2496
+ try {
2497
+ const result = await this.facade.cycleModel(direction);
2498
+ if (result === undefined) {
2499
+ const msg = this.facade.getScopedModels().length > 0 ? "Only one model in scope" : "Only one model available";
2500
+ this.showStatus(msg);
2501
+ }
2502
+ else {
2503
+ this.footer.invalidate();
2504
+ this.updateEditorBorderColor();
2505
+ const thinkingStr = result.model.reasoning && result.thinkingLevel !== "off" ? ` (thinking: ${result.thinkingLevel})` : "";
2506
+ this.showStatus(`Switched to ${result.model.name || result.model.id}${thinkingStr}`);
2507
+ void this.maybeWarnAboutAnthropicSubscriptionAuth(result.model);
2508
+ }
2509
+ }
2510
+ catch (error) {
2511
+ this.showError(error instanceof Error ? error.message : String(error));
2512
+ }
2513
+ }
2514
+ toggleToolOutputExpansion() {
2515
+ this.setToolsExpanded(!this.toolOutputExpanded);
2516
+ }
2517
+ setToolsExpanded(expanded) {
2518
+ if (expanded === this.toolOutputExpanded)
2519
+ return;
2520
+ this.toolOutputExpanded = expanded;
2521
+ const activeHeader = this.builtInHeader;
2522
+ if (isExpandable(activeHeader)) {
2523
+ activeHeader.setExpanded(expanded);
2524
+ }
2525
+ for (const container of [this.loadedResourcesContainer, this.chatContainer]) {
2526
+ for (const child of container.children) {
2527
+ if (isExpandable(child)) {
2528
+ child.setExpanded(expanded);
2529
+ }
2530
+ }
2531
+ }
2532
+ this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
2533
+ }
2534
+ /** Update rendered assistant messages without rebuilding live tool components. */
2535
+ updateThinkingBlockVisibility() {
2536
+ for (const child of this.chatContainer.children) {
2537
+ if (child instanceof AssistantMessageComponent) {
2538
+ child.setHideThinkingBlock(this.hideThinkingBlock);
2539
+ }
2540
+ }
2541
+ this.ui.requestRender();
2542
+ }
2543
+ toggleThinkingBlockVisibility() {
2544
+ this.hideThinkingBlock = !this.hideThinkingBlock;
2545
+ this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
2546
+ this.updateThinkingBlockVisibility();
2547
+ this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
2548
+ }
2549
+ async handleOpenExternalEditor() {
2550
+ const editorCmd = this.settingsManager.getExternalEditorCommand();
2551
+ const content = this.editor.getExpandedText?.() ?? this.editor.getText();
2552
+ this.ui.stop();
2553
+ try {
2554
+ const result = await editInExternalEditor({
2555
+ command: editorCmd,
2556
+ content,
2557
+ });
2558
+ if (result.status === "complete") {
2559
+ this.editor.setText(result.content);
2560
+ }
2561
+ }
2562
+ finally {
2563
+ this.ui.start();
2564
+ this.ui.requestRender(true);
2565
+ }
2566
+ }
2567
+ // =========================================================================
2568
+ // UI helpers
2569
+ // =========================================================================
2570
+ clearEditor() {
2571
+ this.editor.setText("");
2572
+ this.ui.requestRender();
2573
+ }
2574
+ showError(errorMessage) {
2575
+ this.chatContainer.addChild(new Spacer(1));
2576
+ this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
2577
+ this.ui.requestRender();
2578
+ }
2579
+ showWarning(warningMessage) {
2580
+ this.chatContainer.addChild(new Spacer(1));
2581
+ this.chatContainer.addChild(new Text(theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
2582
+ this.ui.requestRender();
2583
+ }
2584
+ showNewVersionNotification(release) {
2585
+ const action = theme.fg("accent", `${APP_NAME} update`);
2586
+ const updateInstruction = theme.fg("muted", `New version ${release.version} is available. Run `) + action;
2587
+ const changelogUrl = process.env.AGENT_FORGE_CHANGELOG_URL;
2588
+ const changelogLine = changelogUrl
2589
+ ? theme.fg("muted", "Changelog: ") +
2590
+ (getCapabilities().hyperlinks
2591
+ ? hyperlink(theme.fg("accent", changelogUrl), changelogUrl)
2592
+ : theme.fg("accent", changelogUrl))
2593
+ : theme.fg("muted", "Changelog URL is not configured.");
2594
+ const note = release.note?.trim();
2595
+ this.chatContainer.addChild(new Spacer(1));
2596
+ this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
2597
+ this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction}`, 1, 0));
2598
+ if (note) {
2599
+ this.chatContainer.addChild(new Spacer(1));
2600
+ this.chatContainer.addChild(new Markdown(note, 1, 0, this.getMarkdownThemeWithSettings(), {
2601
+ color: (text) => theme.fg("muted", text),
2602
+ }));
2603
+ this.chatContainer.addChild(new Spacer(1));
2604
+ }
2605
+ this.chatContainer.addChild(new Text(changelogLine, 1, 0));
2606
+ this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
2607
+ this.ui.requestRender();
2608
+ }
2609
+ showPackageUpdateNotification(packages) {
2610
+ const action = theme.fg("accent", `${APP_NAME} update --extensions`);
2611
+ const updateInstruction = theme.fg("muted", "Package updates are available. Run ") + action;
2612
+ const packageLines = packages.map((pkg) => `- ${pkg}`).join("\n");
2613
+ this.chatContainer.addChild(new Spacer(1));
2614
+ this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
2615
+ this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
2616
+ this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
2617
+ this.ui.requestRender();
2618
+ }
2619
+ /**
2620
+ * Get all queued messages (read-only).
2621
+ * Combines session queue and compaction queue.
2622
+ */
2623
+ getAllQueuedMessages() {
2624
+ return {
2625
+ steering: [
2626
+ ...this.facade.getSteeringMessages(),
2627
+ ...this.compactionQueuedMessages.filter((msg) => msg.mode === "steer").map((msg) => msg.text),
2628
+ ],
2629
+ followUp: [
2630
+ ...this.facade.getFollowUpMessages(),
2631
+ ...this.compactionQueuedMessages.filter((msg) => msg.mode === "followUp").map((msg) => msg.text),
2632
+ ],
2633
+ };
2634
+ }
2635
+ /**
2636
+ * Clear all queued messages and return their contents.
2637
+ * Clears both session queue and compaction queue.
2638
+ */
2639
+ clearAllQueues() {
2640
+ const { steering, followUp } = this.facade.clearQueue();
2641
+ const compactionSteering = this.compactionQueuedMessages
2642
+ .filter((msg) => msg.mode === "steer")
2643
+ .map((msg) => msg.text);
2644
+ const compactionFollowUp = this.compactionQueuedMessages
2645
+ .filter((msg) => msg.mode === "followUp")
2646
+ .map((msg) => msg.text);
2647
+ this.compactionQueuedMessages = [];
2648
+ return {
2649
+ steering: [...steering, ...compactionSteering],
2650
+ followUp: [...followUp, ...compactionFollowUp],
2651
+ };
2652
+ }
2653
+ updatePendingMessagesDisplay() {
2654
+ this.pendingMessagesContainer.clear();
2655
+ const { steering: steeringMessages, followUp: followUpMessages } = this.getAllQueuedMessages();
2656
+ if (steeringMessages.length > 0 || followUpMessages.length > 0) {
2657
+ this.pendingMessagesContainer.addChild(new Spacer(1));
2658
+ for (const message of steeringMessages) {
2659
+ const text = theme.fg("dim", `Steering: ${message}`);
2660
+ this.pendingMessagesContainer.addChild(new TruncatedText(text, 1, 0));
2661
+ }
2662
+ for (const message of followUpMessages) {
2663
+ const text = theme.fg("dim", `Follow-up: ${message}`);
2664
+ this.pendingMessagesContainer.addChild(new TruncatedText(text, 1, 0));
2665
+ }
2666
+ const dequeueHint = this.getAppKeyDisplay("app.message.dequeue");
2667
+ const hintText = theme.fg("dim", `↳ ${dequeueHint} to edit all queued messages`);
2668
+ this.pendingMessagesContainer.addChild(new TruncatedText(hintText, 1, 0));
2669
+ }
2670
+ }
2671
+ restoreQueuedMessagesToEditor(options) {
2672
+ const { steering, followUp } = this.clearAllQueues();
2673
+ const allQueued = [...steering, ...followUp];
2674
+ if (allQueued.length === 0) {
2675
+ this.updatePendingMessagesDisplay();
2676
+ if (options?.abort) {
2677
+ this.agent.abort();
2678
+ }
2679
+ return 0;
2680
+ }
2681
+ const queuedText = allQueued.join("\n\n");
2682
+ const currentText = options?.currentText ?? this.editor.getText();
2683
+ const combinedText = [queuedText, currentText].filter((t) => t.trim()).join("\n\n");
2684
+ this.editor.setText(combinedText);
2685
+ this.updatePendingMessagesDisplay();
2686
+ if (options?.abort) {
2687
+ this.agent.abort();
2688
+ }
2689
+ return allQueued.length;
2690
+ }
2691
+ queueCompactionMessage(text, mode) {
2692
+ this.compactionQueuedMessages.push({ text, mode });
2693
+ this.editor.addToHistory?.(text);
2694
+ this.editor.setText("");
2695
+ this.updatePendingMessagesDisplay();
2696
+ this.showStatus("Queued message for after compaction");
2697
+ }
2698
+ async flushCompactionQueue(options) {
2699
+ if (this.compactionQueuedMessages.length === 0) {
2700
+ return;
2701
+ }
2702
+ const queuedMessages = [...this.compactionQueuedMessages];
2703
+ this.compactionQueuedMessages = [];
2704
+ this.updatePendingMessagesDisplay();
2705
+ const restoreQueue = (error) => {
2706
+ this.facade.clearQueue();
2707
+ this.compactionQueuedMessages = queuedMessages;
2708
+ this.updatePendingMessagesDisplay();
2709
+ this.showError(`Failed to send queued message${queuedMessages.length > 1 ? "s" : ""}: ${error instanceof Error ? error.message : String(error)}`);
2710
+ };
2711
+ try {
2712
+ if (options?.willRetry) {
2713
+ // When retry is pending, queue messages for the retry turn
2714
+ for (const message of queuedMessages) {
2715
+ if (message.mode === "followUp") {
2716
+ await this.facade.followUp(message.text);
2717
+ }
2718
+ else {
2719
+ await this.facade.steer(message.text);
2720
+ }
2721
+ }
2722
+ this.updatePendingMessagesDisplay();
2723
+ return;
2724
+ }
2725
+ const [firstPrompt, ...rest] = queuedMessages;
2726
+ // Start a prompt when idle, or queue it into a run still finishing compaction.
2727
+ const promptPromise = this.facade
2728
+ .prompt(firstPrompt.text, { streamingBehavior: firstPrompt.mode })
2729
+ .catch((error) => {
2730
+ restoreQueue(error);
2731
+ });
2732
+ // Queue remaining messages
2733
+ for (const message of rest) {
2734
+ if (message.mode === "followUp") {
2735
+ await this.facade.followUp(message.text);
2736
+ }
2737
+ else {
2738
+ await this.facade.steer(message.text);
2739
+ }
2740
+ }
2741
+ this.updatePendingMessagesDisplay();
2742
+ void promptPromise;
2743
+ }
2744
+ catch (error) {
2745
+ restoreQueue(error);
2746
+ }
2747
+ }
2748
+ /** Move pending bash components from pending area to chat */
2749
+ flushPendingBashComponents() {
2750
+ for (const component of this.pendingBashComponents) {
2751
+ this.pendingMessagesContainer.removeChild(component);
2752
+ this.chatContainer.addChild(component);
2753
+ }
2754
+ this.pendingBashComponents = [];
2755
+ }
2756
+ // =========================================================================
2757
+ // Selectors
2758
+ // Suite/thinking/model/scoped-models/user-message-fork/clone selectors are
2759
+ // implemented in ./interactive-selectors.ts (S5 slice 5) behind the
2760
+ // SelectorsHost interface; same-name delegates below keep the command
2761
+ // dispatch and prototype-level tests bound to these names. The selector
2762
+ // infrastructure (showSelector/disposeActiveSelector), the settings/tree/
2763
+ // session selectors, and resume stay on the mode: the settings and tree
2764
+ // selectors assemble from broad private UI state, and the session/resume
2765
+ // path is the documented session-boundary carve-out (SessionManager
2766
+ // manager-level writes plus per-entry display reads).
2767
+ // =========================================================================
2768
+ disposeActiveSelector() {
2769
+ const dispose = this.activeSelectorDispose;
2770
+ this.activeSelectorToken = undefined;
2771
+ this.activeSelectorDispose = undefined;
2772
+ dispose?.();
2773
+ }
2774
+ /**
2775
+ * Shows a selector component in place of the editor.
2776
+ * @param create Factory that receives a `done` callback and returns the component and focus target
2777
+ */
2778
+ showSelector(create) {
2779
+ const token = {};
2780
+ let dispose;
2781
+ const done = () => {
2782
+ dispose?.();
2783
+ if (this.activeSelectorToken !== token)
2784
+ return;
2785
+ this.activeSelectorToken = undefined;
2786
+ this.activeSelectorDispose = undefined;
2787
+ this.editorContainer.clear();
2788
+ this.editorContainer.addChild(this.editor);
2789
+ this.ui.setFocus(this.editor);
2790
+ };
2791
+ const created = create(done);
2792
+ dispose = created.dispose;
2793
+ this.disposeActiveSelector();
2794
+ this.activeSelectorToken = token;
2795
+ this.activeSelectorDispose = dispose;
2796
+ this.editorContainer.clear();
2797
+ this.editorContainer.addChild(created.component);
2798
+ this.ui.setFocus(created.focus);
2799
+ this.ui.requestRender();
2800
+ }
2801
+ showSettingsSelector() {
2802
+ this.showSelector((done) => {
2803
+ let selector;
2804
+ const defaultProvider = this.settingsManager.getDefaultProvider();
2805
+ const defaultModelId = this.settingsManager.getDefaultModel();
2806
+ const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : "not set";
2807
+ selector = new SettingsSelectorComponent({
2808
+ autoCompact: this.facade.isAutoCompactionEnabled(),
2809
+ defaultModel,
2810
+ currentModel: this.facade.getModel(),
2811
+ availableDefaultModels: this.facade.getAvailableModels(),
2812
+ showImages: this.settingsManager.getShowImages(),
2813
+ imageWidthCells: this.settingsManager.getImageWidthCells(),
2814
+ autoResizeImages: this.settingsManager.getImageAutoResize(),
2815
+ blockImages: this.settingsManager.getBlockImages(),
2816
+ enableSkillCommands: this.settingsManager.getEnableSkillCommands(),
2817
+ steeringMode: this.facade.getSteeringMode(),
2818
+ followUpMode: this.facade.getFollowUpMode(),
2819
+ transport: this.settingsManager.getTransport(),
2820
+ httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
2821
+ thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
2822
+ availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
2823
+ modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
2824
+ currentTheme: this.themeController.getThemeSelection() || "dark",
2825
+ terminalTheme: this.themeController.getTerminalTheme(),
2826
+ availableThemes: getAvailableThemes(),
2827
+ hideThinkingBlock: this.hideThinkingBlock,
2828
+ mermaidRenderingMode: this.settingsManager.getMermaidRenderingMode(),
2829
+ collapseChangelog: this.settingsManager.getCollapseChangelog(),
2830
+ doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
2831
+ treeFilterMode: this.settingsManager.getTreeFilterMode(),
2832
+ showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
2833
+ showCacheMissNotices: this.settingsManager.getShowCacheMissNotices(),
2834
+ editorPaddingX: this.settingsManager.getEditorPaddingX(),
2835
+ outputPad: this.settingsManager.getOutputPad(),
2836
+ autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
2837
+ quietStartup: this.settingsManager.getQuietStartup(),
2838
+ clearOnShrink: this.settingsManager.getClearOnShrink(),
2839
+ showTerminalProgress: this.settingsManager.getShowTerminalProgress(),
2840
+ tuiMode: this.ui.mode,
2841
+ fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
2842
+ fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
2843
+ fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
2844
+ warnings: this.settingsManager.getWarnings(),
2845
+ }, {
2846
+ onAutoCompactChange: (enabled) => {
2847
+ this.facade.setAutoCompactionEnabled(enabled);
2848
+ this.footer.setAutoCompactEnabled(enabled);
2849
+ },
2850
+ onShowImagesChange: (enabled) => {
2851
+ this.settingsManager.setShowImages(enabled);
2852
+ for (const child of this.chatContainer.children) {
2853
+ if (child instanceof ToolExecutionComponent) {
2854
+ child.setShowImages(enabled);
2855
+ }
2856
+ }
2857
+ },
2858
+ onImageWidthCellsChange: (width) => {
2859
+ this.settingsManager.setImageWidthCells(width);
2860
+ for (const child of this.chatContainer.children) {
2861
+ if (child instanceof ToolExecutionComponent) {
2862
+ child.setImageWidthCells(width);
2863
+ }
2864
+ }
2865
+ },
2866
+ onAutoResizeImagesChange: (enabled) => {
2867
+ this.settingsManager.setImageAutoResize(enabled);
2868
+ },
2869
+ onBlockImagesChange: (blocked) => {
2870
+ this.settingsManager.setBlockImages(blocked);
2871
+ },
2872
+ onEnableSkillCommandsChange: (enabled) => {
2873
+ this.settingsManager.setEnableSkillCommands(enabled);
2874
+ this.setupAutocompleteProvider();
2875
+ },
2876
+ onSteeringModeChange: (mode) => {
2877
+ this.facade.setSteeringMode(mode);
2878
+ },
2879
+ onFollowUpModeChange: (mode) => {
2880
+ this.facade.setFollowUpMode(mode);
2881
+ },
2882
+ onTransportChange: (transport) => {
2883
+ this.settingsManager.setTransport(transport);
2884
+ this.session.host.setTransport(transport);
2885
+ },
2886
+ onHttpIdleTimeoutMsChange: (timeoutMs) => {
2887
+ this.settingsManager.setHttpIdleTimeoutMs(timeoutMs);
2888
+ configureHttpDispatcher(timeoutMs);
2889
+ this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
2890
+ },
2891
+ onModelThinkingLevelChange: (provider, modelId, level) => {
2892
+ this.settingsManager.setModelThinkingLevel(provider, modelId, level);
2893
+ // If the override is for the current model, apply it to the session too
2894
+ const current = this.facade.getModel();
2895
+ if (current && current.provider === provider && current.id === modelId) {
2896
+ this.facade.setThinkingLevel(level);
2897
+ this.footer.invalidate();
2898
+ this.updateEditorBorderColor();
2899
+ }
2900
+ },
2901
+ onModelThinkingLevelRemove: (provider, modelId) => {
2902
+ this.settingsManager.removeModelThinkingLevel(provider, modelId);
2903
+ // If the override was for the current model, revert to global default
2904
+ const current = this.facade.getModel();
2905
+ if (current && current.provider === provider && current.id === modelId) {
2906
+ const globalDefault = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
2907
+ this.facade.setThinkingLevel(globalDefault);
2908
+ this.footer.invalidate();
2909
+ this.updateEditorBorderColor();
2910
+ }
2911
+ },
2912
+ onThemeChange: (themeSetting) => {
2913
+ this.settingsManager.setTheme(themeSetting);
2914
+ void this.themeController.setThemeSetting(themeSetting);
2915
+ },
2916
+ onThemePreview: (themeName) => this.themeController.preview(themeName),
2917
+ onHideThinkingBlockChange: (hidden) => {
2918
+ this.hideThinkingBlock = hidden;
2919
+ this.settingsManager.setHideThinkingBlock(hidden);
2920
+ this.updateThinkingBlockVisibility();
2921
+ },
2922
+ onMermaidRenderingModeChange: (mode) => {
2923
+ this.settingsManager.setMermaidRenderingMode(mode);
2924
+ this.chatContainer.invalidate();
2925
+ this.ui.requestRender();
2926
+ },
2927
+ onShowCacheMissNoticesChange: (shown) => {
2928
+ this.settingsManager.setShowCacheMissNotices(shown);
2929
+ this.rebuildChatFromMessages();
2930
+ },
2931
+ onCollapseChangelogChange: (collapsed) => {
2932
+ this.settingsManager.setCollapseChangelog(collapsed);
2933
+ },
2934
+ onQuietStartupChange: (enabled) => {
2935
+ this.settingsManager.setQuietStartup(enabled);
2936
+ },
2937
+ onDoubleEscapeActionChange: (action) => {
2938
+ this.settingsManager.setDoubleEscapeAction(action);
2939
+ },
2940
+ onTreeFilterModeChange: (mode) => {
2941
+ this.settingsManager.setTreeFilterMode(mode);
2942
+ },
2943
+ onShowHardwareCursorChange: (enabled) => {
2944
+ this.settingsManager.setShowHardwareCursor(enabled);
2945
+ this.ui.setShowHardwareCursor(enabled);
2946
+ },
2947
+ onEditorPaddingXChange: (padding) => {
2948
+ this.settingsManager.setEditorPaddingX(padding);
2949
+ this.defaultEditor.setPaddingX(padding);
2950
+ if (this.editor !== this.defaultEditor && this.editor.setPaddingX !== undefined) {
2951
+ this.editor.setPaddingX(padding);
2952
+ }
2953
+ },
2954
+ onOutputPadChange: (padding) => {
2955
+ this.settingsManager.setOutputPad(padding);
2956
+ this.outputPad = padding;
2957
+ if (this.streamingComponent || this.facade.isStreaming()) {
2958
+ for (const child of this.chatContainer.children) {
2959
+ if (child instanceof AssistantMessageComponent ||
2960
+ child instanceof CustomMessageComponent ||
2961
+ child instanceof UserMessageComponent) {
2962
+ child.setOutputPad(padding);
2963
+ }
2964
+ }
2965
+ if (this.streamingComponent) {
2966
+ this.streamingComponent.setOutputPad(padding);
2967
+ }
2968
+ this.ui.requestRender();
2969
+ return;
2970
+ }
2971
+ this.rebuildChatFromMessages();
2972
+ },
2973
+ onAutocompleteMaxVisibleChange: (maxVisible) => {
2974
+ this.settingsManager.setAutocompleteMaxVisible(maxVisible);
2975
+ this.defaultEditor.setAutocompleteMaxVisible(maxVisible);
2976
+ if (this.editor !== this.defaultEditor && this.editor.setAutocompleteMaxVisible !== undefined) {
2977
+ this.editor.setAutocompleteMaxVisible(maxVisible);
2978
+ }
2979
+ },
2980
+ onClearOnShrinkChange: (enabled) => {
2981
+ this.settingsManager.setClearOnShrink(enabled);
2982
+ this.ui.setClearOnShrink(enabled);
2983
+ if (!enabled && !this.activeStatusIndicator) {
2984
+ this.statusContainer.clear();
2985
+ }
2986
+ },
2987
+ onShowTerminalProgressChange: (enabled) => {
2988
+ this.settingsManager.setShowTerminalProgress(enabled);
2989
+ },
2990
+ onTuiModeChange: (mode) => {
2991
+ if (!this.switchTuiMode(mode)) {
2992
+ selector?.getSettingsList().updateValue("tui-mode", this.ui.mode);
2993
+ this.showStatus("Close active overlays before changing TUI mode");
2994
+ return;
2995
+ }
2996
+ this.settingsManager.setTuiMode(mode);
2997
+ if (!this.activeStatusIndicator)
2998
+ this.statusContainer.clear();
2999
+ this.showStatus(`TUI mode: ${mode}`);
3000
+ },
3001
+ onFullscreenExitOutputChange: (output) => {
3002
+ this.settingsManager.setFullscreenExitOutput(output);
3003
+ },
3004
+ onFullscreenScrollbarChange: (mode) => {
3005
+ this.settingsManager.setFullscreenScrollbar(mode);
3006
+ this.applyFullscreenScrollbarSetting();
3007
+ },
3008
+ onFullscreenCopyOnSelectChange: (enabled) => {
3009
+ this.settingsManager.setFullscreenCopyOnSelect(enabled);
3010
+ if (this.renderer instanceof TuiAltScreen)
3011
+ this.renderer.setCopyOnSelect(enabled);
3012
+ },
3013
+ onWarningsChange: (warnings) => {
3014
+ this.settingsManager.setWarnings(warnings);
3015
+ },
3016
+ onCancel: () => {
3017
+ done();
3018
+ this.ui.requestRender();
3019
+ },
3020
+ });
3021
+ return { component: selector, focus: selector.getSettingsList() };
3022
+ });
3023
+ }
3024
+ /** /thinking command entry; implementation in ./interactive-selectors.ts (S5 slice 5). */
3025
+ handleThinkingCommand(searchTerm) {
3026
+ selectorsFlow.handleThinkingCommand(this, searchTerm);
3027
+ }
3028
+ /** Thinking level apply; implementation in ./interactive-selectors.ts (S5 slice 5). */
3029
+ selectThinkingLevel(level, persist) {
3030
+ selectorsFlow.selectThinkingLevel(this, level, persist);
3031
+ }
3032
+ /** Thinking level picker; implementation in ./interactive-selectors.ts (S5 slice 5). */
3033
+ showThinkingSelector() {
3034
+ selectorsFlow.showThinkingSelector(this);
3035
+ }
3036
+ /**
3037
+ * Current session's suite id, read from the session custom entry recorded at
3038
+ * creation (设计 §10.1). Never inferred from settings or env; undefined when
3039
+ * the session carries no suite entry (e.g. resumed legacy sessions).
3040
+ * Internal collaboration surface; exposed for ./interactive-selectors.ts
3041
+ * (S5 slice 5) while the read stays on the mode (session-boundary carve-out).
3042
+ */
3043
+ getCurrentSessionSuiteId() {
3044
+ const entries = this.facade.getEntries();
3045
+ for (let i = entries.length - 1; i >= 0; i--) {
3046
+ const entry = entries[i];
3047
+ if (entry.type !== "custom" || entry.customType !== SUITE_SESSION_ENTRY_TYPE)
3048
+ continue;
3049
+ const suiteId = entry.data?.suiteId;
3050
+ if (typeof suiteId === "string" && suiteId.trim().length > 0)
3051
+ return suiteId;
3052
+ }
3053
+ return undefined;
3054
+ }
3055
+ sessionSuiteIdCache;
3056
+ /** Host-visible for ./interactive-selectors.ts (S5 slice 5): narrow session read. */
3057
+ getAvailableThinkingLevels() {
3058
+ return this.facade.getAvailableThinkingLevels();
3059
+ }
3060
+ /** Host-visible for ./interactive-selectors.ts (S5 slice 5): narrow session read. */
3061
+ getUserMessagesForForking() {
3062
+ return this.facade.getUserMessagesForForking();
3063
+ }
3064
+ /**
3065
+ * Bound suite id of a listed session (设计 §10.1), read from the session
3066
+ * file's binding entry and cached per path — the selector refilters the
3067
+ * list on every keystroke.
3068
+ */
3069
+ readSessionSuiteId(sessionPath) {
3070
+ this.sessionSuiteIdCache ??= new Map();
3071
+ if (this.sessionSuiteIdCache.has(sessionPath))
3072
+ return this.sessionSuiteIdCache.get(sessionPath);
3073
+ const suiteId = readSessionSuiteIdFromFile(sessionPath);
3074
+ this.sessionSuiteIdCache.set(sessionPath, suiteId);
3075
+ return suiteId;
3076
+ }
3077
+ /** /suite command entry; implementation in ./interactive-selectors.ts (S5 slice 5). */
3078
+ handleSuiteCommand(suiteId) {
3079
+ selectorsFlow.handleSuiteCommand(this, suiteId);
3080
+ }
3081
+ /** Suite list overlay; implementation in ./interactive-selectors.ts (S5 slice 5). */
3082
+ showSuiteSelector(availableSuites) {
3083
+ selectorsFlow.showSuiteSelector(this, availableSuites);
3084
+ }
3085
+ /**
3086
+ * Shared suite list overlay (设计 §9); implementation in
3087
+ * ./interactive-selectors.ts (S5 slice 5).
3088
+ */
3089
+ openSuiteListSelector(callbacks) {
3090
+ selectorsFlow.openSuiteListSelector(this, callbacks);
3091
+ }
3092
+ /**
3093
+ * Interactive recovery for an unresolved startup suite id (设计 §9): pick a
3094
+ * suite, persist it as the project setting, then rebuild the session with
3095
+ * the selected suite via the same /new assembly path. Cancelling keeps the
3096
+ * fallback assembly the runtime started with.
3097
+ */
3098
+ async showStartupSuiteSelector(pending) {
3099
+ const selected = await new Promise((resolve) => {
3100
+ this.openSuiteListSelector({
3101
+ availableSuites: pending.available,
3102
+ note: `Suite "${pending.requestedId}" was not found. The selected suite applies to the new session.`,
3103
+ onSelect: (suiteId) => resolve(suiteId),
3104
+ onCancel: () => resolve(undefined),
3105
+ });
3106
+ });
3107
+ if (selected === undefined) {
3108
+ this.showWarning(`Suite "${pending.requestedId}" was not found — continuing without a suite. Use /suite to choose one.`);
3109
+ return;
3110
+ }
3111
+ this.settingsManager.setProjectSuite(selected);
3112
+ try {
3113
+ await this.runtimeFacade.newSession();
3114
+ this.showStatus(`Suite set to ${selected} — new session started`);
3115
+ }
3116
+ catch (error) {
3117
+ await this.handleFatalRuntimeError("Failed to create session", error);
3118
+ }
3119
+ }
3120
+ /** /model command entry; implementation in ./interactive-selectors.ts (S5 slice 5). */
3121
+ async handleModelCommand(searchTerm) {
3122
+ await selectorsFlow.handleModelCommand(this, searchTerm);
3123
+ }
3124
+ /** Exact model lookup; implementation in ./interactive-selectors.ts (S5 slice 5). */
3125
+ async findExactModelMatch(searchTerm) {
3126
+ return selectorsFlow.findExactModelMatch(this, searchTerm);
3127
+ }
3128
+ /**
3129
+ * Update the footer's available provider count from the current snapshot without
3130
+ * refreshing catalogs. Host-visible for ./interactive-auth.ts (S5 slice 3).
3131
+ */
3132
+ updateAvailableProviderCount() {
3133
+ const models = this.facade.getScopedModels().length > 0
3134
+ ? this.facade.getScopedModels().map((scoped) => scoped.model)
3135
+ : this.facade.getAvailableModels();
3136
+ const uniqueProviders = new Set(models.map((model) => model.provider));
3137
+ this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size);
3138
+ }
3139
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3). */
3140
+ async maybeWarnAboutAnthropicSubscriptionAuth(model = this.facade.getModel()) {
3141
+ if (this.settingsManager.getWarnings().anthropicExtraUsage === false) {
3142
+ return;
3143
+ }
3144
+ if (this.anthropicSubscriptionWarningShown) {
3145
+ return;
3146
+ }
3147
+ if (!model || model.provider !== "anthropic") {
3148
+ return;
3149
+ }
3150
+ try {
3151
+ if ((await this.facade.checkProviderAuth("anthropic"))?.type === "oauth") {
3152
+ this.anthropicSubscriptionWarningShown = true;
3153
+ this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);
3154
+ return;
3155
+ }
3156
+ const apiKey = (await this.facade.getProviderAuth(model.provider))?.auth.apiKey;
3157
+ if (!isAnthropicSubscriptionAuthKey(apiKey)) {
3158
+ return;
3159
+ }
3160
+ this.anthropicSubscriptionWarningShown = true;
3161
+ this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);
3162
+ }
3163
+ catch {
3164
+ // Ignore auth lookup failures for warning-only checks.
3165
+ }
3166
+ }
3167
+ /** Model picker; implementation in ./interactive-selectors.ts (S5 slice 5). */
3168
+ showModelSelector(initialSearchInput) {
3169
+ selectorsFlow.showModelSelector(this, initialSearchInput);
3170
+ }
3171
+ /** Scoped-models picker; implementation in ./interactive-selectors.ts (S5 slice 5). */
3172
+ showModelsSelector() {
3173
+ selectorsFlow.showModelsSelector(this);
3174
+ }
3175
+ /** Fork picker; implementation in ./interactive-selectors.ts (S5 slice 5). */
3176
+ showUserMessageSelector() {
3177
+ selectorsFlow.showUserMessageSelector(this);
3178
+ }
3179
+ /** /clone command entry; implementation in ./interactive-selectors.ts (S5 slice 5). */
3180
+ async handleCloneCommand() {
3181
+ await selectorsFlow.handleCloneCommand(this);
3182
+ }
3183
+ showTreeSelector(initialSelectedId) {
3184
+ const tree = this.facade.getTree();
3185
+ const realLeafId = this.facade.getLeafId();
3186
+ const initialFilterMode = this.settingsManager.getTreeFilterMode();
3187
+ if (tree.length === 0) {
3188
+ this.showStatus("No entries in session");
3189
+ return;
3190
+ }
3191
+ this.showSelector((done) => {
3192
+ const selector = new TreeSelectorComponent(tree, realLeafId, this.ui.terminal.rows, async (entryId) => {
3193
+ // Selecting the current leaf is a no-op (already there)
3194
+ if (entryId === this.facade.getLeafId()) {
3195
+ done();
3196
+ this.showStatus("Already at this point");
3197
+ return;
3198
+ }
3199
+ // Ask about summarization
3200
+ done(); // Close selector first
3201
+ // Loop until user makes a complete choice or cancels to tree
3202
+ let wantsSummary = false;
3203
+ let customInstructions;
3204
+ // Check if we should skip the prompt (user preference to always default to no summary)
3205
+ if (!this.settingsManager.getBranchSummarySkipPrompt()) {
3206
+ while (true) {
3207
+ const summaryChoice = await this.showDialogSelector("Summarize branch?", [
3208
+ "No summary",
3209
+ "Summarize",
3210
+ "Summarize with custom prompt",
3211
+ ]);
3212
+ if (summaryChoice === undefined) {
3213
+ // User pressed escape - re-show tree selector with same selection
3214
+ this.showTreeSelector(entryId);
3215
+ return;
3216
+ }
3217
+ wantsSummary = summaryChoice !== "No summary";
3218
+ if (summaryChoice === "Summarize with custom prompt") {
3219
+ customInstructions = await this.showDialogEditor("Custom summarization instructions");
3220
+ if (customInstructions === undefined) {
3221
+ // User cancelled - loop back to summary selector
3222
+ continue;
3223
+ }
3224
+ }
3225
+ // User made a complete choice
3226
+ break;
3227
+ }
3228
+ }
3229
+ // The user committed to navigating: stop the active response first.
3230
+ if (this.facade.isStreaming()) {
3231
+ this.restoreQueuedMessagesToEditor();
3232
+ await this.facade.abort();
3233
+ }
3234
+ // Set up escape handler and status indicator if summarizing
3235
+ let showingSummaryIndicator = false;
3236
+ const originalOnEscape = this.defaultEditor.onEscape;
3237
+ if (wantsSummary) {
3238
+ this.defaultEditor.onEscape = () => {
3239
+ this.facade.abortBranchSummary();
3240
+ };
3241
+ this.chatContainer.addChild(new Spacer(1));
3242
+ this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
3243
+ showingSummaryIndicator = true;
3244
+ this.ui.requestRender();
3245
+ }
3246
+ try {
3247
+ const result = await this.facade.navigateTree(entryId, {
3248
+ summarize: wantsSummary,
3249
+ customInstructions,
3250
+ });
3251
+ if (result.aborted) {
3252
+ // Summarization aborted - re-show tree selector with same selection
3253
+ this.showStatus("Branch summarization cancelled");
3254
+ this.showTreeSelector(entryId);
3255
+ return;
3256
+ }
3257
+ if (result.cancelled) {
3258
+ this.showStatus("Navigation cancelled");
3259
+ return;
3260
+ }
3261
+ // Update UI
3262
+ this.chatContainer.clear();
3263
+ this.renderInitialMessages();
3264
+ if (result.editorText && !this.editor.getText().trim()) {
3265
+ this.editor.setText(result.editorText);
3266
+ }
3267
+ this.showStatus("Navigated to selected point");
3268
+ void this.flushCompactionQueue({ willRetry: false });
3269
+ }
3270
+ catch (error) {
3271
+ this.showError(error instanceof Error ? error.message : String(error));
3272
+ }
3273
+ finally {
3274
+ if (showingSummaryIndicator) {
3275
+ this.clearStatusIndicator("branchSummary");
3276
+ }
3277
+ this.defaultEditor.onEscape = originalOnEscape;
3278
+ }
3279
+ }, () => {
3280
+ done();
3281
+ this.ui.requestRender();
3282
+ }, (entryId, label) => {
3283
+ this.facade.appendLabelChange(entryId, label);
3284
+ this.ui.requestRender();
3285
+ }, initialSelectedId, initialFilterMode);
3286
+ selector.onCopy = async (text) => {
3287
+ if (!text) {
3288
+ this.showError("Selected entry has no text to copy");
3289
+ return;
3290
+ }
3291
+ try {
3292
+ await copyToClipboard(text);
3293
+ this.showStatus("Copied selected message to clipboard");
3294
+ }
3295
+ catch (error) {
3296
+ this.showError(error instanceof Error ? error.message : String(error));
3297
+ }
3298
+ };
3299
+ return { component: selector, focus: selector };
3300
+ });
3301
+ }
3302
+ showSessionSelector() {
3303
+ this.showSelector((done) => {
3304
+ const selector = new SessionSelectorComponent((onProgress) => this.runtimeFacade.listSessions(onProgress), (onProgress) => this.runtimeFacade.listAllSessions(onProgress), async (sessionPath) => {
3305
+ done();
3306
+ await this.handleResumeSession(sessionPath);
3307
+ }, () => {
3308
+ done();
3309
+ this.ui.requestRender();
3310
+ }, () => {
3311
+ void this.shutdown();
3312
+ }, () => this.ui.requestRender(), {
3313
+ renameSession: async (sessionFilePath, nextName) => {
3314
+ const next = (nextName ?? "").trim();
3315
+ if (!next)
3316
+ return;
3317
+ const mgr = SessionManager.open(sessionFilePath);
3318
+ mgr.appendSessionInfo(next);
3319
+ },
3320
+ showRenameHint: true,
3321
+ keybindings: this.keybindings,
3322
+ // 会话选择器默认只列当前方案的会话;跨方案会话仅在显式
3323
+ // "show all" 后可见(设计 §10.1)。
3324
+ suiteFilter: {
3325
+ currentSuiteId: this.getCurrentSessionSuiteId(),
3326
+ getSessionSuiteId: (session) => this.readSessionSuiteId(session.path),
3327
+ },
3328
+ }, this.runtimeFacade.getSessionFile());
3329
+ return { component: selector, focus: selector };
3330
+ });
3331
+ }
3332
+ async handleResumeSession(sessionPath, options) {
3333
+ this.clearStatusIndicator();
3334
+ try {
3335
+ const result = await this.runtimeFacade.switchSession(sessionPath, {
3336
+ withSession: options?.withSession,
3337
+ });
3338
+ if (result.cancelled) {
3339
+ return result;
3340
+ }
3341
+ this.showStatus("Resumed session");
3342
+ this.detectCrossSuiteResume();
3343
+ return result;
3344
+ }
3345
+ catch (error) {
3346
+ if (error instanceof MissingSessionCwdError) {
3347
+ const selectedCwd = await this.promptForMissingSessionCwd(error);
3348
+ if (!selectedCwd) {
3349
+ this.showStatus("Resume cancelled");
3350
+ return { cancelled: true };
3351
+ }
3352
+ const result = await this.runtimeFacade.switchSession(sessionPath, {
3353
+ cwdOverride: selectedCwd,
3354
+ withSession: options?.withSession,
3355
+ });
3356
+ if (result.cancelled) {
3357
+ return result;
3358
+ }
3359
+ this.showStatus("Resumed session in current cwd");
3360
+ this.detectCrossSuiteResume();
3361
+ return result;
3362
+ }
3363
+ return this.handleFatalRuntimeError("Failed to resume session", error);
3364
+ }
3365
+ }
3366
+ /**
3367
+ * Cross-suite resume detection (设计 §10.1 最小可用版): compare the loaded
3368
+ * session's original suite binding with the suite resolved from the current
3369
+ * settings/env — the id the resumed session was actually reassembled with
3370
+ * (assembly happens at session creation, so reassembly is the existing
3371
+ * behavior). On a mismatch, record the fact for later debugging: an info
3372
+ * status line plus a `suite_mismatch` custom entry on the session. No
3373
+ * context serialization or conversion is attempted.
3374
+ */
3375
+ detectCrossSuiteResume() {
3376
+ const originalSuiteId = this.getCurrentSessionSuiteId();
3377
+ // Pre-suite (legacy) sessions carry no binding; nothing to compare.
3378
+ if (originalSuiteId === undefined)
3379
+ return;
3380
+ const currentSuiteId = resolveSuiteId({
3381
+ envSuite: process.env[SUITE_ENV_VAR],
3382
+ settings: this.settingsManager,
3383
+ agentDir: getAgentDir(),
3384
+ });
3385
+ if (currentSuiteId === originalSuiteId)
3386
+ return;
3387
+ this.showStatus(`Cross-suite compatible mode: session created with "${originalSuiteId}", assembling with "${currentSuiteId}"`);
3388
+ this.facade.recordSuiteMismatch(originalSuiteId, currentSuiteId);
3389
+ }
3390
+ // =========================================================================
3391
+ // Login/authentication (implementation in ./interactive-auth.ts, S5 slice 3)
3392
+ // Host-visible narrow accessors plus same-name delegates; prototype-level
3393
+ // tests and the command dispatch bind to these names.
3394
+ // =========================================================================
3395
+ /**
3396
+ * Host-visible for ./interactive-auth.ts (D-048): narrow credential/provider
3397
+ * auth projection of the session's ModelRuntime through the stable facade.
3398
+ * The full runtime never crosses the host boundary (D-047 裁决 3's
3399
+ * credential-management semantics stay open).
3400
+ */
3401
+ getModelAuthRuntime() {
3402
+ return this.facade.getModelAuthRuntime();
3403
+ }
3404
+ /** Host-visible for ./interactive-auth.ts (D-048): available model snapshot. */
3405
+ getAvailableModels() {
3406
+ return this.facade.getAvailableModels();
3407
+ }
3408
+ /** Host-visible for ./interactive-selectors.ts (D-048): narrow catalog-refresh projection. */
3409
+ getModelCatalog() {
3410
+ return this.facade.getModelCatalog();
3411
+ }
3412
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3): opaque session identity. */
3413
+ getSessionIdentity() {
3414
+ return this.session;
3415
+ }
3416
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3). */
3417
+ isSameSessionIdentity(identity) {
3418
+ return this.session === identity;
3419
+ }
3420
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3): stable facade read. */
3421
+ getSelectedModel() {
3422
+ return this.facade.getModel();
3423
+ }
3424
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3): stable facade write. */
3425
+ async setSelectedModel(model) {
3426
+ await this.facade.setModel(model, { persist: true });
3427
+ }
3428
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3). */
3429
+ invalidateFooter() {
3430
+ this.footer.invalidate();
3431
+ }
3432
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3); delegates to the selector area. */
3433
+ showAuthSelector(create) {
3434
+ this.showSelector(create);
3435
+ }
3436
+ /** Login provider options; implementation in ./interactive-auth.ts (S5 slice 3). */
3437
+ getLoginProviderOptions(authType) {
3438
+ return authFlow.getLoginProviderOptions(this, authType);
3439
+ }
3440
+ /** Logout provider options; implementation in ./interactive-auth.ts (S5 slice 3). */
3441
+ async getLogoutProviderOptions() {
3442
+ return authFlow.getLogoutProviderOptions(this);
3443
+ }
3444
+ /** Login provider lookup; implementation in ./interactive-auth.ts (S5 slice 3). */
3445
+ findLoginProviderOptions(providerRef) {
3446
+ return authFlow.findLoginProviderOptions(this, providerRef);
3447
+ }
3448
+ /** /login command entry; implementation in ./interactive-auth.ts (S5 slice 3). */
3449
+ async handleLoginCommand(providerRef) {
3450
+ await authFlow.handleLoginCommand(this, providerRef);
3451
+ }
3452
+ /** Login branch by auth type; implementation in ./interactive-auth.ts (S5 slice 3). */
3453
+ async startProviderLogin(providerOption) {
3454
+ await authFlow.startProviderLogin(this, providerOption);
3455
+ }
3456
+ /** Auth type selector; implementation in ./interactive-auth.ts (S5 slice 3). */
3457
+ showLoginAuthTypeSelector(providerOptions) {
3458
+ authFlow.showLoginAuthTypeSelector(this, providerOptions);
3459
+ }
3460
+ /** Login provider selector; implementation in ./interactive-auth.ts (S5 slice 3). */
3461
+ showLoginProviderSelector(authType, initialSearchInput) {
3462
+ authFlow.showLoginProviderSelector(this, authType, initialSearchInput);
3463
+ }
3464
+ /** Login/logout selector entry; implementation in ./interactive-auth.ts (S5 slice 3). */
3465
+ async showOAuthSelector(mode) {
3466
+ await authFlow.showOAuthSelector(this, mode);
3467
+ }
3468
+ /** Post-login completion; implementation in ./interactive-auth.ts (S5 slice 3). */
3469
+ async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
3470
+ await authFlow.completeProviderAuthentication(this, providerId, providerName, authType, previousModel);
3471
+ }
3472
+ /** Ambient auth notice; implementation in ./interactive-auth.ts (S5 slice 3). */
3473
+ showAmbientAuthDialog(providerOption) {
3474
+ authFlow.showAmbientAuthDialog(this, providerOption);
3475
+ }
3476
+ /** API key login dialog; implementation in ./interactive-auth.ts (S5 slice 3). */
3477
+ async showApiKeyLoginDialog(providerId, providerName) {
3478
+ await authFlow.showApiKeyLoginDialog(this, providerId, providerName);
3479
+ }
3480
+ /** Auth select prompt; implementation in ./interactive-auth.ts (S5 slice 3). */
3481
+ showAuthSelect(dialog, prompt) {
3482
+ return authFlow.showAuthSelect(this, dialog, prompt);
3483
+ }
3484
+ /** Auth prompt plumbing; implementation in ./interactive-auth.ts (S5 slice 3). */
3485
+ async showAuthPrompt(dialog, prompt) {
3486
+ return authFlow.showAuthPrompt(this, dialog, prompt);
3487
+ }
3488
+ /** Auth event rendering; implementation in ./interactive-auth.ts (S5 slice 3). */
3489
+ notifyAuthDialog(dialog, event) {
3490
+ authFlow.notifyAuthDialog(this, dialog, event);
3491
+ }
3492
+ /** Provider login call; implementation in ./interactive-auth.ts (S5 slice 3). */
3493
+ async loginProvider(dialog, providerId, method) {
3494
+ await authFlow.loginProvider(this, dialog, providerId, method);
3495
+ }
3496
+ /** OAuth login dialog; implementation in ./interactive-auth.ts (S5 slice 3). */
3497
+ async showLoginDialog(providerId, providerName) {
3498
+ await authFlow.showLoginDialog(this, providerId, providerName);
3499
+ }
3500
+ // =========================================================================
3501
+ // Command handlers
3502
+ // =========================================================================
3503
+ async handleReloadCommand() {
3504
+ if (this.facade.isStreaming()) {
3505
+ this.showWarning("Wait for the current response to finish before reloading.");
3506
+ return;
3507
+ }
3508
+ if (this.facade.isCompacting()) {
3509
+ this.showWarning("Wait for compaction to finish before reloading.");
3510
+ return;
3511
+ }
3512
+ this.resetDialogUI();
3513
+ const reloadBox = new Container();
3514
+ const borderColor = (s) => theme.fg("border", s);
3515
+ reloadBox.addChild(new DynamicBorder(borderColor));
3516
+ reloadBox.addChild(new Spacer(1));
3517
+ reloadBox.addChild(new Text(theme.fg("muted", "Reloading keybindings, skills, prompts, themes, and context files..."), 1, 0));
3518
+ reloadBox.addChild(new Spacer(1));
3519
+ reloadBox.addChild(new DynamicBorder(borderColor));
3520
+ const previousEditor = this.editor;
3521
+ this.editorContainer.clear();
3522
+ this.editorContainer.addChild(reloadBox);
3523
+ this.ui.setFocus(reloadBox);
3524
+ this.ui.requestRender(true);
3525
+ await new Promise((resolve) => process.nextTick(resolve));
3526
+ const dismissReloadBox = (editor) => {
3527
+ this.editorContainer.clear();
3528
+ this.editorContainer.addChild(editor);
3529
+ this.ui.setFocus(editor);
3530
+ this.ui.requestRender();
3531
+ };
3532
+ let chatRestoredBeforeSessionStart = false;
3533
+ let reloadBoxDismissed = false;
3534
+ const restoreChatBeforeSessionStart = () => {
3535
+ if (chatRestoredBeforeSessionStart) {
3536
+ return;
3537
+ }
3538
+ this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
3539
+ this.outputPad = this.settingsManager.getOutputPad();
3540
+ this.rebuildChatFromMessages();
3541
+ chatRestoredBeforeSessionStart = true;
3542
+ };
3543
+ try {
3544
+ await this.facade.reload({ beforeSessionStart: restoreChatBeforeSessionStart });
3545
+ restoreChatBeforeSessionStart();
3546
+ this.keybindings.reload();
3547
+ const activeHeader = this.builtInHeader;
3548
+ if (isExpandable(activeHeader)) {
3549
+ activeHeader.setExpanded(this.toolOutputExpanded);
3550
+ }
3551
+ setRegisteredThemes(buildRegisteredThemes(this.facade.getThemes().themes));
3552
+ this.applyRuntimeSettings();
3553
+ await this.themeController.applyFromSettings();
3554
+ this.setupAutocompleteProvider();
3555
+ this.showLoadedResources({
3556
+ force: false,
3557
+ showDiagnosticsWhenQuiet: true,
3558
+ });
3559
+ const modelsJsonError = this.facade.getModelsError();
3560
+ if (modelsJsonError) {
3561
+ this.showError(`models.json error: ${modelsJsonError}`);
3562
+ }
3563
+ this.showStatus("Reloaded keybindings, skills, prompts, themes, and context files");
3564
+ dismissReloadBox(this.editor);
3565
+ reloadBoxDismissed = true;
3566
+ }
3567
+ catch (error) {
3568
+ // v8 ignore next -- reloadBoxDismissed 置位后 catch 前无可抛出点,恒走 dismiss 分支
3569
+ if (!reloadBoxDismissed) {
3570
+ dismissReloadBox(previousEditor);
3571
+ }
3572
+ this.showError(`Reload failed: ${error instanceof Error ? error.message : String(error)}`);
3573
+ }
3574
+ }
3575
+ async handleExportCommand(text) {
3576
+ const outputPath = this.getPathCommandArgument(text, "/export");
3577
+ try {
3578
+ if (outputPath?.endsWith(".jsonl")) {
3579
+ const filePath = this.facade.exportToJsonl(outputPath);
3580
+ this.showStatus(`Session exported to: ${filePath}`);
3581
+ }
3582
+ else {
3583
+ const filePath = await this.facade.exportToHtml(outputPath, {
3584
+ themeName: theme.name,
3585
+ });
3586
+ this.showStatus(`Session exported to: ${filePath}`);
3587
+ }
3588
+ }
3589
+ catch (error) {
3590
+ this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
3591
+ }
3592
+ }
3593
+ getPathCommandArgument(text, command) {
3594
+ if (text === command) {
3595
+ return undefined;
3596
+ }
3597
+ if (!text.startsWith(`${command} `)) {
3598
+ return undefined;
3599
+ }
3600
+ const argsString = text.slice(command.length + 1).trimStart();
3601
+ if (!argsString) {
3602
+ return undefined;
3603
+ }
3604
+ const firstChar = argsString[0];
3605
+ if (firstChar === '"' || firstChar === "'") {
3606
+ const closingQuoteIndex = argsString.indexOf(firstChar, 1);
3607
+ if (closingQuoteIndex < 0) {
3608
+ return undefined;
3609
+ }
3610
+ return argsString.slice(1, closingQuoteIndex);
3611
+ }
3612
+ const firstWhitespaceIndex = argsString.search(/\s/);
3613
+ if (firstWhitespaceIndex < 0) {
3614
+ return argsString;
3615
+ }
3616
+ return argsString.slice(0, firstWhitespaceIndex);
3617
+ }
3618
+ async handleImportCommand(text) {
3619
+ const inputPath = this.getPathCommandArgument(text, "/import");
3620
+ if (!inputPath) {
3621
+ this.showError("Usage: /import <path.jsonl>");
3622
+ return;
3623
+ }
3624
+ const confirmed = await this.showDialogConfirm("Import session", `Replace current session with ${inputPath}?`);
3625
+ if (!confirmed) {
3626
+ this.showStatus("Import cancelled");
3627
+ return;
3628
+ }
3629
+ try {
3630
+ this.clearStatusIndicator();
3631
+ const result = await this.runtimeFacade.importFromJsonl(inputPath);
3632
+ if (result.cancelled) {
3633
+ this.showStatus("Import cancelled");
3634
+ return;
3635
+ }
3636
+ this.showStatus(`Session imported from: ${inputPath}`);
3637
+ }
3638
+ catch (error) {
3639
+ if (error instanceof MissingSessionCwdError) {
3640
+ const selectedCwd = await this.promptForMissingSessionCwd(error);
3641
+ if (!selectedCwd) {
3642
+ this.showStatus("Import cancelled");
3643
+ return;
3644
+ }
3645
+ const result = await this.runtimeFacade.importFromJsonl(inputPath, selectedCwd);
3646
+ if (result.cancelled) {
3647
+ this.showStatus("Import cancelled");
3648
+ return;
3649
+ }
3650
+ this.showStatus(`Session imported from: ${inputPath}`);
3651
+ return;
3652
+ }
3653
+ if (error instanceof SessionImportFileNotFoundError) {
3654
+ this.showError(`Failed to import session: ${error.message}`);
3655
+ return;
3656
+ }
3657
+ await this.handleFatalRuntimeError("Failed to import session", error);
3658
+ }
3659
+ }
3660
+ async handleCopyCommand(options = {}) {
3661
+ if (options.preferSelection &&
3662
+ this.ui instanceof TuiAltScreen &&
3663
+ !this.ui.getCopyOnSelect() &&
3664
+ this.ui.hasActiveSelection()) {
3665
+ await this.ui.copyActiveSelectionToClipboard();
3666
+ return;
3667
+ }
3668
+ const text = this.facade.getLastAssistantText();
3669
+ if (!text) {
3670
+ this.showError("No agent messages to copy yet.");
3671
+ return;
3672
+ }
3673
+ try {
3674
+ await copyToClipboard(text);
3675
+ if (options.flashConfirmation && this.ui instanceof TuiAltScreen) {
3676
+ this.ui.flash("Copied!");
3677
+ }
3678
+ else {
3679
+ this.showStatus("Copied last agent message to clipboard");
3680
+ }
3681
+ }
3682
+ catch (error) {
3683
+ this.showError(error instanceof Error ? error.message : String(error));
3684
+ }
3685
+ }
3686
+ handleNameCommand(text) {
3687
+ const name = text.replace(/^\/name\s*/, "").trim();
3688
+ if (!name) {
3689
+ const currentName = this.facade.getSessionName();
3690
+ if (currentName) {
3691
+ this.chatContainer.addChild(new Spacer(1));
3692
+ this.chatContainer.addChild(new Text(theme.fg("dim", `Session name: ${currentName}`), 1, 0));
3693
+ }
3694
+ else {
3695
+ this.showWarning("Usage: /name <name>");
3696
+ }
3697
+ this.ui.requestRender();
3698
+ return;
3699
+ }
3700
+ this.facade.setSessionName(name);
3701
+ const sessionName = this.facade.getSessionName();
3702
+ if (sessionName !== name) {
3703
+ this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`);
3704
+ }
3705
+ this.chatContainer.addChild(new Spacer(1));
3706
+ this.chatContainer.addChild(new Text(theme.fg("dim", `Session name set: ${sessionName ?? name}`), 1, 0));
3707
+ this.ui.requestRender();
3708
+ }
3709
+ handleSessionCommand() {
3710
+ const stats = this.facade.getSessionStats();
3711
+ const sessionName = this.facade.getSessionName();
3712
+ const entries = this.facade.getEntries();
3713
+ const cacheWaste = computeCacheWaste(entries, this.facade.getModelPriceSource());
3714
+ // Cost/token totals per provider/model actually used (e.g. OpenRouter `auto`
3715
+ // resolves to a concrete responseModel). Usage without model attribution is
3716
+ // grouped separately so the breakdown reconciles with the session total.
3717
+ const usageBreakdown = getUsageCostBreakdown(entries);
3718
+ let info = `${theme.bold("Session Info")}\n\n`;
3719
+ if (sessionName) {
3720
+ info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
3721
+ }
3722
+ info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
3723
+ info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
3724
+ info += `${theme.bold("Messages")}\n`;
3725
+ info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
3726
+ info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
3727
+ info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
3728
+ info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
3729
+ info += `${theme.bold("Tokens")}\n`;
3730
+ // "Input" is the full prompt volume. With cache activity, split it into
3731
+ // cached (served from cache) vs uncached (everything else) - the only
3732
+ // provider-independent split. Cache writes, where reported, are a detail
3733
+ // of the uncached portion.
3734
+ const { input, cacheRead, cacheWrite } = stats.tokens;
3735
+ const promptTokens = input + cacheRead + cacheWrite;
3736
+ info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
3737
+ if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
3738
+ const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
3739
+ info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
3740
+ const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
3741
+ info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
3742
+ }
3743
+ info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
3744
+ info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
3745
+ // 双维度统计(用户裁决 2026-09-25):总计之外按供应商/模型分桶——缓存读/写、
3746
+ // 命中率、费用逐桶可见。此前该拆分门控在 cost>0 且多桶才渲染,单价为 0 的
3747
+ // 自定义供应商(如自建代理)永远看不到。
3748
+ if (usageBreakdown.length > 0) {
3749
+ info += `\n${theme.bold("By Provider/Model")}\n`;
3750
+ for (const entry of usageBreakdown) {
3751
+ const bucket = entry.totals;
3752
+ const promptBucket = bucket.input + bucket.cacheRead + bucket.cacheWrite;
3753
+ let line = ` ${theme.bold(entry.key)}`;
3754
+ if (promptBucket > 0) {
3755
+ line += `\n ${theme.fg("dim", "Input:")} ${promptBucket.toLocaleString()}`;
3756
+ if (bucket.cacheRead > 0 || bucket.cacheWrite > 0) {
3757
+ const rate = promptBucket > 0 ? ((bucket.cacheRead / promptBucket) * 100).toFixed(1) : "0.0";
3758
+ line += ` ${theme.fg("dim", `(cache ${rate}%, W ${bucket.cacheWrite.toLocaleString()})`)}`;
3759
+ }
3760
+ }
3761
+ if (bucket.output > 0)
3762
+ line += `\n ${theme.fg("dim", "Output:")} ${bucket.output.toLocaleString()}`;
3763
+ if (entry.cost > 0)
3764
+ line += ` ${theme.fg("dim", `$${entry.cost.toFixed(3)}`)}`;
3765
+ info += `${line}\n`;
3766
+ }
3767
+ }
3768
+ if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
3769
+ info += `\n${theme.bold("Cost")}\n`;
3770
+ info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
3771
+ if (usageBreakdown.length > 1) {
3772
+ for (const entry of usageBreakdown) {
3773
+ info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
3774
+ }
3775
+ }
3776
+ if (cacheWaste.missedTokens > 0) {
3777
+ const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
3778
+ const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
3779
+ info +=
3780
+ cacheWaste.missedCost >= 0.0001
3781
+ ? `\n${theme.fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
3782
+ : `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
3783
+ }
3784
+ }
3785
+ this.chatContainer.addChild(new Spacer(1));
3786
+ this.chatContainer.addChild(new Text(info, 1, 0));
3787
+ this.ui.requestRender();
3788
+ }
3789
+ handleMetricsCommand(turnsArg) {
3790
+ const provider = this.options.getMetrics;
3791
+ if (!provider) {
3792
+ this.showWarning("Metrics are not available: the observability plugin is not mounted in this session");
3793
+ return;
3794
+ }
3795
+ let windowTurns;
3796
+ if (turnsArg !== undefined) {
3797
+ const parsed = Number.parseInt(turnsArg, 10);
3798
+ if (!Number.isSafeInteger(parsed) || parsed < 1) {
3799
+ this.showWarning(`Invalid turns: ${turnsArg}. Usage: /metrics [turns]`);
3800
+ return;
3801
+ }
3802
+ windowTurns = parsed;
3803
+ }
3804
+ let snapshot;
3805
+ try {
3806
+ const result = provider({ windowTurns });
3807
+ if (result === undefined) {
3808
+ this.showWarning("Metrics are not available: the observability plugin is not mounted in this session");
3809
+ return;
3810
+ }
3811
+ snapshot = result;
3812
+ }
3813
+ catch (error) {
3814
+ this.showError(error instanceof Error ? error.message : String(error));
3815
+ return;
3816
+ }
3817
+ this.chatContainer.addChild(new Spacer(1));
3818
+ this.chatContainer.addChild(new Text(formatMetricsSnapshot(snapshot), 1, 0));
3819
+ this.ui.requestRender();
3820
+ }
3821
+ handleChangelogCommand() {
3822
+ const changelogPath = getChangelogPath();
3823
+ const allEntries = parseChangelog(changelogPath);
3824
+ const changelogMarkdown = allEntries.length > 0
3825
+ ? allEntries
3826
+ .reverse()
3827
+ .map((e) => normalizeChangelogLinks(e.content, e))
3828
+ .join("\n\n")
3829
+ : "No changelog entries found.";
3830
+ this.chatContainer.addChild(new Spacer(1));
3831
+ this.chatContainer.addChild(new DynamicBorder());
3832
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
3833
+ this.chatContainer.addChild(new Spacer(1));
3834
+ this.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, this.getMarkdownThemeWithSettings()));
3835
+ this.chatContainer.addChild(new DynamicBorder());
3836
+ this.ui.requestRender();
3837
+ }
3838
+ /**
3839
+ * Get capitalized display string for an app keybinding action.
3840
+ */
3841
+ getAppKeyDisplay(action) {
3842
+ return keyDisplayText(action);
3843
+ }
3844
+ /**
3845
+ * Get capitalized display string for an editor keybinding action.
3846
+ */
3847
+ getEditorKeyDisplay(action) {
3848
+ return keyDisplayText(action);
3849
+ }
3850
+ handleHelpCommand() {
3851
+ const section = (title, rows) => {
3852
+ if (rows.length === 0)
3853
+ return "";
3854
+ let table = `\n**${title}**\n| Command | Description |\n|---------|-------------|\n`;
3855
+ for (const row of rows) {
3856
+ const command = row.hint ? `\`/${row.name} ${row.hint}\`` : `\`/${row.name}\``;
3857
+ table += `| ${command} | ${row.description ?? ""} |\n`;
3858
+ }
3859
+ return table;
3860
+ };
3861
+ const builtinRows = BUILTIN_SLASH_COMMANDS.map((command) => ({
3862
+ name: command.name,
3863
+ hint: command.argumentHint,
3864
+ description: command.description,
3865
+ }));
3866
+ const promptRows = this.facade.getPromptTemplates().map((template) => ({
3867
+ name: template.name,
3868
+ hint: template.argumentHint,
3869
+ description: template.description,
3870
+ }));
3871
+ const skillRows = this.facade.getSkills().skills.map((skill) => ({
3872
+ name: `skill:${skill.name}`,
3873
+ description: skill.description,
3874
+ }));
3875
+ const help = section("Built-in commands", builtinRows) +
3876
+ section("Prompt templates", promptRows) +
3877
+ section("Skills", skillRows) +
3878
+ "\nType `/` for autocomplete. Use `/hotkeys` for keyboard shortcuts.";
3879
+ this.chatContainer.addChild(new Spacer(1));
3880
+ this.chatContainer.addChild(new DynamicBorder());
3881
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "Available Commands")), 1, 0));
3882
+ this.chatContainer.addChild(new Markdown(help.trim(), 1, 1, this.getMarkdownThemeWithSettings()));
3883
+ this.chatContainer.addChild(new DynamicBorder());
3884
+ this.ui.requestRender();
3885
+ }
3886
+ handleHotkeysCommand() {
3887
+ // Navigation keybindings
3888
+ const cursorUp = this.getEditorKeyDisplay("tui.editor.cursorUp");
3889
+ const cursorDown = this.getEditorKeyDisplay("tui.editor.cursorDown");
3890
+ const cursorLeft = this.getEditorKeyDisplay("tui.editor.cursorLeft");
3891
+ const cursorRight = this.getEditorKeyDisplay("tui.editor.cursorRight");
3892
+ const cursorWordLeft = this.getEditorKeyDisplay("tui.editor.cursorWordLeft");
3893
+ const cursorWordRight = this.getEditorKeyDisplay("tui.editor.cursorWordRight");
3894
+ const cursorLineStart = this.getEditorKeyDisplay("tui.editor.cursorLineStart");
3895
+ const cursorLineEnd = this.getEditorKeyDisplay("tui.editor.cursorLineEnd");
3896
+ const jumpForward = this.getEditorKeyDisplay("tui.editor.jumpForward");
3897
+ const jumpBackward = this.getEditorKeyDisplay("tui.editor.jumpBackward");
3898
+ const pageUp = this.getEditorKeyDisplay("tui.editor.pageUp");
3899
+ const pageDown = this.getEditorKeyDisplay("tui.editor.pageDown");
3900
+ // Editing keybindings
3901
+ const submit = this.getEditorKeyDisplay("tui.input.submit");
3902
+ const newLine = this.getEditorKeyDisplay("tui.input.newLine");
3903
+ const deleteWordBackward = this.getEditorKeyDisplay("tui.editor.deleteWordBackward");
3904
+ const deleteWordForward = this.getEditorKeyDisplay("tui.editor.deleteWordForward");
3905
+ const deleteToLineStart = this.getEditorKeyDisplay("tui.editor.deleteToLineStart");
3906
+ const deleteToLineEnd = this.getEditorKeyDisplay("tui.editor.deleteToLineEnd");
3907
+ const yank = this.getEditorKeyDisplay("tui.editor.yank");
3908
+ const yankPop = this.getEditorKeyDisplay("tui.editor.yankPop");
3909
+ const undo = this.getEditorKeyDisplay("tui.editor.undo");
3910
+ const tab = this.getEditorKeyDisplay("tui.input.tab");
3911
+ // App keybindings
3912
+ const interrupt = this.getAppKeyDisplay("app.interrupt");
3913
+ const clear = this.getAppKeyDisplay("app.clear");
3914
+ const exit = this.getAppKeyDisplay("app.exit");
3915
+ const suspend = this.getAppKeyDisplay("app.suspend");
3916
+ const cycleThinkingLevel = this.getAppKeyDisplay("app.thinking.cycle");
3917
+ const cycleModelForward = this.getAppKeyDisplay("app.model.cycleForward");
3918
+ const selectModel = this.getAppKeyDisplay("app.model.select");
3919
+ const expandTools = this.getAppKeyDisplay("app.tools.expand");
3920
+ const toggleThinking = this.getAppKeyDisplay("app.thinking.toggle");
3921
+ const externalEditor = this.getAppKeyDisplay("app.editor.external");
3922
+ const cycleModelBackward = this.getAppKeyDisplay("app.model.cycleBackward");
3923
+ const copyMessage = this.getAppKeyDisplay("app.message.copy");
3924
+ const followUp = this.getAppKeyDisplay("app.message.followUp");
3925
+ const dequeue = this.getAppKeyDisplay("app.message.dequeue");
3926
+ const pasteImage = this.getAppKeyDisplay("app.clipboard.pasteImage");
3927
+ const hotkeys = `
3928
+ **Navigation**
3929
+ | Key | Action |
3930
+ |-----|--------|
3931
+ | \`${cursorUp}\` / \`${cursorDown}\` / \`${cursorLeft}\` / \`${cursorRight}\` | Move cursor / browse history |
3932
+ | \`${cursorWordLeft}\` / \`${cursorWordRight}\` | Move by word |
3933
+ | \`${cursorLineStart}\` | Start of line |
3934
+ | \`${cursorLineEnd}\` | End of line |
3935
+ | \`${jumpForward}\` | Jump forward to character |
3936
+ | \`${jumpBackward}\` | Jump backward to character |
3937
+ | \`${pageUp}\` / \`${pageDown}\` | Scroll by page |
3938
+
3939
+ **Editing**
3940
+ | Key | Action |
3941
+ |-----|--------|
3942
+ | \`${submit}\` | Send message |
3943
+ | \`${newLine}\` | New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""} |
3944
+ | \`${deleteWordBackward}\` | Delete word backwards |
3945
+ | \`${deleteWordForward}\` | Delete word forwards |
3946
+ | \`${deleteToLineStart}\` | Delete to start of line |
3947
+ | \`${deleteToLineEnd}\` | Delete to end of line |
3948
+ | \`${yank}\` | Paste the most-recently-deleted text |
3949
+ | \`${yankPop}\` | Cycle through the deleted text after pasting |
3950
+ | \`${undo}\` | Undo |
3951
+
3952
+ **Other**
3953
+ | Key | Action |
3954
+ |-----|--------|
3955
+ | \`${tab}\` | Path completion / accept autocomplete |
3956
+ | \`${interrupt}\` | Cancel autocomplete / abort streaming |
3957
+ | \`${clear}\` | Clear editor (first) / exit (second) |
3958
+ | \`${exit}\` | Exit (when editor is empty) |
3959
+ | \`${suspend}\` | Suspend to background |
3960
+ | \`${cycleThinkingLevel}\` | Cycle thinking level |
3961
+ | \`${cycleModelForward}\` / \`${cycleModelBackward}\` | Cycle models |
3962
+ | \`${selectModel}\` | Open model selector |
3963
+ | \`${expandTools}\` | Toggle tool output expansion |
3964
+ | \`${toggleThinking}\` | Toggle thinking block visibility |
3965
+ | \`${externalEditor}\` | Edit message in external editor |
3966
+ | \`${copyMessage}\` | Copy last assistant message |
3967
+ | \`${followUp}\` | Queue follow-up message |
3968
+ | \`${dequeue}\` | Restore queued messages |
3969
+ | \`${pasteImage}\` | Paste image or text from clipboard |
3970
+ | \`/\` | Slash commands |
3971
+ | \`!\` | Run bash command |
3972
+ | \`!!\` | Run bash command (excluded from context) |
3973
+ `;
3974
+ this.chatContainer.addChild(new Spacer(1));
3975
+ this.chatContainer.addChild(new DynamicBorder());
3976
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "Keyboard Shortcuts")), 1, 0));
3977
+ this.chatContainer.addChild(new Spacer(1));
3978
+ this.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, this.getMarkdownThemeWithSettings()));
3979
+ this.chatContainer.addChild(new DynamicBorder());
3980
+ this.ui.requestRender();
3981
+ }
3982
+ async handleClearCommand() {
3983
+ this.clearStatusIndicator();
3984
+ try {
3985
+ const result = await this.runtimeFacade.newSession();
3986
+ if (result.cancelled) {
3987
+ return;
3988
+ }
3989
+ this.chatContainer.addChild(new Spacer(1));
3990
+ this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ New session started")}`, 1, 1));
3991
+ this.ui.requestRender();
3992
+ }
3993
+ catch (error) {
3994
+ await this.handleFatalRuntimeError("Failed to create session", error);
3995
+ }
3996
+ }
3997
+ handleDebugCommand() {
3998
+ const width = this.ui.terminal.columns;
3999
+ const height = this.ui.terminal.rows;
4000
+ const allLines = this.ui.render(width);
4001
+ const debugLogPath = getDebugLogPath();
4002
+ const debugData = [
4003
+ `Debug output at ${new Date().toISOString()}`,
4004
+ `Terminal: ${width}x${height}`,
4005
+ `Total lines: ${allLines.length}`,
4006
+ "",
4007
+ "=== All rendered lines with visible widths ===",
4008
+ ...allLines.map((line, idx) => {
4009
+ const vw = visibleWidth(line);
4010
+ const escaped = JSON.stringify(line);
4011
+ return `[${idx}] (w=${vw}) ${escaped}`;
4012
+ }),
4013
+ "",
4014
+ "=== Agent messages (JSONL) ===",
4015
+ ...this.facade
4016
+ .getSessionAPI()
4017
+ .getMessages()
4018
+ .map((msg) => JSON.stringify(msg)),
4019
+ "",
4020
+ ].join("\n");
4021
+ fs.mkdirSync(path.dirname(debugLogPath), { recursive: true });
4022
+ fs.writeFileSync(debugLogPath, debugData);
4023
+ this.chatContainer.addChild(new Spacer(1));
4024
+ this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ Debug log written")}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
4025
+ this.ui.requestRender();
4026
+ }
4027
+ handleArminSaysHi() {
4028
+ this.chatContainer.addChild(new Spacer(1));
4029
+ this.chatContainer.addChild(new ArminComponent(this.ui));
4030
+ this.ui.requestRender();
4031
+ }
4032
+ handleDaxnuts() {
4033
+ this.chatContainer.addChild(new Spacer(1));
4034
+ this.chatContainer.addChild(new DaxnutsComponent(this.ui));
4035
+ this.ui.requestRender();
4036
+ }
4037
+ /** Host-visible for ./interactive-auth.ts (S5 slice 3). */
4038
+ checkDaxnutsEasterEgg(model) {
4039
+ if (model.provider === "opencode" && model.id.toLowerCase().includes("kimi-k2.5")) {
4040
+ this.handleDaxnuts();
4041
+ }
4042
+ }
4043
+ async handleBashCommand(command, excludeFromContext = false) {
4044
+ // Dispatch the user.bash lifecycle facts, then execute locally.
4045
+ this.facade.emitUserBash(excludeFromContext);
4046
+ // Normal execution path
4047
+ const isDeferred = this.facade.isStreaming();
4048
+ this.bashComponent = new BashExecutionComponent(command, this.ui, excludeFromContext);
4049
+ if (isDeferred) {
4050
+ // Show in pending area when agent is streaming
4051
+ this.pendingMessagesContainer.addChild(this.bashComponent);
4052
+ this.pendingBashComponents.push(this.bashComponent);
4053
+ }
4054
+ else {
4055
+ // Show in chat immediately when agent is idle
4056
+ this.chatContainer.addChild(this.bashComponent);
4057
+ }
4058
+ this.ui.requestRender();
4059
+ try {
4060
+ const result = await this.facade.executeBash(command, (chunk) => {
4061
+ if (this.bashComponent) {
4062
+ this.bashComponent.appendOutput(chunk);
4063
+ this.ui.requestRender();
4064
+ }
4065
+ }, { excludeFromContext });
4066
+ if (this.bashComponent) {
4067
+ this.bashComponent.setComplete(result.exitCode, result.cancelled, result.truncated ? { truncated: true, content: result.output } : undefined, result.fullOutputPath);
4068
+ }
4069
+ }
4070
+ catch (error) {
4071
+ if (this.bashComponent) {
4072
+ this.bashComponent.setComplete(undefined, false);
4073
+ }
4074
+ this.showError(`Bash command failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4075
+ }
4076
+ this.bashComponent = undefined;
4077
+ this.ui.requestRender();
4078
+ }
4079
+ async handleCompactCommand(customInstructions) {
4080
+ this.clearStatusIndicator();
4081
+ try {
4082
+ await this.facade.compact(customInstructions);
4083
+ }
4084
+ catch {
4085
+ // Ignore, will be emitted as an event
4086
+ }
4087
+ }
4088
+ stop(fullscreenExitOutput = this.settingsManager.getFullscreenExitOutput()) {
4089
+ this.disposeActiveSelector();
4090
+ if (this.settingsManager.getShowTerminalProgress()) {
4091
+ this.ui.terminal.setProgress(false);
4092
+ }
4093
+ this.clearStatusIndicator();
4094
+ this.themeController.disableAutoSync();
4095
+ this.footer.dispose();
4096
+ this.footerDataProvider.dispose();
4097
+ if (this.unsubscribe) {
4098
+ this.unsubscribe();
4099
+ }
4100
+ if (this.isInitialized) {
4101
+ this.stopInteractiveTui(fullscreenExitOutput);
4102
+ this.isInitialized = false;
4103
+ }
4104
+ this.unregisterSignalHandlers();
4105
+ }
4106
+ }
4107
+ //# sourceMappingURL=interactive-mode.js.map