talos-code 0.0.1 → 0.1.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 (401) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +111 -3
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  4. package/dist/archive/zip.js +73 -0
  5. package/dist/args.js +97 -0
  6. package/dist/automations/history-store.js +34 -0
  7. package/dist/automations/policy-store.js +43 -0
  8. package/dist/automations/runner.js +107 -0
  9. package/dist/automations/schedule.js +85 -0
  10. package/dist/automations/windows-task.js +53 -0
  11. package/dist/commands/advanced-cli.js +233 -0
  12. package/dist/commands/checkpoint-cli.js +45 -0
  13. package/dist/commands/config-cli.js +107 -0
  14. package/dist/commands/context.js +17 -0
  15. package/dist/commands/extensions-cli.js +207 -0
  16. package/dist/commands/project-cli.js +74 -0
  17. package/dist/commands/project-commands.js +143 -0
  18. package/dist/commands/provider-cli.js +185 -0
  19. package/dist/commands/services-cli.js +248 -0
  20. package/dist/commands/session-cli.js +171 -0
  21. package/dist/commands/system-cli.js +405 -0
  22. package/dist/config/commands.js +60 -0
  23. package/dist/config/load.js +382 -0
  24. package/dist/config/migrations.js +48 -0
  25. package/dist/config/types.js +11 -0
  26. package/dist/diagnostics/development-log.js +154 -0
  27. package/dist/diagnostics/doctor.js +104 -0
  28. package/dist/diagnostics/redact.js +80 -0
  29. package/dist/diagnostics/zip.js +52 -0
  30. package/dist/errors.js +156 -0
  31. package/dist/events/bridge.js +130 -0
  32. package/dist/extensions/installer.js +178 -0
  33. package/dist/extensions/package-schema.js +24 -0
  34. package/dist/headless/result.js +84 -0
  35. package/dist/headless/run.js +230 -0
  36. package/dist/i18n/en/approval.js +43 -0
  37. package/dist/i18n/en/common.js +9 -0
  38. package/dist/i18n/en/credentials.js +82 -0
  39. package/dist/i18n/en/errors.js +246 -0
  40. package/dist/i18n/en/firstrun.js +89 -0
  41. package/dist/i18n/en/providers.js +37 -0
  42. package/dist/i18n/en/screen.js +736 -0
  43. package/dist/i18n/en/tools.js +127 -0
  44. package/dist/i18n/en.js +14 -0
  45. package/dist/i18n/error-view.js +307 -0
  46. package/dist/i18n/index.js +19 -0
  47. package/dist/i18n/kernel-map.js +139 -0
  48. package/dist/io.js +45 -0
  49. package/dist/main.js +330 -0
  50. package/dist/paths.js +41 -0
  51. package/dist/protocol/v2/codec.js +9 -0
  52. package/dist/protocol/v2/events.js +555 -0
  53. package/dist/protocol/v2/index.js +4 -0
  54. package/dist/protocol/v2/replay.js +28 -0
  55. package/dist/protocol/v2/types.js +1 -0
  56. package/dist/provider/control-plane.js +135 -0
  57. package/dist/provider/environment-keys.js +275 -0
  58. package/dist/provider/health.js +110 -0
  59. package/dist/provider/missing-key.js +48 -0
  60. package/dist/provider/model-catalog.js +168 -0
  61. package/dist/provider/provider-text.js +13 -0
  62. package/dist/provider/store.js +95 -0
  63. package/dist/provider/system-keyring.js +214 -0
  64. package/dist/runtime/active-run.js +63 -0
  65. package/dist/runtime/agent-tree.js +74 -0
  66. package/dist/runtime/attachments.js +84 -0
  67. package/dist/runtime/brokered-executor.js +395 -0
  68. package/dist/runtime/context-status.js +76 -0
  69. package/dist/runtime/create-runtime.js +111 -0
  70. package/dist/runtime/model-profile.js +361 -0
  71. package/dist/runtime/output-store.js +137 -0
  72. package/dist/runtime/provider-attempts.js +185 -0
  73. package/dist/runtime/replay-buffer.js +153 -0
  74. package/dist/runtime/repo.js +95 -0
  75. package/dist/runtime/session-facade.js +135 -0
  76. package/dist/runtime/session-summary.js +125 -0
  77. package/dist/runtime/supervisor.js +262 -0
  78. package/dist/runtime/talos-composition.js +1006 -0
  79. package/dist/runtime/types.js +5 -0
  80. package/dist/runtime/usage-snapshot.js +82 -0
  81. package/dist/security/auto-classifier.js +38 -0
  82. package/dist/security/credential-free-environment.js +54 -0
  83. package/dist/security/evaluate.js +243 -0
  84. package/dist/security/execution-backends.js +236 -0
  85. package/dist/security/execution-broker.js +102 -0
  86. package/dist/security/forge-scan.js +74 -0
  87. package/dist/security/from-approval.js +39 -0
  88. package/dist/security/mxc-execution-backend.js +281 -0
  89. package/dist/security/permission-engine.js +138 -0
  90. package/dist/security/permission-explanation.js +54 -0
  91. package/dist/security/persist.js +179 -0
  92. package/dist/security/plugin-guard.js +230 -0
  93. package/dist/security/process-tree-evidence-store.js +74 -0
  94. package/dist/security/process-tree-probe.js +554 -0
  95. package/dist/security/project-resource-inventory.js +186 -0
  96. package/dist/security/project-trust-gate.js +38 -0
  97. package/dist/security/project-trust.js +367 -0
  98. package/dist/security/rule-parser.js +201 -0
  99. package/dist/security/shell-segmentation.js +68 -0
  100. package/dist/security/trust-authority.js +324 -0
  101. package/dist/security/types.js +1 -0
  102. package/dist/security/workspace-identity.js +102 -0
  103. package/dist/services/automation-facade.js +59 -0
  104. package/dist/services/forge-facade.js +77 -0
  105. package/dist/services/hook-facade.js +240 -0
  106. package/dist/services/index.js +16 -0
  107. package/dist/services/library-facade.js +174 -0
  108. package/dist/services/mcp-facade.js +348 -0
  109. package/dist/services/memory-facade.js +126 -0
  110. package/dist/services/notes-facade.js +157 -0
  111. package/dist/services/plugin-facade.js +308 -0
  112. package/dist/services/research-facade.js +110 -0
  113. package/dist/services/task-board-facade.js +236 -0
  114. package/dist/services/workflow-catalog.js +246 -0
  115. package/dist/sessions/export-format.js +98 -0
  116. package/dist/sessions/metadata-store.js +160 -0
  117. package/dist/sessions/share.js +122 -0
  118. package/dist/sessions/transfer.js +16 -0
  119. package/dist/subcommands.js +62 -0
  120. package/dist/tui/agent-roster.js +36 -0
  121. package/dist/tui/app.js +3761 -0
  122. package/dist/tui/approval.js +36 -0
  123. package/dist/tui/boot/boot-sequence.js +76 -0
  124. package/dist/tui/boot/cinematic.js +243 -0
  125. package/dist/tui/boot/desktop-logo.js +82 -0
  126. package/dist/tui/boot.js +3 -0
  127. package/dist/tui/busy-input.js +58 -0
  128. package/dist/tui/catalog-service.js +559 -0
  129. package/dist/tui/components/assistant-stream.js +1 -0
  130. package/dist/tui/components/command-menu.js +68 -0
  131. package/dist/tui/components/composer.js +219 -0
  132. package/dist/tui/components/diff.js +35 -0
  133. package/dist/tui/components/footer.js +48 -0
  134. package/dist/tui/components/header.js +6 -0
  135. package/dist/tui/components/markdown.js +305 -0
  136. package/dist/tui/components/status-indicator.js +32 -0
  137. package/dist/tui/components/terminal-shell.js +205 -0
  138. package/dist/tui/components/thinking-row.js +19 -0
  139. package/dist/tui/components/tool-row.js +97 -0
  140. package/dist/tui/components/transcript-virtualizer.js +165 -0
  141. package/dist/tui/components/transcript.js +43 -0
  142. package/dist/tui/diff-model.js +77 -0
  143. package/dist/tui/editor-history.js +21 -0
  144. package/dist/tui/editor.js +210 -0
  145. package/dist/tui/event-adapter.js +436 -0
  146. package/dist/tui/exit-output.js +58 -0
  147. package/dist/tui/external-editor.js +53 -0
  148. package/dist/tui/file-completion.js +89 -0
  149. package/dist/tui/focus-manager.js +5 -0
  150. package/dist/tui/highlight.js +30 -0
  151. package/dist/tui/input-router.js +18 -0
  152. package/dist/tui/interrupt.js +99 -0
  153. package/dist/tui/keybindings.js +194 -0
  154. package/dist/tui/keymap-resolver.js +91 -0
  155. package/dist/tui/launch-state.js +139 -0
  156. package/dist/tui/line-diff.js +57 -0
  157. package/dist/tui/live-activity.js +45 -0
  158. package/dist/tui/metrics.js +123 -0
  159. package/dist/tui/onboarding.js +36 -0
  160. package/dist/tui/overlays/agent-tree.js +39 -0
  161. package/dist/tui/overlays/approval-dialog.js +640 -0
  162. package/dist/tui/overlays/automation-center.js +51 -0
  163. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  164. package/dist/tui/overlays/context-inspector.js +36 -0
  165. package/dist/tui/overlays/effort-line.js +110 -0
  166. package/dist/tui/overlays/forge-center.js +46 -0
  167. package/dist/tui/overlays/help-dialog.js +16 -0
  168. package/dist/tui/overlays/history-picker.js +37 -0
  169. package/dist/tui/overlays/hook-center.js +70 -0
  170. package/dist/tui/overlays/library-center.js +55 -0
  171. package/dist/tui/overlays/mcp-center.js +60 -0
  172. package/dist/tui/overlays/memory-center.js +63 -0
  173. package/dist/tui/overlays/model-picker.js +72 -0
  174. package/dist/tui/overlays/notes-center.js +53 -0
  175. package/dist/tui/overlays/overlay-host.js +8 -0
  176. package/dist/tui/overlays/plugin-center.js +76 -0
  177. package/dist/tui/overlays/provider-picker.js +145 -0
  178. package/dist/tui/overlays/queue-editor.js +32 -0
  179. package/dist/tui/overlays/research-center.js +59 -0
  180. package/dist/tui/overlays/scroll-window.js +234 -0
  181. package/dist/tui/overlays/session-picker.js +115 -0
  182. package/dist/tui/overlays/tasks-center.js +83 -0
  183. package/dist/tui/overlays/theme-picker.js +21 -0
  184. package/dist/tui/overlays/transcript-search.js +58 -0
  185. package/dist/tui/overlays/trust-center.js +29 -0
  186. package/dist/tui/overlays/workflow-center.js +46 -0
  187. package/dist/tui/project-file-index.js +214 -0
  188. package/dist/tui/project-references.js +85 -0
  189. package/dist/tui/project-trust-prompt.js +287 -0
  190. package/dist/tui/prompt-history-store.js +116 -0
  191. package/dist/tui/queue-store.js +110 -0
  192. package/dist/tui/regions/budget.js +59 -0
  193. package/dist/tui/regions/views.js +96 -0
  194. package/dist/tui/render-coordinator.js +148 -0
  195. package/dist/tui/render-scheduler.js +4 -0
  196. package/dist/tui/run.js +69 -0
  197. package/dist/tui/selection-list.js +29 -0
  198. package/dist/tui/session-controller.js +778 -0
  199. package/dist/tui/session-export.js +54 -0
  200. package/dist/tui/shell-input.js +35 -0
  201. package/dist/tui/shell-layout.js +48 -0
  202. package/dist/tui/shell-model.js +98 -0
  203. package/dist/tui/slash-commands.js +80 -0
  204. package/dist/tui/state.js +151 -0
  205. package/dist/tui/status-bar.js +125 -0
  206. package/dist/tui/status-view.js +40 -0
  207. package/dist/tui/terminal-capabilities.js +9 -0
  208. package/dist/tui/terminal-session.js +11 -0
  209. package/dist/tui/text-width.js +66 -0
  210. package/dist/tui/theme-catalog.js +25 -0
  211. package/dist/tui/theme-store.js +23 -0
  212. package/dist/tui/theme.js +23 -0
  213. package/dist/tui/tool-display.js +135 -0
  214. package/dist/tui/tool-facts.js +1 -0
  215. package/dist/tui/tools/bash-renderer.js +32 -0
  216. package/dist/tui/tools/change.js +61 -0
  217. package/dist/tui/tools/edit-renderer.js +17 -0
  218. package/dist/tui/tools/generic-renderer.js +13 -0
  219. package/dist/tui/tools/list-renderer.js +14 -0
  220. package/dist/tui/tools/read-renderer.js +13 -0
  221. package/dist/tui/tools/registry.js +20 -0
  222. package/dist/tui/tools/row-format.js +187 -0
  223. package/dist/tui/tools/search-renderer.js +38 -0
  224. package/dist/tui/tools/shared.js +97 -0
  225. package/dist/tui/tools/write-renderer.js +15 -0
  226. package/dist/tui/transcript-model.js +441 -0
  227. package/dist/tui/ui-preferences.js +79 -0
  228. package/dist/tui/usage-view.js +77 -0
  229. package/dist/tui/vim-mode.js +99 -0
  230. package/dist/update/check.js +15 -0
  231. package/dist/update/npm.js +51 -0
  232. package/dist/update/run.js +129 -0
  233. package/dist/version.js +2 -0
  234. package/dist/workspace/checkpoint-store.js +210 -0
  235. package/dist/workspace/checkpoint.js +413 -0
  236. package/dist/workspace/restore.js +232 -0
  237. package/package.json +63 -5
  238. package/vendor/context-engine/package.json +11 -0
  239. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  240. package/vendor/context-engine/src/contracts.mjs +48 -0
  241. package/vendor/context-engine/src/engine.mjs +445 -0
  242. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  243. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  244. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  245. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  246. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  247. package/vendor/context-engine/src/profiles.mjs +10 -0
  248. package/vendor/context-engine/src/retrieval.mjs +104 -0
  249. package/vendor/context-engine/src/summary.mjs +97 -0
  250. package/vendor/context-engine/src/usage.mjs +34 -0
  251. package/vendor/harness-ui/package.json +38 -0
  252. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  253. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  254. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  255. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  256. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  257. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  258. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  259. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  260. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  261. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  262. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  263. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  264. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  265. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  266. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  267. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  268. package/vendor/harness-ui/src/config.mjs +697 -0
  269. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  270. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  271. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  272. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  273. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  274. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  275. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  276. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  277. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  278. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  279. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  280. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  281. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  282. package/vendor/harness-ui/src/doctor.mjs +142 -0
  283. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  284. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  285. package/vendor/harness-ui/src/document-report.mjs +331 -0
  286. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  287. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  288. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  289. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  290. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  291. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  292. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  293. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  294. package/vendor/harness-ui/src/git-service.mjs +626 -0
  295. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  296. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  297. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  298. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  299. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  300. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  301. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  302. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  303. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  304. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  305. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  306. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  307. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  308. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  309. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  310. package/vendor/harness-ui/src/library-store.mjs +652 -0
  311. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  312. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  313. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  314. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  315. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  316. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  317. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  318. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  319. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  320. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  321. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  322. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  323. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  324. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  325. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  326. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  327. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  328. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  329. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  330. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  331. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  332. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  333. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  334. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  335. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  336. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  337. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  338. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  339. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  340. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  341. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  342. package/vendor/harness-ui/src/research/card.mjs +235 -0
  343. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  344. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  345. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  346. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  347. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  348. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  349. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  350. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  351. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  352. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  353. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  354. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  355. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  356. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  357. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  358. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  359. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  360. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  361. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  362. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  363. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  364. package/vendor/harness-ui/src/research/report.mjs +203 -0
  365. package/vendor/harness-ui/src/research/run.mjs +527 -0
  366. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  367. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  368. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  369. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  370. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  371. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  372. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  373. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  374. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  375. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  376. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  377. package/vendor/harness-ui/src/session-store.mjs +220 -0
  378. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  379. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  380. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  381. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  382. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  383. package/vendor/harness-ui/src/static-files.mjs +96 -0
  384. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  385. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  386. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  387. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  388. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  389. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  390. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  391. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  392. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  393. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  394. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  395. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  396. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  397. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  398. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  399. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  400. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  401. package/vendor/manifest.json +170 -0
@@ -0,0 +1,40 @@
1
+ /*
2
+ * R5b D7 (owner decision Q-R5-17): what `/status` adds to its R4 block — the sandbox verdict, the permission rules counted
3
+ * in each scope's own file, the open tasks and the notes, and the session's usage in the status bar's own words. A fact
4
+ * that could not be read says so; nothing is shown as zero because it was not measured.
5
+ */
6
+ import { t } from "../i18n/index.js";
7
+ import { readConfigScope } from "../config/load.js";
8
+ import { statusBar } from "./status-bar.js";
9
+ const size = (value) => Array.isArray(value) ? value.length : 0;
10
+ export async function permissionRuleCounts({ paths, projectRoot }) {
11
+ try {
12
+ const count = async (scope) => { const rules = (await readConfigScope({ paths, projectRoot, scope })).permissions; return { allow: size(rules?.allow), ask: size(rules?.ask), deny: size(rules?.deny) }; };
13
+ const [user, project, projectUser] = await Promise.all([count('user'), count('project'), count('project-user')]);
14
+ return { user, project, projectUser };
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ /** The usage segments of the status bar (tokens, cache, context, cost, compactions), unshortened, in one line. */
21
+ export function usageLine(snapshot, model) {
22
+ if (!snapshot)
23
+ return null;
24
+ const parts = statusBar({ snapshot, model, width: 10_000, safety: { fullAccess: false, noSandbox: false } }).segments.filter(row => ['tokens', 'cached', 'context', 'cost', 'compactions'].includes(row.id)).map(row => row.text);
25
+ return parts.length ? parts.join(' · ') : null;
26
+ }
27
+ export function statusFactLines(facts) {
28
+ const lines = [t(facts.sandbox === true ? 'screen.status.sandboxVerified' : facts.sandbox === false ? 'screen.status.sandboxNone' : 'screen.status.sandboxUnknown')];
29
+ if (!facts.rules)
30
+ lines.push(t('screen.status.rulesUnknown'));
31
+ else {
32
+ const total = (row) => row.allow + row.ask + row.deny;
33
+ const { user, project, projectUser } = facts.rules;
34
+ const all = { allow: user.allow + project.allow + projectUser.allow, ask: user.ask + project.ask + projectUser.ask, deny: user.deny + project.deny + projectUser.deny };
35
+ lines.push(total(all) === 0 ? t('screen.status.rulesNone') : t('screen.status.rules', { ...all, user: total(user), project: total(project), projectUser: total(projectUser) }));
36
+ }
37
+ lines.push(facts.work ? t('screen.status.work', facts.work) : t('screen.status.workUnknown'));
38
+ lines.push(facts.usage ? t('screen.status.usage', { usage: facts.usage }) : t('screen.status.usageNone'));
39
+ return lines;
40
+ }
@@ -0,0 +1,9 @@
1
+ export function detectTerminalCapabilities({ stdinIsTTY, stdoutIsTTY, color, env }) {
2
+ const interactive = stdinIsTTY && stdoutIsTTY;
3
+ const dumb = env.TERM === 'dumb';
4
+ const noColor = typeof env.NO_COLOR === 'string' && env.NO_COLOR.length > 0;
5
+ const reduced = env.TALOS_REDUCED_MOTION === '1' || env.TALOS_REDUCED_MOTION === 'true';
6
+ const unicode = interactive && !dumb;
7
+ const effectiveColor = interactive && !dumb && color && !noColor;
8
+ return { interactive, color: effectiveColor, motion: effectiveColor && !reduced, unicode };
9
+ }
@@ -0,0 +1,11 @@
1
+ export function createTerminalSessionPlan({ capabilities, env, supportsAlternateScreen = true, }) {
2
+ if (!capabilities.interactive)
3
+ return { mode: 'plain', alternateScreen: false, paintBackground: false, fallbackReason: 'non-interactive' };
4
+ if (env.TERM === 'dumb')
5
+ return { mode: 'plain', alternateScreen: false, paintBackground: false, fallbackReason: 'term-dumb' };
6
+ if (!supportsAlternateScreen)
7
+ return { mode: 'plain', alternateScreen: false, paintBackground: false, fallbackReason: 'alternate-screen-unavailable' };
8
+ if (!capabilities.color)
9
+ return { mode: 'mono', alternateScreen: true, paintBackground: false, fallbackReason: null };
10
+ return { mode: 'full', alternateScreen: true, paintBackground: true, fallbackReason: null };
11
+ }
@@ -0,0 +1,66 @@
1
+ /* R1 gate E4/E16: TALOS measures text with the SAME function Ink 7.1.1 uses to lay it out (`string-width` 8.2.2, the
2
+ one copy in the lockfile, hoisted beside Ink). The hand-rolled table this replaces disagreed with Ink on 17 of 63
3
+ fixtures (SGR, tabs, ZWSP, flags, text-presentation symbols ☺ ⚠ © ™ ✔ ▶, combining marks, controls), and a row
4
+ count computed with one width and rendered with another is how a frame overflows (review D-02/D-04).
5
+ It is imported here, not declared in package.json, per the lane rule "no new dependency"; see the lane hand-back. */
6
+ import stringWidth from 'string-width';
7
+ const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
8
+ export function splitGraphemes(text) { return [...segmenter.segment(text)].map(x => x.segment); }
9
+ export function displayWidth(text) { return stringWidth(String(text)); }
10
+ export function truncateDisplay(text, width) { if (displayWidth(text) <= width)
11
+ return text; if (width <= 1)
12
+ return '…'; let out = '', used = 0; for (const g of splitGraphemes(text)) {
13
+ const w = displayWidth(g);
14
+ if (used + w + 1 > width)
15
+ break;
16
+ out += g;
17
+ used += w;
18
+ } return `${out}…`; }
19
+ /* Keeps both ends of a long value (a workspace path): the tail says which folder, the head says which drive/root. */
20
+ export function truncateMiddle(text, width) {
21
+ if (displayWidth(text) <= width)
22
+ return text;
23
+ if (width <= 1)
24
+ return '…';
25
+ const graphemes = splitGraphemes(text);
26
+ const budget = width - 1;
27
+ let head = '', tail = '', used = 0, left = 0, right = graphemes.length - 1;
28
+ while (left <= right) {
29
+ const takeTail = displayWidth(tail) <= displayWidth(head);
30
+ const g = takeTail ? graphemes[right] : graphemes[left];
31
+ const w = displayWidth(g);
32
+ if (used + w > budget)
33
+ break;
34
+ used += w;
35
+ if (takeTail) {
36
+ tail = g + tail;
37
+ right--;
38
+ }
39
+ else {
40
+ head += g;
41
+ left++;
42
+ }
43
+ }
44
+ return `${head}…${tail}`;
45
+ }
46
+ /* Hard-wraps text into rows of at most `width` columns by grapheme, the way a terminal fills cells. Used where TALOS
47
+ owns the line breaks itself (the composer, chrome), so the row count is exact before render (E4). */
48
+ export function wrapDisplay(text, width) {
49
+ const limit = Math.max(1, Math.floor(width));
50
+ const rows = [];
51
+ for (const line of String(text).split('\n')) {
52
+ let row = '', used = 0;
53
+ for (const g of splitGraphemes(line)) {
54
+ const w = displayWidth(g);
55
+ if (used + w > limit && row !== '') {
56
+ rows.push(row);
57
+ row = '';
58
+ used = 0;
59
+ }
60
+ row += g;
61
+ used += w;
62
+ }
63
+ rows.push(row);
64
+ }
65
+ return rows;
66
+ }
@@ -0,0 +1,25 @@
1
+ /** `color-mix(in srgb, a amount%, b)` for #rrggbb. */
2
+ export function mixHex(a, amount, b) {
3
+ const parse = (hex) => [1, 3, 5].map(i => parseInt(hex.slice(i, i + 2), 16));
4
+ const [x, y] = [parse(a), parse(b)];
5
+ const t = Math.max(0, Math.min(100, amount)) / 100;
6
+ return `#${x.map((v, i) => Math.round(v * t + y[i] * (1 - t)).toString(16).padStart(2, '0')).join('')}`;
7
+ }
8
+ const theme = (id, label, accent, background) => ({ id, label, accent, background, muted: mixHex(accent, 62, background) });
9
+ export const DEFAULT_THEME_ACCENT = 'calm';
10
+ export const TALOS_THEME_ACCENTS = Object.freeze([
11
+ theme('calm', 'Calm', '#c08b3c', '#1e1f22'),
12
+ theme('forge', 'Forge', '#c98b32', '#080b11'),
13
+ theme('terminal', 'Terminal', '#63f08e', '#020403'),
14
+ theme('aurora', 'Aurora', '#42e7c7', '#071113'),
15
+ theme('ember', 'Ember', '#ff5c62', '#10090a'),
16
+ theme('atlas', 'Atlas', '#d49a52', '#07101f'),
17
+ theme('noir', 'Noir', '#f2f2f2', '#050505'),
18
+ theme('signal', 'Signal', '#ff6f61', '#091011'),
19
+ theme('violet', 'Violet', '#b794f6', '#0d0a19'),
20
+ theme('telemetry', 'Telemetry', '#6ad4d4', '#0b0f11'),
21
+ ]);
22
+ export function isThemeAccentId(id) { return TALOS_THEME_ACCENTS.some(row => row.id === id); }
23
+ export function themeAccent(id) {
24
+ return TALOS_THEME_ACCENTS.find(row => row.id === id) ?? TALOS_THEME_ACCENTS.find(row => row.id === DEFAULT_THEME_ACCENT);
25
+ }
@@ -0,0 +1,23 @@
1
+ import { createTuiTheme } from "./theme.js";
2
+ import { DEFAULT_THEME_ACCENT, TALOS_THEME_ACCENTS, isThemeAccentId } from "./theme-catalog.js";
3
+ /** What /theme offers, in the product's order, mono last. */
4
+ export const THEME_CHOICES = Object.freeze([...TALOS_THEME_ACCENTS.map(row => row.id), 'mono']);
5
+ export function parseThemeChoice(value) {
6
+ const id = typeof value === 'string' ? value.trim().toLowerCase() : '';
7
+ return THEME_CHOICES.includes(id) ? id : null;
8
+ }
9
+ export function liveTheme(base, id) {
10
+ const capabilities = id === 'mono' ? { ...base, color: false, motion: false } : base;
11
+ return { id, capabilities, theme: createTuiTheme(capabilities, isThemeAccentId(id) ? id : DEFAULT_THEME_ACCENT) };
12
+ }
13
+ export function createThemeStore(base, id = DEFAULT_THEME_ACCENT) {
14
+ let snapshot = liveTheme(base, id);
15
+ const listeners = new Set();
16
+ return {
17
+ getSnapshot: () => snapshot,
18
+ subscribe(listener) { listeners.add(listener); return () => { listeners.delete(listener); }; },
19
+ set(next) { if (next === snapshot.id)
20
+ return; snapshot = liveTheme(base, next); for (const listener of [...listeners])
21
+ listener(); },
22
+ };
23
+ }
@@ -0,0 +1,23 @@
1
+ import { DEFAULT_THEME_ACCENT, themeAccent } from "./theme-catalog.js";
2
+ export function createTuiTheme(c, accentId = DEFAULT_THEME_ACCENT) {
3
+ const accent = themeAccent(accentId);
4
+ return {
5
+ id: accent.id,
6
+ colors: c.color ? {
7
+ background: accent.background,
8
+ foreground: '#F5F5F4',
9
+ accent: accent.accent,
10
+ muted: accent.muted,
11
+ success: '#34D399',
12
+ warning: '#FBBF24',
13
+ danger: '#FB7185',
14
+ } : {},
15
+ glyphs: c.unicode
16
+ ? { spinner: ['⠋', '⠙', '⠹', '⠸'], success: '✓', error: '!', branch: '├', bullet: '•' }
17
+ : { spinner: ['-', '\\', '|', '/'], success: 'OK', error: '!', branch: '+', bullet: '*' },
18
+ };
19
+ }
20
+ const SURFACE_COLOR = {
21
+ boot: 'accent', transcript: 'accent', picker: 'accent', approval: 'warning', tool: 'success', footer: 'muted',
22
+ };
23
+ export function themeColor(theme, surface) { return theme.colors[SURFACE_COLOR[surface]]; }
@@ -0,0 +1,135 @@
1
+ /*
2
+ * R2 CONTRACT (owner: lane T). The ONE table that turns a kernel tool name into what the screen shows (Q-R2-3, gate
3
+ * E3), zipped once on the kernel name as Qwen zips `ToolNames` with `ToolDisplayNames` (`cli/src/ui/utils/
4
+ * tool-display-map.ts:12-24`, 2026-09-06). Every surface reads it: transcript rows and renderer lookup (tools/registry.ts),
5
+ * approval title and summary (overlays/approval-dialog.ts), permission mapping (security/from-approval.ts). The model
6
+ * keeps the kernel names and argument keys (gate E2): this file maps for display and never renames what it receives.
7
+ *
8
+ * The 46 rows are the kernel's own tools, measured, not remembered: `ATTREZZI` (talosHarness.mjs:1571-1741, 7 tools),
9
+ * `ATTREZZI_ESTESI` (:1829-2806, 38 tools) and `carica_skill` (:7603-7612), 53 distinct argument keys — the gate's §1.3
10
+ * count. test/i18n/tools-labels.test.ts imports those schemas and fails on a tool or key without a row here.
11
+ */
12
+ import { en } from "../i18n/en.js";
13
+ import { t } from "../i18n/index.js";
14
+ const row = (permission, renderer, ...primary) => ({ permission, renderer, primary });
15
+ /*
16
+ * `permission` is the tool the permission engine judges the call as (security/types.ts). The kernel asks for approval on
17
+ * 30 of them (`verificaPermessoConBarriera`, talosHarness.mjs:8166-9714): reads are Read, the two file writers Write (a
18
+ * write judged as Read was ALLOWED inside the project without asking, evaluate.ts:130 — review E-07), the targeted edit
19
+ * Edit, the two command runners Bash, the web tools WebFetch; TALOS's own services are TalosService with the kernel
20
+ * name as operation. `primary` lists the argument keys whose value stands beside the label, first present wins.
21
+ */
22
+ const TABLE = {
23
+ elenca: row('Read', 'list', 'percorso'),
24
+ cerca: row('Read', 'search', 'testo', 'nome'),
25
+ leggi: row('Read', 'read', 'percorso'),
26
+ scrivi: row('Write', 'write', 'percorso'),
27
+ prova: row('Bash', 'bash'),
28
+ shell: row('Bash', 'bash', 'comando'),
29
+ naviga: row('WebFetch', 'generic', 'url'),
30
+ web_search: row('WebFetch', 'generic', 'query'),
31
+ artifact_create: row('TalosService', 'generic', 'titolo'),
32
+ document_create: row('TalosService', 'generic', 'title'),
33
+ time_now: row('TalosService', 'generic'),
34
+ delega_sottotask: row('TalosService', 'generic', 'task'),
35
+ generate_image: row('TalosService', 'generic', 'prompt'),
36
+ library_list: row('TalosService', 'generic'),
37
+ library_search: row('TalosService', 'generic', 'query'),
38
+ library_read: row('TalosService', 'generic', 'id'),
39
+ library_file_origin: row('TalosService', 'generic', 'id'),
40
+ library_rename: row('TalosService', 'generic', 'name', 'id'),
41
+ library_delete: row('TalosService', 'generic', 'id'),
42
+ library_export: row('TalosService', 'generic', 'reference'),
43
+ library_context_policy_update: row('TalosService', 'generic', 'action'),
44
+ notes_list: row('TalosService', 'generic'),
45
+ notes_create: row('TalosService', 'generic', 'title'),
46
+ notes_update: row('TalosService', 'generic', 'title', 'id'),
47
+ notes_delete: row('TalosService', 'generic', 'id'),
48
+ tasks_list: row('TalosService', 'generic', 'status'),
49
+ tasks_create: row('TalosService', 'generic', 'title'),
50
+ tasks_complete: row('TalosService', 'generic', 'id'),
51
+ tasks_update: row('TalosService', 'generic', 'title', 'id'),
52
+ tasks_delete: row('TalosService', 'generic', 'id'),
53
+ memory_search: row('TalosService', 'generic', 'query'),
54
+ memory_write: row('TalosService', 'generic', 'title'),
55
+ memory_update: row('TalosService', 'generic', 'title', 'id'),
56
+ memory_delete: row('TalosService', 'generic', 'id'),
57
+ research_list: row('TalosService', 'generic', 'status'),
58
+ research_start: row('TalosService', 'generic', 'question'),
59
+ research_read: row('TalosService', 'generic', 'id'),
60
+ research_rename: row('TalosService', 'generic', 'title', 'id'),
61
+ research_pause: row('TalosService', 'generic', 'id'),
62
+ research_resume: row('TalosService', 'generic', 'id'),
63
+ research_cancel: row('TalosService', 'generic', 'id'),
64
+ research_delete: row('TalosService', 'generic', 'id'),
65
+ research_deposit: row('Write', 'generic'),
66
+ tool_create: row('TalosService', 'generic', 'title'),
67
+ file_edit: row('Edit', 'edit', 'percorso'),
68
+ carica_skill: row('TalosService', 'generic', 'nome'),
69
+ };
70
+ export const KERNEL_TOOL_NAMES = Object.freeze(Object.keys(TABLE));
71
+ const WORDS_COMPLETE = true;
72
+ void WORDS_COMPLETE;
73
+ export function isKernelTool(name) { return typeof name === 'string' && Object.hasOwn(TABLE, name); }
74
+ export function rendererKindFor(name) { return isKernelTool(name) ? TABLE[name].renderer : 'generic'; }
75
+ /* A tool the kernel did not declare is named by whoever wrote it: an MCP server (`mcp__<server>__<tool>`,
76
+ harness-ui/src/mcp-session.mjs:47), a plugin (`plugin__<plugin>__<tool>`, plugin-session.mjs:52), the Tool Forge
77
+ (`forge_<id>`, forge-contract.mjs:127), or anything else. Their parts are split by these exact prefixes. */
78
+ export function externalToolParts(name) {
79
+ for (const kind of ['mcp', 'plugin']) {
80
+ const prefix = `${kind}__`;
81
+ if (!name.startsWith(prefix))
82
+ continue;
83
+ const rest = name.slice(prefix.length), split = rest.indexOf('__');
84
+ if (split > 0 && split < rest.length - 2)
85
+ return { kind, owner: rest.slice(0, split), tool: rest.slice(split + 2) };
86
+ }
87
+ if (name.startsWith('forge_') && name.length > 6)
88
+ return { kind: 'forge', owner: null, tool: name.slice(6) };
89
+ return null;
90
+ }
91
+ /** snake_case, kebab-case and camelCase → lower-case words. */
92
+ function words(name) { return name.replace(/([a-z0-9])([A-Z])/gu, '$1 $2').replace(/[_\-.\s]+/gu, ' ').trim().toLowerCase(); }
93
+ function capitalised(text) { return text ? text[0].toUpperCase() + text.slice(1) : text; }
94
+ function permissionOfExternal(name) { const parts = externalToolParts(name); return parts?.kind === 'mcp' ? 'Mcp' : parts?.kind === 'plugin' ? 'Plugin' : 'TalosService'; }
95
+ /** The permission tool the engine judges this tool as: from the table, or from the external prefix. */
96
+ export function permissionToolFor(name) { return isKernelTool(name) ? TABLE[name].permission : permissionOfExternal(name); }
97
+ /** The English label of an argument key: the dictionary's when it has one, otherwise the key in words. */
98
+ export function argumentLabel(key) { const id = `tool.arg.${key}`; return Object.hasOwn(en, id) ? t(id) : words(key); }
99
+ /* Keys an unknown tool's primary argument is looked for under (Hermes `_PRIMARY_ARGS`, agent/display.py:353-361, 2026-09-22). */
100
+ const EXTERNAL_PRIMARY = ['path', 'file_path', 'file', 'url', 'query', 'command', 'pattern', 'name', 'title', 'id'];
101
+ function primaryValue(keys, args) {
102
+ if (!args)
103
+ return null;
104
+ for (const key of keys) {
105
+ const value = args[key];
106
+ if ((typeof value === 'string' && value.trim() !== '') || typeof value === 'number' || typeof value === 'boolean')
107
+ return String(value);
108
+ }
109
+ return null;
110
+ }
111
+ function externalLabel(name) {
112
+ const parts = externalToolParts(name);
113
+ if (parts?.kind === 'mcp')
114
+ return t('tool.mcp.label', { tool: capitalised(words(parts.tool)), server: parts.owner });
115
+ if (parts?.kind === 'plugin')
116
+ return t('tool.plugin.label', { tool: capitalised(words(parts.tool)), plugin: parts.owner });
117
+ if (parts?.kind === 'forge')
118
+ return t('tool.forge.label', { tool: capitalised(words(parts.tool)) });
119
+ return capitalised(words(name)) || t('tool.unknown.label');
120
+ }
121
+ /**
122
+ * What the screen shows for a tool call: the English label and verb, the VALUE of its primary argument when `args` is
123
+ * given (null when absent or not a plain value), the permission tool it is judged as, and the raw kernel name, which
124
+ * only an expanded detail shows (Q-R2-3).
125
+ */
126
+ export function toolDisplay(kernelName, args) {
127
+ if (isKernelTool(kernelName)) {
128
+ const entry = TABLE[kernelName];
129
+ return { label: t(`tool.${kernelName}.label`), verb: t(`tool.${kernelName}.verb`), primaryArg: primaryValue(entry.primary, args), permissionTool: entry.permission, raw: kernelName };
130
+ }
131
+ const label = externalLabel(kernelName);
132
+ return { label, verb: t('tool.unknown.verb', { tool: label }), primaryArg: primaryValue(EXTERNAL_PRIMARY, args), permissionTool: permissionOfExternal(kernelName), raw: kernelName };
133
+ }
134
+ /** The argument keys a tool's primary value is read from, in order (the table's `primary`; R3 renderers read it too). */
135
+ export function primaryArgumentKeys(kernelName) { return isKernelTool(kernelName) ? TABLE[kernelName].primary : EXTERNAL_PRIMARY; }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ import { boundedLines, detailWidth, formatDuration, moreLines, outputTail, outputText, parseArgs, sanitizeDisplayText, withoutKernelExitLine } from "./shared.js";
2
+ import { truncateDisplay } from "../text-width.js";
3
+ import { t } from "../../i18n/index.js";
4
+ /* R2 lane T: the kernel's `shell` sends `comando` and the model's own `descrizione` ("shown to the person watching",
5
+ talosHarness.mjs:1702-1720), which leads the detail; `prova` sends no argument at all.
6
+ R3 (Q-R3-10): the output is a TAIL — the last 5 lines (errors are at the end), 40 in the expanded view — with the lines
7
+ above it counted. While the command runs, the live tail ends with `+N lines · T s`; a sandboxed command streams
8
+ nothing today (brokered-executor.ts:343-352), so its row says `running T s` and the output arrives at the end.
9
+ The kernel's `exit N [sandbox: …]` first line is hidden (shared.ts, gate E3); a person's `!` command is labelled `!`. */
10
+ const TAIL = 5, TAIL_EXPANDED = 40;
11
+ export const renderBash = (row, context) => {
12
+ const a = parseArgs(row);
13
+ const command = String(a.comando ?? a.command ?? a.cmd ?? a.raw ?? '').trim();
14
+ const description = typeof a.descrizione === 'string' ? a.descrizione.trim() : typeof a.description === 'string' ? a.description.trim() : '';
15
+ const detail = description ? boundedLines(description, context.width, context.expanded ? 4 : 1) : [];
16
+ const live = row.status === 'queued' || row.status === 'running' || row.status === 'streaming';
17
+ let liveTail = false;
18
+ if (row.status !== 'denied') {
19
+ const tail = outputTail(live ? row.liveOutput : withoutKernelExitLine(outputText(row)), context.expanded ? TAIL_EXPANDED : TAIL);
20
+ detail.push(...tail.lines.map(line => truncateDisplay(sanitizeDisplayText(line), detailWidth(context.width)) || ' '));
21
+ const summary = tail.hidden > 0 ? [moreLines(tail.hidden, tail.atLeast)] : [];
22
+ if (live && tail.lines.length) {
23
+ liveTail = true;
24
+ const elapsed = row.startedAt === null ? 0 : Math.max(0, context.now - row.startedAt);
25
+ if (elapsed >= 1000)
26
+ summary.push(formatDuration(elapsed));
27
+ }
28
+ if (summary.length)
29
+ detail.push(summary.join(' · '));
30
+ }
31
+ return { ...(row.origin === 'person' ? { label: t('tool.person.label') } : {}), target: command, result: [], detail, command: true, showsOutput: true, liveTail };
32
+ };
@@ -0,0 +1,61 @@
1
+ /*
2
+ * R3 lane RD (Q-R3-4, gate E10): a write or edit row reads its change through the ONE line diff (line-diff.ts). A row is
3
+ * drawn many times (every frame, every height estimate), so a file change is diffed once per change object and a pair
4
+ * of edit fragments once per text (bounded cache); the expanded view renders the model with components/diff.ts.
5
+ */
6
+ import { t, tn } from "../../i18n/index.js";
7
+ import { renderDiffModel } from "../components/diff.js";
8
+ import { lineDiff } from "../line-diff.js";
9
+ import { lineCount } from "./shared.js";
10
+ const DIFFS = new WeakMap();
11
+ export function changeDiff(change) {
12
+ let diff = DIFFS.get(change);
13
+ if (!diff) {
14
+ diff = lineDiff(change.before, change.after, { path: change.path });
15
+ DIFFS.set(change, diff);
16
+ }
17
+ return diff;
18
+ }
19
+ export function summarizeChange(change) {
20
+ const diff = changeDiff(change);
21
+ return { newFile: change.before === null, lines: lineCount(change.after), added: diff.approximate ? null : diff.added, removed: diff.approximate ? null : diff.removed };
22
+ }
23
+ export function changeSummaryOf(row) { return row.changeSummary ?? (row.change ? summarizeChange(row.change) : null); }
24
+ /** The result facts of a change: `new file · N lines`, `+a −r`, or `N lines` when it was too large to compare. */
25
+ export function resultOfChange(summary) {
26
+ if (summary.newFile)
27
+ return [t('tool.result.newFile'), tn('tool.result.lines', summary.lines)];
28
+ if (summary.added === null || summary.removed === null)
29
+ return [tn('tool.result.lines', summary.lines)];
30
+ return [t('tool.result.changes', { added: summary.added, removed: summary.removed })];
31
+ }
32
+ /* Edit fragments are small; the cache keeps the last few pairs so a redraw does not diff again. */
33
+ const FRAGMENTS = new Map();
34
+ const FRAGMENT_CACHE = 64, FRAGMENT_KEY_MAX = 64 * 1024;
35
+ /** The diff of an edit's two fragments: their line numbers are not the file's, so none is claimed (no numbers, no `@@`).
36
+ * A fragment is a piece of a line-ended file, so both get a final line break before diffing: `line` and `line\n` are the
37
+ * same line here (for a whole file jsdiff, like git, rightly tells them apart). */
38
+ const lineEnded = (text) => text === '' || text.endsWith('\n') ? text : text + '\n';
39
+ export function fragmentDiff(oldText, newText, path) {
40
+ const key = oldText.length + newText.length <= FRAGMENT_KEY_MAX ? `${path}\u0000${oldText}\u0000${newText}` : null;
41
+ const cached = key === null ? undefined : FRAGMENTS.get(key);
42
+ if (cached)
43
+ return cached;
44
+ const diff = lineDiff(lineEnded(oldText), lineEnded(newText), { path });
45
+ const model = { ...diff.model, files: diff.model.files.map(file => ({ ...file, rows: file.rows.filter(row => row.kind !== 'hunk').map(row => ({ ...row, oldLine: null, newLine: null })) })) };
46
+ const result = { ...diff, model };
47
+ if (key !== null) {
48
+ FRAGMENTS.set(key, result);
49
+ if (FRAGMENTS.size > FRAGMENT_CACHE)
50
+ FRAGMENTS.delete(FRAGMENTS.keys().next().value);
51
+ }
52
+ return result;
53
+ }
54
+ /* The expanded view of a change is bounded like every other detail: the first lines of the diff, then how many more. */
55
+ const MAX_DIFF_LINES = 400;
56
+ export function diffDetail(diff, width) {
57
+ const lines = renderDiffModel(diff.model, width).lines.filter(line => line.kind !== 'file').map(line => line.text);
58
+ if (lines.length <= MAX_DIFF_LINES)
59
+ return lines;
60
+ return [...lines.slice(0, MAX_DIFF_LINES), tn('tool.diff.more', lines.length - MAX_DIFF_LINES)];
61
+ }
@@ -0,0 +1,17 @@
1
+ import { parseArgs } from "./shared.js";
2
+ import { changeDiff, changeSummaryOf, diffDetail, fragmentDiff, resultOfChange } from "./change.js";
3
+ import { t } from "../../i18n/index.js";
4
+ /* R2 lane T: the kernel's `file_edit` sends `percorso`, `old_string`, `new_string` (talosHarness.mjs:2786-2806).
5
+ R3 (Q-R3-4, gate E10): `+a −r` from the ONE line diff (line-diff.ts, jsdiff) — of the whole file when the kernel reported
6
+ the change (`file.changed`), of the two fragments before that. The multiset count that stood here is gone: it saw a
7
+ moved line as no change and an edit of one of two identical lines as nothing (gate §3.1). */
8
+ export const renderEdit = (row, context) => {
9
+ const a = parseArgs(row);
10
+ const path = String(a.percorso ?? a.path ?? a.file ?? '').trim();
11
+ const oldText = String(a.oldText ?? a.old_string ?? a.before ?? ''), newText = String(a.newText ?? a.new_string ?? a.after ?? '');
12
+ const summary = changeSummaryOf(row);
13
+ const fragment = summary && summary.added !== null ? null : fragmentDiff(oldText, newText, path);
14
+ const result = fragment ? [t('tool.result.changes', { added: fragment.added, removed: fragment.removed })] : resultOfChange(summary);
15
+ const detail = !context.expanded ? [] : diffDetail(row.change ? changeDiff(row.change) : fragment ?? fragmentDiff(oldText, newText, path), context.width);
16
+ return { target: path, result, detail };
17
+ };
@@ -0,0 +1,13 @@
1
+ import { argumentLine, boundedLines, outputText, parseArgs } from "./shared.js";
2
+ import { primaryArgumentKeys, toolDisplay } from "../tool-display.js";
3
+ /* R2 lane T (review D-07, Q-R2-3): the title is the English label and the primary argument's value; every other argument
4
+ is one `label: value` line, a structure counted and never printed as JSON. R3: a refused call shows its reason, not
5
+ its output (row-format.ts). */
6
+ export const renderGeneric = (row, context) => {
7
+ const a = parseArgs(row);
8
+ const view = toolDisplay(row.name, a);
9
+ const primaryKey = view.primaryArg === null ? null : primaryArgumentKeys(row.name).find(key => a[key] !== undefined && String(a[key]) === view.primaryArg) ?? null;
10
+ const argLines = Object.entries(a).filter(([key]) => key !== primaryKey).map(([key, value]) => argumentLine(key, value));
11
+ const details = [...boundedLines(argLines.join('\n'), context.width, context.expanded ? 12 : 2), ...(row.status === 'denied' ? [] : boundedLines(outputText(row), context.width, context.expanded ? 12 : 3))];
12
+ return { target: view.primaryArg ?? '', result: [], detail: details, showsOutput: true };
13
+ };
@@ -0,0 +1,14 @@
1
+ import { boundedLines, outputText, parseArgs } from "./shared.js";
2
+ import { tn } from "../../i18n/index.js";
3
+ /* R3 (Q-R3-1, gate §2.3): `List folder <path> · N entries`. The kernel's `elenca` (elencaDaCartella,
4
+ talosHarness.mjs:3487) answers one path per line, `no files and no folders. …` for an empty folder, and a sentence for a
5
+ folder it cannot read or a refusal; those exact shapes are pinned by r3-rd-tool-rows.test.ts, anything else gets no count. */
6
+ const EMPTY = /^no files and no folders\. /u;
7
+ const NOT_COUNTED = /^REFUSED\. | is not a readable folder of this workspace\. /u;
8
+ export const renderList = (row, context) => {
9
+ const a = parseArgs(row);
10
+ const path = String(a.percorso ?? a.path ?? a.folder ?? a.raw ?? '').trim();
11
+ const text = outputText(row).trim();
12
+ const count = EMPTY.test(text) ? 0 : NOT_COUNTED.test(text) ? null : text.split(/\r?\n/u).filter(line => line.trim()).length;
13
+ return { target: path, result: count === null ? [] : [tn('tool.result.entries', count)], detail: row.status === 'denied' || count === 0 ? [] : boundedLines(text, context.width, context.expanded ? 12 : 3), showsOutput: true };
14
+ };
@@ -0,0 +1,13 @@
1
+ import { lineCount, parseArgs } from "./shared.js";
2
+ import { t, tn } from "../../i18n/index.js";
3
+ /* R2 lane T: the kernel's `leggi` sends `percorso` (talosHarness.mjs:1601-1608); the English spellings stay accepted.
4
+ R3 (Q-R3-1): the row says what was read — `N lines` of the content returned, or the range the call asked for. */
5
+ export const renderRead = row => {
6
+ const a = parseArgs(row);
7
+ const path = String(a.percorso ?? a.path ?? a.file ?? a.filename ?? a.raw ?? '').trim();
8
+ const offset = Number.isFinite(a.offset) ? Number(a.offset) : Number.isFinite(a.start) ? Number(a.start) : 1;
9
+ const limit = Number.isFinite(a.limit) ? Number(a.limit) : Number.isFinite(a.lines) ? Number(a.lines) : null;
10
+ const count = tn('tool.result.lines', lineCount(row.finalOutput));
11
+ const result = limit !== null ? [t('tool.read.lines', { from: offset, to: offset + Math.max(0, limit - 1) })] : offset > 1 ? [t('tool.read.from', { from: offset }), count] : [count];
12
+ return { target: path, result, detail: [] };
13
+ };
@@ -0,0 +1,20 @@
1
+ import { rendererKindFor } from "../tool-display.js";
2
+ import { composeToolRow } from "./row-format.js";
3
+ import { renderRead } from "./read-renderer.js";
4
+ import { renderWrite } from "./write-renderer.js";
5
+ import { renderEdit } from "./edit-renderer.js";
6
+ import { renderBash } from "./bash-renderer.js";
7
+ import { renderSearch } from "./search-renderer.js";
8
+ import { renderList } from "./list-renderer.js";
9
+ import { renderGeneric } from "./generic-renderer.js";
10
+ /* R2 lane T (gate E3): the renderer is chosen through the ONE tool table, by kernel name (tool-display.ts). Before R2 this
11
+ map was keyed `Read`/`Write`/`Bash`…, which no kernel tool is called, so every row fell to the generic renderer and
12
+ printed its raw JSON arguments (review D-07). */
13
+ const RENDERERS = { read: renderRead, write: renderWrite, edit: renderEdit, bash: renderBash, search: renderSearch, list: renderList, generic: renderGeneric };
14
+ /** The row of one tool call at `width` columns; `expanded` is the Ctrl+O view; `now` drives a running row's elapsed time. */
15
+ export function renderTool(row, width, expanded, now = Date.now()) {
16
+ const context = { width: Number.isFinite(width) ? Math.max(1, Math.floor(width)) : Number.POSITIVE_INFINITY, expanded, now };
17
+ return composeToolRow(row, RENDERERS[rendererKindFor(row.name)](row, context), context);
18
+ }
19
+ export function rendererForTool(name) { return { kind: rendererKindFor(name), render: renderTool }; }
20
+ export { renderRead, renderWrite, renderEdit, renderBash, renderSearch, renderList, renderGeneric };