@ai-agent-forge/agent-forge 0.86.7 → 0.88.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 (717) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +10 -11
  3. package/dist/artifacts/artifact-store.d.ts.map +1 -1
  4. package/dist/artifacts/artifact-store.js +9 -5
  5. package/dist/artifacts/artifact-store.js.map +1 -1
  6. package/dist/bundle/.build-manifest.json +430 -413
  7. package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
  8. package/dist/bundle/chunks/chunk-HLJEVRWP.js +13 -0
  9. package/dist/bundle/chunks/chunk-YGHQME4V.js +1456 -0
  10. package/dist/bundle/chunks/image-resize-worker.js +12 -1
  11. package/dist/bundle/chunks/{virtual-modules-3IZ4MYSQ.js → virtual-modules-KZ5DRH7Q.js} +1 -1
  12. package/dist/bundle/cli.js +1 -1
  13. package/dist/bundle/client.js +1 -1
  14. package/dist/bundle/index.js +2 -2
  15. package/dist/bundle/rpc-entry.js +1 -1
  16. package/dist/cli/args.d.ts.map +1 -1
  17. package/dist/cli/args.js +231 -185
  18. package/dist/cli/args.js.map +1 -1
  19. package/dist/cli/auth-check.d.ts.map +1 -1
  20. package/dist/cli/auth-check.js +17 -4
  21. package/dist/cli/auth-check.js.map +1 -1
  22. package/dist/cli/auth-command.d.ts.map +1 -1
  23. package/dist/cli/auth-command.js +15 -9
  24. package/dist/cli/auth-command.js.map +1 -1
  25. package/dist/cli/credential-print.d.ts.map +1 -1
  26. package/dist/cli/credential-print.js +14 -7
  27. package/dist/cli/credential-print.js.map +1 -1
  28. package/dist/cli/experimental/command.d.ts.map +1 -1
  29. package/dist/cli/experimental/command.js +6 -5
  30. package/dist/cli/experimental/command.js.map +1 -1
  31. package/dist/cli/list-models.d.ts.map +1 -1
  32. package/dist/cli/list-models.js +9 -8
  33. package/dist/cli/list-models.js.map +1 -1
  34. package/dist/cli/plugin-manager-controller.d.ts.map +1 -1
  35. package/dist/cli/plugin-manager-controller.js +2 -1
  36. package/dist/cli/plugin-manager-controller.js.map +1 -1
  37. package/dist/cli/serve.d.ts.map +1 -1
  38. package/dist/cli/serve.js +8 -5
  39. package/dist/cli/serve.js.map +1 -1
  40. package/dist/client/remote-session.d.ts.map +1 -1
  41. package/dist/client/remote-session.js +16 -9
  42. package/dist/client/remote-session.js.map +1 -1
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js +5 -3
  45. package/dist/config.js.map +1 -1
  46. package/dist/core/agent-capability-contract.d.ts +0 -7
  47. package/dist/core/agent-capability-contract.d.ts.map +1 -1
  48. package/dist/core/agent-capability-contract.js +72 -68
  49. package/dist/core/agent-capability-contract.js.map +1 -1
  50. package/dist/core/agent-session-bash.d.ts.map +1 -1
  51. package/dist/core/agent-session-bash.js +5 -4
  52. package/dist/core/agent-session-bash.js.map +1 -1
  53. package/dist/core/agent-session-compaction.d.ts +6 -10
  54. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  55. package/dist/core/agent-session-compaction.js +35 -133
  56. package/dist/core/agent-session-compaction.js.map +1 -1
  57. package/dist/core/agent-session-context.d.ts.map +1 -1
  58. package/dist/core/agent-session-context.js +18 -13
  59. package/dist/core/agent-session-context.js.map +1 -1
  60. package/dist/core/agent-session-internal.d.ts +0 -6
  61. package/dist/core/agent-session-internal.d.ts.map +1 -1
  62. package/dist/core/agent-session-internal.js.map +1 -1
  63. package/dist/core/agent-session-model.d.ts.map +1 -1
  64. package/dist/core/agent-session-model.js +2 -1
  65. package/dist/core/agent-session-model.js.map +1 -1
  66. package/dist/core/agent-session-retry.d.ts.map +1 -1
  67. package/dist/core/agent-session-retry.js +3 -3
  68. package/dist/core/agent-session-retry.js.map +1 -1
  69. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  70. package/dist/core/agent-session-runtime.js +7 -6
  71. package/dist/core/agent-session-runtime.js.map +1 -1
  72. package/dist/core/agent-session-services.d.ts +1 -1
  73. package/dist/core/agent-session-services.d.ts.map +1 -1
  74. package/dist/core/agent-session-services.js.map +1 -1
  75. package/dist/core/agent-session-tools.d.ts.map +1 -1
  76. package/dist/core/agent-session-tools.js +3 -2
  77. package/dist/core/agent-session-tools.js.map +1 -1
  78. package/dist/core/agent-session.d.ts +40 -22
  79. package/dist/core/agent-session.d.ts.map +1 -1
  80. package/dist/core/agent-session.js +147 -67
  81. package/dist/core/agent-session.js.map +1 -1
  82. package/dist/core/auth-guidance.d.ts.map +1 -1
  83. package/dist/core/auth-guidance.js +11 -5
  84. package/dist/core/auth-guidance.js.map +1 -1
  85. package/dist/core/auth-storage.d.ts.map +1 -1
  86. package/dist/core/auth-storage.js +9 -6
  87. package/dist/core/auth-storage.js.map +1 -1
  88. package/dist/core/compaction/compaction.d.ts.map +1 -1
  89. package/dist/core/compaction/compaction.js +2 -1
  90. package/dist/core/compaction/compaction.js.map +1 -1
  91. package/dist/core/embedded-sdk.d.ts.map +1 -1
  92. package/dist/core/embedded-sdk.js +10 -6
  93. package/dist/core/embedded-sdk.js.map +1 -1
  94. package/dist/core/export-html/index.d.ts.map +1 -1
  95. package/dist/core/export-html/index.js +9 -4
  96. package/dist/core/export-html/index.js.map +1 -1
  97. package/dist/core/extensions/agent-composition.d.ts.map +1 -1
  98. package/dist/core/extensions/agent-composition.js +26 -19
  99. package/dist/core/extensions/agent-composition.js.map +1 -1
  100. package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
  101. package/dist/core/extensions/bootstrap-agent-loop.js +3 -2
  102. package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
  103. package/dist/core/extensions/bootstrap-compaction-policy.d.ts.map +1 -1
  104. package/dist/core/extensions/bootstrap-compaction-policy.js +0 -34
  105. package/dist/core/extensions/bootstrap-compaction-policy.js.map +1 -1
  106. package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
  107. package/dist/core/extensions/bootstrap-lifecycle.js +20 -17
  108. package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
  109. package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -1
  110. package/dist/core/extensions/bootstrap-overflow-policy.js +2 -1
  111. package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -1
  112. package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -1
  113. package/dist/core/extensions/bootstrap-retry-policy.js +4 -3
  114. package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -1
  115. package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -1
  116. package/dist/core/extensions/bootstrap-skills.js +7 -6
  117. package/dist/core/extensions/bootstrap-skills.js.map +1 -1
  118. package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -1
  119. package/dist/core/extensions/bootstrap-tools.js +2 -1
  120. package/dist/core/extensions/bootstrap-tools.js.map +1 -1
  121. package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
  122. package/dist/core/extensions/capability-plugin.js +37 -13
  123. package/dist/core/extensions/capability-plugin.js.map +1 -1
  124. package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -1
  125. package/dist/core/extensions/capability-runtime-events.js +17 -13
  126. package/dist/core/extensions/capability-runtime-events.js.map +1 -1
  127. package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -1
  128. package/dist/core/extensions/capability-runtime-guards.js +16 -15
  129. package/dist/core/extensions/capability-runtime-guards.js.map +1 -1
  130. package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -1
  131. package/dist/core/extensions/capability-runtime-manifest.js +52 -30
  132. package/dist/core/extensions/capability-runtime-manifest.js.map +1 -1
  133. package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -1
  134. package/dist/core/extensions/capability-runtime-validation.js +66 -65
  135. package/dist/core/extensions/capability-runtime-validation.js.map +1 -1
  136. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  137. package/dist/core/extensions/capability-runtime.js +147 -127
  138. package/dist/core/extensions/capability-runtime.js.map +1 -1
  139. package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -1
  140. package/dist/core/extensions/compaction-memory-failure-mode.js +3 -2
  141. package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -1
  142. package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -1
  143. package/dist/core/extensions/context-strategy-binding.js +7 -4
  144. package/dist/core/extensions/context-strategy-binding.js.map +1 -1
  145. package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
  146. package/dist/core/extensions/lifecycle-catalog.js +290 -279
  147. package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
  148. package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -1
  149. package/dist/core/extensions/lifecycle-delivery-queue.js +3 -2
  150. package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -1
  151. package/dist/core/extensions/provider-failover.d.ts +7 -3
  152. package/dist/core/extensions/provider-failover.d.ts.map +1 -1
  153. package/dist/core/extensions/provider-failover.js +9 -8
  154. package/dist/core/extensions/provider-failover.js.map +1 -1
  155. package/dist/core/facade/coding-agent-facade.d.ts +6 -6
  156. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  157. package/dist/core/facade/coding-agent-facade.js +2 -3
  158. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  159. package/dist/core/http-dispatcher.d.ts.map +1 -1
  160. package/dist/core/http-dispatcher.js +2 -1
  161. package/dist/core/http-dispatcher.js.map +1 -1
  162. package/dist/core/i18n/index.d.ts +14 -0
  163. package/dist/core/i18n/index.d.ts.map +1 -0
  164. package/dist/core/i18n/index.js +67 -0
  165. package/dist/core/i18n/index.js.map +1 -0
  166. package/dist/core/i18n/locales/en/example.d.ts +7 -0
  167. package/dist/core/i18n/locales/en/example.d.ts.map +1 -0
  168. package/dist/core/i18n/locales/en/example.js +7 -0
  169. package/dist/core/i18n/locales/en/example.js.map +1 -0
  170. package/dist/core/i18n/locales/zh-cn/cli.d.ts +8 -0
  171. package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -0
  172. package/dist/core/i18n/locales/zh-cn/cli.js +229 -0
  173. package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -0
  174. package/dist/core/i18n/locales/zh-cn/common.d.ts +6 -0
  175. package/dist/core/i18n/locales/zh-cn/common.d.ts.map +1 -0
  176. package/dist/core/i18n/locales/zh-cn/common.js +6 -0
  177. package/dist/core/i18n/locales/zh-cn/common.js.map +1 -0
  178. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +13 -0
  179. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -0
  180. package/dist/core/i18n/locales/zh-cn/core-contract-core.js +173 -0
  181. package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -0
  182. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts +12 -0
  183. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -0
  184. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +582 -0
  185. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -0
  186. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +9 -0
  187. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -0
  188. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +55 -0
  189. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -0
  190. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts +11 -0
  191. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -0
  192. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +455 -0
  193. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -0
  194. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts +9 -0
  195. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -0
  196. package/dist/core/i18n/locales/zh-cn/core-errors.js +191 -0
  197. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -0
  198. package/dist/core/i18n/locales/zh-cn/example.d.ts +7 -0
  199. package/dist/core/i18n/locales/zh-cn/example.d.ts.map +1 -0
  200. package/dist/core/i18n/locales/zh-cn/example.js +10 -0
  201. package/dist/core/i18n/locales/zh-cn/example.js.map +1 -0
  202. package/dist/core/i18n/locales/zh-cn/index.d.ts +2 -0
  203. package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -0
  204. package/dist/core/i18n/locales/zh-cn/index.js +41 -0
  205. package/dist/core/i18n/locales/zh-cn/index.js.map +1 -0
  206. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts +10 -0
  207. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -0
  208. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +267 -0
  209. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -0
  210. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts +11 -0
  211. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts.map +1 -0
  212. package/dist/core/i18n/locales/zh-cn/keybindings.js +67 -0
  213. package/dist/core/i18n/locales/zh-cn/keybindings.js.map +1 -0
  214. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts +7 -0
  215. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -0
  216. package/dist/core/i18n/locales/zh-cn/slash-commands.js +39 -0
  217. package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -0
  218. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts +10 -0
  219. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts.map +1 -0
  220. package/dist/core/i18n/locales/zh-cn/tui-builtin.js +15 -0
  221. package/dist/core/i18n/locales/zh-cn/tui-builtin.js.map +1 -0
  222. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts +13 -0
  223. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -0
  224. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +102 -0
  225. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -0
  226. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts +12 -0
  227. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts.map +1 -0
  228. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js +286 -0
  229. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js.map +1 -0
  230. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts +9 -0
  231. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts.map +1 -0
  232. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js +79 -0
  233. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js.map +1 -0
  234. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts +8 -0
  235. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts.map +1 -0
  236. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js +72 -0
  237. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js.map +1 -0
  238. package/dist/core/keybindings.d.ts +15 -0
  239. package/dist/core/keybindings.d.ts.map +1 -1
  240. package/dist/core/keybindings.js +18 -0
  241. package/dist/core/keybindings.js.map +1 -1
  242. package/dist/core/logger.d.ts.map +1 -1
  243. package/dist/core/logger.js +5 -1
  244. package/dist/core/logger.js.map +1 -1
  245. package/dist/core/model-config.d.ts +0 -1
  246. package/dist/core/model-config.d.ts.map +1 -1
  247. package/dist/core/model-config.js +9 -1
  248. package/dist/core/model-config.js.map +1 -1
  249. package/dist/core/model-registry.d.ts.map +1 -1
  250. package/dist/core/model-registry.js +2 -1
  251. package/dist/core/model-registry.js.map +1 -1
  252. package/dist/core/model-runtime.d.ts.map +1 -1
  253. package/dist/core/model-runtime.js +11 -7
  254. package/dist/core/model-runtime.js.map +1 -1
  255. package/dist/core/package-install-host.d.ts.map +1 -1
  256. package/dist/core/package-install-host.js +4 -3
  257. package/dist/core/package-install-host.js.map +1 -1
  258. package/dist/core/package-manager.d.ts.map +1 -1
  259. package/dist/core/package-manager.js +15 -10
  260. package/dist/core/package-manager.js.map +1 -1
  261. package/dist/core/package-resource-collection.d.ts.map +1 -1
  262. package/dist/core/package-resource-collection.js +2 -1
  263. package/dist/core/package-resource-collection.js.map +1 -1
  264. package/dist/core/package-source.d.ts.map +1 -1
  265. package/dist/core/package-source.js +3 -2
  266. package/dist/core/package-source.js.map +1 -1
  267. package/dist/core/provider-composer.d.ts +2 -2
  268. package/dist/core/provider-composer.d.ts.map +1 -1
  269. package/dist/core/provider-composer.js +29 -21
  270. package/dist/core/provider-composer.js.map +1 -1
  271. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  272. package/dist/core/remote-catalog-provider.js +6 -2
  273. package/dist/core/remote-catalog-provider.js.map +1 -1
  274. package/dist/core/resolve-config-value.d.ts.map +1 -1
  275. package/dist/core/resolve-config-value.js +15 -5
  276. package/dist/core/resolve-config-value.js.map +1 -1
  277. package/dist/core/sdk.d.ts +27 -5
  278. package/dist/core/sdk.d.ts.map +1 -1
  279. package/dist/core/sdk.js +80 -55
  280. package/dist/core/sdk.js.map +1 -1
  281. package/dist/core/session-cwd.d.ts.map +1 -1
  282. package/dist/core/session-cwd.js +5 -2
  283. package/dist/core/session-cwd.js.map +1 -1
  284. package/dist/core/session-export.d.ts.map +1 -1
  285. package/dist/core/session-export.js +2 -1
  286. package/dist/core/session-export.js.map +1 -1
  287. package/dist/core/session-manager.d.ts.map +1 -1
  288. package/dist/core/session-manager.js +39 -29
  289. package/dist/core/session-manager.js.map +1 -1
  290. package/dist/core/session-storage.d.ts.map +1 -1
  291. package/dist/core/session-storage.js +3 -3
  292. package/dist/core/session-storage.js.map +1 -1
  293. package/dist/core/settings-manager.d.ts +20 -20
  294. package/dist/core/settings-manager.d.ts.map +1 -1
  295. package/dist/core/settings-manager.js +47 -59
  296. package/dist/core/settings-manager.js.map +1 -1
  297. package/dist/core/slash-commands.d.ts.map +1 -1
  298. package/dist/core/slash-commands.js +53 -32
  299. package/dist/core/slash-commands.js.map +1 -1
  300. package/dist/core/system-prompt.d.ts.map +1 -1
  301. package/dist/core/system-prompt.js +25 -2
  302. package/dist/core/system-prompt.js.map +1 -1
  303. package/dist/core/tools/bash.d.ts.map +1 -1
  304. package/dist/core/tools/bash.js +11 -7
  305. package/dist/core/tools/bash.js.map +1 -1
  306. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  307. package/dist/core/tools/edit-diff.js +9 -4
  308. package/dist/core/tools/edit-diff.js.map +1 -1
  309. package/dist/core/tools/edit.d.ts.map +1 -1
  310. package/dist/core/tools/edit.js +4 -3
  311. package/dist/core/tools/edit.js.map +1 -1
  312. package/dist/core/tools/index.d.ts.map +1 -1
  313. package/dist/core/tools/index.js +3 -2
  314. package/dist/core/tools/index.js.map +1 -1
  315. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  316. package/dist/core/tools/output-accumulator.js +2 -1
  317. package/dist/core/tools/output-accumulator.js.map +1 -1
  318. package/dist/core/tools/read.d.ts.map +1 -1
  319. package/dist/core/tools/read.js +6 -2
  320. package/dist/core/tools/read.js.map +1 -1
  321. package/dist/core/tools/write.d.ts.map +1 -1
  322. package/dist/core/tools/write.js +2 -1
  323. package/dist/core/tools/write.js.map +1 -1
  324. package/dist/durable/durable-service.d.ts.map +1 -1
  325. package/dist/durable/durable-service.js +25 -18
  326. package/dist/durable/durable-service.js.map +1 -1
  327. package/dist/host/checkpoint-commit.d.ts.map +1 -1
  328. package/dist/host/checkpoint-commit.js +2 -1
  329. package/dist/host/checkpoint-commit.js.map +1 -1
  330. package/dist/host/manual-compaction.d.ts.map +1 -1
  331. package/dist/host/manual-compaction.js +2 -1
  332. package/dist/host/manual-compaction.js.map +1 -1
  333. package/dist/host/output-projection.d.ts +0 -13
  334. package/dist/host/output-projection.d.ts.map +1 -1
  335. package/dist/host/output-projection.js +16 -2
  336. package/dist/host/output-projection.js.map +1 -1
  337. package/dist/host/summary-retry.d.ts.map +1 -1
  338. package/dist/host/summary-retry.js +3 -2
  339. package/dist/host/summary-retry.js.map +1 -1
  340. package/dist/main.d.ts.map +1 -1
  341. package/dist/main.js +97 -60
  342. package/dist/main.js.map +1 -1
  343. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  344. package/dist/modes/interactive/components/agents-view.js +18 -15
  345. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  346. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  347. package/dist/modes/interactive/components/assistant-message.js +6 -5
  348. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  349. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/bash-execution.js +12 -7
  351. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  352. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/bordered-loader.js +2 -1
  354. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  355. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  356. package/dist/modes/interactive/components/branch-summary-message.js +6 -5
  357. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  358. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  359. package/dist/modes/interactive/components/compaction-summary-message.js +9 -5
  360. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  361. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  362. package/dist/modes/interactive/components/config-selector.js +18 -15
  363. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  364. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  365. package/dist/modes/interactive/components/custom-entry.js +2 -1
  366. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  367. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  368. package/dist/modes/interactive/components/dialog-editor.js +5 -4
  369. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  370. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  371. package/dist/modes/interactive/components/dialog-input.js +2 -1
  372. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  373. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  374. package/dist/modes/interactive/components/dialog-selector.js +4 -3
  375. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  376. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/first-time-setup.js +11 -10
  378. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  379. package/dist/modes/interactive/components/footer.d.ts +0 -2
  380. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  381. package/dist/modes/interactive/components/footer.js +8 -10
  382. package/dist/modes/interactive/components/footer.js.map +1 -1
  383. package/dist/modes/interactive/components/index.d.ts +1 -0
  384. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  385. package/dist/modes/interactive/components/index.js +1 -0
  386. package/dist/modes/interactive/components/index.js.map +1 -1
  387. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  388. package/dist/modes/interactive/components/keybinding-hints.js +3 -2
  389. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  390. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/login-dialog.js +12 -11
  392. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  393. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  394. package/dist/modes/interactive/components/mermaid.js +6 -2
  395. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  396. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/model-selector.js +28 -16
  398. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  399. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  400. package/dist/modes/interactive/components/oauth-selector.js +10 -9
  401. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  402. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  403. package/dist/modes/interactive/components/plugin-manager-entry.js +22 -13
  404. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  405. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  406. package/dist/modes/interactive/components/plugin-selection-entry.js +27 -12
  407. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  408. package/dist/modes/interactive/components/queue-manager-selector.d.ts +60 -0
  409. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -0
  410. package/dist/modes/interactive/components/queue-manager-selector.js +166 -0
  411. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -0
  412. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  413. package/dist/modes/interactive/components/scoped-models-selector.js +16 -14
  414. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  415. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  416. package/dist/modes/interactive/components/session-selector.js +43 -31
  417. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  418. package/dist/modes/interactive/components/settings-selector.d.ts +4 -6
  419. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  420. package/dist/modes/interactive/components/settings-selector.js +115 -120
  421. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  422. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  423. package/dist/modes/interactive/components/settings-submenu.js +5 -4
  424. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  425. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  426. package/dist/modes/interactive/components/show-images-selector.js +3 -2
  427. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  428. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  429. package/dist/modes/interactive/components/skill-invocation-message.js +4 -3
  430. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  431. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  432. package/dist/modes/interactive/components/status-indicator.js +14 -5
  433. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  434. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/theme-selector.js +2 -1
  436. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  437. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/thinking-selector.js +11 -4
  439. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  440. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  441. package/dist/modes/interactive/components/tool-execution.js +8 -3
  442. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  443. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  444. package/dist/modes/interactive/components/tree-list.js +7 -6
  445. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  446. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  447. package/dist/modes/interactive/components/tree-render.js +28 -23
  448. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  449. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/tree-selector.js +9 -7
  451. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  452. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/user-message-selector.js +5 -4
  454. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  455. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/workflow-view.js +36 -21
  457. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  458. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  459. package/dist/modes/interactive/external-editor.js +2 -1
  460. package/dist/modes/interactive/external-editor.js.map +1 -1
  461. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  462. package/dist/modes/interactive/interactive-auth.js +71 -40
  463. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  464. package/dist/modes/interactive/interactive-commands.d.ts +1 -0
  465. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  466. package/dist/modes/interactive/interactive-commands.js +3 -0
  467. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  468. package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -1
  469. package/dist/modes/interactive/interactive-dialog-ui.js +5 -5
  470. package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -1
  471. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  472. package/dist/modes/interactive/interactive-format.js +34 -18
  473. package/dist/modes/interactive/interactive-format.js.map +1 -1
  474. package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -1
  475. package/dist/modes/interactive/interactive-helpers.js +7 -2
  476. package/dist/modes/interactive/interactive-helpers.js.map +1 -1
  477. package/dist/modes/interactive/interactive-mode.d.ts +4 -2
  478. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  479. package/dist/modes/interactive/interactive-mode.js +350 -279
  480. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  481. package/dist/modes/interactive/interactive-selectors.d.ts +9 -0
  482. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  483. package/dist/modes/interactive/interactive-selectors.js +79 -25
  484. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  485. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  486. package/dist/modes/interactive/theme/theme-controller.js +5 -1
  487. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  488. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  489. package/dist/modes/interactive/theme/theme.js +26 -23
  490. package/dist/modes/interactive/theme/theme.js.map +1 -1
  491. package/dist/modes/json-event.d.ts.map +1 -1
  492. package/dist/modes/json-event.js +3 -2
  493. package/dist/modes/json-event.js.map +1 -1
  494. package/dist/modes/print-mode.d.ts.map +1 -1
  495. package/dist/modes/print-mode.js +3 -2
  496. package/dist/modes/print-mode.js.map +1 -1
  497. package/dist/modes/rpc/rpc-client.d.ts +0 -8
  498. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  499. package/dist/modes/rpc/rpc-client.js +3 -14
  500. package/dist/modes/rpc/rpc-client.js.map +1 -1
  501. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  502. package/dist/modes/rpc/rpc-mode.js +0 -9
  503. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  504. package/dist/modes/rpc/rpc-types.d.ts +0 -19
  505. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  506. package/dist/modes/rpc/rpc-types.js.map +1 -1
  507. package/dist/package-manager-cli.d.ts.map +1 -1
  508. package/dist/package-manager-cli.js +28 -13
  509. package/dist/package-manager-cli.js.map +1 -1
  510. package/dist/plugins/ecosystem/catalog.d.ts.map +1 -1
  511. package/dist/plugins/ecosystem/catalog.js +3 -2
  512. package/dist/plugins/ecosystem/catalog.js.map +1 -1
  513. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  514. package/dist/plugins/ecosystem/cli.js +2 -1
  515. package/dist/plugins/ecosystem/cli.js.map +1 -1
  516. package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -1
  517. package/dist/plugins/ecosystem/default-plugin-market.js +3 -2
  518. package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -1
  519. package/dist/plugins/ecosystem/distribution.d.ts.map +1 -1
  520. package/dist/plugins/ecosystem/distribution.js +2 -1
  521. package/dist/plugins/ecosystem/distribution.js.map +1 -1
  522. package/dist/plugins/ecosystem/installer.d.ts.map +1 -1
  523. package/dist/plugins/ecosystem/installer.js +3 -2
  524. package/dist/plugins/ecosystem/installer.js.map +1 -1
  525. package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
  526. package/dist/plugins/ecosystem/node-disk-registry-source.js +20 -17
  527. package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
  528. package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -1
  529. package/dist/plugins/ecosystem/node-distribution-host.js +35 -34
  530. package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -1
  531. package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
  532. package/dist/plugins/ecosystem/node-npm-registry-source.js +35 -34
  533. package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
  534. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
  535. package/dist/plugins/ecosystem/node-package-install-host.js +9 -8
  536. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
  537. package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
  538. package/dist/plugins/ecosystem/node-package-install-persistence.js +4 -3
  539. package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
  540. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +9 -2
  541. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  542. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +44 -5
  543. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  544. package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -1
  545. package/dist/plugins/ecosystem/node-plugin-trust-root.js +10 -9
  546. package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -1
  547. package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -1
  548. package/dist/plugins/ecosystem/node-registry-source.js +31 -30
  549. package/dist/plugins/ecosystem/node-registry-source.js.map +1 -1
  550. package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -1
  551. package/dist/plugins/ecosystem/node-release-package-source.js +30 -29
  552. package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -1
  553. package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -1
  554. package/dist/plugins/ecosystem/node-tar-writer.js +11 -10
  555. package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -1
  556. package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -1
  557. package/dist/plugins/ecosystem/node-url-package-source.js +21 -20
  558. package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -1
  559. package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -1
  560. package/dist/plugins/ecosystem/plugin-acquisition.js +3 -2
  561. package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -1
  562. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +9 -1
  563. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
  564. package/dist/plugins/ecosystem/plugin-bootstrap.js +5 -0
  565. package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -1
  566. package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -1
  567. package/dist/plugins/ecosystem/registry-cli-adapter.js +2 -1
  568. package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -1
  569. package/dist/plugins/ecosystem/registry.d.ts.map +1 -1
  570. package/dist/plugins/ecosystem/registry.js +35 -32
  571. package/dist/plugins/ecosystem/registry.js.map +1 -1
  572. package/dist/plugins/ecosystem/resolver.d.ts.map +1 -1
  573. package/dist/plugins/ecosystem/resolver.js +3 -2
  574. package/dist/plugins/ecosystem/resolver.js.map +1 -1
  575. package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -1
  576. package/dist/plugins/ecosystem/selection-store.js +11 -10
  577. package/dist/plugins/ecosystem/selection-store.js.map +1 -1
  578. package/dist/plugins/ecosystem/selection.d.ts.map +1 -1
  579. package/dist/plugins/ecosystem/selection.js +8 -7
  580. package/dist/plugins/ecosystem/selection.js.map +1 -1
  581. package/dist/plugins/ecosystem/state.d.ts.map +1 -1
  582. package/dist/plugins/ecosystem/state.js +24 -23
  583. package/dist/plugins/ecosystem/state.js.map +1 -1
  584. package/dist/plugins/ecosystem/updates.d.ts.map +1 -1
  585. package/dist/plugins/ecosystem/updates.js +5 -4
  586. package/dist/plugins/ecosystem/updates.js.map +1 -1
  587. package/dist/plugins/mcp-http.d.ts +0 -17
  588. package/dist/plugins/mcp-http.d.ts.map +1 -1
  589. package/dist/plugins/mcp-http.js +30 -7
  590. package/dist/plugins/mcp-http.js.map +1 -1
  591. package/dist/plugins/plugin-supervisor.d.ts.map +1 -1
  592. package/dist/plugins/plugin-supervisor.js +19 -1
  593. package/dist/plugins/plugin-supervisor.js.map +1 -1
  594. package/dist/profile/first-roles.d.ts.map +1 -1
  595. package/dist/profile/first-roles.js +10 -1
  596. package/dist/profile/first-roles.js.map +1 -1
  597. package/dist/profile/goal-plugin.d.ts.map +1 -1
  598. package/dist/profile/goal-plugin.js +24 -5
  599. package/dist/profile/goal-plugin.js.map +1 -1
  600. package/dist/profile/identity.d.ts.map +1 -1
  601. package/dist/profile/identity.js +7 -6
  602. package/dist/profile/identity.js.map +1 -1
  603. package/dist/profile/lock.d.ts.map +1 -1
  604. package/dist/profile/lock.js +15 -1
  605. package/dist/profile/lock.js.map +1 -1
  606. package/dist/profile/plan-plugin.d.ts.map +1 -1
  607. package/dist/profile/plan-plugin.js +26 -13
  608. package/dist/profile/plan-plugin.js.map +1 -1
  609. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  610. package/dist/profile/plugin-profiles.js +2 -1
  611. package/dist/profile/plugin-profiles.js.map +1 -1
  612. package/dist/profile/policy-manifest.d.ts.map +1 -1
  613. package/dist/profile/policy-manifest.js +5 -4
  614. package/dist/profile/policy-manifest.js.map +1 -1
  615. package/dist/profile/profile-registry.d.ts +0 -12
  616. package/dist/profile/profile-registry.d.ts.map +1 -1
  617. package/dist/profile/profile-registry.js +14 -1
  618. package/dist/profile/profile-registry.js.map +1 -1
  619. package/dist/profile/role-catalog.d.ts +0 -1
  620. package/dist/profile/role-catalog.d.ts.map +1 -1
  621. package/dist/profile/role-catalog.js +17 -15
  622. package/dist/profile/role-catalog.js.map +1 -1
  623. package/dist/profile/role-orchestrator.d.ts.map +1 -1
  624. package/dist/profile/role-orchestrator.js +8 -7
  625. package/dist/profile/role-orchestrator.js.map +1 -1
  626. package/dist/profile/role-runner.d.ts.map +1 -1
  627. package/dist/profile/role-runner.js +3 -2
  628. package/dist/profile/role-runner.js.map +1 -1
  629. package/dist/profile/root-facade.d.ts.map +1 -1
  630. package/dist/profile/root-facade.js +2 -1
  631. package/dist/profile/root-facade.js.map +1 -1
  632. package/dist/profile/skill-discovery-wiring.d.ts.map +1 -1
  633. package/dist/profile/skill-discovery-wiring.js +7 -2
  634. package/dist/profile/skill-discovery-wiring.js.map +1 -1
  635. package/dist/profile/state-store.d.ts.map +1 -1
  636. package/dist/profile/state-store.js +13 -9
  637. package/dist/profile/state-store.js.map +1 -1
  638. package/dist/profile/todo-plugin.d.ts.map +1 -1
  639. package/dist/profile/todo-plugin.js +9 -4
  640. package/dist/profile/todo-plugin.js.map +1 -1
  641. package/dist/profiles/builtin-suites.d.ts +13 -6
  642. package/dist/profiles/builtin-suites.d.ts.map +1 -1
  643. package/dist/profiles/builtin-suites.js +15 -6
  644. package/dist/profiles/builtin-suites.js.map +1 -1
  645. package/dist/profiles/suite-loader.d.ts +25 -1
  646. package/dist/profiles/suite-loader.d.ts.map +1 -1
  647. package/dist/profiles/suite-loader.js +34 -9
  648. package/dist/profiles/suite-loader.js.map +1 -1
  649. package/dist/remote/server-entry.d.ts.map +1 -1
  650. package/dist/remote/server-entry.js +3 -2
  651. package/dist/remote/server-entry.js.map +1 -1
  652. package/dist/remote/session-source.d.ts.map +1 -1
  653. package/dist/remote/session-source.js +8 -4
  654. package/dist/remote/session-source.js.map +1 -1
  655. package/dist/share/session-share.d.ts.map +1 -1
  656. package/dist/share/session-share.js +14 -2
  657. package/dist/share/session-share.js.map +1 -1
  658. package/dist/testing/plugin-testkit.d.ts.map +1 -1
  659. package/dist/testing/plugin-testkit.js +4 -3
  660. package/dist/testing/plugin-testkit.js.map +1 -1
  661. package/dist/testing/runtime-delivery-queue.d.ts.map +1 -1
  662. package/dist/testing/runtime-delivery-queue.js +2 -1
  663. package/dist/testing/runtime-delivery-queue.js.map +1 -1
  664. package/dist/testing/session-plugin-testkit.d.ts.map +1 -1
  665. package/dist/testing/session-plugin-testkit.js +10 -7
  666. package/dist/testing/session-plugin-testkit.js.map +1 -1
  667. package/dist/utils/ansi.d.ts.map +1 -1
  668. package/dist/utils/ansi.js +2 -1
  669. package/dist/utils/ansi.js.map +1 -1
  670. package/dist/utils/clipboard.d.ts.map +1 -1
  671. package/dist/utils/clipboard.js +7 -6
  672. package/dist/utils/clipboard.js.map +1 -1
  673. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  674. package/dist/utils/image-resize-worker.js +3 -2
  675. package/dist/utils/image-resize-worker.js.map +1 -1
  676. package/dist/utils/photon.d.ts +2 -2
  677. package/dist/utils/photon.d.ts.map +1 -1
  678. package/dist/utils/photon.js +2 -2
  679. package/dist/utils/photon.js.map +1 -1
  680. package/dist/utils/shell.d.ts.map +1 -1
  681. package/dist/utils/shell.js +9 -8
  682. package/dist/utils/shell.js.map +1 -1
  683. package/dist/utils/tools-manager.d.ts.map +1 -1
  684. package/dist/utils/tools-manager.js +23 -13
  685. package/dist/utils/tools-manager.js.map +1 -1
  686. package/dist/utils/version-check.d.ts.map +1 -1
  687. package/dist/utils/version-check.js +5 -1
  688. package/dist/utils/version-check.js.map +1 -1
  689. package/docs/compaction.md +1 -3
  690. package/docs/docs.json +4 -0
  691. package/docs/index.md +1 -0
  692. package/docs/keybindings.md +3 -0
  693. package/docs/mcp.md +103 -0
  694. package/docs/models.md +14 -22
  695. package/docs/providers.md +0 -1
  696. package/docs/quickstart.md +1 -1
  697. package/docs/rpc.md +1 -26
  698. package/docs/sdk.md +4 -6
  699. package/docs/settings.md +10 -12
  700. package/docs/skills.md +1 -9
  701. package/docs/terminal-setup.md +2 -3
  702. package/docs/usage.md +7 -6
  703. package/examples/extensions/with-deps/package-lock.json +2 -2
  704. package/examples/extensions/with-deps/package.json +1 -1
  705. package/examples/extensions/with-deps/plugin.json +1 -1
  706. package/examples/sdk/10-settings.ts +2 -4
  707. package/examples/sdk/12-full-control.ts +1 -2
  708. package/package.json +1 -3
  709. package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
  710. package/dist/core/extensions/microcompact.d.ts +0 -80
  711. package/dist/core/extensions/microcompact.d.ts.map +0 -1
  712. package/dist/core/extensions/microcompact.js +0 -134
  713. package/dist/core/extensions/microcompact.js.map +0 -1
  714. package/dist/server/create-harness.d.ts +0 -26
  715. package/dist/server/create-harness.d.ts.map +0 -1
  716. package/dist/server/create-harness.js +0 -106
  717. package/dist/server/create-harness.js.map +0 -1
@@ -20,6 +20,7 @@ import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defau
20
20
  import { createCodingAgentFacade, createCodingAgentRuntimeFacade, } from "../../core/facade/index.js";
21
21
  import { FooterDataProvider } from "../../core/footer-data-provider.js";
22
22
  import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
23
+ import { setI18nLanguage, t } from "../../core/i18n/index.js";
23
24
  import { KeybindingsManager } from "../../core/keybindings.js";
24
25
  import { createCompactionSummaryMessage } from "../../core/messages.js";
25
26
  import { DefaultPackageManager } from "../../core/package-manager.js";
@@ -149,6 +150,14 @@ export function createInteractiveTui(options) {
149
150
  return error instanceof Error ? error.message : String(error);
150
151
  }
151
152
  },
153
+ // tui 包自带文案的注入式翻译(批次⑦):默认英文,en 下逐字节不变;
154
+ // 前导/尾随空格在 t() 外拼接(t() 会 trim key)。
155
+ labels: {
156
+ searchTitle: ` ${t("Find transcript")}`,
157
+ searchNoMatches: `${t("No matches")} `,
158
+ copied: t("Copied!"),
159
+ copyFailed: t("Copy failed"),
160
+ },
152
161
  });
153
162
  }
154
163
  return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
@@ -168,7 +177,7 @@ export function createInteractiveTuiReference(getTui) {
168
177
  if (currentTui !== methodTui) {
169
178
  const currentMethod = Reflect.get(currentTui, property, currentTui);
170
179
  if (typeof currentMethod !== "function") {
171
- throw new TypeError(`TUI property ${String(property)} is not callable`);
180
+ throw new TypeError(t("TUI property {property} is not callable", { property: String(property) }));
172
181
  }
173
182
  methodTui = currentTui;
174
183
  method = currentMethod;
@@ -270,8 +279,8 @@ export class InteractiveMode {
270
279
  workingMessage = undefined;
271
280
  workingVisible = true;
272
281
  workingIndicatorOptions = undefined;
273
- defaultWorkingMessage = "Working...";
274
- defaultHiddenThinkingLabel = "Thinking...";
282
+ defaultWorkingMessage = t("Working...");
283
+ defaultHiddenThinkingLabel = t("Thinking...");
275
284
  hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
276
285
  lastSigintTime = 0;
277
286
  lastEscapeTime = 0;
@@ -297,8 +306,6 @@ export class InteractiveMode {
297
306
  getMode: () => this.settingsManager.getMermaidRenderingMode(),
298
307
  theme,
299
308
  });
300
- // Skill commands: command name -> skill file path
301
- skillCommands = new Map();
302
309
  // Agent subscription unsubscribe function
303
310
  unsubscribe;
304
311
  signalCleanupHandlers = [];
@@ -366,6 +373,7 @@ export class InteractiveMode {
366
373
  // manager (D-047) and the constructor uses it before anything else.
367
374
  this.options = { ...options };
368
375
  this.runtimeHost = runtimeHost;
376
+ setI18nLanguage(this.settingsManager.getUiLanguage());
369
377
  setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
370
378
  const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
371
379
  this.options.tuiMode = tuiMode;
@@ -413,7 +421,6 @@ export class InteractiveMode {
413
421
  this.editorContainer.addChild(this.editor);
414
422
  this.footerDataProvider = new FooterDataProvider(this.facade.getCwd());
415
423
  this.footer = new FooterComponent(this.session, this.footerDataProvider);
416
- this.footer.setAutoCompactEnabled(this.facade.isAutoCompactionEnabled());
417
424
  this.footerContainer = new Container();
418
425
  this.footerContainer.addChild(this.footer);
419
426
  this.failoverTicker = new ProviderFailoverTicker(() => this.footer.isProviderFailoverOpen(), () => this.ui.requestRender());
@@ -537,20 +544,19 @@ export class InteractiveMode {
537
544
  description: definition.description,
538
545
  ...(definition.argumentHint && { argumentHint: definition.argumentHint }),
539
546
  })), [builtinCommandNames, templateCommandNames, [...resourceSkillCommandNames]]);
540
- // Build skill commands from session.skills (if enabled)
541
- this.skillCommands.clear();
547
+ // Skill commands register unconditionally (D-079: the enableSkillCommands
548
+ // switch is retired). A capability command claiming the same skill:name
549
+ // still wins: conflicting names are rejected by AgentSession, so neither
550
+ // side is offered as an executable completion.
542
551
  const skillCommandList = [];
543
- if (this.settingsManager.getEnableSkillCommands()) {
544
- for (const skill of this.facade.getSkills().skills) {
545
- const commandName = `skill:${skill.name}`;
546
- if (capabilityCommandNames.has(commandName))
547
- continue;
548
- this.skillCommands.set(commandName, skill.filePath);
549
- skillCommandList.push({
550
- name: commandName,
551
- description: this.prefixAutocompleteDescription(skill.description, skill.sourceInfo),
552
- });
553
- }
552
+ for (const skill of this.facade.getSkills().skills) {
553
+ const commandName = `skill:${skill.name}`;
554
+ if (capabilityCommandNames.has(commandName))
555
+ continue;
556
+ skillCommandList.push({
557
+ name: commandName,
558
+ description: this.prefixAutocompleteDescription(skill.description, skill.sourceInfo),
559
+ });
554
560
  }
555
561
  return new CombinedAutocompleteProvider([...slashCommands, ...templateCommands, ...capabilityCommands, ...skillCommandList], this.facade.getCwd(), this.fdPath);
556
562
  }
@@ -577,11 +583,14 @@ export class InteractiveMode {
577
583
  if (this.settingsManager.getCollapseChangelog()) {
578
584
  const versionMatch = this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/);
579
585
  const latestVersion = versionMatch ? versionMatch[1] : this.version;
580
- const condensedText = `Updated to v${latestVersion}. Use ${theme.bold("/changelog")} to view full changelog.`;
586
+ const condensedText = t("Updated to v{version}. Use {command} to view full changelog.", {
587
+ version: latestVersion,
588
+ command: theme.bold("/changelog"),
589
+ });
581
590
  this.chatContainer.addChild(new Text(condensedText, 1, 0));
582
591
  }
583
592
  else {
584
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
593
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", t("What's New"))), 1, 0));
585
594
  this.chatContainer.addChild(new Spacer(1));
586
595
  this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
587
596
  this.chatContainer.addChild(new Spacer(1));
@@ -593,7 +602,7 @@ export class InteractiveMode {
593
602
  tui.addChild(component);
594
603
  if (TuiLayouts.isViewportTUI(tui)) {
595
604
  if (!this.fullscreenLayoutRoot)
596
- throw new Error("Fullscreen layout is not initialized");
605
+ throw new Error(t("Fullscreen layout is not initialized"));
597
606
  tui.setLayoutRoot(this.fullscreenLayoutRoot);
598
607
  }
599
608
  }
@@ -673,9 +682,11 @@ export class InteractiveMode {
673
682
  .join(", ");
674
683
  const cycleKeys = this.keybindings.getKeys("app.model.cycleForward");
675
684
  const cycleHint = cycleKeys.length > 0
676
- ? theme.fg("muted", ` (${formatKeyText(cycleKeys.join("/"), { capitalize: true })} to cycle)`)
685
+ ? theme.fg("muted", ` ${t("({key} to cycle)", {
686
+ key: formatKeyText(cycleKeys.join("/"), { capitalize: true }),
687
+ })}`)
677
688
  : "";
678
- console.log(theme.fg("dim", `Model scope: ${modelList}${cycleHint}`));
689
+ console.log(theme.fg("dim", t("Model scope: {models}{hint}", { models: modelList, hint: cycleHint })));
679
690
  }
680
691
  // Keep one component tree and remount it when changing renderers.
681
692
  // Widget chrome is fixed empty; no initialization render needed.
@@ -722,30 +733,32 @@ export class InteractiveMode {
722
733
  // Build startup instructions using keybinding hint helpers
723
734
  const hint = (keybinding, description) => keyHint(keybinding, description);
724
735
  const expandedInstructions = [
725
- hint("app.interrupt", "to interrupt"),
726
- hint("app.clear", "to clear"),
727
- rawKeyHint(`${keyText("app.clear")} twice`, "to exit"),
728
- hint("app.exit", "to exit (empty)"),
729
- hint("app.suspend", "to suspend"),
730
- keyHint("tui.editor.deleteToLineEnd", "to delete to end"),
731
- hint("app.tools.expand", "to expand tools"),
732
- hint("app.thinking.toggle", "to expand thinking"),
733
- hint("app.editor.external", "for external editor"),
734
- rawKeyHint("/", "for commands"),
735
- rawKeyHint("!", "to run bash"),
736
- rawKeyHint("!!", "to run bash (no context)"),
737
- hint("app.clipboard.pasteImage", "to paste image (with text fallback)"),
738
- rawKeyHint("drop files", "to attach"),
736
+ hint("app.interrupt", t("to interrupt")),
737
+ hint("app.clear", t("to clear")),
738
+ rawKeyHint(t("{key} twice", { key: keyText("app.clear") }), t("to exit")),
739
+ hint("app.exit", t("to exit (empty)")),
740
+ hint("app.suspend", t("to suspend")),
741
+ keyHint("tui.editor.deleteToLineEnd", t("to delete to end")),
742
+ hint("app.tools.expand", t("to expand tools")),
743
+ hint("app.thinking.toggle", t("to expand thinking")),
744
+ hint("app.editor.external", t("for external editor")),
745
+ rawKeyHint("/", t("for commands")),
746
+ rawKeyHint("!", t("to run bash")),
747
+ rawKeyHint("!!", t("to run bash (no context)")),
748
+ hint("app.clipboard.pasteImage", t("to paste image (with text fallback)")),
749
+ rawKeyHint("drop files", t("to attach")),
739
750
  ].join("\n");
740
751
  const compactInstructions = [
741
- hint("app.interrupt", "interrupt"),
742
- rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`, "clear/exit"),
743
- rawKeyHint("/", "commands"),
744
- rawKeyHint("!", "bash"),
745
- hint("app.tools.expand", "more"),
752
+ hint("app.interrupt", t("interrupt")),
753
+ rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`, t("clear/exit")),
754
+ rawKeyHint("/", t("commands")),
755
+ rawKeyHint("!", t("bash")),
756
+ hint("app.tools.expand", t("more")),
746
757
  ].join(theme.fg("muted", " · "));
747
- const compactOnboarding = theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help and loaded resources.`);
748
- 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.`);
758
+ const compactOnboarding = theme.fg("dim", t("Press {key} to show full startup help and loaded resources.", {
759
+ key: keyText("app.tools.expand"),
760
+ }));
761
+ const onboarding = theme.fg("dim", t("Agent Forge can explain its own features and look up its docs. Ask it how to use or extend Agent Forge."));
749
762
  this.builtInHeader = new ExpandableText(() => `${logo}\n${compactInstructions}\n${compactOnboarding}\n\n${onboarding}`, () => `${logo}\n${expandedInstructions}\n\n${onboarding}`, this.getStartupExpansionState(), 1, 0);
750
763
  // Setup UI layout
751
764
  this.headerContainer.addChild(new Spacer(1));
@@ -873,11 +886,11 @@ export class InteractiveMode {
873
886
  }
874
887
  }
875
888
  if (migratedProviders && migratedProviders.length > 0) {
876
- this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
889
+ this.showWarning(t("Migrated credentials to auth.json: {providers}", { providers: migratedProviders.join(", ") }));
877
890
  }
878
891
  const modelsJsonError = this.facade.getModelsError();
879
892
  if (modelsJsonError) {
880
- this.showError(`models.json error: ${modelsJsonError}`);
893
+ this.showError(t("models.json error: {error}", { error: modelsJsonError }));
881
894
  }
882
895
  if (modelFallbackMessage) {
883
896
  this.showWarning(modelFallbackMessage);
@@ -889,7 +902,7 @@ export class InteractiveMode {
889
902
  await this.facade.prompt(initialMessage, { images: initialImages });
890
903
  }
891
904
  catch (error) {
892
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
905
+ const errorMessage = error instanceof Error ? error.message : t("Unknown error occurred");
893
906
  this.showError(errorMessage);
894
907
  }
895
908
  }
@@ -899,7 +912,7 @@ export class InteractiveMode {
899
912
  await this.facade.prompt(message);
900
913
  }
901
914
  catch (error) {
902
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
915
+ const errorMessage = error instanceof Error ? error.message : t("Unknown error occurred");
903
916
  this.showError(errorMessage);
904
917
  }
905
918
  }
@@ -918,7 +931,7 @@ export class InteractiveMode {
918
931
  await this.promptWithEmptyReplyRetry(userInput);
919
932
  }
920
933
  catch (error) {
921
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
934
+ const errorMessage = error instanceof Error ? error.message : t("Unknown error occurred");
922
935
  this.showError(errorMessage);
923
936
  }
924
937
  }
@@ -942,7 +955,7 @@ export class InteractiveMode {
942
955
  return;
943
956
  if (contentText(lastAssistant.content).trim().length > 0)
944
957
  return;
945
- this.showStatus("Previous reply was empty, retrying...");
958
+ this.showStatus(t("Previous reply was empty, retrying..."));
946
959
  await this.facade.prompt(EMPTY_REPLY_RETRY_PROMPT);
947
960
  }
948
961
  async checkForPackageUpdates() {
@@ -996,10 +1009,10 @@ export class InteractiveMode {
996
1009
  if (extendedKeys === undefined)
997
1010
  return undefined;
998
1011
  if (extendedKeys !== "on" && extendedKeys !== "always") {
999
- return "tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.";
1012
+ return t("tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.");
1000
1013
  }
1001
1014
  if (extendedKeysFormat === "xterm") {
1002
- 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.";
1015
+ return t("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.");
1003
1016
  }
1004
1017
  return undefined;
1005
1018
  }
@@ -1137,7 +1150,7 @@ export class InteractiveMode {
1137
1150
  .map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`))
1138
1151
  .join("\n");
1139
1152
  const contextCompactList = formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
1140
- addLoadedSection("Context", contextCompactList, contextList);
1153
+ addLoadedSection(t("Context"), contextCompactList, contextList);
1141
1154
  }
1142
1155
  const skills = skillsResult.skills;
1143
1156
  if (skills.length > 0) {
@@ -1147,7 +1160,7 @@ export class InteractiveMode {
1147
1160
  formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1148
1161
  });
1149
1162
  const skillCompactList = formatCompactList(skills.map((skill) => skill.name));
1150
- addLoadedSection("Skills", skillCompactList, skillList);
1163
+ addLoadedSection(t("Skills"), skillCompactList, skillList);
1151
1164
  }
1152
1165
  const templates = this.facade.getPromptTemplates();
1153
1166
  if (templates.length > 0) {
@@ -1166,7 +1179,7 @@ export class InteractiveMode {
1166
1179
  },
1167
1180
  });
1168
1181
  const promptCompactList = formatCompactList(templates.map((template) => `/${template.name}`));
1169
- addLoadedSection("Prompts", promptCompactList, templateList);
1182
+ addLoadedSection(t("Prompts"), promptCompactList, templateList);
1170
1183
  }
1171
1184
  // Show loaded themes (excluding built-in)
1172
1185
  const loadedThemes = themesResult.themes;
@@ -1181,7 +1194,7 @@ export class InteractiveMode {
1181
1194
  formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1182
1195
  });
1183
1196
  const themeCompactList = formatCompactList(customThemes.map((loadedTheme) => loadedTheme.name ?? this.getCompactPathLabel(loadedTheme.sourcePath, loadedTheme.sourceInfo)));
1184
- addLoadedSection("Themes", themeCompactList, themeList);
1197
+ addLoadedSection(t("Themes"), themeCompactList, themeList);
1185
1198
  }
1186
1199
  }
1187
1200
  // v8 ignore next -- showDiagnostics 为假时上方已提前返回,此处恒为真
@@ -1189,19 +1202,19 @@ export class InteractiveMode {
1189
1202
  const skillDiagnostics = skillsResult.diagnostics;
1190
1203
  if (skillDiagnostics.length > 0) {
1191
1204
  const warningLines = this.formatDiagnostics(skillDiagnostics, sourceInfos);
1192
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Skill conflicts]")}\n${warningLines}`, 0, 0));
1205
+ this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", t("[Skill conflicts]"))}\n${warningLines}`, 0, 0));
1193
1206
  this.loadedResourcesContainer.addChild(new Spacer(1));
1194
1207
  }
1195
1208
  const promptDiagnostics = promptsResult.diagnostics;
1196
1209
  if (promptDiagnostics.length > 0) {
1197
1210
  const warningLines = this.formatDiagnostics(promptDiagnostics, sourceInfos);
1198
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines}`, 0, 0));
1211
+ this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", t("[Prompt conflicts]"))}\n${warningLines}`, 0, 0));
1199
1212
  this.loadedResourcesContainer.addChild(new Spacer(1));
1200
1213
  }
1201
1214
  const themeDiagnostics = themesResult.diagnostics;
1202
1215
  if (themeDiagnostics.length > 0) {
1203
1216
  const warningLines = this.formatDiagnostics(themeDiagnostics, sourceInfos);
1204
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Theme conflicts]")}\n${warningLines}`, 0, 0));
1217
+ this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", t("[Theme conflicts]"))}\n${warningLines}`, 0, 0));
1205
1218
  this.loadedResourcesContainer.addChild(new Spacer(1));
1206
1219
  }
1207
1220
  }
@@ -1222,6 +1235,7 @@ export class InteractiveMode {
1222
1235
  this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
1223
1236
  }
1224
1237
  applyRuntimeSettings() {
1238
+ setI18nLanguage(this.settingsManager.getUiLanguage());
1225
1239
  setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
1226
1240
  configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
1227
1241
  this.applyFullscreenScrollbarSetting();
@@ -1230,7 +1244,6 @@ export class InteractiveMode {
1230
1244
  this.renderer.setWheelScrollLines(this.settingsManager.getFullscreenWheelScrollLines());
1231
1245
  }
1232
1246
  this.footer.setSession(this.session);
1233
- this.footer.setAutoCompactEnabled(this.facade.isAutoCompactionEnabled());
1234
1247
  this.footerDataProvider.setCwd(this.facade.getCwd());
1235
1248
  // The switched session carries its own failover snapshot history; re-check
1236
1249
  // whether the countdown ticker is needed.
@@ -1378,7 +1391,7 @@ export class InteractiveMode {
1378
1391
  this.workingVisible = true;
1379
1392
  this.setWorkingIndicator();
1380
1393
  if (this.activeStatusIndicator?.kind === "working") {
1381
- this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
1394
+ this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} ${t("({key} to interrupt)", { key: keyText("app.interrupt") })}`);
1382
1395
  }
1383
1396
  this.setHiddenThinkingLabel();
1384
1397
  }
@@ -1480,7 +1493,14 @@ export class InteractiveMode {
1480
1493
  this.restoreQueuedMessagesToEditor({ abort: true, cancelAgentTasks: false });
1481
1494
  const activeAgents = this.facade.getActiveAgentTaskCount();
1482
1495
  if (activeAgents > 0) {
1483
- this.showStatus(`${activeAgents} 个子代理仍在运行 · /stop-agents 终止全部(Esc 只停当前回合)`);
1496
+ // 单复数拆双 key 保 en 语法(批次⑩规则,同 handleStopAgentsCommand)。
1497
+ this.showStatus(activeAgents === 1
1498
+ ? t("{count} subagent still running · /stop-agents stops all (Esc only stops the current turn)", {
1499
+ count: activeAgents,
1500
+ })
1501
+ : t("{count} subagents still running · /stop-agents stops all (Esc only stops the current turn)", {
1502
+ count: activeAgents,
1503
+ }));
1484
1504
  }
1485
1505
  }
1486
1506
  else if (this.facade.isBashRunning()) {
@@ -1492,17 +1512,12 @@ export class InteractiveMode {
1492
1512
  this.updateEditorBorderColor();
1493
1513
  }
1494
1514
  else if (!this.editor.getText().trim()) {
1495
- // Double-escape with empty editor triggers /tree, /fork, or nothing based on setting
1515
+ // Double-escape with empty editor triggers /tree or nothing based on setting
1496
1516
  const action = this.settingsManager.getDoubleEscapeAction();
1497
- if (action !== "none") {
1517
+ if (action === "tree") {
1498
1518
  const now = Date.now();
1499
1519
  if (now - this.lastEscapeTime < 500) {
1500
- if (action === "tree") {
1501
- this.showTreeSelector();
1502
- }
1503
- else {
1504
- this.showUserMessageSelector();
1505
- }
1520
+ this.showTreeSelector();
1506
1521
  this.lastEscapeTime = 0;
1507
1522
  }
1508
1523
  else {
@@ -1598,7 +1613,7 @@ export class InteractiveMode {
1598
1613
  if (!text.trim())
1599
1614
  return;
1600
1615
  this.pendingUserInputs.push(text);
1601
- this.showStatus("Startup in progress — input queued and will run when startup completes");
1616
+ this.showStatus(t("Startup in progress — input queued and will run when startup completes"));
1602
1617
  }
1603
1618
  setupEditorSubmitHandler() {
1604
1619
  this.defaultEditor.onSubmit = async (rawText) => {
@@ -1656,7 +1671,7 @@ export class InteractiveMode {
1656
1671
  const command = isExcluded ? text.slice(2).trim() : text.slice(1).trim();
1657
1672
  if (command) {
1658
1673
  if (this.facade.isBashRunning()) {
1659
- this.showWarning("A bash command is already running. Press Esc to cancel it first.");
1674
+ this.showWarning(t("A bash command is already running. Press Esc to cancel it first."));
1660
1675
  this.editor.setText(text);
1661
1676
  return true;
1662
1677
  }
@@ -1813,14 +1828,16 @@ export class InteractiveMode {
1813
1828
  const retryAttempt = this.facade.getRetryAttempt();
1814
1829
  errorMessage =
1815
1830
  retryAttempt > 0
1816
- ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
1817
- : "Operation aborted";
1831
+ ? retryAttempt === 1
1832
+ ? t("Aborted after {count} retry attempt", { count: retryAttempt })
1833
+ : t("Aborted after {count} retry attempts", { count: retryAttempt })
1834
+ : t("Operation aborted");
1818
1835
  this.streamingMessage.errorMessage = errorMessage;
1819
1836
  }
1820
1837
  this.streamingComponent.updateContent(this.streamingMessage, false);
1821
1838
  if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
1822
1839
  if (!errorMessage) {
1823
- errorMessage = this.streamingMessage.errorMessage || "Error";
1840
+ errorMessage = this.streamingMessage.errorMessage || t("Error");
1824
1841
  }
1825
1842
  for (const [, component] of this.pendingTools.entries()) {
1826
1843
  component.updateResult({
@@ -1929,16 +1946,16 @@ export class InteractiveMode {
1929
1946
  this.clearStatusIndicator("compaction");
1930
1947
  if (event.aborted) {
1931
1948
  if (event.reason === "manual") {
1932
- this.showError("Compaction cancelled");
1949
+ this.showError(t("Compaction cancelled"));
1933
1950
  }
1934
1951
  else {
1935
- this.showStatus("Auto-compaction cancelled");
1952
+ this.showStatus(t("Auto-compaction cancelled"));
1936
1953
  }
1937
1954
  }
1938
1955
  else if (event.result) {
1939
1956
  const entries = this.facade.getContextEntries();
1940
1957
  if (entries[0]?.type !== "compaction") {
1941
- throw new Error("Completed compaction is missing from the session context");
1958
+ throw new Error(t("Completed compaction is missing from the session context"));
1942
1959
  }
1943
1960
  this.chatContainer.clear();
1944
1961
  // The latest compaction is prepended for model context; append it below at its chronological position.
@@ -1967,7 +1984,7 @@ export class InteractiveMode {
1967
1984
  break;
1968
1985
  }
1969
1986
  case "compaction_skipped": {
1970
- this.showStatus("Auto-compaction skipped: nothing to compact");
1987
+ this.showStatus(t("Auto-compaction skipped: nothing to compact"));
1971
1988
  this.ui.requestRender();
1972
1989
  break;
1973
1990
  }
@@ -1990,7 +2007,10 @@ export class InteractiveMode {
1990
2007
  this.clearStatusIndicator("retry");
1991
2008
  // Show error only on final failure (success shows normal response)
1992
2009
  if (!event.success) {
1993
- this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
2010
+ this.showError(t("Retry failed after {count} attempts: {error}", {
2011
+ count: event.attempt,
2012
+ error: event.finalError || t("Unknown error"),
2013
+ }));
1994
2014
  }
1995
2015
  this.ui.requestRender();
1996
2016
  break;
@@ -2034,7 +2054,7 @@ export class InteractiveMode {
2034
2054
  this.chatContainer.addChild(new Spacer(1));
2035
2055
  this.managedToolStatusStarted = true;
2036
2056
  }
2037
- const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
2057
+ const message = status.type === "warning" ? t("Warning: {message}", { message: status.message }) : status.message;
2038
2058
  const color = status.type === "warning" ? "warning" : "dim";
2039
2059
  this.chatContainer.addChild(new Text(theme.fg(color, message), 1, 0));
2040
2060
  this.lastStatusSpacer = undefined;
@@ -2183,11 +2203,13 @@ export class InteractiveMode {
2183
2203
  const retryAttempt = this.facade.getRetryAttempt();
2184
2204
  errorMessage =
2185
2205
  retryAttempt > 0
2186
- ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
2187
- : "Operation aborted";
2206
+ ? retryAttempt === 1
2207
+ ? t("Aborted after {count} retry attempt", { count: retryAttempt })
2208
+ : t("Aborted after {count} retry attempts", { count: retryAttempt })
2209
+ : t("Operation aborted");
2188
2210
  }
2189
2211
  else {
2190
- errorMessage = message.errorMessage || "Error";
2212
+ errorMessage = message.errorMessage || t("Error");
2191
2213
  }
2192
2214
  component.updateResult({ content: [{ type: "text", text: errorMessage }], isError: true });
2193
2215
  }
@@ -2249,9 +2271,9 @@ export class InteractiveMode {
2249
2271
  const { usage } = notice;
2250
2272
  const tokens = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
2251
2273
  const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
2252
- const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
2274
+ const label = notice.kind === "compaction" ? t("Compaction") : t("Branch summary");
2253
2275
  this.chatContainer.addChild(new Spacer(1));
2254
- this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
2276
+ this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${t("{tokens} tokens billed{cost}", { tokens: formatTokens(tokens), cost })}`), 1, 0));
2255
2277
  }
2256
2278
  static countDroppedThinkingBlocks(message) {
2257
2279
  let count = 0;
@@ -2286,9 +2308,8 @@ export class InteractiveMode {
2286
2308
  }
2287
2309
  if (droppedCount <= previousDroppedCount)
2288
2310
  return;
2289
- const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
2290
2311
  this.chatContainer.addChild(new Spacer(1));
2291
- this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
2312
+ this.chatContainer.addChild(new Text(theme.fg("warning", t("Anthropic dropped {count} thinking blocks (details in session)", { count: droppedCount })), 1, 0));
2292
2313
  }
2293
2314
  /**
2294
2315
  * Show a transcript notice when a completed assistant message paid for a
@@ -2307,13 +2328,13 @@ export class InteractiveMode {
2307
2328
  if (miss.missedTokens < 20_000 && miss.missedCost < 0.1)
2308
2329
  return;
2309
2330
  const cost = miss.missedCost >= 0.01 ? ` (~$${miss.missedCost.toFixed(2)})` : "";
2310
- const reBilled = `${formatTokens(miss.missedTokens)} tokens re-billed${cost}`;
2311
- let label = "Cache miss";
2331
+ const reBilled = t("{tokens} tokens re-billed{cost}", { tokens: formatTokens(miss.missedTokens), cost });
2332
+ let label = t("Cache miss");
2312
2333
  if (miss.modelChanged) {
2313
- label = "Cache miss after model switch";
2334
+ label = t("Cache miss after model switch");
2314
2335
  }
2315
2336
  else if (miss.idleMs >= CACHE_TTL_MS) {
2316
- label = `Cache miss after ${Math.round(miss.idleMs / 60_000)}m idle`;
2337
+ label = t("Cache miss after {minutes}m idle", { minutes: Math.round(miss.idleMs / 60_000) });
2317
2338
  }
2318
2339
  const text = theme.fg("warning", `${label}: ${reBilled}`);
2319
2340
  this.chatContainer.addChild(new Spacer(1));
@@ -2329,8 +2350,9 @@ export class InteractiveMode {
2329
2350
  const allEntries = this.facade.getEntries();
2330
2351
  const compactionCount = allEntries.filter((e) => e.type === "compaction").length;
2331
2352
  if (compactionCount > 0) {
2332
- const times = compactionCount === 1 ? "1 time" : `${compactionCount} times`;
2333
- this.showStatus(`Session compacted ${times}`);
2353
+ this.showStatus(compactionCount === 1
2354
+ ? t("Session compacted {count} time", { count: compactionCount })
2355
+ : t("Session compacted {count} times", { count: compactionCount }));
2334
2356
  }
2335
2357
  }
2336
2358
  async getUserInput() {
@@ -2404,7 +2426,7 @@ export class InteractiveMode {
2404
2426
  await this.runtimeFacade.dispose();
2405
2427
  const resumeCommand = formatResumeCommand(this.runtimeFacade);
2406
2428
  if (resumeCommand) {
2407
- process.stdout.write(`${chalk.dim("To resume this session:")} ${resumeCommand}\n`);
2429
+ process.stdout.write(`${chalk.dim(t("To resume this session:"))} ${resumeCommand}\n`);
2408
2430
  }
2409
2431
  process.exit(0);
2410
2432
  }
@@ -2444,7 +2466,7 @@ export class InteractiveMode {
2444
2466
  this.ui.stop();
2445
2467
  }
2446
2468
  catch { }
2447
- console.error(`${APP_NAME} exiting due to uncaughtException:`);
2469
+ console.error(t("{app} exiting due to uncaughtException:", { app: APP_NAME }));
2448
2470
  console.error(error);
2449
2471
  process.exit(1);
2450
2472
  }
@@ -2499,7 +2521,7 @@ export class InteractiveMode {
2499
2521
  }
2500
2522
  handleCtrlZ() {
2501
2523
  if (process.platform === "win32") {
2502
- this.showStatus("Suspend to background is not supported on Windows");
2524
+ this.showStatus(t("Suspend to background is not supported on Windows"));
2503
2525
  return;
2504
2526
  }
2505
2527
  // Keep the event loop alive while suspended. Without this, stopping the TUI
@@ -2560,16 +2582,19 @@ export class InteractiveMode {
2560
2582
  handleDequeue() {
2561
2583
  const restored = this.restoreQueuedMessagesToEditor();
2562
2584
  if (restored === 0) {
2563
- this.showStatus("No queued messages to restore");
2585
+ this.showStatus(t("No queued messages to restore"));
2586
+ }
2587
+ else if (restored === 1) {
2588
+ this.showStatus(t("Restored {count} queued message to editor", { count: restored }));
2564
2589
  }
2565
2590
  else {
2566
- this.showStatus(`Restored ${restored} queued message${restored > 1 ? "s" : ""} to editor`);
2591
+ this.showStatus(t("Restored {count} queued messages to editor", { count: restored }));
2567
2592
  }
2568
2593
  }
2569
2594
  /** /queue command host face (single-entry iron law): queues the given text for after the current run. A bare /queue cannot mirror the keybinding — the editor buffer is cleared on submit before the command runs — so it prints usage instead of silently doing nothing. */
2570
2595
  handleQueueCommand(text) {
2571
2596
  if (text === undefined || text.trim() === "") {
2572
- this.showStatus("Usage: /queue <text>");
2597
+ this.showStatus(t("Usage: /queue <text>"));
2573
2598
  return Promise.resolve();
2574
2599
  }
2575
2600
  return this.handleFollowUp(text);
@@ -2578,6 +2603,16 @@ export class InteractiveMode {
2578
2603
  handleDequeueCommand() {
2579
2604
  this.handleDequeue();
2580
2605
  }
2606
+ /** /queue-list command host face: open the queued-message manager selector. Both queues empty is a status message, not an empty overlay. */
2607
+ handleQueueListCommand() {
2608
+ const steering = this.facade.getSteeringMessages();
2609
+ const followUp = this.facade.getFollowUpMessages();
2610
+ if (steering.length === 0 && followUp.length === 0) {
2611
+ this.showStatus(t("No queued messages to manage"));
2612
+ return;
2613
+ }
2614
+ selectorsFlow.showQueueManagerSelector(this);
2615
+ }
2581
2616
  /** /editor command host face: edit the current input in an external editor. */
2582
2617
  handleEditorCommand() {
2583
2618
  return this.handleOpenExternalEditor();
@@ -2596,26 +2631,31 @@ export class InteractiveMode {
2596
2631
  cycleThinkingLevel() {
2597
2632
  const newLevel = this.facade.cycleThinkingLevel();
2598
2633
  if (newLevel === undefined) {
2599
- this.showStatus("Current model does not support thinking");
2634
+ this.showStatus(t("Current model does not support thinking"));
2600
2635
  }
2601
2636
  else {
2602
2637
  this.footer.invalidate();
2603
2638
  this.updateEditorBorderColor();
2604
- this.showStatus(`Thinking level: ${newLevel}`);
2639
+ this.showStatus(t("Thinking level: {level}", { level: newLevel }));
2605
2640
  }
2606
2641
  }
2607
2642
  async cycleModel(direction) {
2608
2643
  try {
2609
2644
  const result = await this.facade.cycleModel(direction);
2610
2645
  if (result === undefined) {
2611
- const msg = this.facade.getScopedModels().length > 0 ? "Only one model in scope" : "Only one model available";
2646
+ const msg = this.facade.getScopedModels().length > 0 ? t("Only one model in scope") : t("Only one model available");
2612
2647
  this.showStatus(msg);
2613
2648
  }
2614
2649
  else {
2615
2650
  this.footer.invalidate();
2616
2651
  this.updateEditorBorderColor();
2617
- const thinkingStr = result.model.reasoning && result.thinkingLevel !== "off" ? ` (thinking: ${result.thinkingLevel})` : "";
2618
- this.showStatus(`Switched to ${result.model.name || result.model.id}${thinkingStr}`);
2652
+ const thinkingStr = result.model.reasoning && result.thinkingLevel !== "off"
2653
+ ? ` ${t("(thinking: {level})", { level: result.thinkingLevel })}`
2654
+ : "";
2655
+ this.showStatus(t("Switched to {model}{thinking}", {
2656
+ model: result.model.name || result.model.id,
2657
+ thinking: thinkingStr,
2658
+ }));
2619
2659
  void this.maybeWarnAboutAnthropicSubscriptionAuth(result.model);
2620
2660
  }
2621
2661
  }
@@ -2641,7 +2681,7 @@ export class InteractiveMode {
2641
2681
  }
2642
2682
  }
2643
2683
  }
2644
- this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
2684
+ this.showStatus(expanded ? t("Tool output: expanded") : t("Tool output: collapsed"));
2645
2685
  }
2646
2686
  /** Update rendered assistant messages without rebuilding live tool components. */
2647
2687
  updateThinkingBlockVisibility() {
@@ -2656,7 +2696,7 @@ export class InteractiveMode {
2656
2696
  this.hideThinkingBlock = !this.hideThinkingBlock;
2657
2697
  this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
2658
2698
  this.updateThinkingBlockVisibility();
2659
- this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
2699
+ this.showStatus(this.hideThinkingBlock ? t("Thinking blocks: hidden") : t("Thinking blocks: visible"));
2660
2700
  }
2661
2701
  async handleOpenExternalEditor() {
2662
2702
  const editorCmd = this.settingsManager.getExternalEditorCommand();
@@ -2685,28 +2725,28 @@ export class InteractiveMode {
2685
2725
  }
2686
2726
  showError(errorMessage) {
2687
2727
  this.chatContainer.addChild(new Spacer(1));
2688
- this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
2728
+ this.chatContainer.addChild(new Text(theme.fg("error", t("Error: {message}", { message: errorMessage })), this.outputPad, 0));
2689
2729
  this.ui.requestRender();
2690
2730
  }
2691
2731
  showWarning(warningMessage) {
2692
2732
  this.chatContainer.addChild(new Spacer(1));
2693
- this.chatContainer.addChild(new Text(theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
2733
+ this.chatContainer.addChild(new Text(theme.fg("warning", t("Warning: {message}", { message: warningMessage })), 1, 0));
2694
2734
  this.ui.requestRender();
2695
2735
  }
2696
2736
  showNewVersionNotification(release) {
2697
2737
  const action = theme.fg("accent", `${APP_NAME} update`);
2698
- const updateInstruction = theme.fg("muted", `New version ${release.version} is available. Run `) + action;
2738
+ const updateInstruction = theme.fg("muted", `${t("New version {version} is available. Run", { version: release.version })} `) + action;
2699
2739
  const changelogUrl = process.env.AGENT_FORGE_CHANGELOG_URL;
2700
2740
  const changelogLine = changelogUrl
2701
- ? theme.fg("muted", "Changelog: ") +
2741
+ ? theme.fg("muted", `${t("Changelog:")} `) +
2702
2742
  (getCapabilities().hyperlinks
2703
2743
  ? hyperlink(theme.fg("accent", changelogUrl), changelogUrl)
2704
2744
  : theme.fg("accent", changelogUrl))
2705
- : theme.fg("muted", "Changelog URL is not configured.");
2745
+ : theme.fg("muted", t("Changelog URL is not configured."));
2706
2746
  const note = release.note?.trim();
2707
2747
  this.chatContainer.addChild(new Spacer(1));
2708
2748
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
2709
- this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction}`, 1, 0));
2749
+ this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", t("Update Available")))}\n${updateInstruction}`, 1, 0));
2710
2750
  if (note) {
2711
2751
  this.chatContainer.addChild(new Spacer(1));
2712
2752
  this.chatContainer.addChild(new Markdown(note, 1, 0, this.getMarkdownThemeWithSettings(), {
@@ -2720,11 +2760,11 @@ export class InteractiveMode {
2720
2760
  }
2721
2761
  showPackageUpdateNotification(packages) {
2722
2762
  const action = theme.fg("accent", `${APP_NAME} update --extensions`);
2723
- const updateInstruction = theme.fg("muted", "Package updates are available. Run ") + action;
2763
+ const updateInstruction = theme.fg("muted", `${t("Package updates are available. Run")} `) + action;
2724
2764
  const packageLines = packages.map((pkg) => `- ${pkg}`).join("\n");
2725
2765
  this.chatContainer.addChild(new Spacer(1));
2726
2766
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
2727
- this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
2767
+ this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", t("Package Updates Available")))}\n${updateInstruction}\n${theme.fg("muted", `${t("Packages:")}`)}\n${packageLines}`, 1, 0));
2728
2768
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
2729
2769
  this.ui.requestRender();
2730
2770
  }
@@ -2762,23 +2802,24 @@ export class InteractiveMode {
2762
2802
  followUp: [...followUp, ...compactionFollowUp],
2763
2803
  };
2764
2804
  }
2805
+ /** Host-visible for ./interactive-selectors.ts (queue manager close path). */
2765
2806
  updatePendingMessagesDisplay() {
2766
2807
  this.pendingMessagesContainer.clear();
2767
2808
  const { steering: steeringMessages, followUp: followUpMessages } = this.getAllQueuedMessages();
2768
2809
  if (steeringMessages.length > 0 || followUpMessages.length > 0) {
2769
2810
  this.pendingMessagesContainer.addChild(new Spacer(1));
2770
2811
  for (const message of steeringMessages) {
2771
- const text = theme.fg("dim", `Steering: ${message}`);
2812
+ const text = theme.fg("dim", t("Steering: {message}", { message }));
2772
2813
  this.pendingMessagesContainer.addChild(new TruncatedText(text, 1, 0));
2773
2814
  }
2774
2815
  for (const message of followUpMessages) {
2775
- const text = theme.fg("dim", `Follow-up: ${message}`);
2816
+ const text = theme.fg("dim", t("Follow-up: {message}", { message }));
2776
2817
  this.pendingMessagesContainer.addChild(new TruncatedText(text, 1, 0));
2777
2818
  }
2778
2819
  // The dequeue keybinding's shipped default was cleared (iron law):
2779
2820
  // /queue's sibling command is the discoverable entry.
2780
2821
  const dequeueHint = this.getAppKeyDisplay("app.message.dequeue") || "/dequeue";
2781
- const hintText = theme.fg("dim", `↳ ${dequeueHint} to edit all queued messages`);
2822
+ const hintText = theme.fg("dim", t("↳ {key} to edit all queued messages", { key: dequeueHint }));
2782
2823
  this.pendingMessagesContainer.addChild(new TruncatedText(hintText, 1, 0));
2783
2824
  }
2784
2825
  }
@@ -2810,7 +2851,7 @@ export class InteractiveMode {
2810
2851
  this.editor.addToHistory?.(text);
2811
2852
  this.editor.setText("");
2812
2853
  this.updatePendingMessagesDisplay();
2813
- this.showStatus("Queued message for after compaction");
2854
+ this.showStatus(t("Queued message for after compaction"));
2814
2855
  }
2815
2856
  async flushCompactionQueue(options) {
2816
2857
  if (this.compactionQueuedMessages.length === 0) {
@@ -2823,7 +2864,13 @@ export class InteractiveMode {
2823
2864
  this.facade.clearQueue();
2824
2865
  this.compactionQueuedMessages = queuedMessages;
2825
2866
  this.updatePendingMessagesDisplay();
2826
- this.showError(`Failed to send queued message${queuedMessages.length > 1 ? "s" : ""}: ${error instanceof Error ? error.message : String(error)}`);
2867
+ this.showError(queuedMessages.length > 1
2868
+ ? t("Failed to send queued messages: {error}", {
2869
+ error: error instanceof Error ? error.message : String(error),
2870
+ })
2871
+ : t("Failed to send queued message: {error}", {
2872
+ error: error instanceof Error ? error.message : String(error),
2873
+ }));
2827
2874
  };
2828
2875
  try {
2829
2876
  if (options?.willRetry) {
@@ -2920,9 +2967,8 @@ export class InteractiveMode {
2920
2967
  let selector;
2921
2968
  const defaultProvider = this.settingsManager.getDefaultProvider();
2922
2969
  const defaultModelId = this.settingsManager.getDefaultModel();
2923
- const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : "not set";
2970
+ const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : t("not set");
2924
2971
  selector = new SettingsSelectorComponent({
2925
- autoCompact: this.facade.isAutoCompactionEnabled(),
2926
2972
  defaultModel,
2927
2973
  currentModel: this.facade.getModel(),
2928
2974
  availableDefaultModels: this.facade.getAvailableModels(),
@@ -2930,7 +2976,6 @@ export class InteractiveMode {
2930
2976
  imageWidthCells: this.settingsManager.getImageWidthCells(),
2931
2977
  autoResizeImages: this.settingsManager.getImageAutoResize(),
2932
2978
  blockImages: this.settingsManager.getBlockImages(),
2933
- enableSkillCommands: this.settingsManager.getEnableSkillCommands(),
2934
2979
  steeringMode: this.facade.getSteeringMode(),
2935
2980
  followUpMode: this.facade.getFollowUpMode(),
2936
2981
  transport: this.settingsManager.getTransport(),
@@ -2945,6 +2990,7 @@ export class InteractiveMode {
2945
2990
  mermaidRenderingMode: this.settingsManager.getMermaidRenderingMode(),
2946
2991
  collapseChangelog: this.settingsManager.getCollapseChangelog(),
2947
2992
  doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
2993
+ uiLanguage: this.settingsManager.getUiLanguage(),
2948
2994
  treeFilterMode: this.settingsManager.getTreeFilterMode(),
2949
2995
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
2950
2996
  showCacheMissNotices: this.settingsManager.getShowCacheMissNotices(),
@@ -2961,10 +3007,6 @@ export class InteractiveMode {
2961
3007
  fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
2962
3008
  warnings: this.settingsManager.getWarnings(),
2963
3009
  }, {
2964
- onAutoCompactChange: (enabled) => {
2965
- this.facade.setAutoCompactionEnabled(enabled);
2966
- this.footer.setAutoCompactEnabled(enabled);
2967
- },
2968
3010
  onShowImagesChange: (enabled) => {
2969
3011
  this.settingsManager.setShowImages(enabled);
2970
3012
  for (const child of this.chatContainer.children) {
@@ -2987,10 +3029,6 @@ export class InteractiveMode {
2987
3029
  onBlockImagesChange: (blocked) => {
2988
3030
  this.settingsManager.setBlockImages(blocked);
2989
3031
  },
2990
- onEnableSkillCommandsChange: (enabled) => {
2991
- this.settingsManager.setEnableSkillCommands(enabled);
2992
- this.setupAutocompleteProvider();
2993
- },
2994
3032
  onSteeringModeChange: (mode) => {
2995
3033
  this.facade.setSteeringMode(mode);
2996
3034
  },
@@ -3004,7 +3042,7 @@ export class InteractiveMode {
3004
3042
  onHttpIdleTimeoutMsChange: (timeoutMs) => {
3005
3043
  this.settingsManager.setHttpIdleTimeoutMs(timeoutMs);
3006
3044
  configureHttpDispatcher(timeoutMs);
3007
- this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
3045
+ this.showStatus(t("HTTP idle timeout: {value}", { value: formatHttpIdleTimeoutMs(timeoutMs) }));
3008
3046
  },
3009
3047
  onModelThinkingLevelChange: (provider, modelId, level) => {
3010
3048
  this.settingsManager.setModelThinkingLevel(provider, modelId, level);
@@ -3055,6 +3093,11 @@ export class InteractiveMode {
3055
3093
  onDoubleEscapeActionChange: (action) => {
3056
3094
  this.settingsManager.setDoubleEscapeAction(action);
3057
3095
  },
3096
+ onUiLanguageChange: (language) => {
3097
+ this.settingsManager.setUiLanguage(language);
3098
+ setI18nLanguage(language);
3099
+ this.ui.requestRender();
3100
+ },
3058
3101
  onTreeFilterModeChange: (mode) => {
3059
3102
  this.settingsManager.setTreeFilterMode(mode);
3060
3103
  },
@@ -3108,13 +3151,13 @@ export class InteractiveMode {
3108
3151
  onTuiModeChange: (mode) => {
3109
3152
  if (!this.switchTuiMode(mode)) {
3110
3153
  selector?.getSettingsList().updateValue("tui-mode", this.ui.mode);
3111
- this.showStatus("Close active overlays before changing TUI mode");
3154
+ this.showStatus(t("Close active overlays before changing TUI mode"));
3112
3155
  return;
3113
3156
  }
3114
3157
  this.settingsManager.setTuiMode(mode);
3115
3158
  if (!this.activeStatusIndicator)
3116
3159
  this.statusContainer.clear();
3117
- this.showStatus(`TUI mode: ${mode}`);
3160
+ this.showStatus(t("TUI mode: {mode}", { mode }));
3118
3161
  },
3119
3162
  onFullscreenExitOutputChange: (output) => {
3120
3163
  this.settingsManager.setFullscreenExitOutput(output);
@@ -3222,22 +3265,26 @@ export class InteractiveMode {
3222
3265
  const selected = await new Promise((resolve) => {
3223
3266
  this.openSuiteListSelector({
3224
3267
  availableSuites: pending.available,
3225
- note: `Suite "${pending.requestedId}" was not found. The selected suite applies to the new session.`,
3268
+ note: t('Suite "{id}" was not found. The selected suite applies to the new session.', {
3269
+ id: pending.requestedId,
3270
+ }),
3226
3271
  onSelect: (suiteId) => resolve(suiteId),
3227
3272
  onCancel: () => resolve(undefined),
3228
3273
  });
3229
3274
  });
3230
3275
  if (selected === undefined) {
3231
- this.showWarning(`Suite "${pending.requestedId}" was not found — continuing without a suite. Use /suite to choose one.`);
3276
+ this.showWarning(t('Suite "{id}" was not found — continuing without a suite. Use /suite to choose one.', {
3277
+ id: pending.requestedId,
3278
+ }));
3232
3279
  return;
3233
3280
  }
3234
3281
  this.settingsManager.setProjectSuite(selected);
3235
3282
  try {
3236
3283
  await this.runtimeFacade.newSession();
3237
- this.showStatus(`Suite set to ${selected} — new session started`);
3284
+ this.showStatus(t("Suite set to {id} — new session started", { id: selected }));
3238
3285
  }
3239
3286
  catch (error) {
3240
- await this.handleFatalRuntimeError("Failed to create session", error);
3287
+ await this.handleFatalRuntimeError(t("Failed to create session"), error);
3241
3288
  }
3242
3289
  }
3243
3290
  /** /model command entry; implementation in ./interactive-selectors.ts (S5 slice 5). */
@@ -3273,7 +3320,7 @@ export class InteractiveMode {
3273
3320
  try {
3274
3321
  if ((await this.facade.checkProviderAuth("anthropic"))?.type === "oauth") {
3275
3322
  this.anthropicSubscriptionWarningShown = true;
3276
- this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);
3323
+ this.showWarning(t(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING));
3277
3324
  return;
3278
3325
  }
3279
3326
  const apiKey = (await this.facade.getProviderAuth(model.provider))?.auth.apiKey;
@@ -3281,7 +3328,7 @@ export class InteractiveMode {
3281
3328
  return;
3282
3329
  }
3283
3330
  this.anthropicSubscriptionWarningShown = true;
3284
- this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);
3331
+ this.showWarning(t(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING));
3285
3332
  }
3286
3333
  catch {
3287
3334
  // Ignore auth lookup failures for warning-only checks.
@@ -3314,7 +3361,7 @@ export class InteractiveMode {
3314
3361
  .getEntries()
3315
3362
  .some((entry) => entry.type === "custom" && entry.customType === "workflow.state");
3316
3363
  if (!hasSnapshot) {
3317
- this.showStatus("No workflow in this session");
3364
+ this.showStatus(t("No workflow in this session"));
3318
3365
  return;
3319
3366
  }
3320
3367
  this.showSelector((done) => {
@@ -3328,7 +3375,7 @@ export class InteractiveMode {
3328
3375
  done();
3329
3376
  this.editor.setText(text);
3330
3377
  this.ui.requestRender();
3331
- this.showStatus("Workflow action staged — review in the editor and submit");
3378
+ this.showStatus(t("Workflow action staged — review in the editor and submit"));
3332
3379
  };
3333
3380
  return { component: view, focus: view, dispose: () => view.dispose() };
3334
3381
  });
@@ -3344,7 +3391,7 @@ export class InteractiveMode {
3344
3391
  const agentDir = getAgentDir();
3345
3392
  const sessions = listAgentSessions({ agentDir, parentAgentSession: this.facade.getSessionId() });
3346
3393
  if (sessions.length === 0) {
3347
- this.showStatus("No subagent sessions in this session");
3394
+ this.showStatus(t("No subagent sessions in this session"));
3348
3395
  return;
3349
3396
  }
3350
3397
  this.showSelector((done) => {
@@ -3363,7 +3410,7 @@ export class InteractiveMode {
3363
3410
  const realLeafId = this.facade.getLeafId();
3364
3411
  const initialFilterMode = this.settingsManager.getTreeFilterMode();
3365
3412
  if (tree.length === 0) {
3366
- this.showStatus("No entries in session");
3413
+ this.showStatus(t("No entries in session"));
3367
3414
  return;
3368
3415
  }
3369
3416
  this.showSelector((done) => {
@@ -3371,7 +3418,7 @@ export class InteractiveMode {
3371
3418
  // Selecting the current leaf is a no-op (already there)
3372
3419
  if (entryId === this.facade.getLeafId()) {
3373
3420
  done();
3374
- this.showStatus("Already at this point");
3421
+ this.showStatus(t("Already at this point"));
3375
3422
  return;
3376
3423
  }
3377
3424
  // Ask about summarization
@@ -3382,19 +3429,19 @@ export class InteractiveMode {
3382
3429
  // Check if we should skip the prompt (user preference to always default to no summary)
3383
3430
  if (!this.settingsManager.getBranchSummarySkipPrompt()) {
3384
3431
  while (true) {
3385
- const summaryChoice = await this.showDialogSelector("Summarize branch?", [
3386
- "No summary",
3387
- "Summarize",
3388
- "Summarize with custom prompt",
3432
+ const summaryChoice = await this.showDialogSelector(t("Summarize branch?"), [
3433
+ t("No summary"),
3434
+ t("Summarize"),
3435
+ t("Summarize with custom prompt"),
3389
3436
  ]);
3390
3437
  if (summaryChoice === undefined) {
3391
3438
  // User pressed escape - re-show tree selector with same selection
3392
3439
  this.showTreeSelector(entryId);
3393
3440
  return;
3394
3441
  }
3395
- wantsSummary = summaryChoice !== "No summary";
3396
- if (summaryChoice === "Summarize with custom prompt") {
3397
- customInstructions = await this.showDialogEditor("Custom summarization instructions");
3442
+ wantsSummary = summaryChoice !== t("No summary");
3443
+ if (summaryChoice === t("Summarize with custom prompt")) {
3444
+ customInstructions = await this.showDialogEditor(t("Custom summarization instructions"));
3398
3445
  if (customInstructions === undefined) {
3399
3446
  // User cancelled - loop back to summary selector
3400
3447
  continue;
@@ -3429,12 +3476,12 @@ export class InteractiveMode {
3429
3476
  });
3430
3477
  if (result.aborted) {
3431
3478
  // Summarization aborted - re-show tree selector with same selection
3432
- this.showStatus("Branch summarization cancelled");
3479
+ this.showStatus(t("Branch summarization cancelled"));
3433
3480
  this.showTreeSelector(entryId);
3434
3481
  return;
3435
3482
  }
3436
3483
  if (result.cancelled) {
3437
- this.showStatus("Navigation cancelled");
3484
+ this.showStatus(t("Navigation cancelled"));
3438
3485
  return;
3439
3486
  }
3440
3487
  // Update UI
@@ -3443,7 +3490,7 @@ export class InteractiveMode {
3443
3490
  if (result.editorText && !this.editor.getText().trim()) {
3444
3491
  this.editor.setText(result.editorText);
3445
3492
  }
3446
- this.showStatus("Navigated to selected point");
3493
+ this.showStatus(t("Navigated to selected point"));
3447
3494
  void this.flushCompactionQueue({ willRetry: false });
3448
3495
  }
3449
3496
  catch (error) {
@@ -3464,12 +3511,12 @@ export class InteractiveMode {
3464
3511
  }, initialSelectedId, initialFilterMode);
3465
3512
  selector.onCopy = async (text) => {
3466
3513
  if (!text) {
3467
- this.showError("Selected entry has no text to copy");
3514
+ this.showError(t("Selected entry has no text to copy"));
3468
3515
  return;
3469
3516
  }
3470
3517
  try {
3471
3518
  await copyToClipboard(text);
3472
- this.showStatus("Copied selected message to clipboard");
3519
+ this.showStatus(t("Copied selected message to clipboard"));
3473
3520
  }
3474
3521
  catch (error) {
3475
3522
  this.showError(error instanceof Error ? error.message : String(error));
@@ -3517,7 +3564,7 @@ export class InteractiveMode {
3517
3564
  if (result.cancelled) {
3518
3565
  return result;
3519
3566
  }
3520
- this.showStatus("Resumed session");
3567
+ this.showStatus(t("Resumed session"));
3521
3568
  this.detectCrossSuiteResume();
3522
3569
  return result;
3523
3570
  }
@@ -3525,7 +3572,7 @@ export class InteractiveMode {
3525
3572
  if (error instanceof MissingSessionCwdError) {
3526
3573
  const selectedCwd = await this.promptForMissingSessionCwd(error);
3527
3574
  if (!selectedCwd) {
3528
- this.showStatus("Resume cancelled");
3575
+ this.showStatus(t("Resume cancelled"));
3529
3576
  return { cancelled: true };
3530
3577
  }
3531
3578
  const result = await this.runtimeFacade.switchSession(sessionPath, {
@@ -3535,11 +3582,11 @@ export class InteractiveMode {
3535
3582
  if (result.cancelled) {
3536
3583
  return result;
3537
3584
  }
3538
- this.showStatus("Resumed session in current cwd");
3585
+ this.showStatus(t("Resumed session in current cwd"));
3539
3586
  this.detectCrossSuiteResume();
3540
3587
  return result;
3541
3588
  }
3542
- return this.handleFatalRuntimeError("Failed to resume session", error);
3589
+ return this.handleFatalRuntimeError(t("Failed to resume session"), error);
3543
3590
  }
3544
3591
  }
3545
3592
  /**
@@ -3563,7 +3610,10 @@ export class InteractiveMode {
3563
3610
  });
3564
3611
  if (currentSuiteId === originalSuiteId)
3565
3612
  return;
3566
- this.showStatus(`Cross-suite compatible mode: session created with "${originalSuiteId}", assembling with "${currentSuiteId}"`);
3613
+ this.showStatus(t('Cross-suite compatible mode: session created with "{from}", assembling with "{to}"', {
3614
+ from: originalSuiteId,
3615
+ to: currentSuiteId,
3616
+ }));
3567
3617
  this.facade.recordSuiteMismatch(originalSuiteId, currentSuiteId);
3568
3618
  }
3569
3619
  // =========================================================================
@@ -3681,11 +3731,11 @@ export class InteractiveMode {
3681
3731
  // =========================================================================
3682
3732
  async handleReloadCommand() {
3683
3733
  if (this.facade.isStreaming()) {
3684
- this.showWarning("Wait for the current response to finish before reloading.");
3734
+ this.showWarning(t("Wait for the current response to finish before reloading."));
3685
3735
  return;
3686
3736
  }
3687
3737
  if (this.facade.isCompacting()) {
3688
- this.showWarning("Wait for compaction to finish before reloading.");
3738
+ this.showWarning(t("Wait for compaction to finish before reloading."));
3689
3739
  return;
3690
3740
  }
3691
3741
  this.resetDialogUI();
@@ -3693,7 +3743,7 @@ export class InteractiveMode {
3693
3743
  const borderColor = (s) => theme.fg("border", s);
3694
3744
  reloadBox.addChild(new DynamicBorder(borderColor));
3695
3745
  reloadBox.addChild(new Spacer(1));
3696
- reloadBox.addChild(new Text(theme.fg("muted", "Reloading keybindings, skills, prompts, themes, and context files..."), 1, 0));
3746
+ reloadBox.addChild(new Text(theme.fg("muted", t("Reloading keybindings, skills, prompts, themes, and context files...")), 1, 0));
3697
3747
  reloadBox.addChild(new Spacer(1));
3698
3748
  reloadBox.addChild(new DynamicBorder(borderColor));
3699
3749
  const previousEditor = this.editor;
@@ -3737,9 +3787,9 @@ export class InteractiveMode {
3737
3787
  });
3738
3788
  const modelsJsonError = this.facade.getModelsError();
3739
3789
  if (modelsJsonError) {
3740
- this.showError(`models.json error: ${modelsJsonError}`);
3790
+ this.showError(t("models.json error: {error}", { error: modelsJsonError }));
3741
3791
  }
3742
- this.showStatus("Reloaded keybindings, skills, prompts, themes, and context files");
3792
+ this.showStatus(t("Reloaded keybindings, skills, prompts, themes, and context files"));
3743
3793
  dismissReloadBox(this.editor);
3744
3794
  reloadBoxDismissed = true;
3745
3795
  }
@@ -3748,7 +3798,7 @@ export class InteractiveMode {
3748
3798
  if (!reloadBoxDismissed) {
3749
3799
  dismissReloadBox(previousEditor);
3750
3800
  }
3751
- this.showError(`Reload failed: ${error instanceof Error ? error.message : String(error)}`);
3801
+ this.showError(t("Reload failed: {error}", { error: error instanceof Error ? error.message : String(error) }));
3752
3802
  }
3753
3803
  }
3754
3804
  async handleExportCommand(text) {
@@ -3756,17 +3806,19 @@ export class InteractiveMode {
3756
3806
  try {
3757
3807
  if (outputPath?.endsWith(".jsonl")) {
3758
3808
  const filePath = this.facade.exportToJsonl(outputPath);
3759
- this.showStatus(`Session exported to: ${filePath}`);
3809
+ this.showStatus(t("Session exported to: {path}", { path: filePath }));
3760
3810
  }
3761
3811
  else {
3762
3812
  const filePath = await this.facade.exportToHtml(outputPath, {
3763
3813
  themeName: theme.name,
3764
3814
  });
3765
- this.showStatus(`Session exported to: ${filePath}`);
3815
+ this.showStatus(t("Session exported to: {path}", { path: filePath }));
3766
3816
  }
3767
3817
  }
3768
3818
  catch (error) {
3769
- this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
3819
+ this.showError(t("Failed to export session: {error}", {
3820
+ error: error instanceof Error ? error.message : t("Unknown error"),
3821
+ }));
3770
3822
  }
3771
3823
  }
3772
3824
  getPathCommandArgument(text, command) {
@@ -3797,43 +3849,43 @@ export class InteractiveMode {
3797
3849
  async handleImportCommand(text) {
3798
3850
  const inputPath = this.getPathCommandArgument(text, "/import");
3799
3851
  if (!inputPath) {
3800
- this.showError("Usage: /import <path.jsonl>");
3852
+ this.showError(t("Usage: /import <path.jsonl>"));
3801
3853
  return;
3802
3854
  }
3803
- const confirmed = await this.showDialogConfirm("Import session", `Replace current session with ${inputPath}?`);
3855
+ const confirmed = await this.showDialogConfirm(t("Import session"), t("Replace current session with {path}?", { path: inputPath }));
3804
3856
  if (!confirmed) {
3805
- this.showStatus("Import cancelled");
3857
+ this.showStatus(t("Import cancelled"));
3806
3858
  return;
3807
3859
  }
3808
3860
  try {
3809
3861
  this.clearStatusIndicator();
3810
3862
  const result = await this.runtimeFacade.importFromJsonl(inputPath);
3811
3863
  if (result.cancelled) {
3812
- this.showStatus("Import cancelled");
3864
+ this.showStatus(t("Import cancelled"));
3813
3865
  return;
3814
3866
  }
3815
- this.showStatus(`Session imported from: ${inputPath}`);
3867
+ this.showStatus(t("Session imported from: {path}", { path: inputPath }));
3816
3868
  }
3817
3869
  catch (error) {
3818
3870
  if (error instanceof MissingSessionCwdError) {
3819
3871
  const selectedCwd = await this.promptForMissingSessionCwd(error);
3820
3872
  if (!selectedCwd) {
3821
- this.showStatus("Import cancelled");
3873
+ this.showStatus(t("Import cancelled"));
3822
3874
  return;
3823
3875
  }
3824
3876
  const result = await this.runtimeFacade.importFromJsonl(inputPath, selectedCwd);
3825
3877
  if (result.cancelled) {
3826
- this.showStatus("Import cancelled");
3878
+ this.showStatus(t("Import cancelled"));
3827
3879
  return;
3828
3880
  }
3829
- this.showStatus(`Session imported from: ${inputPath}`);
3881
+ this.showStatus(t("Session imported from: {path}", { path: inputPath }));
3830
3882
  return;
3831
3883
  }
3832
3884
  if (error instanceof SessionImportFileNotFoundError) {
3833
- this.showError(`Failed to import session: ${error.message}`);
3885
+ this.showError(t("Failed to import session: {error}", { error: error.message }));
3834
3886
  return;
3835
3887
  }
3836
- await this.handleFatalRuntimeError("Failed to import session", error);
3888
+ await this.handleFatalRuntimeError(t("Failed to import session"), error);
3837
3889
  }
3838
3890
  }
3839
3891
  async handleCopyCommand(options = {}) {
@@ -3846,16 +3898,16 @@ export class InteractiveMode {
3846
3898
  }
3847
3899
  const text = this.facade.getLastAssistantText();
3848
3900
  if (!text) {
3849
- this.showError("No agent messages to copy yet.");
3901
+ this.showError(t("No agent messages to copy yet."));
3850
3902
  return;
3851
3903
  }
3852
3904
  try {
3853
3905
  await copyToClipboard(text);
3854
3906
  if (options.flashConfirmation && this.ui instanceof TuiAltScreen) {
3855
- this.ui.flash("Copied!");
3907
+ this.ui.flash(t("Copied!"));
3856
3908
  }
3857
3909
  else {
3858
- this.showStatus("Copied last agent message to clipboard");
3910
+ this.showStatus(t("Copied last agent message to clipboard"));
3859
3911
  }
3860
3912
  }
3861
3913
  catch (error) {
@@ -3868,10 +3920,10 @@ export class InteractiveMode {
3868
3920
  const currentName = this.facade.getSessionName();
3869
3921
  if (currentName) {
3870
3922
  this.chatContainer.addChild(new Spacer(1));
3871
- this.chatContainer.addChild(new Text(theme.fg("dim", `Session name: ${currentName}`), 1, 0));
3923
+ this.chatContainer.addChild(new Text(theme.fg("dim", t("Session name: {name}", { name: currentName })), 1, 0));
3872
3924
  }
3873
3925
  else {
3874
- this.showWarning("Usage: /name <name>");
3926
+ this.showWarning(t("Usage: /name <name>"));
3875
3927
  }
3876
3928
  this.ui.requestRender();
3877
3929
  return;
@@ -3879,10 +3931,13 @@ export class InteractiveMode {
3879
3931
  this.facade.setSessionName(name);
3880
3932
  const sessionName = this.facade.getSessionName();
3881
3933
  if (sessionName !== name) {
3882
- this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`);
3934
+ this.showWarning(t("Session name was normalized from {from} to {to}", {
3935
+ from: JSON.stringify(name),
3936
+ to: JSON.stringify(sessionName),
3937
+ }));
3883
3938
  }
3884
3939
  this.chatContainer.addChild(new Spacer(1));
3885
- this.chatContainer.addChild(new Text(theme.fg("dim", `Session name set: ${sessionName ?? name}`), 1, 0));
3940
+ this.chatContainer.addChild(new Text(theme.fg("dim", t("Session name set: {name}", { name: sessionName ?? name })), 1, 0));
3886
3941
  this.ui.requestRender();
3887
3942
  }
3888
3943
  /**
@@ -3892,11 +3947,13 @@ export class InteractiveMode {
3892
3947
  handleStopAgentsCommand() {
3893
3948
  const active = this.facade.getActiveAgentTaskCount();
3894
3949
  if (active === 0) {
3895
- this.showStatus("No background subagents running");
3950
+ this.showStatus(t("No background subagents running"));
3896
3951
  return;
3897
3952
  }
3898
3953
  this.facade.abortAgentTasks();
3899
- this.showStatus(`Terminated ${active} background subagent${active === 1 ? "" : "s"}`);
3954
+ this.showStatus(active === 1
3955
+ ? t("Terminated {count} background subagent", { count: active })
3956
+ : t("Terminated {count} background subagents", { count: active }));
3900
3957
  }
3901
3958
  handleSessionCommand() {
3902
3959
  const stats = this.facade.getSessionStats();
@@ -3907,71 +3964,81 @@ export class InteractiveMode {
3907
3964
  // resolves to a concrete responseModel). Usage without model attribution is
3908
3965
  // grouped separately so the breakdown reconciles with the session total.
3909
3966
  const usageBreakdown = getUsageCostBreakdown(entries);
3910
- let info = `${theme.bold("Session Info")}\n\n`;
3967
+ let info = `${theme.bold(t("Session Info"))}\n\n`;
3911
3968
  if (sessionName) {
3912
- info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
3913
- }
3914
- info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
3915
- info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
3916
- info += `${theme.bold("Messages")}\n`;
3917
- info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
3918
- info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
3919
- info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
3920
- info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
3921
- info += `${theme.bold("Tokens")}\n`;
3969
+ info += `${theme.fg("dim", t("Name:"))} ${sessionName}\n`;
3970
+ }
3971
+ info += `${theme.fg("dim", t("File:"))} ${stats.sessionFile ?? t("In-memory")}\n`;
3972
+ info += `${theme.fg("dim", t("ID:"))} ${stats.sessionId}\n\n`;
3973
+ info += `${theme.bold(t("Messages"))}\n`;
3974
+ info += `${theme.fg("dim", t("Total:"))} ${stats.totalMessages}\n`;
3975
+ info += `${theme.fg("dim", t("User:"))} ${stats.userMessages}\n`;
3976
+ info += `${theme.fg("dim", t("Assistant:"))} ${stats.assistantMessages}\n`;
3977
+ info += `${theme.fg("dim", t("Tools:"))} ${t("{calls} calls, {results} results", {
3978
+ calls: stats.toolCalls,
3979
+ results: stats.toolResults,
3980
+ })}\n\n`;
3981
+ info += `${theme.bold(t("Tokens"))}\n`;
3922
3982
  // "Input" is the full prompt volume. With cache activity, split it into
3923
3983
  // cached (served from cache) vs uncached (everything else) - the only
3924
3984
  // provider-independent split. Cache writes, where reported, are a detail
3925
3985
  // of the uncached portion.
3926
3986
  const { input, cacheRead, cacheWrite } = stats.tokens;
3927
3987
  const promptTokens = input + cacheRead + cacheWrite;
3928
- info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
3988
+ info += `${theme.fg("dim", t("Input:"))} ${promptTokens.toLocaleString()}\n`;
3929
3989
  if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
3930
3990
  const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
3931
- info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
3932
- const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
3933
- info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
3991
+ info += ` ${theme.fg("dim", t("Cached:"))} ${cacheRead.toLocaleString()} ${hitRate}\n`;
3992
+ const written = cacheWrite > 0
3993
+ ? ` ${theme.fg("dim", t("({count} written to cache)", { count: cacheWrite.toLocaleString() }))}`
3994
+ : "";
3995
+ info += ` ${theme.fg("dim", t("Uncached:"))} ${(input + cacheWrite).toLocaleString()}${written}\n`;
3934
3996
  }
3935
- info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
3936
- info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
3997
+ info += `${theme.fg("dim", t("Output:"))} ${stats.tokens.output.toLocaleString()}\n`;
3998
+ info += `${theme.fg("dim", t("Total:"))} ${stats.tokens.total.toLocaleString()}\n`;
3937
3999
  // 双维度统计(用户裁决 2026-09-25):总计之外按供应商/模型分桶——缓存读/写、
3938
4000
  // 命中率、费用逐桶可见。此前该拆分门控在 cost>0 且多桶才渲染,单价为 0 的
3939
4001
  // 自定义供应商(如自建代理)永远看不到。
3940
4002
  if (usageBreakdown.length > 0) {
3941
- info += `\n${theme.bold("By Provider/Model")}\n`;
4003
+ info += `\n${theme.bold(t("By Provider/Model"))}\n`;
3942
4004
  for (const entry of usageBreakdown) {
3943
4005
  const bucket = entry.totals;
3944
4006
  const promptBucket = bucket.input + bucket.cacheRead + bucket.cacheWrite;
3945
4007
  let line = ` ${theme.bold(entry.key)}`;
3946
4008
  if (promptBucket > 0) {
3947
- line += `\n ${theme.fg("dim", "Input:")} ${promptBucket.toLocaleString()}`;
4009
+ line += `\n ${theme.fg("dim", t("Input:"))} ${promptBucket.toLocaleString()}`;
3948
4010
  if (bucket.cacheRead > 0 || bucket.cacheWrite > 0) {
3949
4011
  const rate = promptBucket > 0 ? ((bucket.cacheRead / promptBucket) * 100).toFixed(1) : "0.0";
3950
- line += ` ${theme.fg("dim", `(cache ${rate}%, W ${bucket.cacheWrite.toLocaleString()})`)}`;
4012
+ line += ` ${theme.fg("dim", t("(cache {rate}%, W {written})", { rate, written: bucket.cacheWrite.toLocaleString() }))}`;
3951
4013
  }
3952
4014
  }
3953
4015
  if (bucket.output > 0)
3954
- line += `\n ${theme.fg("dim", "Output:")} ${bucket.output.toLocaleString()}`;
4016
+ line += `\n ${theme.fg("dim", t("Output:"))} ${bucket.output.toLocaleString()}`;
3955
4017
  if (entry.cost > 0)
3956
4018
  line += ` ${theme.fg("dim", `$${entry.cost.toFixed(3)}`)}`;
3957
4019
  info += `${line}\n`;
3958
4020
  }
3959
4021
  }
3960
4022
  if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
3961
- info += `\n${theme.bold("Cost")}\n`;
3962
- info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
4023
+ info += `\n${theme.bold(t("Cost"))}\n`;
4024
+ info += `${theme.fg("dim", t("Total:"))} $${stats.cost.toFixed(3)}`;
3963
4025
  if (usageBreakdown.length > 1) {
3964
4026
  for (const entry of usageBreakdown) {
3965
- info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
4027
+ info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", t("({tokens} tokens)", { tokens: formatTokens(entry.tokens) }))}`;
3966
4028
  }
3967
4029
  }
3968
4030
  if (cacheWaste.missedTokens > 0) {
3969
- const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
3970
- const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
4031
+ const missLabel = cacheWaste.missCount === 1
4032
+ ? t("{count} miss", { count: cacheWaste.missCount })
4033
+ : t("{count} misses", { count: cacheWaste.missCount });
4034
+ const detail = t("{tokens} tokens, {misses}", {
4035
+ tokens: cacheWaste.missedTokens.toLocaleString(),
4036
+ misses: missLabel,
4037
+ });
3971
4038
  info +=
3972
4039
  cacheWaste.missedCost >= 0.0001
3973
- ? `\n${theme.fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
3974
- : `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
4040
+ ? `\n${theme.fg("dim", t("Cache Re-billed:"))} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
4041
+ : `\n${theme.fg("dim", t("Cache Re-billed:"))} ${detail}`;
3975
4042
  }
3976
4043
  }
3977
4044
  this.chatContainer.addChild(new Spacer(1));
@@ -3981,14 +4048,14 @@ export class InteractiveMode {
3981
4048
  handleMetricsCommand(turnsArg) {
3982
4049
  const provider = this.options.getMetrics;
3983
4050
  if (!provider) {
3984
- this.showWarning("Metrics are not available: the observability plugin is not mounted in this session");
4051
+ this.showWarning(t("Metrics are not available: the observability plugin is not mounted in this session"));
3985
4052
  return;
3986
4053
  }
3987
4054
  let windowTurns;
3988
4055
  if (turnsArg !== undefined) {
3989
4056
  const parsed = Number.parseInt(turnsArg, 10);
3990
4057
  if (!Number.isSafeInteger(parsed) || parsed < 1) {
3991
- this.showWarning(`Invalid turns: ${turnsArg}. Usage: /metrics [turns]`);
4058
+ this.showWarning(t("Invalid turns: {turns}. Usage: /metrics [turns]", { turns: turnsArg }));
3992
4059
  return;
3993
4060
  }
3994
4061
  windowTurns = parsed;
@@ -3997,7 +4064,7 @@ export class InteractiveMode {
3997
4064
  try {
3998
4065
  const result = provider({ windowTurns });
3999
4066
  if (result === undefined) {
4000
- this.showWarning("Metrics are not available: the observability plugin is not mounted in this session");
4067
+ this.showWarning(t("Metrics are not available: the observability plugin is not mounted in this session"));
4001
4068
  return;
4002
4069
  }
4003
4070
  snapshot = result;
@@ -4018,10 +4085,10 @@ export class InteractiveMode {
4018
4085
  .reverse()
4019
4086
  .map((e) => normalizeChangelogLinks(e.content, e))
4020
4087
  .join("\n\n")
4021
- : "No changelog entries found.";
4088
+ : t("No changelog entries found.");
4022
4089
  this.chatContainer.addChild(new Spacer(1));
4023
4090
  this.chatContainer.addChild(new DynamicBorder());
4024
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
4091
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", t("What's New"))), 1, 0));
4025
4092
  this.chatContainer.addChild(new Spacer(1));
4026
4093
  this.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, this.getMarkdownThemeWithSettings()));
4027
4094
  this.chatContainer.addChild(new DynamicBorder());
@@ -4043,7 +4110,7 @@ export class InteractiveMode {
4043
4110
  const section = (title, rows) => {
4044
4111
  if (rows.length === 0)
4045
4112
  return "";
4046
- let table = `\n**${title}**\n| Command | Description |\n|---------|-------------|\n`;
4113
+ let table = `\n**${title}**\n| ${t("Command")} | ${t("Description")} |\n|---------|-------------|\n`;
4047
4114
  for (const row of rows) {
4048
4115
  const command = row.hint ? `\`/${row.name} ${row.hint}\`` : `\`/${row.name}\``;
4049
4116
  table += `| ${command} | ${row.description ?? ""} |\n`;
@@ -4064,13 +4131,13 @@ export class InteractiveMode {
4064
4131
  name: `skill:${skill.name}`,
4065
4132
  description: skill.description,
4066
4133
  }));
4067
- const help = section("Built-in commands", builtinRows) +
4068
- section("Prompt templates", promptRows) +
4069
- section("Skills", skillRows) +
4070
- "\nType `/` for autocomplete. Use `/hotkeys` for keyboard shortcuts.";
4134
+ const help = section(t("Built-in commands"), builtinRows) +
4135
+ section(t("Prompt templates"), promptRows) +
4136
+ section(t("Skills"), skillRows) +
4137
+ `\n${t("Type `/` for autocomplete. Use `/hotkeys` for keyboard shortcuts.")}`;
4071
4138
  this.chatContainer.addChild(new Spacer(1));
4072
4139
  this.chatContainer.addChild(new DynamicBorder());
4073
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "Available Commands")), 1, 0));
4140
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", t("Available Commands"))), 1, 0));
4074
4141
  this.chatContainer.addChild(new Markdown(help.trim(), 1, 1, this.getMarkdownThemeWithSettings()));
4075
4142
  this.chatContainer.addChild(new DynamicBorder());
4076
4143
  this.ui.requestRender();
@@ -4118,68 +4185,70 @@ export class InteractiveMode {
4118
4185
  const pasteImage = this.getAppKeyDisplay("app.clipboard.pasteImage");
4119
4186
  // Iron law (2026-10-01): these shipped defaults were cleared in favor of
4120
4187
  // the /model command; the row only appears when a user re-configures a key.
4121
- const selectModelRow = selectModel ? `| \`${selectModel}\` | Open model selector |\n` : "";
4188
+ const selectModelRow = selectModel ? `| \`${selectModel}\` | ${t("Open model selector")} |\n` : "";
4122
4189
  // Iron law (2026-10-02 复审): ctrl+g/ctrl+x stay bound only for the
4123
4190
  // components without a command channel — the main editor ignores them
4124
4191
  // (/editor and /copy are its single entries), so the rows say where
4125
4192
  // each key actually acts.
4126
- const copyMessageRow = copyMessage ? `| \`${copyMessage}\` | Copy selection in /tree |\n` : "";
4193
+ const copyMessageRow = copyMessage ? `| \`${copyMessage}\` | ${t("Copy selection in /tree")} |\n` : "";
4127
4194
  const externalEditorRow = externalEditor
4128
- ? `| \`${externalEditor}\` | External editor (inside dialog inputs) |\n`
4195
+ ? `| \`${externalEditor}\` | ${t("External editor (inside dialog inputs)")} |\n`
4129
4196
  : "";
4130
4197
  // Iron law (2026-10-01): the message queue is the /queue and /dequeue
4131
4198
  // commands' feature; rows only appear when a user re-configures a key.
4132
- const followUpRow = followUp ? `| \`${followUp}\` | Queue follow-up message |\n` : "";
4133
- const dequeueRow = dequeue ? `| \`${dequeue}\` | Restore queued messages |\n` : "";
4134
- const cycleThinkingRow = cycleThinkingLevel ? `| \`${cycleThinkingLevel}\` | Cycle thinking level |\n` : "";
4199
+ const followUpRow = followUp ? `| \`${followUp}\` | ${t("Queue follow-up message")} |\n` : "";
4200
+ const dequeueRow = dequeue ? `| \`${dequeue}\` | ${t("Restore queued messages")} |\n` : "";
4201
+ const cycleThinkingRow = cycleThinkingLevel
4202
+ ? `| \`${cycleThinkingLevel}\` | ${t("Cycle thinking level")} |\n`
4203
+ : "";
4135
4204
  const cycleModelsRow = cycleModelForward || cycleModelBackward
4136
- ? `| \`${cycleModelForward}\` / \`${cycleModelBackward}\` | Cycle models |\n`
4205
+ ? `| \`${cycleModelForward}\` / \`${cycleModelBackward}\` | ${t("Cycle models")} |\n`
4137
4206
  : "";
4138
4207
  // Suspend has no default key on native Windows; hide the row there.
4139
- const suspendRow = suspend ? `| \`${suspend}\` | Suspend to background |\n` : "";
4208
+ const suspendRow = suspend ? `| \`${suspend}\` | ${t("Suspend to background")} |\n` : "";
4140
4209
  const hotkeys = `
4141
- **Navigation**
4142
- | Key | Action |
4210
+ **${t("Navigation")}**
4211
+ | ${t("Key")} | ${t("Action")} |
4143
4212
  |-----|--------|
4144
- | \`${cursorUp}\` / \`${cursorDown}\` / \`${cursorLeft}\` / \`${cursorRight}\` | Move cursor / browse history |
4145
- | \`${cursorWordLeft}\` / \`${cursorWordRight}\` | Move by word |
4146
- | \`${cursorLineStart}\` | Start of line |
4147
- | \`${cursorLineEnd}\` | End of line |
4148
- | \`${jumpForward}\` | Jump forward to character |
4149
- | \`${jumpBackward}\` | Jump backward to character |
4150
- | \`${pageUp}\` / \`${pageDown}\` | Scroll by page |
4213
+ | \`${cursorUp}\` / \`${cursorDown}\` / \`${cursorLeft}\` / \`${cursorRight}\` | ${t("Move cursor / browse history")} |
4214
+ | \`${cursorWordLeft}\` / \`${cursorWordRight}\` | ${t("Move by word")} |
4215
+ | \`${cursorLineStart}\` | ${t("Start of line")} |
4216
+ | \`${cursorLineEnd}\` | ${t("End of line")} |
4217
+ | \`${jumpForward}\` | ${t("Jump forward to character")} |
4218
+ | \`${jumpBackward}\` | ${t("Jump backward to character")} |
4219
+ | \`${pageUp}\` / \`${pageDown}\` | ${t("Scroll by page")} |
4151
4220
 
4152
- **Editing**
4153
- | Key | Action |
4221
+ **${t("Editing")}**
4222
+ | ${t("Key")} | ${t("Action")} |
4154
4223
  |-----|--------|
4155
- | \`${submit}\` | Send message |
4156
- | \`${newLine}\` | New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""} |
4157
- | \`${deleteWordBackward}\` | Delete word backwards |
4158
- | \`${deleteWordForward}\` | Delete word forwards |
4159
- | \`${deleteToLineStart}\` | Delete to start of line |
4160
- | \`${deleteToLineEnd}\` | Delete to end of line |
4161
- | \`${yank}\` | Paste the most-recently-deleted text |
4162
- | \`${yankPop}\` | Cycle through the deleted text after pasting |
4163
- | \`${undo}\` | Undo |
4224
+ | \`${submit}\` | ${t("Send message")} |
4225
+ | \`${newLine}\` | ${process.platform === "win32" ? t("New line (Ctrl+Enter on Windows Terminal)") : t("New line")} |
4226
+ | \`${deleteWordBackward}\` | ${t("Delete word backwards")} |
4227
+ | \`${deleteWordForward}\` | ${t("Delete word forwards")} |
4228
+ | \`${deleteToLineStart}\` | ${t("Delete to start of line")} |
4229
+ | \`${deleteToLineEnd}\` | ${t("Delete to end of line")} |
4230
+ | \`${yank}\` | ${t("Paste the most-recently-deleted text")} |
4231
+ | \`${yankPop}\` | ${t("Cycle through the deleted text after pasting")} |
4232
+ | \`${undo}\` | ${t("Undo")} |
4164
4233
 
4165
- **Other**
4166
- | Key | Action |
4234
+ **${t("Other")}**
4235
+ | ${t("Key")} | ${t("Action")} |
4167
4236
  |-----|--------|
4168
- | \`${tab}\` | Path completion / accept autocomplete |
4169
- | \`${interrupt}\` | Cancel autocomplete / abort streaming |
4170
- | \`${clear}\` | Clear editor (first) / exit (second) |
4171
- | \`${exit}\` | Exit (when editor is empty) |
4172
- ${suspendRow}${cycleThinkingRow}${cycleModelsRow}${selectModelRow}| \`${expandTools}\` | Toggle tool output expansion |
4173
- | \`${toggleThinking}\` | Toggle thinking block visibility |
4237
+ | \`${tab}\` | ${t("Path completion / accept autocomplete")} |
4238
+ | \`${interrupt}\` | ${t("Cancel autocomplete / abort streaming")} |
4239
+ | \`${clear}\` | ${t("Clear editor (first) / exit (second)")} |
4240
+ | \`${exit}\` | ${t("Exit (when editor is empty)")} |
4241
+ ${suspendRow}${cycleThinkingRow}${cycleModelsRow}${selectModelRow}| \`${expandTools}\` | ${t("Toggle tool output expansion")} |
4242
+ | \`${toggleThinking}\` | ${t("Toggle thinking block visibility")} |
4174
4243
  ${externalEditorRow}${copyMessageRow}${followUpRow}${dequeueRow}
4175
- | \`${pasteImage}\` | Paste image or text from clipboard |
4176
- | \`/\` | Slash commands |
4177
- | \`!\` | Run bash command |
4178
- | \`!!\` | Run bash command (excluded from context) |
4244
+ | \`${pasteImage}\` | ${t("Paste image or text from clipboard")} |
4245
+ | \`/\` | ${t("Slash commands")} |
4246
+ | \`!\` | ${t("Run bash command")} |
4247
+ | \`!!\` | ${t("Run bash command (excluded from context)")} |
4179
4248
  `;
4180
4249
  this.chatContainer.addChild(new Spacer(1));
4181
4250
  this.chatContainer.addChild(new DynamicBorder());
4182
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "Keyboard Shortcuts")), 1, 0));
4251
+ this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", t("Keyboard Shortcuts"))), 1, 0));
4183
4252
  this.chatContainer.addChild(new Spacer(1));
4184
4253
  this.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, this.getMarkdownThemeWithSettings()));
4185
4254
  this.chatContainer.addChild(new DynamicBorder());
@@ -4193,7 +4262,7 @@ ${externalEditorRow}${copyMessageRow}${followUpRow}${dequeueRow}
4193
4262
  return;
4194
4263
  }
4195
4264
  this.chatContainer.addChild(new Spacer(1));
4196
- this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ New session started")}`, 1, 1));
4265
+ this.chatContainer.addChild(new Text(`${theme.fg("accent", t("✓ New session started"))}`, 1, 1));
4197
4266
  this.ui.requestRender();
4198
4267
  }
4199
4268
  catch (error) {
@@ -4206,18 +4275,18 @@ ${externalEditorRow}${copyMessageRow}${followUpRow}${dequeueRow}
4206
4275
  const allLines = this.ui.render(width);
4207
4276
  const debugLogPath = getDebugLogPath();
4208
4277
  const debugData = [
4209
- `Debug output at ${new Date().toISOString()}`,
4210
- `Terminal: ${width}x${height}`,
4211
- `Total lines: ${allLines.length}`,
4278
+ t("Debug output at {date}", { date: new Date().toISOString() }),
4279
+ t("Terminal: {columns}x{rows}", { columns: width, rows: height }),
4280
+ t("Total lines: {count}", { count: allLines.length }),
4212
4281
  "",
4213
- "=== All rendered lines with visible widths ===",
4282
+ t("=== All rendered lines with visible widths ==="),
4214
4283
  ...allLines.map((line, idx) => {
4215
4284
  const vw = visibleWidth(line);
4216
4285
  const escaped = JSON.stringify(line);
4217
4286
  return `[${idx}] (w=${vw}) ${escaped}`;
4218
4287
  }),
4219
4288
  "",
4220
- "=== Agent messages (JSONL) ===",
4289
+ t("=== Agent messages (JSONL) ==="),
4221
4290
  ...this.facade
4222
4291
  .getSessionAPI()
4223
4292
  .getMessages()
@@ -4227,7 +4296,7 @@ ${externalEditorRow}${copyMessageRow}${followUpRow}${dequeueRow}
4227
4296
  fs.mkdirSync(path.dirname(debugLogPath), { recursive: true });
4228
4297
  fs.writeFileSync(debugLogPath, debugData);
4229
4298
  this.chatContainer.addChild(new Spacer(1));
4230
- this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ Debug log written")}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
4299
+ this.chatContainer.addChild(new Text(`${theme.fg("accent", t("✓ Debug log written"))}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
4231
4300
  this.ui.requestRender();
4232
4301
  }
4233
4302
  handleArminSaysHi() {
@@ -4277,7 +4346,9 @@ ${externalEditorRow}${copyMessageRow}${followUpRow}${dequeueRow}
4277
4346
  if (this.bashComponent) {
4278
4347
  this.bashComponent.setComplete(undefined, false);
4279
4348
  }
4280
- this.showError(`Bash command failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4349
+ this.showError(t("Bash command failed: {error}", {
4350
+ error: error instanceof Error ? error.message : t("Unknown error"),
4351
+ }));
4281
4352
  }
4282
4353
  this.bashComponent = undefined;
4283
4354
  this.ui.requestRender();