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,111 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { findTalosRepoRoot } from "./repo.js";
4
+ import { ensureCliPaths, resolveCliPaths } from "../paths.js";
5
+ import { composeTalosRuntime } from "./talos-composition.js";
6
+ import { assertProjectTrusted } from "../security/project-trust-gate.js";
7
+ import { createCliExecutionBroker } from "../security/execution-backends.js";
8
+ import { createUnbuildableExecutionBroker } from "./brokered-executor.js";
9
+ import { environmentKeyModeForEntry } from "../provider/environment-keys.js";
10
+ import { createRuntimeSupervisor } from "./supervisor.js";
11
+ import { developmentLog, developmentLogError } from "../diagnostics/development-log.js";
12
+ /**
13
+ * ⛔ Il default e' il broker VERO, per identita' e non per somiglianza.
14
+ * `composeTalosRuntime` ha sempre accettato `brokerFactory`, e fino a questa fetta NESSUNO gliela
15
+ * passava: i due ingressi qui sotto omettevano il campo, quindi ogni comando digitato finiva nel
16
+ * ripiego e dichiarava «nessun broker configurato». Il collegamento sta QUI e non nella
17
+ * composizione, perche' la composizione e' gia' parametrica: e' l'ingresso che non sceglieva.
18
+ */
19
+ export const DEFAULT_EXECUTION_BROKER_FACTORY = createCliExecutionBroker;
20
+ /**
21
+ * Consegna alla composizione una fabbrica che costruisce il broker la PRIMA volta che la
22
+ * composizione la chiama, e poi restituisce sempre la stessa istanza.
23
+ *
24
+ * ⛔ Perche' si costruisce DENTRO la chiamata della composizione e non qui: una revisione ha
25
+ * provato a costruire il broker e poi buttarlo via (mutazione M10), e le prove restavano verdi,
26
+ * perche' contavano le costruzioni e non chi le chiedeva. Adesso l'unico modo di costruirlo e'
27
+ * che la composizione lo chieda: costruito e raggiunto sono la stessa cosa.
28
+ * ⛔ Perche' l'istanza e' una sola: il backend misura l'albero di processi al primo `available()`
29
+ * e memoizza quella misura per la sua vita. Una costruzione per comando rifarebbe la sonda ogni
30
+ * volta, e sarebbe un difetto di prestazioni invisibile, perche' il comando funzionerebbe lo stesso.
31
+ *
32
+ * ⛔⛔ E perche' il `try` esiste: la disponibilita' e' a prova di guasto in due versi OPPOSTI.
33
+ * Per l'ISOLAMENTO si chiude (un backend che non prova il suo confinamento non esegue niente:
34
+ * lo decide `execution-broker.ts`). Per l'ESECUZIONE si apre: se il broker non si riesce
35
+ * nemmeno a COSTRUIRE, il comando della persona gira lo stesso attraverso il kernel.
36
+ * ⛔⛔ Ma NON in silenzio (revisione, round 2): prima questo `catch` restituiva «nessun broker» e la
37
+ * riga diceva «non configurato in questa build», anche per un TypeError di contratto. Ora il
38
+ * broker sostituto rifiuta ogni esecuzione portando il codice dell'errore vero, e la riga dice
39
+ * «the isolation broker could not be built (<codice>: <messaggio>)».
40
+ */
41
+ export function resolveExecutionBrokerFactory(input) {
42
+ const factory = input.brokerFactory ?? DEFAULT_EXECUTION_BROKER_FACTORY;
43
+ let broker;
44
+ return { brokerFactory: (options) => {
45
+ if (broker)
46
+ return broker;
47
+ try {
48
+ const built = factory(options);
49
+ broker = built ?? createUnbuildableExecutionBroker(Object.assign(new TypeError('the broker factory returned no broker'), { code: 'EXECUTION_BROKER_FACTORY_RETURNED_NOTHING' }));
50
+ }
51
+ catch (cause) {
52
+ developmentLogError('runtime.broker.construct_failure', cause, { platform: options.platform }, 'runtime-create');
53
+ broker = createUnbuildableExecutionBroker(cause);
54
+ }
55
+ return broker;
56
+ } };
57
+ }
58
+ /**
59
+ * ⛔ `prepared` restituisce l'INTERO argomento di `composeTalosRuntime`, non dei pezzi da
60
+ * riassemblare due volte. Cosi' i due ingressi non possono divergere: una differenza fra loro e'
61
+ * il modo in cui una funzione finisce per esistere in un comando e non nell'altro, ed e' gia'
62
+ * successo in questo programma. Qui non c'e' un secondo posto dove sbagliarla.
63
+ * ⛔ Il broker si costruisce DOPO il cancello della fiducia: un progetto non fidato non arriva
64
+ * nemmeno a toccare la cache delle prove.
65
+ */
66
+ async function prepared(input) {
67
+ const root = input.repoRoot ?? findTalosRepoRoot(process.cwd());
68
+ const paths = input.paths ?? resolveCliPaths(process.env, process.platform, homedir());
69
+ await ensureCliPaths(paths);
70
+ if (!input.trustVerified)
71
+ await assertProjectTrusted({ projectRoot: input.projectRoot, trustRoot: paths.trust.projects });
72
+ return { repoRoot: root, projectRoot: input.projectRoot, paths, model: input.model ?? 'openai:gpt-5-mini', ...(input.keyring !== undefined ? { keyring: input.keyring } : {}), ...resolveExecutionBrokerFactory(input) };
73
+ }
74
+ /**
75
+ * ⭐ B1 slice 18 — WHO USES AN ENVIRONMENT KEY WITHOUT ASKING.
76
+ * The ENTRY decides, and says so explicitly (fix round, condition 3): `main.ts` passes `consent` for the interactive screen and
77
+ * `use` for `talos -p`; the one-shot commands that run a model pass `use` and state the key's origin; `talos provider` passes
78
+ * `consent`. Measured by the coordinator before this round: with the subcommands left on this factory's default,
79
+ * `talos research start` in CI with `OPENROUTER_API_KEY` set exited 2 and sent nothing.
80
+ * ⛔ A caller that forgets to choose gets `consent` from both factories: the closed behaviour.
81
+ * ⛔ `TALOS_ENVIRONMENT_KEYS=consent`, which the screen sets on every child it spawns, closes whatever the entry asked for; no
82
+ * value of that variable opens anything (`environmentKeyModeForEntry`).
83
+ */
84
+ function entryMode(input) { return environmentKeyModeForEntry(input.environmentKeys ?? 'consent', process.env); }
85
+ async function composeRuntimeContext(input) {
86
+ developmentLog('runtime.compose.begin', { projectRoot: input.projectRoot, model: input.model ?? null, environmentKeys: input.environmentKeys ?? 'consent' }, 'debug', 'runtime-create');
87
+ const context = await composeTalosRuntime({ ...await prepared(input), environmentKeys: entryMode(input) });
88
+ developmentLog('runtime.compose.ready', { projectRoot: input.projectRoot, model: input.model ?? null }, 'info', 'runtime-create');
89
+ return context;
90
+ }
91
+ function supervisorRoot(input) {
92
+ const paths = input.paths ?? resolveCliPaths(process.env, process.platform, homedir());
93
+ return join(paths.dataRoot, 'runtime-supervisor');
94
+ }
95
+ export async function createCliRuntime(input) {
96
+ const initial = await composeRuntimeContext(input);
97
+ return createRuntimeSupervisor({
98
+ initialRuntime: initial.runtime,
99
+ runtimeFactory: async () => (await composeRuntimeContext(input)).runtime,
100
+ journalRoot: supervisorRoot(input),
101
+ });
102
+ }
103
+ export async function createCliRuntimeContext(input) {
104
+ const initial = await composeRuntimeContext(input);
105
+ const runtime = createRuntimeSupervisor({
106
+ initialRuntime: initial.runtime,
107
+ runtimeFactory: async () => (await composeRuntimeContext(input)).runtime,
108
+ journalRoot: supervisorRoot(input),
109
+ });
110
+ return { ...initial, runtime };
111
+ }
@@ -0,0 +1,361 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ /*
10
+ * R5 CONTRACT (owner: lane R; stub written by the coordinator so both lanes compile). Owner decision Q-R5-3: a model's
11
+ * context window comes from the registry rows, the provider's live list when it carries the fields, Ollama's /api/show, a
12
+ * person's override (config `models.<provider:model>.contextWindow`) and the models.dev catalogue (one outbound request, no
13
+ * key, 4 h cache). `null` means nobody knows it: the screen then says `ctx ?` and never invents a number (gate E1). Lane S
14
+ * only CALLS modelProfile; lane R owns the body and may add loaders, never change this signature.
15
+ *
16
+ * R5a lane R — the body. `modelProfile` is synchronous (the screen calls it while drawing): it reads layers that the
17
+ * composition fills and keeps fresh, highest first:
18
+ * 1. `override` the person's `models.<provider:model>.contextWindow` (and, optional, `.maxOutputTokens`), config/load.ts;
19
+ * 2. `ollama-show` a local Ollama's own answer for the model (see `ollamaWindow`);
20
+ * 3. `provider` rows the provider's store keeps (`provider-runtime.json` `modelli`) and live catalogue rows that carry a
21
+ * window (catalog-service.ts, e.g. OpenRouter's `context_length`);
22
+ * 4. `registry` the kernel registry's documented rows (`modelliNoti`, `modelliDiRiserva`: dated sources);
23
+ * 5. `models.dev` the kernel's catalogue adapter (model-catalog-models-dev.mjs), under gate E7 (see `createModelsDevLoader`).
24
+ * The window comes from the highest layer that has one; the reserve (the model's maximum output, which the kernel sends as
25
+ * `max_tokens` once the Context Engine prepares the request, talosHarness.mjs `preparedContext.measurement.responseReserve`)
26
+ * from the highest layer that knows it. When no layer knows the output limit the reserve is Pi's default for a model without
27
+ * one, 16,384 (pi-mono packages/coding-agent/src/core/provider-composer.ts:225 `maxTokens: definition.maxTokens ?? 16384`,
28
+ * 2026-09-24), never more than a quarter of the window.
29
+ */
30
+ import { pathToFileURL } from 'node:url';
31
+ import { join } from 'node:path';
32
+ const DEFAULT_RESERVE = 16_384;
33
+ /*
34
+ * R5a (owner decision 2026-09-24, from the s22 acceptance run): the Context Engine runs only for a window of 64k tokens or
35
+ * more. TALOS's own instructions and tools are about 11.1k tokens; the engine's input limit is the window minus the reserve
36
+ * (a quarter of a small window) minus a 15 % heuristic margin (context-engine profiles.mjs:6), about 0.6 x the window: a 16k
37
+ * window failed every turn (CTX_CONTEXT_OVERFLOW) and anything under ~40k compacts at once. Below this TALOS keeps its simple
38
+ * mode (the kernel's path) and the screen says so once (tui/usage-view.ts smallWindowNotice).
39
+ */
40
+ export const CONTEXT_ENGINE_MIN_WINDOW = 64_000;
41
+ const state = {
42
+ rowsFor: (() => ({ runtime: [], registry: [] })),
43
+ registry: {},
44
+ overrides: new Map(),
45
+ ollama: new Map(),
46
+ live: new Map(),
47
+ modelsDev: new Map(),
48
+ };
49
+ function positiveInteger(value) { return Number.isSafeInteger(value) && Number(value) > 0 ? Number(value) : null; }
50
+ function positiveNumber(value) { const n = typeof value === 'string' && value.trim() !== '' ? Number(value) : value; return typeof n === 'number' && Number.isFinite(n) && n >= 0 ? n : null; }
51
+ function keyOf(provider, model) { const prefix = `${provider}:`; return `${provider}:${model.startsWith(prefix) ? model.slice(prefix.length) : model}`; }
52
+ function day(value) { if (typeof value !== 'string' || !value)
53
+ return null; const match = /^\d{4}-\d{2}-\d{2}/u.exec(value); return match ? match[0] : null; }
54
+ function today(now = Date.now()) { return new Date(now).toISOString().slice(0, 10); }
55
+ /** The composition's sources: the provider store's rows and the registry's, read live on every call (they are small). A new
56
+ * composition is a new runtime: what an earlier one learnt from the network (live lists, Ollama, models.dev) is dropped and
57
+ * learnt again (models.dev from its disk cache). */
58
+ export function configureModelProfiles({ rowsFor, registry }) {
59
+ state.rowsFor = rowsFor;
60
+ state.registry = registry ?? {};
61
+ state.overrides.clear();
62
+ state.ollama.clear();
63
+ state.live.clear();
64
+ state.modelsDev.clear();
65
+ }
66
+ /** Test and restart hygiene: every layer back to empty. */
67
+ export function resetModelProfiles() {
68
+ state.rowsFor = () => ({ runtime: [], registry: [] });
69
+ state.registry = {};
70
+ state.overrides.clear();
71
+ state.ollama.clear();
72
+ state.live.clear();
73
+ state.modelsDev.clear();
74
+ }
75
+ /** `config.models` (validated by config/load.ts): `{"provider:model":{contextWindow,maxOutputTokens?}}`. */
76
+ export function setModelOverrides(models) {
77
+ state.overrides.clear();
78
+ if (!models || typeof models !== 'object' || Array.isArray(models))
79
+ return;
80
+ for (const [id, row] of Object.entries(models)) {
81
+ const windowTokens = positiveInteger(row?.contextWindow), outputTokens = positiveInteger(row?.maxOutputTokens);
82
+ if (windowTokens === null && outputTokens === null)
83
+ continue;
84
+ const split = splitModelId(id);
85
+ if (!split)
86
+ continue;
87
+ state.overrides.set(keyOf(split.provider, split.model), { windowTokens, outputTokens });
88
+ }
89
+ }
90
+ /** The provider part of a TALOS model id: a known registry prefix, else OpenRouter (model-destination.mjs:65-75). */
91
+ export function splitModelId(id) {
92
+ if (typeof id !== 'string' || !id.trim())
93
+ return null;
94
+ const cut = id.indexOf(':');
95
+ if (cut > 0) {
96
+ const provider = id.slice(0, cut);
97
+ if (Object.hasOwn(state.registry, provider) || provider === 'openrouter' || provider === 'ollama' || provider === 'local')
98
+ return { provider, model: id.slice(cut + 1) };
99
+ }
100
+ return { provider: 'openrouter', model: id };
101
+ }
102
+ /** A local engine (the registry's `catalogo.fonte: 'runtime-locale'`: Ollama, LM Studio, the embedded runtime). */
103
+ export function isLocalProvider(provider) {
104
+ if (!provider)
105
+ return false;
106
+ if (provider === 'local')
107
+ return true;
108
+ return state.registry[provider]?.catalogo?.fonte === 'runtime-locale';
109
+ }
110
+ /** Rows from a provider's live catalogue (OpenRouter `/models`, a kernel probe list): those that carry a window. */
111
+ export function rememberProviderModelRows(provider, rows, now = Date.now()) {
112
+ for (const row of rows ?? []) {
113
+ const raw = String(row?.id ?? row?.modelId ?? '').trim();
114
+ if (!raw)
115
+ continue;
116
+ const windowTokens = positiveInteger(row?.context_length ?? row?.contextLength ?? row?.contextWindow);
117
+ const outputTokens = positiveInteger(row?.top_provider?.max_completion_tokens ?? row?.maxOutputTokens ?? row?.max_output_tokens);
118
+ const prompt = positiveNumber(row?.pricing?.prompt), completion = positiveNumber(row?.pricing?.completion), cacheRead = positiveNumber(row?.pricing?.input_cache_read);
119
+ const price = prompt !== null && completion !== null ? { inputPerMTok: prompt * 1_000_000, outputPerMTok: completion * 1_000_000, cacheReadPerMTok: cacheRead === null ? null : cacheRead * 1_000_000, source: `${provider} model list`, date: today(now) } : null;
120
+ if (windowTokens === null && outputTokens === null && !price)
121
+ continue;
122
+ state.live.set(keyOf(provider, raw), { windowTokens, outputTokens, date: today(now), price });
123
+ }
124
+ }
125
+ /** Ollama's own window for a model (see `ollamaWindow`). */
126
+ export function rememberOllamaWindow(provider, model, windowTokens, now = Date.now()) {
127
+ const key = keyOf(provider, model);
128
+ if (windowTokens === null) {
129
+ state.ollama.delete(key);
130
+ return;
131
+ }
132
+ state.ollama.set(key, { windowTokens, outputTokens: null, date: today(now) });
133
+ }
134
+ function registryLayers(provider, model) {
135
+ let rows = { runtime: [], registry: [] };
136
+ try {
137
+ rows = state.rowsFor(provider) ?? rows;
138
+ }
139
+ catch { /* a source that cannot be read is no source */ }
140
+ const same = (row) => { const raw = String(row?.id ?? row?.modelId ?? ''); return raw === model || raw === `${provider}:${model}`; };
141
+ const layer = (row) => row ? { windowTokens: positiveInteger(row.contextLength ?? row.contextWindow ?? row.max_context_length ?? row.maxInputTokens), outputTokens: positiveInteger(row.maxOutputTokens ?? row.max_output_tokens ?? row.outputTokenLimit), date: day(row.dataMetadati ?? row.data) } : null;
142
+ const runtimeRow = (rows.runtime ?? []).find(same), registryRow = (rows.registry ?? []).find(same);
143
+ const record = state.registry[provider];
144
+ const own = registryRow?.prezzi;
145
+ const price = own && positiveNumber(own.ingresso) !== null && positiveNumber(own.uscita) !== null
146
+ ? { inputPerMTok: positiveNumber(own.ingresso), outputPerMTok: positiveNumber(own.uscita), cacheReadPerMTok: positiveNumber(own.cache), source: typeof record?.prezzi?.fonte === 'string' ? record.prezzi.fonte : 'TALOS provider registry', date: day(record?.prezzi?.data) ?? day(registryRow?.data) }
147
+ : null;
148
+ return { provider: layer(runtimeRow), registry: layer(registryRow), price };
149
+ }
150
+ export function modelProfile(input) {
151
+ const provider = typeof input?.provider === 'string' ? input.provider : '';
152
+ const model = typeof input?.model === 'string' ? input.model : '';
153
+ if (!provider || !model)
154
+ return null;
155
+ const key = keyOf(provider, model);
156
+ const bare = key.slice(provider.length + 1);
157
+ const fixed = registryLayers(provider, bare);
158
+ const override = state.overrides.get(key);
159
+ const layers = [
160
+ ['override', override ? { windowTokens: override.windowTokens, outputTokens: override.outputTokens, date: null } : null],
161
+ ['ollama-show', state.ollama.get(key)],
162
+ ['provider', fixed.provider],
163
+ ['provider', state.live.get(key)],
164
+ ['registry', fixed.registry],
165
+ ['models.dev', state.modelsDev.get(key)],
166
+ ];
167
+ const windowLayer = layers.find(([, layer]) => layer?.windowTokens);
168
+ if (!windowLayer)
169
+ return null;
170
+ const [source, chosen] = windowLayer;
171
+ const windowTokens = chosen.windowTokens;
172
+ const output = layers.find(([, layer]) => layer?.outputTokens)?.[1]?.outputTokens ?? null;
173
+ const responseReserve = output !== null && output < windowTokens ? output : Math.max(1, Math.min(DEFAULT_RESERVE, Math.floor(windowTokens / 4)));
174
+ if (responseReserve >= windowTokens)
175
+ return null;
176
+ return { windowTokens, responseReserve, source, date: chosen.date };
177
+ }
178
+ /** Where the window of `modelProfile` comes from, for the context status's provenance: a row's own dated source URL when the
179
+ * registry or the provider's store names one, else the layer's name. */
180
+ export function modelProfileEvidence(input) {
181
+ const profile = modelProfile(input);
182
+ if (!profile)
183
+ return null;
184
+ if (profile.source === 'registry' || profile.source === 'provider') {
185
+ let rows = { runtime: [], registry: [] };
186
+ try {
187
+ rows = state.rowsFor(input.provider) ?? rows;
188
+ }
189
+ catch { /* no rows */ }
190
+ const bare = keyOf(input.provider, input.model).slice(input.provider.length + 1);
191
+ const row = [...(rows.runtime ?? []), ...(rows.registry ?? [])].find((candidate) => { const raw = String(candidate?.id ?? candidate?.modelId ?? ''); return raw === bare || raw === `${input.provider}:${bare}`; });
192
+ const url = typeof row?.fonteMetadati === 'string' ? row.fonteMetadati : typeof row?.fonte === 'string' ? row.fonte : null;
193
+ if (url)
194
+ return { source: url, date: profile.date };
195
+ }
196
+ return { source: profile.source, date: profile.date };
197
+ }
198
+ /** The list price of a model from a NAMED source (registry, live list, models.dev), or null. Never invented. */
199
+ export function modelPrice(input) {
200
+ const provider = typeof input?.provider === 'string' ? input.provider : '';
201
+ const model = typeof input?.model === 'string' ? input.model : '';
202
+ if (!provider || !model || isLocalProvider(provider))
203
+ return null;
204
+ const key = keyOf(provider, model);
205
+ const bare = key.slice(provider.length + 1);
206
+ return registryLayers(provider, bare).price ?? state.live.get(key)?.price ?? state.modelsDev.get(key)?.price ?? null;
207
+ }
208
+ /*
209
+ * OLLAMA. The window Ollama runs a model with is NOT the model's trained maximum (`model_info.<arch>.context_length`, which
210
+ * /api/show and /api/tags report): it is the Modelfile's `num_ctx`, else the server's default — "Context length to use unless
211
+ * otherwise specified (default: 4k/32k/256k based on VRAM)" (ollama/ollama envconfig/config.go, 98acec40, 2026-09-15). A
212
+ * loaded model reports the window it really has in /api/ps `context_length` (api/types.go `ProcessModelResponse`, d0c8cdb7,
213
+ * 2026-09-18). So: `num_ctx` from /api/show `parameters` when set; else /api/ps for a loaded model; else unknown. The trained
214
+ * maximum only caps the first. Same rules as the R4 local list (catalog-service.ts): no key, no redirect, capped, 3 s.
215
+ */
216
+ const OLLAMA_TIMEOUT_MS = 3_000, OLLAMA_MAX_BYTES = 4 * 1024 * 1024;
217
+ async function readJsonCapped(response) {
218
+ if (!response.ok || !response.body) {
219
+ try {
220
+ await response.body?.cancel();
221
+ }
222
+ catch { /* not read */ }
223
+ return null;
224
+ }
225
+ const reader = response.body.getReader();
226
+ const chunks = [];
227
+ let size = 0;
228
+ try {
229
+ for (;;) {
230
+ const { value, done } = await reader.read();
231
+ if (done)
232
+ break;
233
+ size += value.byteLength;
234
+ if (size > OLLAMA_MAX_BYTES)
235
+ return null;
236
+ chunks.push(value);
237
+ }
238
+ }
239
+ finally {
240
+ await reader.cancel().catch(() => { });
241
+ }
242
+ try {
243
+ return JSON.parse(new TextDecoder().decode(Buffer.concat(chunks)));
244
+ }
245
+ catch {
246
+ return null;
247
+ }
248
+ }
249
+ export async function ollamaWindow({ root, model, fetchImpl, signal }) {
250
+ const base = String(root ?? '').trim().replace(/\/+$/u, '').replace(/\/v1$/u, '');
251
+ if (!/^https?:\/\//iu.test(base))
252
+ return null;
253
+ const timeout = () => signal ? AbortSignal.any([signal, AbortSignal.timeout(OLLAMA_TIMEOUT_MS)]) : AbortSignal.timeout(OLLAMA_TIMEOUT_MS);
254
+ let trained = null;
255
+ try {
256
+ const show = await readJsonCapped(await fetchImpl(`${base}/api/show`, { method: 'POST', headers: { 'content-type': 'application/json', accept: 'application/json' }, body: JSON.stringify({ model }), redirect: 'error', signal: timeout() }));
257
+ const info = show?.model_info && typeof show.model_info === 'object' ? show.model_info : {};
258
+ trained = positiveInteger(Object.entries(info).find(([name]) => name.endsWith('.context_length'))?.[1]);
259
+ const numCtx = /(?:^|\n)\s*num_ctx\s+(\d+)\s*(?:\n|$)/u.exec(String(show?.parameters ?? ''));
260
+ if (numCtx) {
261
+ const value = positiveInteger(Number(numCtx[1]));
262
+ if (value !== null)
263
+ return trained !== null ? Math.min(value, trained) : value;
264
+ }
265
+ }
266
+ catch { /* not reachable: unknown */ }
267
+ try {
268
+ const ps = await readJsonCapped(await fetchImpl(`${base}/api/ps`, { method: 'GET', headers: { accept: 'application/json' }, redirect: 'error', signal: timeout() }));
269
+ const row = (Array.isArray(ps?.models) ? ps.models : []).find((entry) => entry?.name === model || entry?.model === model);
270
+ const loaded = positiveInteger(row?.context_length);
271
+ if (loaded !== null)
272
+ return loaded;
273
+ }
274
+ catch { /* not reachable: unknown */ }
275
+ return null;
276
+ }
277
+ /*
278
+ * MODELS.DEV, under gate E7: one outbound GET of https://models.dev/api.json, no key, no personal data; cached 4 h under the
279
+ * data root by the kernel adapter itself (model-catalog-models-dev.mjs: `<dataRoot>/cache/models-dev-<hash>.json`, TTL 4 h,
280
+ * ETag revalidation, schema-checked); this wrapper adds what E7 asks and the adapter does not do: `redirect:'error'`, a body
281
+ * capped at 32 MiB, 15 s (the adapter's own timeout). OFF in test profiles (`provider/store.ts` `isTestProfile`:
282
+ * TALOS_TEST_PROFILE=1 or NODE_TEST_CONTEXT) and when `TALOS_MODELS_DEV=off`: then nothing is imported and nothing is sent.
283
+ */
284
+ export const MODELS_DEV_URL = 'https://models.dev/api.json';
285
+ export const MODELS_DEV_MAX_BYTES = 32 * 1024 * 1024;
286
+ export function modelsDevFetch(fetchImpl, maxBytes = MODELS_DEV_MAX_BYTES) {
287
+ return async (url, init = {}) => {
288
+ const response = await fetchImpl(url, { ...init, redirect: 'error' });
289
+ const declared = Number(response.headers?.get?.('content-length'));
290
+ if (Number.isFinite(declared) && declared > maxBytes) {
291
+ try {
292
+ await response.body?.cancel();
293
+ }
294
+ catch { /* refused */ }
295
+ throw Object.assign(new Error('MODELS_DEV_TOO_LARGE'), { code: 'MODELS_DEV_TOO_LARGE' });
296
+ }
297
+ if (!response.body)
298
+ return response;
299
+ const reader = response.body.getReader();
300
+ const chunks = [];
301
+ let size = 0;
302
+ try {
303
+ for (;;) {
304
+ const { value, done } = await reader.read();
305
+ if (done)
306
+ break;
307
+ size += value.byteLength;
308
+ if (size > maxBytes)
309
+ throw Object.assign(new Error('MODELS_DEV_TOO_LARGE'), { code: 'MODELS_DEV_TOO_LARGE' });
310
+ chunks.push(value);
311
+ }
312
+ }
313
+ finally {
314
+ await reader.cancel().catch(() => { });
315
+ }
316
+ return new Response(Buffer.concat(chunks), { status: response.status, statusText: response.statusText, headers: response.headers });
317
+ };
318
+ }
319
+ export const MODELS_DEV_CACHE_HOURS = 4;
320
+ export function modelsDevSwitch({ env, config, testProfile }) {
321
+ if (testProfile)
322
+ return { enabled: false, reason: 'test' };
323
+ if (String(env.TALOS_MODELS_DEV ?? '').trim().toLowerCase() === 'off')
324
+ return { enabled: false, reason: 'environment' };
325
+ if (config?.catalog?.modelsDev === false)
326
+ return { enabled: false, reason: 'config' };
327
+ return { enabled: true, reason: 'on' };
328
+ }
329
+ export function createModelsDevLoader({ repoRoot, dataRoot, env, config, fetchImpl, testProfile }) {
330
+ if (!modelsDevSwitch({ env, config, testProfile }).enabled)
331
+ return { enabled: false, load: async () => { } };
332
+ let catalog = null;
333
+ const done = new Map();
334
+ const open = () => catalog ??= import(__rewriteRelativeImportExtension(pathToFileURL(join(repoRoot, 'harness-ui', 'src', 'model-catalog-models-dev.mjs')).href))
335
+ .then((m) => m.createModelsDevCatalog({ cartellaStore: dataRoot, url: MODELS_DEV_URL, fetchFn: modelsDevFetch(fetchImpl) }));
336
+ return {
337
+ enabled: true,
338
+ load(provider) {
339
+ const known = done.get(provider);
340
+ if (known)
341
+ return known;
342
+ const work = (async () => {
343
+ const result = await (await open()).ottieni(provider);
344
+ if (!result?.disponibile)
345
+ return;
346
+ const date = day(result.aggiornatoAlle);
347
+ for (const row of result.modelli ?? []) {
348
+ const model = String(row?.modelId ?? '');
349
+ if (!model)
350
+ continue;
351
+ const prices = row?.prezziPerMilione;
352
+ const input = positiveNumber(prices?.input), output = positiveNumber(prices?.output);
353
+ state.modelsDev.set(keyOf(provider, model), { windowTokens: positiveInteger(row.contextLength), outputTokens: positiveInteger(row.maxOutputTokens), date,
354
+ price: input !== null && output !== null ? { inputPerMTok: input, outputPerMTok: output, cacheReadPerMTok: positiveNumber(prices?.cache_read), source: 'models.dev', date } : null });
355
+ }
356
+ })().catch(() => { done.delete(provider); });
357
+ done.set(provider, work);
358
+ return work;
359
+ },
360
+ };
361
+ }
@@ -0,0 +1,137 @@
1
+ /*
2
+ * R5a lane R, S6 — owner decision Q-R5-10 (2026-09-24), gate E6: a long command output is never cut in silence.
3
+ *
4
+ * The CLI holds the whole output before it is cut (brokered-executor.ts), so it keeps it: a private file under the data root
5
+ * (`<dataRoot>/tool-output/<sessionId>/<time>-<id>.txt`), never under the project; folder 0o700 and file 0o600 (on Windows the
6
+ * data root is inside the person's profile, whose ACL already admits only its owner; the mode bits are what POSIX reads),
7
+ * written once (`wx`), redacted with the existing secret patterns (`diagnostics/redact.ts`: the environment's secret values,
8
+ * `KEY=value` assignments, vendor-prefixed tokens, Bearer credentials), and deleted with its session: `deleteSessionToolOutput`
9
+ * for `talos session delete`, `pruneToolOutput` at start for a session whose record is gone.
10
+ *
11
+ * What the model reads is the same cut as before (a quarter kept from the head, three quarters from the tail, 4,000
12
+ * characters: the kernel's `uscitaUtile`, talosHarness.mjs:1489-1506) with an ENGLISH marker in place of the kernel's Italian
13
+ * `… [tolti N caratteri dal mezzo] …`: how much was cut, how much is shown, and the file that holds the rest (Pi, Claude
14
+ * Code, Gemini and OpenCode name the full-output file; gate §8). The marker is model-facing text, not a screen word: it stays
15
+ * English whatever the screen language, and the screen reads its numbers through `parseToolOutputMarker`.
16
+ */
17
+ import { randomUUID } from 'node:crypto';
18
+ import { existsSync } from 'node:fs';
19
+ import { chmod, mkdir, readdir, rm, writeFile } from 'node:fs/promises';
20
+ import { join } from 'node:path';
21
+ import { createRedactor } from "../diagnostics/redact.js";
22
+ /** The kernel's own cut for a command's output: 4,000 characters, a quarter from the head (talosHarness.mjs:1489). */
23
+ export const TOOL_OUTPUT_LIMIT = 4_000;
24
+ export const TOOL_OUTPUT_HEAD_SHARE = 0.25;
25
+ /** A file keeps at most this many characters; beyond it the file says where it stopped. */
26
+ export const TOOL_OUTPUT_FILE_MAX = 8_000_000;
27
+ const FOLDER = 'tool-output';
28
+ const SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
29
+ /** The kernel's Italian cut marker, whole (talosHarness.mjs:1505); pinned against the kernel source by r5a-r-output-store.test.ts. */
30
+ export const KERNEL_CUT_MARKER = /\n\n… \[tolti (?<removed>\d+) caratteri dal mezzo\] …\n\n/u;
31
+ const MARKER = /… \[TALOS cut (?<removed>\d+) characters from the middle of this output; (?<kept>\d+) of (?<total>\d+) characters are shown\.(?: The full output is saved in "(?<path>[^"\r\n]+)"; read that file for the rest\.| The full output could not be saved\.)\] …/u;
32
+ function validSessionId(sessionId) { return typeof sessionId === 'string' && SESSION_ID.test(sessionId) && !sessionId.includes('..'); }
33
+ export function toolOutputRoot(dataRoot) { return join(dataRoot, FOLDER); }
34
+ export function createToolOutputStore({ dataRoot, secretValues = [], now = () => Date.now(), newId = () => randomUUID() }) {
35
+ const redactor = createRedactor(secretValues);
36
+ return {
37
+ async save({ sessionId, text }) {
38
+ if (!validSessionId(sessionId))
39
+ return null;
40
+ try {
41
+ const folder = join(toolOutputRoot(dataRoot), sessionId);
42
+ await mkdir(folder, { recursive: true, mode: 0o700 });
43
+ const body = text.length > TOOL_OUTPUT_FILE_MAX ? `${text.slice(0, TOOL_OUTPUT_FILE_MAX)}\n[TALOS stopped keeping this output after ${TOOL_OUTPUT_FILE_MAX} characters.]\n` : text;
44
+ const file = join(folder, `${now()}-${newId().replace(/[^A-Za-z0-9-]/gu, '').slice(0, 12)}.txt`);
45
+ await writeFile(file, redactor.text(body), { encoding: 'utf8', mode: 0o600, flag: 'wx' });
46
+ try {
47
+ await chmod(file, 0o600);
48
+ }
49
+ catch { /* Windows: the profile's ACL is the boundary */ }
50
+ return { path: file };
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ },
56
+ };
57
+ }
58
+ /** Removes the one folder of one session's kept outputs (named, validated; never a pattern). */
59
+ export async function deleteSessionToolOutput(dataRoot, sessionId) {
60
+ if (!validSessionId(sessionId))
61
+ return false;
62
+ const folder = join(toolOutputRoot(dataRoot), sessionId);
63
+ if (!existsSync(folder))
64
+ return false;
65
+ await rm(folder, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
66
+ return true;
67
+ }
68
+ /**
69
+ * At start: the folders of sessions whose record no longer exists (`<sessionsRoot>/<id>.jsonl`, session-store.mjs:53-56) are
70
+ * removed, one named folder at a time after that check. Returns the ids removed. Never throws.
71
+ */
72
+ export async function pruneToolOutput({ dataRoot, sessionsRoot }) {
73
+ const removed = [];
74
+ let entries = [];
75
+ try {
76
+ entries = await readdir(toolOutputRoot(dataRoot), { withFileTypes: true });
77
+ }
78
+ catch {
79
+ return removed;
80
+ }
81
+ for (const entry of entries) {
82
+ if (!entry.isDirectory() || !validSessionId(entry.name))
83
+ continue;
84
+ if (existsSync(join(sessionsRoot, `${entry.name}.jsonl`)))
85
+ continue;
86
+ try {
87
+ if (await deleteSessionToolOutput(dataRoot, entry.name))
88
+ removed.push(entry.name);
89
+ }
90
+ catch { /* the next start tries again */ }
91
+ }
92
+ return removed;
93
+ }
94
+ function markerText(removed, kept, total, saved) {
95
+ const where = saved ? ` The full output is saved in "${saved.path}"; read that file for the rest.` : ' The full output could not be saved.';
96
+ return `… [TALOS cut ${removed} characters from the middle of this output; ${kept} of ${total} characters are shown.${where}] …`;
97
+ }
98
+ /** The kernel's head/tail cut with the English marker. The text is returned unchanged when it fits. */
99
+ export function cutToolOutput(full, saved, { limit = TOOL_OUTPUT_LIMIT, headShare = TOOL_OUTPUT_HEAD_SHARE } = {}) {
100
+ if (full.length <= limit)
101
+ return full;
102
+ const head = Math.max(0, Math.round(limit * headShare));
103
+ const tail = limit - head;
104
+ return `${full.slice(0, head)}\n\n${markerText(full.length - limit, limit, full.length, saved)}\n\n${full.slice(full.length - tail)}`;
105
+ }
106
+ /** The kernel's own cut (fallback executor): its Italian marker replaced by the English one, the kept text untouched. */
107
+ export function replaceKernelCutMarker(text, saved, { limit = TOOL_OUTPUT_LIMIT } = {}) {
108
+ const match = KERNEL_CUT_MARKER.exec(text);
109
+ if (!match)
110
+ return text;
111
+ const removed = Number(match.groups.removed);
112
+ return text.replace(KERNEL_CUT_MARKER, () => `\n\n${markerText(removed, limit, limit + removed, saved)}\n\n`);
113
+ }
114
+ export function hasKernelCutMarker(text) { return KERNEL_CUT_MARKER.test(text); }
115
+ /**
116
+ * The kernel's ENGLISH marker on a tool result it cut at 8,000 characters (the owner's amendment Q-R5-11, talosHarness.mjs
117
+ * `esitoAttrezzoPerIlModello`, asked for with `toolResultCutMarker`), always the last paragraph of the result. Pinned against
118
+ * the kernel by r5a-r-kernel-amendment.test.ts.
119
+ */
120
+ export const KERNEL_TOOL_RESULT_CUT = /\n\n\[TALOS cut this tool result at (?<limit>\d+) characters: (?<shown>\d+) of (?<total>\d+) characters and (?<shownLines>\d+) of (?<totalLines>\d+) lines are shown\. Ask for a smaller part \(a line range or a search\) to read the rest\.\]$/u;
121
+ export function parseToolResultCut(text) {
122
+ const match = KERNEL_TOOL_RESULT_CUT.exec(String(text ?? ''));
123
+ if (!match)
124
+ return null;
125
+ const g = match.groups;
126
+ return { limitChars: Number(g.limit), shownChars: Number(g.shown), totalChars: Number(g.total), shownLines: Number(g.shownLines), totalLines: Number(g.totalLines) };
127
+ }
128
+ /** The result without the kernel's cut marker, for a screen that states the cut in its own words. */
129
+ export function withoutToolResultCut(text) { return String(text ?? '').replace(KERNEL_TOOL_RESULT_CUT, ''); }
130
+ /** The marker's facts, for the screen (`tool.output.saved`); `path` is null when the output could not be saved. */
131
+ export function parseToolOutputMarker(text) {
132
+ const match = MARKER.exec(String(text ?? ''));
133
+ if (!match)
134
+ return null;
135
+ const g = match.groups;
136
+ return { removedChars: Number(g.removed), keptChars: Number(g.kept), totalChars: Number(g.total), path: g.path ?? null };
137
+ }