talos-code 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +661 -0
  3. package/README.md +116 -3
  4. package/THIRD_PARTY_NOTICES.md +40 -0
  5. package/dist/archive/zip.js +73 -0
  6. package/dist/args.js +100 -0
  7. package/dist/automations/history-store.js +34 -0
  8. package/dist/automations/policy-store.js +43 -0
  9. package/dist/automations/runner.js +107 -0
  10. package/dist/automations/schedule.js +85 -0
  11. package/dist/automations/windows-task.js +53 -0
  12. package/dist/commands/advanced-cli.js +233 -0
  13. package/dist/commands/checkpoint-cli.js +45 -0
  14. package/dist/commands/config-cli.js +107 -0
  15. package/dist/commands/context.js +17 -0
  16. package/dist/commands/extensions-cli.js +207 -0
  17. package/dist/commands/project-cli.js +74 -0
  18. package/dist/commands/project-commands.js +143 -0
  19. package/dist/commands/provider-cli.js +244 -0
  20. package/dist/commands/services-cli.js +248 -0
  21. package/dist/commands/session-cli.js +171 -0
  22. package/dist/commands/system-cli.js +405 -0
  23. package/dist/config/commands.js +60 -0
  24. package/dist/config/load.js +382 -0
  25. package/dist/config/migrations.js +48 -0
  26. package/dist/config/types.js +11 -0
  27. package/dist/diagnostics/development-log.js +154 -0
  28. package/dist/diagnostics/doctor.js +104 -0
  29. package/dist/diagnostics/redact.js +80 -0
  30. package/dist/diagnostics/zip.js +52 -0
  31. package/dist/errors.js +156 -0
  32. package/dist/events/bridge.js +130 -0
  33. package/dist/extensions/installer.js +178 -0
  34. package/dist/extensions/package-schema.js +24 -0
  35. package/dist/headless/result.js +84 -0
  36. package/dist/headless/run.js +230 -0
  37. package/dist/i18n/en/approval.js +46 -0
  38. package/dist/i18n/en/common.js +9 -0
  39. package/dist/i18n/en/credentials.js +92 -0
  40. package/dist/i18n/en/errors.js +267 -0
  41. package/dist/i18n/en/firstrun.js +101 -0
  42. package/dist/i18n/en/providers.js +37 -0
  43. package/dist/i18n/en/screen.js +774 -0
  44. package/dist/i18n/en/tools.js +127 -0
  45. package/dist/i18n/en.js +14 -0
  46. package/dist/i18n/error-view.js +307 -0
  47. package/dist/i18n/index.js +19 -0
  48. package/dist/i18n/kernel-map.js +139 -0
  49. package/dist/io.js +45 -0
  50. package/dist/main.js +331 -0
  51. package/dist/paths.js +41 -0
  52. package/dist/protocol/v2/codec.js +9 -0
  53. package/dist/protocol/v2/events.js +555 -0
  54. package/dist/protocol/v2/index.js +4 -0
  55. package/dist/protocol/v2/replay.js +28 -0
  56. package/dist/protocol/v2/types.js +1 -0
  57. package/dist/provider/control-plane.js +135 -0
  58. package/dist/provider/environment-keys.js +275 -0
  59. package/dist/provider/health.js +110 -0
  60. package/dist/provider/missing-key.js +48 -0
  61. package/dist/provider/model-catalog.js +168 -0
  62. package/dist/provider/openrouter-login.js +172 -0
  63. package/dist/provider/provider-text.js +13 -0
  64. package/dist/provider/store.js +95 -0
  65. package/dist/provider/system-keyring.js +214 -0
  66. package/dist/runtime/active-run.js +63 -0
  67. package/dist/runtime/agent-tree.js +74 -0
  68. package/dist/runtime/attachments.js +84 -0
  69. package/dist/runtime/brokered-executor.js +395 -0
  70. package/dist/runtime/context-archive.js +69 -0
  71. package/dist/runtime/context-status.js +76 -0
  72. package/dist/runtime/create-runtime.js +111 -0
  73. package/dist/runtime/model-profile.js +361 -0
  74. package/dist/runtime/output-store.js +137 -0
  75. package/dist/runtime/provider-attempts.js +185 -0
  76. package/dist/runtime/replay-buffer.js +153 -0
  77. package/dist/runtime/repo.js +95 -0
  78. package/dist/runtime/session-facade.js +135 -0
  79. package/dist/runtime/session-summary.js +125 -0
  80. package/dist/runtime/supervisor.js +265 -0
  81. package/dist/runtime/talos-composition.js +1011 -0
  82. package/dist/runtime/types.js +5 -0
  83. package/dist/runtime/usage-snapshot.js +82 -0
  84. package/dist/security/auto-classifier.js +38 -0
  85. package/dist/security/credential-free-environment.js +54 -0
  86. package/dist/security/evaluate.js +243 -0
  87. package/dist/security/execution-backends.js +236 -0
  88. package/dist/security/execution-broker.js +102 -0
  89. package/dist/security/forge-scan.js +74 -0
  90. package/dist/security/from-approval.js +39 -0
  91. package/dist/security/mxc-execution-backend.js +281 -0
  92. package/dist/security/permission-engine.js +138 -0
  93. package/dist/security/permission-explanation.js +54 -0
  94. package/dist/security/persist.js +179 -0
  95. package/dist/security/plugin-guard.js +230 -0
  96. package/dist/security/process-tree-evidence-store.js +74 -0
  97. package/dist/security/process-tree-probe.js +554 -0
  98. package/dist/security/project-resource-inventory.js +186 -0
  99. package/dist/security/project-trust-gate.js +38 -0
  100. package/dist/security/project-trust.js +367 -0
  101. package/dist/security/rule-parser.js +201 -0
  102. package/dist/security/shell-segmentation.js +68 -0
  103. package/dist/security/trust-authority.js +324 -0
  104. package/dist/security/types.js +1 -0
  105. package/dist/security/workspace-identity.js +102 -0
  106. package/dist/services/automation-facade.js +59 -0
  107. package/dist/services/forge-facade.js +77 -0
  108. package/dist/services/hook-facade.js +240 -0
  109. package/dist/services/index.js +16 -0
  110. package/dist/services/library-facade.js +174 -0
  111. package/dist/services/mcp-facade.js +348 -0
  112. package/dist/services/memory-facade.js +126 -0
  113. package/dist/services/notes-facade.js +157 -0
  114. package/dist/services/plugin-facade.js +308 -0
  115. package/dist/services/research-facade.js +110 -0
  116. package/dist/services/task-board-facade.js +236 -0
  117. package/dist/services/workflow-catalog.js +246 -0
  118. package/dist/sessions/export-format.js +98 -0
  119. package/dist/sessions/metadata-store.js +160 -0
  120. package/dist/sessions/share.js +122 -0
  121. package/dist/sessions/transfer.js +16 -0
  122. package/dist/subcommands.js +62 -0
  123. package/dist/tui/agent-roster.js +36 -0
  124. package/dist/tui/agent-view.js +51 -0
  125. package/dist/tui/app.js +4098 -0
  126. package/dist/tui/approval.js +36 -0
  127. package/dist/tui/boot/boot-sequence.js +76 -0
  128. package/dist/tui/boot/cinematic.js +243 -0
  129. package/dist/tui/boot/desktop-logo.js +82 -0
  130. package/dist/tui/boot.js +3 -0
  131. package/dist/tui/busy-input.js +58 -0
  132. package/dist/tui/catalog-service.js +560 -0
  133. package/dist/tui/components/assistant-stream.js +1 -0
  134. package/dist/tui/components/command-menu.js +68 -0
  135. package/dist/tui/components/composer.js +219 -0
  136. package/dist/tui/components/diff.js +35 -0
  137. package/dist/tui/components/footer.js +48 -0
  138. package/dist/tui/components/header.js +6 -0
  139. package/dist/tui/components/markdown.js +305 -0
  140. package/dist/tui/components/status-indicator.js +38 -0
  141. package/dist/tui/components/terminal-shell.js +214 -0
  142. package/dist/tui/components/thinking-row.js +19 -0
  143. package/dist/tui/components/tool-row.js +97 -0
  144. package/dist/tui/components/transcript-virtualizer.js +165 -0
  145. package/dist/tui/components/transcript.js +43 -0
  146. package/dist/tui/descendant-approvals.js +104 -0
  147. package/dist/tui/diff-model.js +77 -0
  148. package/dist/tui/editor-history.js +21 -0
  149. package/dist/tui/editor.js +210 -0
  150. package/dist/tui/event-adapter.js +436 -0
  151. package/dist/tui/exit-output.js +58 -0
  152. package/dist/tui/external-editor.js +53 -0
  153. package/dist/tui/file-completion.js +89 -0
  154. package/dist/tui/focus-manager.js +5 -0
  155. package/dist/tui/highlight.js +30 -0
  156. package/dist/tui/input-router.js +18 -0
  157. package/dist/tui/interrupt.js +99 -0
  158. package/dist/tui/keybindings.js +194 -0
  159. package/dist/tui/keymap-resolver.js +91 -0
  160. package/dist/tui/launch-state.js +148 -0
  161. package/dist/tui/line-diff.js +57 -0
  162. package/dist/tui/live-activity.js +56 -0
  163. package/dist/tui/metrics.js +123 -0
  164. package/dist/tui/onboarding.js +36 -0
  165. package/dist/tui/overlays/agent-tree.js +43 -0
  166. package/dist/tui/overlays/approval-dialog.js +642 -0
  167. package/dist/tui/overlays/automation-center.js +51 -0
  168. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  169. package/dist/tui/overlays/context-inspector.js +36 -0
  170. package/dist/tui/overlays/effort-line.js +110 -0
  171. package/dist/tui/overlays/forge-center.js +46 -0
  172. package/dist/tui/overlays/help-dialog.js +16 -0
  173. package/dist/tui/overlays/history-picker.js +37 -0
  174. package/dist/tui/overlays/hook-center.js +70 -0
  175. package/dist/tui/overlays/library-center.js +55 -0
  176. package/dist/tui/overlays/mcp-center.js +60 -0
  177. package/dist/tui/overlays/memory-center.js +63 -0
  178. package/dist/tui/overlays/model-picker.js +77 -0
  179. package/dist/tui/overlays/notes-center.js +53 -0
  180. package/dist/tui/overlays/overlay-host.js +8 -0
  181. package/dist/tui/overlays/plugin-center.js +76 -0
  182. package/dist/tui/overlays/provider-picker.js +171 -0
  183. package/dist/tui/overlays/queue-editor.js +32 -0
  184. package/dist/tui/overlays/research-center.js +59 -0
  185. package/dist/tui/overlays/scroll-window.js +234 -0
  186. package/dist/tui/overlays/session-picker.js +115 -0
  187. package/dist/tui/overlays/tasks-center.js +83 -0
  188. package/dist/tui/overlays/theme-picker.js +21 -0
  189. package/dist/tui/overlays/transcript-search.js +58 -0
  190. package/dist/tui/overlays/trust-center.js +29 -0
  191. package/dist/tui/overlays/workflow-center.js +46 -0
  192. package/dist/tui/project-file-index.js +214 -0
  193. package/dist/tui/project-references.js +85 -0
  194. package/dist/tui/project-trust-prompt.js +289 -0
  195. package/dist/tui/prompt-history-store.js +116 -0
  196. package/dist/tui/queue-store.js +110 -0
  197. package/dist/tui/regions/budget.js +59 -0
  198. package/dist/tui/regions/views.js +96 -0
  199. package/dist/tui/render-coordinator.js +148 -0
  200. package/dist/tui/render-scheduler.js +4 -0
  201. package/dist/tui/run.js +69 -0
  202. package/dist/tui/selection-list.js +29 -0
  203. package/dist/tui/session-controller.js +791 -0
  204. package/dist/tui/session-export.js +54 -0
  205. package/dist/tui/setup-wizard.js +46 -0
  206. package/dist/tui/shell-input.js +35 -0
  207. package/dist/tui/shell-layout.js +48 -0
  208. package/dist/tui/shell-model.js +98 -0
  209. package/dist/tui/slash-commands.js +82 -0
  210. package/dist/tui/state.js +151 -0
  211. package/dist/tui/status-bar.js +125 -0
  212. package/dist/tui/status-view.js +40 -0
  213. package/dist/tui/terminal-capabilities.js +9 -0
  214. package/dist/tui/terminal-session.js +11 -0
  215. package/dist/tui/text-width.js +66 -0
  216. package/dist/tui/theme-catalog.js +27 -0
  217. package/dist/tui/theme-store.js +23 -0
  218. package/dist/tui/theme.js +23 -0
  219. package/dist/tui/tool-display.js +135 -0
  220. package/dist/tui/tool-facts.js +1 -0
  221. package/dist/tui/tools/bash-renderer.js +32 -0
  222. package/dist/tui/tools/change.js +61 -0
  223. package/dist/tui/tools/edit-renderer.js +17 -0
  224. package/dist/tui/tools/generic-renderer.js +13 -0
  225. package/dist/tui/tools/list-renderer.js +14 -0
  226. package/dist/tui/tools/read-renderer.js +13 -0
  227. package/dist/tui/tools/registry.js +20 -0
  228. package/dist/tui/tools/row-format.js +187 -0
  229. package/dist/tui/tools/search-renderer.js +38 -0
  230. package/dist/tui/tools/shared.js +97 -0
  231. package/dist/tui/tools/write-renderer.js +15 -0
  232. package/dist/tui/transcript-model.js +441 -0
  233. package/dist/tui/ui-preferences.js +79 -0
  234. package/dist/tui/usage-view.js +77 -0
  235. package/dist/tui/vim-mode.js +99 -0
  236. package/dist/update/check.js +15 -0
  237. package/dist/update/npm.js +51 -0
  238. package/dist/update/run.js +129 -0
  239. package/dist/version.js +2 -0
  240. package/dist/workspace/checkpoint-store.js +210 -0
  241. package/dist/workspace/checkpoint.js +413 -0
  242. package/dist/workspace/restore.js +232 -0
  243. package/package.json +64 -5
  244. package/vendor/context-engine/package.json +11 -0
  245. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  246. package/vendor/context-engine/src/contracts.mjs +48 -0
  247. package/vendor/context-engine/src/engine.mjs +445 -0
  248. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  249. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  250. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  251. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  252. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  253. package/vendor/context-engine/src/profiles.mjs +10 -0
  254. package/vendor/context-engine/src/retrieval.mjs +104 -0
  255. package/vendor/context-engine/src/summary.mjs +97 -0
  256. package/vendor/context-engine/src/usage.mjs +34 -0
  257. package/vendor/harness-ui/package.json +38 -0
  258. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  259. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  260. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  261. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  262. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  263. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  264. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  265. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  266. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  267. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  268. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  269. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  270. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  271. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  272. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  273. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  274. package/vendor/harness-ui/src/config.mjs +697 -0
  275. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  276. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  277. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  278. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  279. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  280. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  281. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  282. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  283. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  284. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  285. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  286. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  287. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  288. package/vendor/harness-ui/src/doctor.mjs +142 -0
  289. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  290. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  291. package/vendor/harness-ui/src/document-report.mjs +331 -0
  292. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  293. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  294. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  295. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  296. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  297. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  298. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  299. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  300. package/vendor/harness-ui/src/git-service.mjs +626 -0
  301. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  302. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  303. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  304. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  305. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  306. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  307. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  308. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  309. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  310. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  311. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  312. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  313. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  314. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  315. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  316. package/vendor/harness-ui/src/library-store.mjs +652 -0
  317. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  318. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  319. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  320. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  321. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  322. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  323. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  324. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  325. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  326. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  327. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  328. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  329. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  330. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  331. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  332. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  333. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  334. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  335. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  336. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  337. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  338. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  339. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  340. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  341. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  342. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  343. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  344. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  345. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  346. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  347. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  348. package/vendor/harness-ui/src/research/card.mjs +235 -0
  349. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  350. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  351. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  352. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  353. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  354. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  355. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  356. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  357. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  358. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  359. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  360. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  361. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  362. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  363. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  364. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  365. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  366. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  367. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  368. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  369. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  370. package/vendor/harness-ui/src/research/report.mjs +203 -0
  371. package/vendor/harness-ui/src/research/run.mjs +527 -0
  372. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  373. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  374. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  375. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  376. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  377. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  378. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  379. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  380. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  381. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  382. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  383. package/vendor/harness-ui/src/session-store.mjs +220 -0
  384. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  385. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  386. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  387. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  388. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  389. package/vendor/harness-ui/src/static-files.mjs +96 -0
  390. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  391. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  392. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  393. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  394. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  395. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  396. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  397. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  398. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  399. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  400. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  401. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  402. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  403. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  404. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  405. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  406. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  407. package/vendor/manifest.json +170 -0
@@ -0,0 +1,214 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { lstatSync, readlinkSync, realpathSync } from 'node:fs';
3
+ import { createRequire } from 'node:module';
4
+ import { basename, dirname, isAbsolute, join, parse, relative, resolve, sep } from 'node:path';
5
+ import { t } from "../i18n/index.js";
6
+ /*
7
+ * ⛔⛔⛔ WHY THE APPROVED-ROOTS GUARD EXISTS — read for B1 slice 19. The file arrived whole with the gold
8
+ * baseline (7e5b048b, "restore verified gold baseline"), and no commit records the reason, so it is read
9
+ * from the code, from its test (a fake module in an ANCESTOR `node_modules` must be refused) and from
10
+ * this host:
11
+ *
12
+ * - Node's resolution does not stop at TALOS's own folders. From `harness-ui/package.json` it walks every
13
+ * ancestor `node_modules` up to the drive root, then `~/.node_modules`, `~/.node_libraries` and
14
+ * `<prefix>/lib/node`.
15
+ * - On Windows the drive root lets any signed-in account create a folder (`icacls C:\` on this host:
16
+ * `NT AUTHORITY\Authenticated Users:(AD)`, and Modify on what they create). Anyone with a local account
17
+ * can therefore create `C:\node_modules`.
18
+ * - `@napi-rs/keyring` is native code that is handed every provider key TALOS stores. Loaded from such a
19
+ * folder, it would run with the owner's rights and could read or send the keys anywhere.
20
+ *
21
+ * On this host that is what happened, harmlessly: `C:\node_modules` is a junction into another
22
+ * checkout's `harness-ui\node_modules`, and a worktree without `harness-ui\node_modules` resolved the
23
+ * keyring there. The guard refused it, correctly; `doctor` just could not say so.
24
+ *
25
+ * ⛔ THE CURE: the module must be resolvable INSIDE the approved roots.
26
+ * - Installed: `cli/scripts/stage-windows.mjs` copies the dependency trees to `app/node_modules` and
27
+ * `app/vendor/harness-ui/node_modules`, both approved (read in code, not staged).
28
+ * - CI: `npm --prefix harness-ui ci`, inside the checkout.
29
+ * - Development: a `harness-ui\node_modules` inside the checkout — a real install, or ONE junction like the
30
+ * `cli\node_modules` every worktree here already has. Node reports the REAL path behind a junction, so
31
+ * the lexical roots alone refuse even that.
32
+ *
33
+ * ⛔⛔ Round 2, after adversarial review: "the real path of an approved root is approved" was too wide. A
34
+ * link at the root can be trusted as far as whoever placed it, but not further: the reviewer loaded an
35
+ * attacker module through a second link someone else could re-point (A2), through a junction into the real
36
+ * `C:\node_modules` (A3), into an ancestor folder (E), and into the drive root itself (E2). A real path is
37
+ * approved now only when ALL of these hold:
38
+ * 1. the approved root is at most a single link, and its target is not a link and not below one — checked
39
+ * as realpath(target) equal to the target, which fails for both;
40
+ * 2. the target is not a drive root;
41
+ * 3. the target is not an ancestor of the checkout;
42
+ * 4. the target is not inside a `node_modules` folder of an ancestor of the checkout — the folders Node's
43
+ * own lookup reaches, and exactly what `C:\node_modules` is; without this, A3 passes 1-3 on any host
44
+ * where that folder is a plain directory instead of a junction;
45
+ * 5. the module lies under `<target>\@napi-rs\keyring\`.
46
+ * ⛔ The verdict is reached BEFORE anything is loaded: a refused module never runs a line of code.
47
+ * ⛔ What this does NOT judge: who may write to the target. A junction to a folder other accounts can write
48
+ * into (a shared temporary folder, another drive's subfolder) passes when it satisfies 1-5. The guard
49
+ * reads no ACLs.
50
+ * ⛔ REFUSED as a design: recognising a junction ABOVE the checkout because its target looks like a TALOS
51
+ * location. Whoever creates `C:\node_modules` chooses where it points.
52
+ */
53
+ function inside(root, candidate) {
54
+ const rel = relative(resolve(root), resolve(candidate));
55
+ return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel));
56
+ }
57
+ function strictlyInside(root, candidate) { return inside(root, candidate) && relative(resolve(root), resolve(candidate)) !== ''; }
58
+ function samePath(a, b) { return relative(resolve(a), resolve(b)) === ''; }
59
+ function approvedModuleRoots(repoRoot) {
60
+ const roots = [join(repoRoot, 'harness-ui', 'node_modules'), join(repoRoot, 'node_modules')];
61
+ if (basename(repoRoot).toLowerCase() === 'vendor')
62
+ roots.push(join(dirname(repoRoot), 'node_modules'));
63
+ return roots;
64
+ }
65
+ /** Every folder above the checkout, nearest first, up to the drive root. */
66
+ function ancestorsOf(path) {
67
+ const out = [];
68
+ let current = dirname(resolve(path));
69
+ for (;;) {
70
+ out.push(current);
71
+ const next = dirname(current);
72
+ if (next === current)
73
+ break;
74
+ current = next;
75
+ }
76
+ return out;
77
+ }
78
+ /** One line, bounded: an error's later lines are stack frames, and doctor prints one line per check. */
79
+ function firstLine(error) {
80
+ const text = error instanceof Error ? error.message : String(error);
81
+ return (text.split(/\r?\n/u)[0] ?? '').slice(0, 300);
82
+ }
83
+ /**
84
+ * The keyring folder a single link at an approved root may stand for, or null. Rules 1-4 of the block
85
+ * above; rule 5 is the caller's containment check against the folder returned here.
86
+ */
87
+ function linkedKeyringFolder(root, repoRoot, fs) {
88
+ try {
89
+ if (!fs.lstat(root).isSymbolicLink())
90
+ return null;
91
+ const target = resolve(dirname(root), fs.readlink(root));
92
+ if (!fs.lstat(target).isDirectory())
93
+ return null;
94
+ const real = fs.realpath(target);
95
+ if (!samePath(real, target))
96
+ return null; /* 1 */
97
+ if (samePath(parse(real).root, real))
98
+ return null; /* 2 */
99
+ if (inside(real, repoRoot))
100
+ return null; /* 3 */
101
+ if (ancestorsOf(repoRoot).some(ancestor => inside(join(ancestor, 'node_modules'), real)))
102
+ return null; /* 4 */
103
+ return join(real, '@napi-rs', 'keyring');
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
109
+ /*
110
+ * R2 (gate E13): how many times this process tried to LOAD the native module (after resolution and the approved-roots check, the
111
+ * step that runs its code). `doctor` reports whether its own run moved it (`nativeModuleLoaded`): the observable by which the
112
+ * acceptance scenario s16 proves that a memory profile never opened the OS store.
113
+ */
114
+ let moduleLoads = 0;
115
+ export function systemKeyringModuleLoads() { return moduleLoads; }
116
+ export function loadTalosSystemKeyring(repoRoot, deps = {}) {
117
+ /* Created on first use and inside the try below: a repoRoot Node refuses as an anchor is a reason, never a throw. */
118
+ let requireFromTalos;
119
+ const talosRequire = () => requireFromTalos ??= createRequire(join(repoRoot, 'harness-ui', 'package.json'));
120
+ const resolveModule = deps.resolve ?? ((request) => talosRequire().resolve(request));
121
+ const loadModule = deps.load ?? ((file) => talosRequire()(file));
122
+ const fs = {
123
+ lstat: deps.lstat ?? ((path) => lstatSync(path)),
124
+ readlink: deps.readlink ?? ((path) => readlinkSync(path)),
125
+ realpath: deps.realpath ?? ((path) => realpathSync(path)),
126
+ };
127
+ const roots = approvedModuleRoots(repoRoot);
128
+ let location;
129
+ try {
130
+ location = resolveModule('@napi-rs/keyring');
131
+ }
132
+ catch (error) {
133
+ if (error?.code === 'MODULE_NOT_FOUND')
134
+ return { ok: false, reason: 'module-missing', approvedRoots: roots };
135
+ return { ok: false, reason: 'load-failed', detail: firstLine(error) };
136
+ }
137
+ const lexical = roots.some(root => inside(root, location));
138
+ const linked = roots.map(root => linkedKeyringFolder(root, repoRoot, fs)).filter((folder) => folder !== null);
139
+ if (!lexical && !linked.some(folder => strictlyInside(folder, location)))
140
+ return { ok: false, reason: 'outside-approved-roots', location, approvedRoots: roots }; /* 5 */
141
+ let mod;
142
+ moduleLoads++;
143
+ try {
144
+ mod = loadModule(location);
145
+ }
146
+ catch (error) {
147
+ return { ok: false, reason: 'load-failed', location, detail: firstLine(error) };
148
+ }
149
+ return typeof mod?.Entry === 'function' ? { ok: true, Entry: mod.Entry, location } : { ok: false, reason: 'invalid-module', location };
150
+ }
151
+ export function keyringModuleAvailable(repoRoot, deps = {}) { return loadTalosSystemKeyring(repoRoot, deps).ok; }
152
+ export async function diagnoseKeyringProbe(keyring, account = randomUUID()) {
153
+ const service = 'talos-cli-doctor';
154
+ const value = `probe-${randomUUID()}`;
155
+ try {
156
+ try {
157
+ await keyring.set(service, account, value);
158
+ }
159
+ catch (error) {
160
+ return { ok: false, stage: 'write', detail: firstLine(error) };
161
+ }
162
+ let read;
163
+ try {
164
+ read = await keyring.get(service, account);
165
+ }
166
+ catch (error) {
167
+ return { ok: false, stage: 'read', detail: firstLine(error) };
168
+ }
169
+ return read === value ? { ok: true } : { ok: false, stage: 'mismatch' };
170
+ }
171
+ finally {
172
+ try {
173
+ await keyring.remove(service, account);
174
+ }
175
+ catch { /* diagnostic cleanup is best effort */ }
176
+ }
177
+ }
178
+ export async function probeSystemKeyring(keyring, account = randomUUID()) { return (await diagnoseKeyringProbe(keyring, account)).ok; }
179
+ /*
180
+ * R2 (gate E1): `KEYRING_TEXT` moved into the dictionary (`i18n/en/credentials.ts`, `store.keyring.*`), words unchanged. These
181
+ * two functions stay the only place that picks them: `doctor` prints them, and the next surface that needs the reason reuses them.
182
+ */
183
+ export function describeKeyringProblem(problem) {
184
+ switch (problem.reason) {
185
+ case 'module-missing': return t('store.keyring.moduleMissing', { roots: problem.approvedRoots.join('; ') });
186
+ case 'outside-approved-roots': return t('store.keyring.outsideApprovedRoots', { location: problem.location, roots: problem.approvedRoots.join('; ') });
187
+ case 'load-failed': return problem.location === undefined ? t('store.keyring.unresolved', { detail: problem.detail }) : t('store.keyring.loadFailed', { location: problem.location, detail: problem.detail });
188
+ case 'invalid-module': return t('store.keyring.invalidModule', { location: problem.location });
189
+ }
190
+ }
191
+ export function describeKeyringProbeFailure(outcome) {
192
+ if (outcome.stage === 'mismatch')
193
+ return t('store.keyring.probeMismatch');
194
+ return t(outcome.stage === 'write' ? 'store.keyring.probeWriteFailed' : 'store.keyring.probeReadFailed', { detail: outcome.detail });
195
+ }
196
+ export function systemKeyringAdapter(Entry) {
197
+ return {
198
+ get(service, account) { try {
199
+ return new Entry(service, account).getPassword() || null;
200
+ }
201
+ catch {
202
+ return null;
203
+ } },
204
+ set(service, account, value) { new Entry(service, account).setPassword(value); },
205
+ remove(service, account) { try {
206
+ new Entry(service, account).deletePassword();
207
+ }
208
+ catch { /* idempotent removal */ } },
209
+ };
210
+ }
211
+ export function createTalosSystemKeyring(repoRoot, deps = {}) {
212
+ const loaded = loadTalosSystemKeyring(repoRoot, deps);
213
+ return loaded.ok ? systemKeyringAdapter(loaded.Entry) : null;
214
+ }
@@ -0,0 +1,63 @@
1
+ import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { join, resolve } from 'node:path';
3
+ function dir(paths) { return join(paths.dataRoot, 'active-runs'); }
4
+ function marker(paths, pid = process.pid) { return join(dir(paths), `${pid}.json`); }
5
+ function alive(pid) { try {
6
+ process.kill(pid, 0);
7
+ return true;
8
+ }
9
+ catch (error) {
10
+ return error?.code === 'EPERM';
11
+ } }
12
+ export async function registerActiveRun(paths, info = {}) {
13
+ const root = dir(paths);
14
+ await mkdir(root, { recursive: true, mode: 0o700 });
15
+ const file = marker(paths);
16
+ const record = { pid: process.pid, startedAt: new Date().toISOString(), ...info };
17
+ await writeFile(file, `${JSON.stringify(record)}\n`, { encoding: 'utf8', mode: 0o600 });
18
+ let released = false;
19
+ return async () => { if (released)
20
+ return; released = true; await rm(file, { force: true }); };
21
+ }
22
+ /* R5b D3: `exceptPid` leaves out a process (the TUI asking about the others: main.ts registers it for its whole life) and
23
+ `projectRoot` counts only the runs of that project; a marker that does not name its project still counts. */
24
+ function sameRoot(a, b) { const x = resolve(a), y = resolve(b); return process.platform === 'win32' ? x.toLowerCase() === y.toLowerCase() : x === y; }
25
+ export async function hasActiveRuns(paths, deps = {}) {
26
+ const isProcessAlive = deps.isProcessAlive ?? alive;
27
+ let names;
28
+ try {
29
+ names = await readdir(dir(paths));
30
+ }
31
+ catch (error) {
32
+ if (error?.code === 'ENOENT')
33
+ return false;
34
+ throw error;
35
+ }
36
+ let any = false;
37
+ for (const name of names) {
38
+ if (!/^\d+\.json$/u.test(name))
39
+ continue;
40
+ const file = join(dir(paths), name);
41
+ let pid = 0;
42
+ let root = null;
43
+ try {
44
+ const data = JSON.parse(await readFile(file, 'utf8'));
45
+ pid = Number(data?.pid);
46
+ root = data?.projectRoot;
47
+ }
48
+ catch {
49
+ await rm(file, { force: true });
50
+ continue;
51
+ }
52
+ if (!Number.isSafeInteger(pid) || pid <= 0 || !isProcessAlive(pid)) {
53
+ await rm(file, { force: true });
54
+ continue;
55
+ }
56
+ if (deps.exceptPid === pid)
57
+ continue;
58
+ if (deps.projectRoot && typeof root === 'string' && root && !sameRoot(root, deps.projectRoot))
59
+ continue;
60
+ any = true;
61
+ }
62
+ return any;
63
+ }
@@ -0,0 +1,74 @@
1
+ export class CliAgentTreeError extends Error {
2
+ code = 'AGENT_TREE_INVALID';
3
+ constructor(message = 'Agent tree input is invalid.') { super(message); this.name = 'CliAgentTreeError'; }
4
+ }
5
+ function copyUsage(value) { return value ? { ...value } : null; }
6
+ function copyCollisions(value) { return value.map(row => ({ ...row })); }
7
+ function copyEvidence(value) { return value ? { ...value } : null; }
8
+ function nodeOf(row, children) {
9
+ return {
10
+ id: row.id,
11
+ parentId: row.parentId,
12
+ nativeDepth: row.depth,
13
+ name: row.name,
14
+ task: row.delegatedTask,
15
+ model: row.model,
16
+ outcome: row.outcome,
17
+ interrupted: row.interrupted,
18
+ startedAt: row.startedAt,
19
+ updatedAt: row.updatedAt,
20
+ endedAt: row.endedAt,
21
+ usage: copyUsage(row.usage),
22
+ collisions: copyCollisions(row.collisions),
23
+ delegationOutcome: row.delegationOutcome,
24
+ delegationEvidence: copyEvidence(row.delegationEvidence),
25
+ children,
26
+ };
27
+ }
28
+ export function buildAgentTree(rows, focusId) {
29
+ const byId = new Map();
30
+ for (const row of rows) {
31
+ if (typeof row.id !== 'string' || !row.id)
32
+ throw new CliAgentTreeError('Agent tree contains an empty session id.');
33
+ if (byId.has(row.id))
34
+ throw new CliAgentTreeError('Agent tree contains duplicate session ids.');
35
+ byId.set(row.id, row);
36
+ }
37
+ const focus = byId.get(focusId);
38
+ if (!focus)
39
+ return null;
40
+ const validParent = new Map();
41
+ const childIds = new Map();
42
+ for (const row of rows) {
43
+ if (!row.parentId)
44
+ continue;
45
+ const parent = byId.get(row.parentId);
46
+ if (!parent || row.depth !== parent.depth + 1)
47
+ continue;
48
+ validParent.set(row.id, parent.id);
49
+ const siblings = childIds.get(parent.id);
50
+ if (siblings)
51
+ siblings.push(row.id);
52
+ else
53
+ childIds.set(parent.id, [row.id]);
54
+ }
55
+ let root = focus;
56
+ const climbSeen = new Set();
57
+ while (validParent.has(root.id)) {
58
+ if (climbSeen.has(root.id))
59
+ throw new CliAgentTreeError('Agent tree contains a delegation cycle.');
60
+ climbSeen.add(root.id);
61
+ const parent = byId.get(validParent.get(root.id));
62
+ if (!parent)
63
+ break;
64
+ root = parent;
65
+ }
66
+ const build = (id) => {
67
+ const row = byId.get(id);
68
+ if (!row)
69
+ throw new CliAgentTreeError('Agent tree references a missing session.');
70
+ const children = (childIds.get(id) ?? []).map(build);
71
+ return nodeOf(row, children);
72
+ };
73
+ return { focusId: focus.id, root: build(root.id) };
74
+ }
@@ -0,0 +1,84 @@
1
+ import path from 'node:path';
2
+ export const ATTACHMENT_MAX_COUNT = 10;
3
+ export const TEXT_ATTACHMENT_MAX_BYTES = 256 * 1024;
4
+ export const TEXT_ATTACHMENTS_MAX_BYTES = 1024 * 1024;
5
+ export const IMAGE_ATTACHMENT_MAX_BYTES = 5 * 1024 * 1024;
6
+ export const IMAGE_ATTACHMENTS_MAX_BYTES = 12 * 1024 * 1024;
7
+ export class CliAttachmentError extends Error {
8
+ code;
9
+ constructor(code, message = code) { super(message); this.name = 'CliAttachmentError'; this.code = code; }
10
+ }
11
+ function safePath(value) {
12
+ if (typeof value !== 'string' || value.length === 0 || value.length > 1024 || /[\0\r\n]/u.test(value) || value.includes('\\') || path.posix.isAbsolute(value) || path.win32.isAbsolute(value) || value.split('/').some(part => part === '..'))
13
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Attachment path is invalid.');
14
+ return value;
15
+ }
16
+ function exactBase64(value) {
17
+ if (typeof value !== 'string' || value.length === 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value))
18
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Attachment image data is invalid.');
19
+ const bytes = Buffer.from(value, 'base64');
20
+ if (bytes.toString('base64') !== value)
21
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Attachment image data is not canonical base64.');
22
+ return bytes;
23
+ }
24
+ export function imageMimeFromBytes(value) {
25
+ const bytes = Buffer.from(value);
26
+ if (bytes.length >= 8 && bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])))
27
+ return 'image/png';
28
+ if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255)
29
+ return 'image/jpeg';
30
+ if (bytes.length >= 12 && bytes.toString('ascii', 0, 4) === 'RIFF' && bytes.toString('ascii', 8, 12) === 'WEBP')
31
+ return 'image/webp';
32
+ return null;
33
+ }
34
+ export function validateCliAttachments(input) {
35
+ if (input === undefined)
36
+ return [];
37
+ if (!Array.isArray(input))
38
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Attachments must be an array.');
39
+ if (input.length > ATTACHMENT_MAX_COUNT)
40
+ throw new CliAttachmentError('ATTACHMENT_COUNT_LIMIT', `A message can attach at most ${ATTACHMENT_MAX_COUNT} files.`);
41
+ let textBytes = 0, imageBytes = 0;
42
+ const out = [];
43
+ for (const row of input) {
44
+ if (!row || typeof row !== 'object')
45
+ throw new CliAttachmentError('ATTACHMENT_INVALID');
46
+ const attachmentPath = safePath(row.path);
47
+ if (row.kind === 'text') {
48
+ if (row.mimeType !== 'text/plain' || typeof row.text !== 'string' || !Number.isSafeInteger(row.bytes) || row.bytes < 0 || Buffer.byteLength(row.text, 'utf8') !== row.bytes)
49
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Text attachment metadata does not match its content.');
50
+ if (row.bytes > TEXT_ATTACHMENT_MAX_BYTES)
51
+ throw new CliAttachmentError('ATTACHMENT_TEXT_TOO_LARGE', `Text references are limited to ${TEXT_ATTACHMENT_MAX_BYTES} bytes each.`);
52
+ textBytes += row.bytes;
53
+ if (textBytes > TEXT_ATTACHMENTS_MAX_BYTES)
54
+ throw new CliAttachmentError('ATTACHMENT_TEXT_TOTAL_LIMIT', `Text references are limited to ${TEXT_ATTACHMENTS_MAX_BYTES} bytes per message.`);
55
+ out.push({ kind: 'text', path: attachmentPath, mimeType: 'text/plain', bytes: row.bytes, text: row.text });
56
+ continue;
57
+ }
58
+ if (row.kind === 'image') {
59
+ if (!['image/png', 'image/jpeg', 'image/webp'].includes(row.mimeType) || !Number.isSafeInteger(row.bytes) || row.bytes <= 0)
60
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Image attachment metadata is invalid.');
61
+ const bytes = exactBase64(row.dataBase64);
62
+ if (bytes.length !== row.bytes)
63
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Image attachment byte count does not match its content.');
64
+ if (row.bytes > IMAGE_ATTACHMENT_MAX_BYTES)
65
+ throw new CliAttachmentError('ATTACHMENT_IMAGE_TOO_LARGE', `Images are limited to ${IMAGE_ATTACHMENT_MAX_BYTES} bytes each.`);
66
+ if (imageMimeFromBytes(bytes) !== row.mimeType)
67
+ throw new CliAttachmentError('ATTACHMENT_IMAGE_SIGNATURE', 'The declared image type does not match its bytes.');
68
+ imageBytes += row.bytes;
69
+ if (imageBytes > IMAGE_ATTACHMENTS_MAX_BYTES)
70
+ throw new CliAttachmentError('ATTACHMENT_IMAGE_TOTAL_LIMIT', `Images are limited to ${IMAGE_ATTACHMENTS_MAX_BYTES} bytes per message.`);
71
+ out.push({ kind: 'image', path: attachmentPath, mimeType: row.mimeType, bytes: row.bytes, dataBase64: row.dataBase64 });
72
+ continue;
73
+ }
74
+ throw new CliAttachmentError('ATTACHMENT_INVALID', 'Attachment kind is unsupported.');
75
+ }
76
+ return out;
77
+ }
78
+ export function renderPromptWithAttachments(prompt, attachments) {
79
+ const textRows = attachments.filter((row) => row.kind === 'text');
80
+ if (textRows.length === 0)
81
+ return prompt;
82
+ const blocks = textRows.map(row => `[TALOS project reference: ${row.path} · ${row.bytes} bytes]\n${row.text}\n[End TALOS project reference]`);
83
+ return `${prompt}\n\n${blocks.join('\n\n')}`;
84
+ }