talos-code 0.0.1 → 0.2.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 (407) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +661 -0
  3. package/README.md +116 -3
  4. package/THIRD_PARTY_NOTICES.md +40 -0
  5. package/dist/archive/zip.js +73 -0
  6. package/dist/args.js +100 -0
  7. package/dist/automations/history-store.js +34 -0
  8. package/dist/automations/policy-store.js +43 -0
  9. package/dist/automations/runner.js +107 -0
  10. package/dist/automations/schedule.js +85 -0
  11. package/dist/automations/windows-task.js +53 -0
  12. package/dist/commands/advanced-cli.js +233 -0
  13. package/dist/commands/checkpoint-cli.js +45 -0
  14. package/dist/commands/config-cli.js +107 -0
  15. package/dist/commands/context.js +17 -0
  16. package/dist/commands/extensions-cli.js +207 -0
  17. package/dist/commands/project-cli.js +74 -0
  18. package/dist/commands/project-commands.js +143 -0
  19. package/dist/commands/provider-cli.js +244 -0
  20. package/dist/commands/services-cli.js +248 -0
  21. package/dist/commands/session-cli.js +171 -0
  22. package/dist/commands/system-cli.js +405 -0
  23. package/dist/config/commands.js +60 -0
  24. package/dist/config/load.js +382 -0
  25. package/dist/config/migrations.js +48 -0
  26. package/dist/config/types.js +11 -0
  27. package/dist/diagnostics/development-log.js +154 -0
  28. package/dist/diagnostics/doctor.js +104 -0
  29. package/dist/diagnostics/redact.js +80 -0
  30. package/dist/diagnostics/zip.js +52 -0
  31. package/dist/errors.js +156 -0
  32. package/dist/events/bridge.js +130 -0
  33. package/dist/extensions/installer.js +178 -0
  34. package/dist/extensions/package-schema.js +24 -0
  35. package/dist/headless/result.js +84 -0
  36. package/dist/headless/run.js +230 -0
  37. package/dist/i18n/en/approval.js +46 -0
  38. package/dist/i18n/en/common.js +9 -0
  39. package/dist/i18n/en/credentials.js +92 -0
  40. package/dist/i18n/en/errors.js +267 -0
  41. package/dist/i18n/en/firstrun.js +101 -0
  42. package/dist/i18n/en/providers.js +37 -0
  43. package/dist/i18n/en/screen.js +774 -0
  44. package/dist/i18n/en/tools.js +127 -0
  45. package/dist/i18n/en.js +14 -0
  46. package/dist/i18n/error-view.js +307 -0
  47. package/dist/i18n/index.js +19 -0
  48. package/dist/i18n/kernel-map.js +139 -0
  49. package/dist/io.js +45 -0
  50. package/dist/main.js +331 -0
  51. package/dist/paths.js +41 -0
  52. package/dist/protocol/v2/codec.js +9 -0
  53. package/dist/protocol/v2/events.js +555 -0
  54. package/dist/protocol/v2/index.js +4 -0
  55. package/dist/protocol/v2/replay.js +28 -0
  56. package/dist/protocol/v2/types.js +1 -0
  57. package/dist/provider/control-plane.js +135 -0
  58. package/dist/provider/environment-keys.js +275 -0
  59. package/dist/provider/health.js +110 -0
  60. package/dist/provider/missing-key.js +48 -0
  61. package/dist/provider/model-catalog.js +168 -0
  62. package/dist/provider/openrouter-login.js +172 -0
  63. package/dist/provider/provider-text.js +13 -0
  64. package/dist/provider/store.js +95 -0
  65. package/dist/provider/system-keyring.js +214 -0
  66. package/dist/runtime/active-run.js +63 -0
  67. package/dist/runtime/agent-tree.js +74 -0
  68. package/dist/runtime/attachments.js +84 -0
  69. package/dist/runtime/brokered-executor.js +395 -0
  70. package/dist/runtime/context-archive.js +69 -0
  71. package/dist/runtime/context-status.js +76 -0
  72. package/dist/runtime/create-runtime.js +111 -0
  73. package/dist/runtime/model-profile.js +361 -0
  74. package/dist/runtime/output-store.js +137 -0
  75. package/dist/runtime/provider-attempts.js +185 -0
  76. package/dist/runtime/replay-buffer.js +153 -0
  77. package/dist/runtime/repo.js +95 -0
  78. package/dist/runtime/session-facade.js +135 -0
  79. package/dist/runtime/session-summary.js +125 -0
  80. package/dist/runtime/supervisor.js +265 -0
  81. package/dist/runtime/talos-composition.js +1011 -0
  82. package/dist/runtime/types.js +5 -0
  83. package/dist/runtime/usage-snapshot.js +82 -0
  84. package/dist/security/auto-classifier.js +38 -0
  85. package/dist/security/credential-free-environment.js +54 -0
  86. package/dist/security/evaluate.js +243 -0
  87. package/dist/security/execution-backends.js +236 -0
  88. package/dist/security/execution-broker.js +102 -0
  89. package/dist/security/forge-scan.js +74 -0
  90. package/dist/security/from-approval.js +39 -0
  91. package/dist/security/mxc-execution-backend.js +281 -0
  92. package/dist/security/permission-engine.js +138 -0
  93. package/dist/security/permission-explanation.js +54 -0
  94. package/dist/security/persist.js +179 -0
  95. package/dist/security/plugin-guard.js +230 -0
  96. package/dist/security/process-tree-evidence-store.js +74 -0
  97. package/dist/security/process-tree-probe.js +554 -0
  98. package/dist/security/project-resource-inventory.js +186 -0
  99. package/dist/security/project-trust-gate.js +38 -0
  100. package/dist/security/project-trust.js +367 -0
  101. package/dist/security/rule-parser.js +201 -0
  102. package/dist/security/shell-segmentation.js +68 -0
  103. package/dist/security/trust-authority.js +324 -0
  104. package/dist/security/types.js +1 -0
  105. package/dist/security/workspace-identity.js +102 -0
  106. package/dist/services/automation-facade.js +59 -0
  107. package/dist/services/forge-facade.js +77 -0
  108. package/dist/services/hook-facade.js +240 -0
  109. package/dist/services/index.js +16 -0
  110. package/dist/services/library-facade.js +174 -0
  111. package/dist/services/mcp-facade.js +348 -0
  112. package/dist/services/memory-facade.js +126 -0
  113. package/dist/services/notes-facade.js +157 -0
  114. package/dist/services/plugin-facade.js +308 -0
  115. package/dist/services/research-facade.js +110 -0
  116. package/dist/services/task-board-facade.js +236 -0
  117. package/dist/services/workflow-catalog.js +246 -0
  118. package/dist/sessions/export-format.js +98 -0
  119. package/dist/sessions/metadata-store.js +160 -0
  120. package/dist/sessions/share.js +122 -0
  121. package/dist/sessions/transfer.js +16 -0
  122. package/dist/subcommands.js +62 -0
  123. package/dist/tui/agent-roster.js +36 -0
  124. package/dist/tui/agent-view.js +51 -0
  125. package/dist/tui/app.js +4098 -0
  126. package/dist/tui/approval.js +36 -0
  127. package/dist/tui/boot/boot-sequence.js +76 -0
  128. package/dist/tui/boot/cinematic.js +243 -0
  129. package/dist/tui/boot/desktop-logo.js +82 -0
  130. package/dist/tui/boot.js +3 -0
  131. package/dist/tui/busy-input.js +58 -0
  132. package/dist/tui/catalog-service.js +560 -0
  133. package/dist/tui/components/assistant-stream.js +1 -0
  134. package/dist/tui/components/command-menu.js +68 -0
  135. package/dist/tui/components/composer.js +219 -0
  136. package/dist/tui/components/diff.js +35 -0
  137. package/dist/tui/components/footer.js +48 -0
  138. package/dist/tui/components/header.js +6 -0
  139. package/dist/tui/components/markdown.js +305 -0
  140. package/dist/tui/components/status-indicator.js +38 -0
  141. package/dist/tui/components/terminal-shell.js +214 -0
  142. package/dist/tui/components/thinking-row.js +19 -0
  143. package/dist/tui/components/tool-row.js +97 -0
  144. package/dist/tui/components/transcript-virtualizer.js +165 -0
  145. package/dist/tui/components/transcript.js +43 -0
  146. package/dist/tui/descendant-approvals.js +104 -0
  147. package/dist/tui/diff-model.js +77 -0
  148. package/dist/tui/editor-history.js +21 -0
  149. package/dist/tui/editor.js +210 -0
  150. package/dist/tui/event-adapter.js +436 -0
  151. package/dist/tui/exit-output.js +58 -0
  152. package/dist/tui/external-editor.js +53 -0
  153. package/dist/tui/file-completion.js +89 -0
  154. package/dist/tui/focus-manager.js +5 -0
  155. package/dist/tui/highlight.js +30 -0
  156. package/dist/tui/input-router.js +18 -0
  157. package/dist/tui/interrupt.js +99 -0
  158. package/dist/tui/keybindings.js +194 -0
  159. package/dist/tui/keymap-resolver.js +91 -0
  160. package/dist/tui/launch-state.js +148 -0
  161. package/dist/tui/line-diff.js +57 -0
  162. package/dist/tui/live-activity.js +56 -0
  163. package/dist/tui/metrics.js +123 -0
  164. package/dist/tui/onboarding.js +36 -0
  165. package/dist/tui/overlays/agent-tree.js +43 -0
  166. package/dist/tui/overlays/approval-dialog.js +642 -0
  167. package/dist/tui/overlays/automation-center.js +51 -0
  168. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  169. package/dist/tui/overlays/context-inspector.js +36 -0
  170. package/dist/tui/overlays/effort-line.js +110 -0
  171. package/dist/tui/overlays/forge-center.js +46 -0
  172. package/dist/tui/overlays/help-dialog.js +16 -0
  173. package/dist/tui/overlays/history-picker.js +37 -0
  174. package/dist/tui/overlays/hook-center.js +70 -0
  175. package/dist/tui/overlays/library-center.js +55 -0
  176. package/dist/tui/overlays/mcp-center.js +60 -0
  177. package/dist/tui/overlays/memory-center.js +63 -0
  178. package/dist/tui/overlays/model-picker.js +77 -0
  179. package/dist/tui/overlays/notes-center.js +53 -0
  180. package/dist/tui/overlays/overlay-host.js +8 -0
  181. package/dist/tui/overlays/plugin-center.js +76 -0
  182. package/dist/tui/overlays/provider-picker.js +171 -0
  183. package/dist/tui/overlays/queue-editor.js +32 -0
  184. package/dist/tui/overlays/research-center.js +59 -0
  185. package/dist/tui/overlays/scroll-window.js +234 -0
  186. package/dist/tui/overlays/session-picker.js +115 -0
  187. package/dist/tui/overlays/tasks-center.js +83 -0
  188. package/dist/tui/overlays/theme-picker.js +21 -0
  189. package/dist/tui/overlays/transcript-search.js +58 -0
  190. package/dist/tui/overlays/trust-center.js +29 -0
  191. package/dist/tui/overlays/workflow-center.js +46 -0
  192. package/dist/tui/project-file-index.js +214 -0
  193. package/dist/tui/project-references.js +85 -0
  194. package/dist/tui/project-trust-prompt.js +289 -0
  195. package/dist/tui/prompt-history-store.js +116 -0
  196. package/dist/tui/queue-store.js +110 -0
  197. package/dist/tui/regions/budget.js +59 -0
  198. package/dist/tui/regions/views.js +96 -0
  199. package/dist/tui/render-coordinator.js +148 -0
  200. package/dist/tui/render-scheduler.js +4 -0
  201. package/dist/tui/run.js +69 -0
  202. package/dist/tui/selection-list.js +29 -0
  203. package/dist/tui/session-controller.js +791 -0
  204. package/dist/tui/session-export.js +54 -0
  205. package/dist/tui/setup-wizard.js +46 -0
  206. package/dist/tui/shell-input.js +35 -0
  207. package/dist/tui/shell-layout.js +48 -0
  208. package/dist/tui/shell-model.js +98 -0
  209. package/dist/tui/slash-commands.js +82 -0
  210. package/dist/tui/state.js +151 -0
  211. package/dist/tui/status-bar.js +125 -0
  212. package/dist/tui/status-view.js +40 -0
  213. package/dist/tui/terminal-capabilities.js +9 -0
  214. package/dist/tui/terminal-session.js +11 -0
  215. package/dist/tui/text-width.js +66 -0
  216. package/dist/tui/theme-catalog.js +27 -0
  217. package/dist/tui/theme-store.js +23 -0
  218. package/dist/tui/theme.js +23 -0
  219. package/dist/tui/tool-display.js +135 -0
  220. package/dist/tui/tool-facts.js +1 -0
  221. package/dist/tui/tools/bash-renderer.js +32 -0
  222. package/dist/tui/tools/change.js +61 -0
  223. package/dist/tui/tools/edit-renderer.js +17 -0
  224. package/dist/tui/tools/generic-renderer.js +13 -0
  225. package/dist/tui/tools/list-renderer.js +14 -0
  226. package/dist/tui/tools/read-renderer.js +13 -0
  227. package/dist/tui/tools/registry.js +20 -0
  228. package/dist/tui/tools/row-format.js +187 -0
  229. package/dist/tui/tools/search-renderer.js +38 -0
  230. package/dist/tui/tools/shared.js +97 -0
  231. package/dist/tui/tools/write-renderer.js +15 -0
  232. package/dist/tui/transcript-model.js +441 -0
  233. package/dist/tui/ui-preferences.js +79 -0
  234. package/dist/tui/usage-view.js +77 -0
  235. package/dist/tui/vim-mode.js +99 -0
  236. package/dist/update/check.js +15 -0
  237. package/dist/update/npm.js +51 -0
  238. package/dist/update/run.js +129 -0
  239. package/dist/version.js +2 -0
  240. package/dist/workspace/checkpoint-store.js +210 -0
  241. package/dist/workspace/checkpoint.js +413 -0
  242. package/dist/workspace/restore.js +232 -0
  243. package/package.json +64 -5
  244. package/vendor/context-engine/package.json +11 -0
  245. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  246. package/vendor/context-engine/src/contracts.mjs +48 -0
  247. package/vendor/context-engine/src/engine.mjs +445 -0
  248. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  249. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  250. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  251. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  252. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  253. package/vendor/context-engine/src/profiles.mjs +10 -0
  254. package/vendor/context-engine/src/retrieval.mjs +104 -0
  255. package/vendor/context-engine/src/summary.mjs +97 -0
  256. package/vendor/context-engine/src/usage.mjs +34 -0
  257. package/vendor/harness-ui/package.json +38 -0
  258. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  259. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  260. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  261. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  262. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  263. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  264. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  265. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  266. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  267. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  268. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  269. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  270. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  271. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  272. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  273. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  274. package/vendor/harness-ui/src/config.mjs +697 -0
  275. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  276. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  277. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  278. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  279. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  280. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  281. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  282. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  283. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  284. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  285. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  286. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  287. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  288. package/vendor/harness-ui/src/doctor.mjs +142 -0
  289. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  290. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  291. package/vendor/harness-ui/src/document-report.mjs +331 -0
  292. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  293. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  294. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  295. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  296. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  297. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  298. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  299. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  300. package/vendor/harness-ui/src/git-service.mjs +626 -0
  301. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  302. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  303. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  304. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  305. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  306. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  307. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  308. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  309. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  310. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  311. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  312. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  313. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  314. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  315. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  316. package/vendor/harness-ui/src/library-store.mjs +652 -0
  317. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  318. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  319. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  320. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  321. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  322. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  323. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  324. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  325. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  326. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  327. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  328. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  329. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  330. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  331. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  332. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  333. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  334. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  335. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  336. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  337. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  338. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  339. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  340. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  341. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  342. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  343. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  344. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  345. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  346. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  347. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  348. package/vendor/harness-ui/src/research/card.mjs +235 -0
  349. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  350. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  351. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  352. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  353. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  354. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  355. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  356. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  357. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  358. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  359. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  360. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  361. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  362. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  363. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  364. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  365. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  366. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  367. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  368. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  369. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  370. package/vendor/harness-ui/src/research/report.mjs +203 -0
  371. package/vendor/harness-ui/src/research/run.mjs +527 -0
  372. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  373. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  374. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  375. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  376. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  377. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  378. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  379. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  380. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  381. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  382. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  383. package/vendor/harness-ui/src/session-store.mjs +220 -0
  384. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  385. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  386. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  387. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  388. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  389. package/vendor/harness-ui/src/static-files.mjs +96 -0
  390. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  391. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  392. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  393. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  394. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  395. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  396. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  397. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  398. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  399. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  400. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  401. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  402. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  403. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  404. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  405. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  406. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  407. package/vendor/manifest.json +170 -0
@@ -0,0 +1,54 @@
1
+ /*
2
+ * R5b D1 (owner decision Q-R5-12): `/export [md|json|jsonl] [file]` in the TUI. Markdown by default (the readable form of
3
+ * sessions/export-format.ts: the person's messages, TALOS's answers, tools in English); JSON and JSONL are the kernel's own
4
+ * rows. With no file, `talos-session-<first 8 of the id>-<YYYYMMDD-HHMM>.<ext>` in the project folder; a relative file is
5
+ * taken from the project folder. Secrets are redacted in every format.
6
+ */
7
+ import { mkdir, writeFile } from 'node:fs/promises';
8
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
9
+ import { createRedactor } from "../diagnostics/redact.js";
10
+ import { exportMarkdown } from "../sessions/export-format.js";
11
+ const FORMATS = ['md', 'json', 'jsonl'];
12
+ /** `/export` arguments: a format word and/or a file, in any order; `format:null` for a word that is not a format or file. */
13
+ export function parseExportArgs(args) {
14
+ let format = null, file = null;
15
+ for (const arg of args) {
16
+ const word = arg.toLowerCase();
17
+ if (FORMATS.includes(word) && format === null) {
18
+ format = word;
19
+ continue;
20
+ }
21
+ if (/[\\/.]/u.test(arg) && file === null) {
22
+ file = arg;
23
+ continue;
24
+ }
25
+ return { format: null, file: null };
26
+ }
27
+ if (format === null && file) {
28
+ const ext = /\.(md|json|jsonl)$/iu.exec(file)?.[1]?.toLowerCase();
29
+ format = ext ?? 'md';
30
+ }
31
+ return { format: format ?? 'md', file };
32
+ }
33
+ const pad = (n) => String(n).padStart(2, '0');
34
+ function defaultName(sessionId, format, now) {
35
+ const stamp = `${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}-${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}`;
36
+ return `talos-session-${sessionId.slice(0, 8)}-${stamp}.${format}`;
37
+ }
38
+ export async function exportSession({ runtime, sessionId, projectRoot, args, now = new Date(), secrets }) {
39
+ const { format, file } = parseExportArgs(args);
40
+ if (!format)
41
+ throw Object.assign(new Error('EXPORT_USAGE'), { code: 'EXPORT_USAGE' });
42
+ const payload = sessionId ? runtime.export(sessionId) : null;
43
+ if (!sessionId || !payload)
44
+ throw Object.assign(new Error('SESSION_NOT_FOUND'), { code: 'SESSION_NOT_FOUND' });
45
+ const redactor = createRedactor(secrets);
46
+ const events = Array.isArray(payload.eventi) ? payload.eventi : [];
47
+ const body = format === 'md' ? exportMarkdown(payload, { secrets })
48
+ : format === 'json' ? `${JSON.stringify(redactor.value(payload), null, 2)}\n`
49
+ : events.map(event => JSON.stringify(redactor.value(event))).join('\n') + (events.length ? '\n' : '');
50
+ const target = file ? (isAbsolute(file) ? file : resolve(projectRoot, file)) : join(projectRoot, defaultName(sessionId, format, now));
51
+ await mkdir(dirname(target), { recursive: true });
52
+ await writeFile(target, body, 'utf8');
53
+ return { path: target, format };
54
+ }
@@ -0,0 +1,46 @@
1
+ /*
2
+ * P17 (owner, 2026-09-25: "mini procedura guidata semplicissima al fresh install"; decisions of 2026-09-26). The first launch
3
+ * chains the windows that already exist: trust (the screen before anything loads) → provider → key or local engine → model,
4
+ * one window at a time with "Step N of 4"; Enter goes on, Esc skips the step, Ctrl+C quits, and what was done stays saved.
5
+ * Only the missing steps run: a key already usable (from the environment too) or a local engine that answers skips them; a
6
+ * credential that exists but is benched is explained by the first frame's line, not asked again (Hermes #113720).
7
+ * Read on 2026-09-26: Claude Code (welcome, theme, login, security notes, terminal setup, trust), Codex (welcome, auth,
8
+ * trust), Hermes (provider + model through the same picker as `hermes model`, skippable, `hermes setup` to redo), Pi (theme
9
+ * and analytics, providers later), OpenCode (no wizard), Gemini CLI (theme, then auth). `/setup` redoes it (Hermes'
10
+ * `hermes setup`). Without an interactive terminal it never runs (clig.dev: "never require a prompt").
11
+ */
12
+ import { t } from "../i18n/index.js";
13
+ export const SETUP_TOTAL = 4;
14
+ const INDEX = { trust: 1, provider: 2, key: 3, model: 4 };
15
+ const NAME = { trust: 'firstrun.setup.stepName.trust', provider: 'firstrun.setup.stepName.provider', key: 'firstrun.setup.stepName.key', model: 'firstrun.setup.stepName.model' };
16
+ /** The line that tells where the person is in the setup; `escSkips:false` when Esc does something else there. */
17
+ export function setupStepLine(step, { escSkips = true } = {}) {
18
+ return t(escSkips ? 'firstrun.setup.stepLine' : 'firstrun.setup.stepLineOnly', { index: INDEX[step], total: SETUP_TOTAL, name: t(NAME[step]) });
19
+ }
20
+ /** The same window, with the setup's step on top (the window's own title stays under it). */
21
+ export function setupOverlay(content, step, options = {}) {
22
+ return { ...content, head: [{ text: setupStepLine(step, options), tone: 'title' }, ...(content.head ?? [])] };
23
+ }
24
+ /**
25
+ * Whether the first launch runs the setup, and from which step. `providerUsable`: the chosen provider has a key usable now
26
+ * (from the environment too) or needs none; `keyBenched`: it has a key that does not work now (explained, not asked again).
27
+ */
28
+ export function setupStart(input) {
29
+ if (!input.firstLaunch)
30
+ return { start: false };
31
+ if (!input.providerChosen)
32
+ return { start: true, from: 'provider' };
33
+ if (input.keyBenched)
34
+ return { start: false };
35
+ if (!input.providerUsable)
36
+ return { start: true, from: 'key' };
37
+ if (!input.modelChosen)
38
+ return { start: true, from: 'model' };
39
+ return { start: false };
40
+ }
41
+ /** What the setup says when it ends: ready with the model, or where to pick it up again. */
42
+ export function setupEndLines(outcome) {
43
+ if (!outcome.ready)
44
+ return [t('firstrun.setup.skipped')];
45
+ return [t('firstrun.setup.ready', { model: outcome.model }), t('firstrun.setup.readyHints')];
46
+ }
@@ -0,0 +1,35 @@
1
+ import { routeInput } from "./input-router.js";
2
+ /*
3
+ * R4 Q-R4-4 (owner, 2026-09-24): a key pressed while the boot is on screen.
4
+ * - Space, Enter and Esc only skip: the person asked for the composer, not for a space, a send or an interrupt. Measured before
5
+ * R4: the key that skipped the boot was also typed into the composer (`│> x`, gate §0.5).
6
+ * - A printable key skips AND stays as type-ahead, also before the runtime is ready (Codex keeps startup drafts, openai/codex
7
+ * #46750, 2026-09-20). Once the boot is skipped and TALOS still waits for the runtime, a space is part of what is typed.
8
+ * - Ctrl+C and Ctrl+D always reach the exit rule (interrupt.ts): the way out is never blocked by the boot.
9
+ * - Any other key skips; it is routed only once the runtime is ready, as before R4 (an action before the runtime exists had
10
+ * nothing to act on). Enter while waiting sends nothing.
11
+ */
12
+ const CONTROL = /^[\x00-\x1f\x7f]/u;
13
+ function printable(ch, key) {
14
+ if (typeof ch !== 'string' || ch.length === 0 || CONTROL.test(ch))
15
+ return false;
16
+ return !key.ctrl && !key.meta && !key.return && !key.escape && !key.tab && !key.backspace && !key.delete
17
+ && !key.upArrow && !key.downArrow && !key.leftArrow && !key.rightArrow && !key.pageUp && !key.pageup && !key.pageDown && !key.pagedown && !key.home && !key.end;
18
+ }
19
+ export function decideShellInput(input) {
20
+ const { ch, key, focus, composerText, commandMenuOpen, trustCenterOpen, approvalExpanded, boot, keymap } = input;
21
+ const base = { skipBoot: false, closeTrustCenter: false, approvalScrollDelta: null, routed: null };
22
+ if (trustCenterOpen)
23
+ return { ...base, closeTrustCenter: Boolean(key.escape || key.return || ch.toLowerCase() === 'q') };
24
+ if (focus === 'approval' && approvalExpanded && (key.pageUp || key.pageup || key.pageDown || key.pagedown || key.upArrow || key.downArrow)) {
25
+ const delta = (key.pageDown || key.pagedown) ? 4 : (key.pageUp || key.pageup) ? -4 : key.downArrow ? 1 : -1;
26
+ return { ...base, approvalScrollDelta: delta };
27
+ }
28
+ const lower = typeof ch === 'string' ? ch.toLowerCase() : '';
29
+ const exitKey = Boolean(key.ctrl && (lower === 'c' || lower === 'd'));
30
+ const onlySkips = !boot.skipped && Boolean(key.return || key.escape || ch === ' ');
31
+ const bootActive = boot.phase !== 'ready' && boot.phase !== 'error';
32
+ const skipBoot = bootActive && !boot.skipped;
33
+ const forwarded = !bootActive || exitKey || (!onlySkips && (printable(ch, key) || boot.runtimeReady));
34
+ return { ...base, skipBoot, routed: forwarded ? routeInput({ ch, key, focus, composerText, commandMenuOpen, keymap }) : null };
35
+ }
@@ -0,0 +1,48 @@
1
+ import { assistantStreamView } from "./components/assistant-stream.js";
2
+ import { composerDisplay } from "./components/composer.js";
3
+ import { mainRosterLine, queueRosterLine, terminalShortcutStrip } from "./components/terminal-shell.js";
4
+ import { thinkingRowText } from "./components/thinking-row.js";
5
+ import { transcriptWindow } from "./components/transcript.js";
6
+ import { deriveLiveActivity } from "./live-activity.js";
7
+ import { queuedActionPreview } from "./shell-model.js";
8
+ import { statusBar } from "./status-bar.js";
9
+ export function shellDimensions(terminalRows, terminalColumns) {
10
+ const rows = Math.max(8, Number(terminalRows) - 15);
11
+ const columns = Math.max(20, Number(terminalColumns));
12
+ return { rows, columns, desiredPageSize: Math.max(4, Math.floor(rows / 2)) };
13
+ }
14
+ export function pickerWindow(rows, selected, size = 10) {
15
+ const start = Math.max(0, Math.min(Math.max(0, rows.length - size), selected - Math.floor(size / 2)));
16
+ return { start, rows: rows.slice(start, start + size) };
17
+ }
18
+ /*
19
+ * The chrome of one frame, Ink-free. R5a (lane S):
20
+ * - S1 (Q-R5-2): the last row is the status row — `Full access · No sandbox · model X · ↑in ↓out · ctx … · ~$… · cmp N ·
21
+ * N new` — from lane R's usage snapshot. Before R5a the footer held the workspace path and `session <uuid>` and the
22
+ * roster's right edge a context label that the context status had replaced (gate finding 1, review D-14).
23
+ * - S9 (D-14): the path stays in the header only, the session id is in /status and in the resume line at exit, the main
24
+ * roster row no longer repeats the model, and the activity row is shown only when it has something to say.
25
+ * - S5 (Q-R5-7): while a turn runs, the shortcut strip says what Enter does in the busy-input mode.
26
+ */
27
+ export function deriveShellLayout(input) {
28
+ const { state, appState, viewport, queuedActions, busySince, bullet, branch } = input;
29
+ const { rows, columns, desiredPageSize } = shellDimensions(input.terminalRows, input.terminalColumns);
30
+ const messages = transcriptWindow(state.messages, viewport);
31
+ const live = assistantStreamView(state.streamingAssistant);
32
+ const reasoning = thinkingRowText(state.reasoning?.text ?? '', appState.reasoningVisible);
33
+ const bar = statusBar({ snapshot: input.snapshot ?? null, model: state.status.model, width: columns, safety: input.safety ?? { fullAccess: false, noSandbox: false }, unseen: viewport.unseen });
34
+ const activity = deriveLiveActivity(state, busySince);
35
+ const visual = composerDisplay(appState.editor);
36
+ /* While the approval dialog is open Enter and Esc answer the dialog, so the busy line would be wrong: the R3 strip stays. */
37
+ const busyInput = input.busyInput && !state.waitingForPerson ? input.busyInput : null;
38
+ const shortcutLine = terminalShortcutStrip({ mode: state.status.permissionMode, running: state.running, queueCount: queuedActions.length, width: columns, ...(busyInput ? { busyInput } : {}) });
39
+ const rosterLine = mainRosterLine({ kind: activity.kind, model: null, width: columns, marker: bullet });
40
+ const queueLine = queueRosterLine({ count: queuedActions.length, preview: queuedActions[0] ? queuedActionPreview(queuedActions[0].text) : null, width: columns, marker: branch });
41
+ return {
42
+ rows, columns, desiredPageSize, messages, live, reasoning, statusBar: bar, footerLine: bar.text, activity,
43
+ showActivity: activity.kind !== 'idle' || input.exitHint === true,
44
+ visual, shortcutLine, rosterLine, queueLine,
45
+ toolRowsLimit: Math.max(2, Math.floor(rows / 3)),
46
+ pickerRowsLimit: Math.max(4, Math.min(12, rows - 4)),
47
+ };
48
+ }
@@ -0,0 +1,98 @@
1
+ import { t } from "../i18n/index.js";
2
+ import { formatPermissionSimulation, simulatePermission } from "../security/permission-explanation.js";
3
+ import { createEditorState, replaceRange } from "./editor.js";
4
+ import { permissionModeLabel } from "./components/terminal-shell.js";
5
+ import { closeFocus, createFocusState, focusForOverlay, openFocus } from "./focus-manager.js";
6
+ import { filterItems } from "./selection-list.js";
7
+ import { parseSlashCommand } from "./slash-commands.js";
8
+ import { statusFactLines } from "./status-view.js";
9
+ const QUEUE_TERMINAL_UNSAFE = /[\x00-\x1f\x7f-\x9f\u2028\u2029\p{Bidi_Control}\p{Default_Ignorable_Code_Point}]/gu;
10
+ export const MODEL_ID = /^[A-Za-z0-9._-]+:[A-Za-z0-9][A-Za-z0-9._/:@-]*$/u;
11
+ /* R2: sentinel values compared by identity AND shown on the status row, so they come from the dictionary once. */
12
+ export const NO_PROVIDER_MODEL = t('screen.model.noneProvider');
13
+ export const NO_MODEL = t('screen.model.noneModel');
14
+ export function queuedActionPreview(value) {
15
+ return String(value).replace(QUEUE_TERMINAL_UNSAFE, character => {
16
+ if (character === '\n' || character === '\r' || character === '\t')
17
+ return ' ';
18
+ const code = character.codePointAt(0);
19
+ return code > 0xffff ? `\\u{${code.toString(16)}}` : `\\u${code.toString(16).padStart(4, '0')}`;
20
+ }).replace(/\s{2,}/gu, ' ').trim();
21
+ }
22
+ export function openOverlay(state, overlay) {
23
+ return { ...state, overlay, focus: openFocus(state.focus, focusForOverlay(overlay.kind)) };
24
+ }
25
+ export function createTuiAppState(editor = createEditorState('')) { return { editor, overlay: null, focus: createFocusState('composer'), reasoningVisible: false, expandedTools: false, redrawNonce: 0 }; }
26
+ export function closeOverlay(state) { return { ...state, overlay: null, focus: closeFocus(state.focus) }; }
27
+ export function reduceAppAction(state, action) {
28
+ if (action.type === 'close-overlay')
29
+ return closeOverlay(state);
30
+ if (action.action === 'model-picker')
31
+ return openOverlay(state, { kind: 'model' });
32
+ if (action.action === 'provider-picker')
33
+ return openOverlay(state, { kind: 'provider' });
34
+ if (action.action === 'help')
35
+ return openOverlay(state, { kind: 'help' });
36
+ if (action.action === 'reasoning-toggle')
37
+ return { ...state, reasoningVisible: !state.reasoningVisible };
38
+ if (action.action === 'tool-details')
39
+ return { ...state, expandedTools: !state.expandedTools };
40
+ if (action.action === 'redraw')
41
+ return { ...state, redrawNonce: state.redrawNonce + 1 };
42
+ if (action.action === 'overlay-close' || action.action === 'picker-cancel')
43
+ return closeOverlay(state);
44
+ return state;
45
+ }
46
+ export function slashCommandIntent(text) {
47
+ const parsed = parseSlashCommand(text);
48
+ if (parsed.name === 'model')
49
+ return parsed.args[0] ? { kind: 'select-model', id: parsed.args[0] } : { kind: 'open-overlay', overlay: { kind: 'model' } };
50
+ if (parsed.name === 'help')
51
+ return { kind: 'open-overlay', overlay: { kind: 'help' } };
52
+ if (parsed.name === 'provider')
53
+ return { kind: 'open-overlay', overlay: { kind: 'provider' } };
54
+ if (parsed.name === 'resume' || parsed.name === 'fork')
55
+ return parsed.args[0] ? { kind: 'session-id', action: parsed.name, id: parsed.args[0] } : { kind: 'open-overlay', overlay: { kind: 'session', action: parsed.name } };
56
+ if (parsed.name === 'redraw')
57
+ return { kind: 'key-action', action: 'redraw' };
58
+ return null;
59
+ }
60
+ export function togglePlanMode(current, base) { return current === 'plan' ? (base === 'plan' ? 'default' : base) : 'plan'; }
61
+ export function permissionDryRunSlash(args, rules, projectRoot) {
62
+ if (args[0] !== 'dry-run')
63
+ return null;
64
+ const command = args.slice(1).join(' ').trim();
65
+ if (!command)
66
+ return t('screen.usage.permissionsDryRun');
67
+ return formatPermissionSimulation(simulatePermission({ rules, action: { tool: 'Bash', command }, projectRoot })).trimEnd();
68
+ }
69
+ const SLASH_CLI_FAMILY = { mcp: 'mcp', hooks: 'hook', plugins: 'plugin', doctor: 'doctor', memory: 'memory', notes: 'notes', tasks: 'tasks', library: 'library', research: 'research', automations: 'automation', forge: 'forge' };
70
+ export function slashCommandToCliArgs(name, args) { const family = SLASH_CLI_FAMILY[name]; if (!family)
71
+ return null; const out = [family, ...args]; if (args.length === 0 && name !== 'doctor')
72
+ out.push('list'); return out; }
73
+ export function pickerMove(action) {
74
+ if (action === 'picker-up')
75
+ return 'up';
76
+ if (action === 'picker-down')
77
+ return 'down';
78
+ if (action === 'picker-page-up')
79
+ return 'page-up';
80
+ if (action === 'picker-page-down')
81
+ return 'page-down';
82
+ if (action === 'picker-home')
83
+ return 'home';
84
+ if (action === 'picker-end')
85
+ return 'end';
86
+ return null;
87
+ }
88
+ export function modelItems(rows, query) { return filterItems(rows.map(row => ({ id: row.id, label: row.name, searchText: `${row.id} ${row.name} ${row.provider}`, group: row.provider, value: row })), query).map(item => item.value); }
89
+ export function providerItems(rows, query) { return filterItems(rows.map(row => ({ id: row.id, label: row.label, searchText: `${row.id} ${row.label} ${row.description}`, group: row.local ? 'local' : 'cloud', value: row })), query).map(item => item.value); }
90
+ export function lastProjectToken(text) { const match = /(?:^|\s)(@[^\s]*)$/u.exec(text); return match?.[1] ?? null; }
91
+ /* R4: the token is replaced in place, so a collapsed paste earlier in the draft stays collapsed and Ctrl+Z undoes it. */
92
+ export function replaceLastProjectToken(state, token, value) { const start = state.text.lastIndexOf(token); return start < 0 ? state : replaceRange(state, start, start + token.length, value); }
93
+ /* R4 Q-R4-13: /status as a small titled block, the permission mode in words (Q-R4-12), an honest line with no session. */
94
+ /* R5b D7 (Q-R5-17): with `facts`, the R4 block is followed by the sandbox, rules, work and usage lines (status-view.ts). */
95
+ export function sessionStatusText({ session, running, model, mode, tools, facts }) {
96
+ const block = t('screen.status.block', { session: session ?? t('screen.status.noSession'), running: t(running ? 'screen.word.yes' : 'screen.word.no'), model, mode: t('screen.status.mode', { mode: permissionModeLabel(mode) }), tools });
97
+ return facts ? [block, ...statusFactLines(facts)].join('\n') : block;
98
+ }
@@ -0,0 +1,82 @@
1
+ import { t } from "../i18n/index.js";
2
+ const SLASH_COMMAND_META = [
3
+ { name: 'help', usage: '' },
4
+ { name: 'provider', usage: '' },
5
+ /* P17 (owner decision 4): the first launch's guided setup, again. */
6
+ { name: 'setup', usage: '' },
7
+ { name: 'model', usage: '[provider:model]' },
8
+ /* R5a (owner 2026-09-24): the reasoning effort of the current model, as a line of nodes. */
9
+ { name: 'effort', usage: '[level]' },
10
+ { name: 'queue', usage: '[show|clear|run]' },
11
+ /* R5a (Q-R5-7, Q-R5-19): what Enter does while TALOS works. */
12
+ { name: 'busy', usage: '[queue|steer|interrupt]' },
13
+ { name: 'permissions', usage: t('screen.slash.permissionsUsage') },
14
+ { name: 'plan', usage: '' },
15
+ { name: 'diff', usage: '' },
16
+ { name: 'status', usage: '' },
17
+ { name: 'context', usage: '' },
18
+ /* R5a (Q-R5-2, Q-R5-8, Q-R5-19): tokens, window, cost and compactions; a view, it runs at once during a turn. */
19
+ { name: 'usage', usage: '' },
20
+ { name: 'compact', usage: '' },
21
+ { name: 'clear', usage: '' },
22
+ { name: 'redraw', usage: '' },
23
+ { name: 'resume', usage: '[session-id]' },
24
+ { name: 'fork', usage: '[session-id]' },
25
+ /* R5b D1 (Q-R5-12): this conversation to a file. */
26
+ { name: 'export', usage: '[md|json|jsonl] [file]' },
27
+ { name: 'rename', usage: '<name>' },
28
+ /* R5b D4 (Q-R5-14): the ten product themes and mono, previewed live. */
29
+ { name: 'theme', usage: '[name]' },
30
+ /* R5b D3 (Q-R5-13): this conversation's checkpoints, with their files; /rewind and /checkpoint are the same command. */
31
+ { name: 'undo', usage: '' },
32
+ /* R5b (Q-R5-19): send the last message again; copy an answer (Hermes /retry, Claude Code and Hermes /copy). */
33
+ { name: 'retry', usage: '' },
34
+ { name: 'copy', usage: '[n]' },
35
+ /* R5b (owner 2026-09-25): the messages you sent in this project, to put one back in the composer. */
36
+ { name: 'history', usage: '' },
37
+ { name: 'mcp', usage: '[list|test|trust|untrust] [server-id]' },
38
+ { name: 'hooks', usage: '[list|dry-run|history|trust|untrust|quarantine|release] [hook-id] [args...]' },
39
+ { name: 'plugins', usage: '[list|install|remove|trust|untrust|quarantine|release] [plugin-id] [args...]' },
40
+ { name: 'doctor', usage: '[args...]' },
41
+ { name: 'memory', usage: '[args...]' },
42
+ { name: 'notes', usage: '[args...]' },
43
+ { name: 'tasks', usage: '[args...]' },
44
+ { name: 'library', usage: '[args...]' },
45
+ { name: 'research', usage: '[args...]' },
46
+ { name: 'automations', usage: '[args...]' },
47
+ { name: 'forge', usage: '[args...]' },
48
+ { name: 'exit', usage: '' },
49
+ ];
50
+ /* R2 (Q-R2-1, gate E1): the descriptions are dictionary words; a later locale overlays the dictionary, not this file. */
51
+ export function slashCommandDescription(name) { return t(`screen.slash.${name}`); }
52
+ export const SLASH_COMMANDS = SLASH_COMMAND_META.map(row => ({
53
+ name: row.name,
54
+ usage: row.usage,
55
+ description: slashCommandDescription(row.name),
56
+ }));
57
+ const SLASH_GROUPS = ['session', 'turn', 'view', 'work', 'extensions'];
58
+ const GROUP_OF = {
59
+ resume: 'session', fork: 'session', rename: 'session', export: 'session', undo: 'session', history: 'session', clear: 'session', compact: 'session', exit: 'session',
60
+ provider: 'turn', setup: 'turn', model: 'turn', effort: 'turn', busy: 'turn', queue: 'turn', retry: 'turn', plan: 'turn', permissions: 'turn',
61
+ help: 'view', status: 'view', context: 'view', usage: 'view', diff: 'view', copy: 'view', theme: 'view', redraw: 'view',
62
+ memory: 'work', notes: 'work', tasks: 'work', library: 'work', research: 'work', automations: 'work', forge: 'work',
63
+ mcp: 'extensions', hooks: 'extensions', plugins: 'extensions', doctor: 'extensions',
64
+ };
65
+ export function slashCommandGroup(name) { return GROUP_OF[name]; }
66
+ export function slashCommandHelp() {
67
+ return SLASH_GROUPS.map(group => t(`screen.help.group.${group}`) + '\n' + SLASH_COMMANDS.filter(command => GROUP_OF[command.name] === group).map(command => {
68
+ const usage = command.usage ? ' ' + command.usage : '';
69
+ return ' /' + command.name + usage + ' — ' + slashCommandDescription(command.name);
70
+ }).join('\n')).join('\n\n');
71
+ }
72
+ function distance(a, b) { const d = Array.from({ length: a.length + 1 }, () => Array(b.length + 1).fill(0)); for (let i = 0; i <= a.length; i++)
73
+ d[i][0] = i; for (let j = 0; j <= b.length; j++)
74
+ d[0][j] = j; for (let i = 1; i <= a.length; i++)
75
+ for (let j = 1; j <= b.length; j++)
76
+ d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)); return d[a.length][b.length]; }
77
+ /* R5b D3 (Q-R5-13): other names for a command (Claude Code's /rewind aliases); the parsed name is the command's own. */
78
+ const SLASH_ALIASES = Object.freeze({ rewind: 'undo', checkpoint: 'undo' });
79
+ export function parseSlashCommand(text) { const parts = text.trim().replace(/^\//u, '').split(/\s+/u).filter(Boolean); const typed = parts.shift() ?? ''; const name = SLASH_ALIASES[typed] ?? typed; const known = SLASH_COMMANDS.some(x => x.name === name); const suggestions = known ? [] : SLASH_COMMANDS.map(x => ({ n: x.name, d: distance(name, x.name) })).filter(x => x.d <= Math.max(2, Math.floor(name.length / 3))).sort((a, b) => a.d - b.d || a.n.localeCompare(b.n)).slice(0, 3).map(x => x.n); return { name, args: parts, suggestions }; }
80
+ export function completeSlashCommand(text) { if (!text.startsWith('/'))
81
+ return []; const raw = text.slice(1); if (/\s/u.test(raw))
82
+ return []; return SLASH_COMMANDS.map(x => '/' + x.name).filter(x => x.startsWith('/' + raw)).sort((a, b) => a.localeCompare(b)); }
@@ -0,0 +1,151 @@
1
+ import { t, tn } from "../i18n/index.js";
2
+ import { toolDisplay } from "./tool-display.js";
3
+ import { createTranscriptModel, reduceTranscriptEvent } from "./transcript-model.js";
4
+ const MAX_RENDER_MESSAGES = 512;
5
+ const MAX_RENDER_TOOLS = 256;
6
+ const MAX_RENDER_WARNINGS = 128;
7
+ const MAX_MESSAGE_CHARS = 256 * 1024;
8
+ const MAX_TOOL_SUMMARY_CHARS = 8 * 1024;
9
+ const MAX_WARNING_CHARS = 2048;
10
+ function tail(value, limit) { if (value.length <= limit)
11
+ return value; return `${t('screen.state.truncated')}\n${value.slice(-(limit - 22))}`; }
12
+ export function initialTuiState(x) { return { sessionId: null, running: false, sentAt: null, waitingForPerson: false, lastTurn: null, turnStartedAt: null, retry: null, compactions: 0, messages: [], streamingAssistant: null, reasoning: null, tools: [], approval: null, usage: null, warnings: [], transcript: createTranscriptModel(), status: { model: x.model, permissionMode: x.permissionMode, branch: null, contextLabel: null } }; }
13
+ function finalizeStreaming(state, messageId) {
14
+ const live = state.streamingAssistant;
15
+ if (!live || live.id !== messageId)
16
+ return state;
17
+ const base = state.messages.length >= MAX_RENDER_MESSAGES ? state.messages.slice(-(MAX_RENDER_MESSAGES - 1)) : state.messages;
18
+ return { ...state, streamingAssistant: null, messages: [...base, { id: live.id, role: 'assistant', text: tail(live.text, MAX_MESSAGE_CHARS) }] };
19
+ }
20
+ function endTurn(state, outcome) {
21
+ return { sentAt: null, waitingForPerson: false, retry: null, lastTurn: { outcome, durationMs: state.turnStartedAt === null ? (state.lastTurn?.durationMs ?? null) : Math.max(0, Date.now() - state.turnStartedAt) }, turnStartedAt: null };
22
+ }
23
+ function activeToolStatus(status) { return status === 'queued' || status === 'approval' || status === 'running' || status === 'streaming'; }
24
+ function closeRunningTools(state, status = 'cancelled') { return state.tools.map(row => activeToolStatus(row.status) ? { ...row, status, endedAt: row.endedAt ?? Date.now() } : row); }
25
+ const whole = (value, fallback = null) => typeof value === 'number' && Number.isFinite(value) && value >= 0 ? Math.floor(value) : fallback;
26
+ /* The model answered again: a retry, if any, is over (message, reasoning or a tool call). */
27
+ const PROGRESS = new Set(['message.started', 'message.delta', 'reasoning.started', 'reasoning.delta', 'tool.started']);
28
+ export function reduceTuiEvent(state, event) {
29
+ state = { ...state, transcript: reduceTranscriptEvent(state.transcript, event) };
30
+ if (event.type === 'provider.attempt') {
31
+ const attempt = whole(event.attempt, 1), maxAttempts = Math.max(attempt, whole(event.maxAttempts, attempt));
32
+ return { ...state, retry: { attempt, maxAttempts, status: whole(event.status), retryAfterMs: whole(event.retryAfterMs), waitMs: whole(event.waitMs), at: Date.now() } };
33
+ }
34
+ if (state.retry && PROGRESS.has(event.type))
35
+ state = { ...state, retry: null };
36
+ if (event.type === 'context.compacted')
37
+ return { ...state, compactions: (state.compactions ?? 0) + 1 };
38
+ if (event.type === 'run.started')
39
+ return { ...state, sessionId: event.sessionId || state.sessionId, running: true, sentAt: null, lastTurn: null, turnStartedAt: Date.now(), retry: null };
40
+ if (event.type === 'message.started') {
41
+ if (event.role !== 'assistant')
42
+ return state;
43
+ const live = state.streamingAssistant, next = live && live.id !== event.messageId ? finalizeStreaming(state, live.id) : state;
44
+ return next.streamingAssistant?.id === event.messageId ? next : { ...next, streamingAssistant: { id: event.messageId, text: '' } };
45
+ }
46
+ if (event.type === 'message.delta') {
47
+ const live = state.streamingAssistant;
48
+ if (live?.id === event.messageId)
49
+ return { ...state, streamingAssistant: { ...live, text: tail(live.text + event.delta, MAX_MESSAGE_CHARS) } };
50
+ const next = live ? finalizeStreaming(state, live.id) : state;
51
+ return { ...next, streamingAssistant: { id: event.messageId, text: tail(event.delta, MAX_MESSAGE_CHARS) } };
52
+ }
53
+ if (event.type === 'message.end')
54
+ return finalizeStreaming(state, event.messageId);
55
+ if (event.type === 'reasoning.started')
56
+ return state.reasoning?.id === event.messageId ? state : { ...state, reasoning: { id: event.messageId, text: '' } };
57
+ if (event.type === 'reasoning.delta') {
58
+ const current = state.reasoning;
59
+ return { ...state, reasoning: current?.id === event.messageId ? { ...current, text: tail(current.text + event.delta, MAX_MESSAGE_CHARS) } : { id: event.messageId, text: tail(event.delta, MAX_MESSAGE_CHARS) } };
60
+ }
61
+ if (event.type === 'reasoning.end')
62
+ return state.reasoning?.id === event.messageId ? { ...state, reasoning: null } : state;
63
+ if (event.type === 'tool.started') {
64
+ const row = { id: event.toolCallId, name: event.toolName, status: 'queued', argsText: '', liveOutput: '', finalOutput: '', startedAt: Date.now(), endedAt: null, outcome: null };
65
+ const existing = state.tools.findIndex(x => x.id === event.toolCallId);
66
+ if (existing >= 0) {
67
+ const tools = state.tools.slice();
68
+ tools[existing] = row;
69
+ return { ...state, tools };
70
+ }
71
+ return { ...state, tools: [...state.tools.slice(-(MAX_RENDER_TOOLS - 1)), row] };
72
+ }
73
+ if (event.type === 'tool.args')
74
+ return { ...state, tools: state.tools.map(row => row.id === event.toolCallId ? { ...row, argsText: tail(row.argsText + event.delta, MAX_TOOL_SUMMARY_CHARS) } : row) };
75
+ if (event.type === 'tool.output')
76
+ return { ...state, tools: state.tools.map(row => row.id === event.toolCallId && activeToolStatus(row.status) ? { ...row, status: 'streaming', liveOutput: tail(row.liveOutput + event.delta, MAX_TOOL_SUMMARY_CHARS) } : row) };
77
+ if (event.type === 'tool.completed')
78
+ return { ...state, tools: state.tools.map(row => row.id === event.toolCallId ? { ...row, status: event.outcome?.status ?? 'completed', finalOutput: tail(event.content, MAX_TOOL_SUMMARY_CHARS), endedAt: Date.now(), outcome: event.outcome ?? null } : row) };
79
+ if (event.type === 'approval.required') {
80
+ /* R2 (gate E3): the tool is named by lane T's display table, never by its kernel name (`scrivi`, `shell`). */
81
+ const p = event.payload;
82
+ const tool = p.tool ?? p.tipo;
83
+ const label = tool ? toolDisplay(String(tool)).label : t('screen.approval.label');
84
+ const detail = String(p.command ?? p.comando ?? p.resource ?? p.percorso ?? p.path ?? '');
85
+ const toolCallId = event.toolCallId ?? null;
86
+ return { ...state, tools: toolCallId ? state.tools.map(row => row.id === toolCallId && activeToolStatus(row.status) ? { ...row, status: 'approval' } : row) : state.tools, approval: { requestId: event.requestId, label, detail, payload: p, toolCallId } };
87
+ }
88
+ if (event.type === 'approval.resolved') {
89
+ const approval = state.approval;
90
+ if (!approval || approval.requestId !== event.requestId)
91
+ return state;
92
+ const tools = approval.toolCallId ? state.tools.map(row => {
93
+ if (row.id !== approval.toolCallId || !activeToolStatus(row.status))
94
+ return row;
95
+ if (event.approved === true)
96
+ return { ...row, status: 'running' };
97
+ if (event.approved === false)
98
+ return { ...row, status: 'failed', endedAt: row.endedAt ?? Date.now() };
99
+ return row;
100
+ }) : state.tools;
101
+ return { ...state, tools, approval: null };
102
+ }
103
+ if (event.type === 'usage.updated')
104
+ return { ...state, usage: event.value, status: { ...state.status, contextLabel: usageLabel(event.value) } };
105
+ if (event.type === 'warning')
106
+ return { ...state, warnings: [...state.warnings.slice(-(MAX_RENDER_WARNINGS - 1)), tail(event.message, MAX_WARNING_CHARS)] };
107
+ if (event.type === 'run.cancelled')
108
+ return { ...state, ...endTurn(state, 'interrupted'), running: false, approval: null, streamingAssistant: null, reasoning: null, tools: closeRunningTools(state, 'cancelled') };
109
+ if (event.type === 'run.failed')
110
+ return { ...state, ...endTurn(state, 'failed'), running: false, approval: null, streamingAssistant: null, reasoning: null, tools: closeRunningTools(state, 'failed'), warnings: [...state.warnings.slice(-(MAX_RENDER_WARNINGS - 1)), tail(event.message, MAX_WARNING_CHARS)] };
111
+ if (event.type === 'run.completed') {
112
+ const finalized = state.streamingAssistant ? finalizeStreaming(state, state.streamingAssistant.id) : state;
113
+ return { ...finalized, ...endTurn(state, 'done'), running: false, approval: null, reasoning: null };
114
+ }
115
+ return state;
116
+ }
117
+ function usageLabel(value) { if (!value || typeof value !== 'object')
118
+ return null; const row = value; const prompt = numberValue(row.prompt_tokens ?? row.promptTokens ?? row.input_tokens ?? row.inputTokens); const completion = numberValue(row.completion_tokens ?? row.completionTokens ?? row.output_tokens ?? row.outputTokens); if (prompt === null && completion === null)
119
+ return null; return `${prompt ?? 0}+${completion ?? 0}`; }
120
+ function numberValue(value) { return typeof value === 'number' && Number.isFinite(value) ? value : null; }
121
+ function objectValue(value) { return value && typeof value === 'object' && !Array.isArray(value) ? value : null; }
122
+ function firstMeasuredNumber(...values) { for (const value of values) {
123
+ const measured = numberValue(value);
124
+ if (measured !== null)
125
+ return measured;
126
+ } return null; }
127
+ export function reasoningUsageEvidence(value) {
128
+ const row = objectValue(value);
129
+ if (!row)
130
+ return { reasoningTokens: null, reasoningCostUsd: null };
131
+ const completion = objectValue(row.completion_tokens_details ?? row.completionTokensDetails);
132
+ const output = objectValue(row.output_tokens_details ?? row.outputTokensDetails);
133
+ const reasoning = objectValue(row.reasoning);
134
+ return {
135
+ reasoningTokens: firstMeasuredNumber(row.reasoning_tokens, row.reasoningTokens, completion?.reasoning_tokens, completion?.reasoningTokens, output?.reasoning_tokens, output?.reasoningTokens, reasoning?.tokens),
136
+ reasoningCostUsd: firstMeasuredNumber(row.reasoning_cost_usd, row.reasoningCostUsd, reasoning?.cost_usd, reasoning?.costUsd),
137
+ };
138
+ }
139
+ export function reasoningUsageLabel(value) {
140
+ const evidence = reasoningUsageEvidence(value);
141
+ if (evidence.reasoningTokens === null && evidence.reasoningCostUsd === null)
142
+ return t('screen.reasoning.notReported');
143
+ const parts = [];
144
+ parts.push(evidence.reasoningTokens === null ? t('screen.reasoning.tokensNotReported') : tn('screen.reasoning.tokens', evidence.reasoningTokens));
145
+ if (evidence.reasoningCostUsd !== null)
146
+ parts.push(t('screen.reasoning.cost', { cost: evidence.reasoningCostUsd }));
147
+ return parts.join(' · ');
148
+ }
149
+ // Temporary compatibility for the old composition root while Task 14 migrates it.
150
+ export const reduceCliEvent = reduceTuiEvent;
151
+ export function selectVisibleTranscript(s, { rows }) { return s.transcript.items.slice(-Math.max(1, rows * 3)); }