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
package/README.md CHANGED
@@ -1,3 +1,111 @@
1
- # talos-code
2
- Official npm package of the TALOS CLI (https://github.com/Ninozzz95/talos).
3
- This first version reserves the name; the CLI is published here.
1
+ # TALOS CLI
2
+
3
+ TALOS in your terminal: a coding agent that reads, edits and runs code in your project, on the model you choose. Every tool
4
+ asks before it acts unless you have allowed it, every file it changes can be restored, and every session can be resumed.
5
+
6
+ The npm package is **`talos-code`**; the command it installs is **`talos`**.
7
+
8
+ ## Install
9
+
10
+ TALOS CLI needs **Node.js 24** (24.18 or later in the 24 line).
11
+
12
+ <!-- test:smoke -->
13
+ ```bash
14
+ npm i -g talos-code
15
+ talos --version
16
+ ```
17
+
18
+ Tested on Windows 11 x64. macOS and Linux are not tested yet in 0.1.0.
19
+
20
+ ## Start
21
+
22
+ Open a terminal in a project and run:
23
+
24
+ <!-- test:smoke -->
25
+ ```bash
26
+ talos
27
+ ```
28
+
29
+ The first time, TALOS asks whether to trust the folder, then which provider and model to use. A key already in your
30
+ environment (for example `OPENAI_API_KEY`) is used only after you agree once; otherwise you type it in hidden input and it
31
+ is kept in the operating system's credential store, never in a file.
32
+
33
+ For a one-shot task, without the interactive screen:
34
+
35
+ <!-- test:smoke -->
36
+ ```bash
37
+ talos -p "inspect this repository and explain the failing tests"
38
+ ```
39
+
40
+ For machine-readable output:
41
+
42
+ <!-- test:smoke -->
43
+ ```bash
44
+ talos -p "summarize the changes" --json
45
+ ```
46
+
47
+ ## Models
48
+
49
+ Cloud providers: OpenAI, Anthropic, Google Gemini, DeepSeek, OpenRouter, Mistral, Groq, xAI, Kimi, Qwen, Z.AI, MiniMax,
50
+ Cerebras, Together, Fireworks, DeepInfra, Novita, Nebius, Hugging Face, Azure AI Foundry, Amazon Bedrock and Google
51
+ Vertex AI. Local engines: Ollama, LM Studio and llama.cpp, with no key. TALOS never falls back from a local model to a cloud
52
+ one on its own.
53
+
54
+ `/provider` sets up a provider, `/model` (or `Alt+P`) picks the model, and `talos doctor` says what is ready.
55
+
56
+ ## What you can rely on
57
+
58
+ - **Permissions.** Each tool is allowed, asked or denied, per project. Modes: `default`, `acceptEdits`, `plan`, `auto`,
59
+ `dontAsk`, `bypassPermissions`.
60
+ - **Undo.** `/undo` restores the files a turn changed, from checkpoints kept outside your repository and outside Git.
61
+ - **Sessions.** `/resume` and `/fork` open a picker; `talos --resume last` continues from the shell. Sessions can be exported
62
+ and imported; an imported session never runs anything by itself.
63
+ - **Context.** With a model whose context window is known and at least 64k tokens, long conversations are compacted at
64
+ half of the window, and the screen says when and how much.
65
+ - **Extensions.** MCP servers, hooks, plugins and custom commands, each trusted explicitly before it runs.
66
+
67
+ In the interactive screen, `?` on an empty prompt shows the keys, `/help` the commands, `Ctrl+L` or `/redraw` repaints.
68
+ `Shift+Enter` adds a line where the terminal reports it; `Ctrl+J` always does. Set `TALOS_REDUCED_MOTION=1` to turn the
69
+ animations off, or pass `--no-color`.
70
+
71
+ ## Your data
72
+
73
+ Nothing is sent anywhere except:
74
+
75
+ - your prompts and the files TALOS reads, to the provider you chose;
76
+ - the public model catalogue at models.dev, for context windows and prices, cached for 4 hours. Turn it off with
77
+ `talos config set catalog.modelsDev false` or `TALOS_MODELS_DEV=off`;
78
+ - the npm registry, only when you run `talos update`.
79
+
80
+ There is no telemetry. Configuration, sessions, checkpoints and logs stay on your machine:
81
+
82
+ | | Windows | macOS / Linux |
83
+ |---|---|---|
84
+ | Configuration | `%APPDATA%\TALOS-CLI` | `~/.config/talos-cli` |
85
+ | Sessions, checkpoints, logs | `%LOCALAPPDATA%\TALOS-CLI` | `~/.local/state/talos-cli` |
86
+
87
+ ## Update
88
+
89
+ <!-- test:smoke -->
90
+ ```bash
91
+ talos update --check
92
+ ```
93
+
94
+ With an npm install, `talos update` tells you if a newer version exists and the command to run
95
+ (`npm i -g talos-code@latest`). It does not change anything by itself.
96
+
97
+ ## Known limits in 0.1.0
98
+
99
+ - Only Windows 11 x64 is tested.
100
+ - Context compaction with a local Ollama model is not yet verified end to end.
101
+ - A local provider that answers 401/403 without needing a key can be set aside as if its key were wrong.
102
+
103
+ ## Help
104
+
105
+ `talos --help` lists every command, `/help` does the same inside the interactive screen, and `talos doctor` says what is
106
+ missing when something does not work. `talos diagnostic bundle --out talos-diagnostic.zip` makes a redacted report for a
107
+ bug; it contains no prompt or file content.
108
+
109
+ ## License
110
+
111
+ AGPL-3.0-only. See `LICENSE` and `THIRD_PARTY_NOTICES.md` in this package.
@@ -0,0 +1,40 @@
1
+ # TALOS CLI Third-Party Notices
2
+
3
+ The package lock is the authoritative inventory for the complete dependency
4
+ graph. The Windows runtime retains dependency package metadata and license
5
+ files under `app/node_modules`.
6
+
7
+ ## Microsoft eXecution Containers SDK 0.8.0
8
+
9
+ - Package: `@microsoft/mxc-sdk` `0.8.0`
10
+ - Upstream: https://github.com/microsoft/mxc
11
+ - Reviewed tag object: `c0ea508293705ddcc60baaf286aafd3776b42eb8`
12
+ - npm integrity: `sha512-pnf5QsASwp+qtRi5uth2GDjwuyG0rHWRpxCf3RbAjQ4wDTNfBX/9l0A+RVZspU2agpF3/11uWB1JisIS7WrNYg==`
13
+ - License: MIT
14
+
15
+ MXC is distributed as a public preview and includes platform-specific native
16
+ executables. TALOS checks host capability evidence before use and does not
17
+ represent preview isolation as a security boundary unless the requested
18
+ AppContainer, Bound File System, network, and process-tree controls have been
19
+ verified on that host.
20
+
21
+ The full upstream MIT license text is retained in
22
+ `app/node_modules/@microsoft/mxc-sdk/LICENSE.md` in packaged runtimes.
23
+
24
+ ## jsdiff 9.0.0
25
+
26
+ - Package: `diff` `9.0.0` (pinned exact, R3 owner decision 2026-09-24)
27
+ - Upstream: https://github.com/kpdecker/jsdiff
28
+ - npm integrity: `sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==`
29
+ - License: BSD-3-Clause
30
+
31
+ Used only to compute line differences for the file-change summaries and diffs TALOS shows; it never touches files.
32
+ The full upstream BSD-3-Clause license text is retained in `app/node_modules/diff/LICENSE` in packaged runtimes.
33
+
34
+ ## Other direct runtime dependencies
35
+
36
+ | Component | Upstream | License |
37
+ |---|---|---|
38
+ | ink 7.1.1 | https://github.com/vadimdemedes/ink | MIT |
39
+ | react 19.3.0 | https://github.com/facebook/react | MIT |
40
+ | string-width 8.2.2 | https://github.com/sindresorhus/string-width | MIT |
@@ -0,0 +1,73 @@
1
+ import { inflateRawSync } from 'node:zlib';
2
+ import { crc32 } from "../diagnostics/zip.js";
3
+ const MAX_ENTRIES = 2048;
4
+ const MAX_ENTRY_BYTES = 64 * 1024 * 1024;
5
+ const MAX_TOTAL_BYTES = 256 * 1024 * 1024;
6
+ function fail(code) { throw Object.assign(new Error(code), { code }); }
7
+ function locateEocd(buf) { for (let i = buf.length - 22; i >= Math.max(0, buf.length - 65_557); i--)
8
+ if (buf.readUInt32LE(i) === 0x06054b50)
9
+ return i; return -1; }
10
+ export function readZipEntries(buf) {
11
+ const eocd = locateEocd(buf);
12
+ if (eocd < 0)
13
+ fail('ZIP_EOCD_NOT_FOUND');
14
+ const disk = buf.readUInt16LE(eocd + 4), centralDisk = buf.readUInt16LE(eocd + 6);
15
+ if (disk !== 0 || centralDisk !== 0)
16
+ fail('ZIP_MULTIDISK_UNSUPPORTED');
17
+ const count = buf.readUInt16LE(eocd + 10);
18
+ if (count > MAX_ENTRIES)
19
+ fail('ZIP_TOO_MANY_ENTRIES');
20
+ let off = buf.readUInt32LE(eocd + 16);
21
+ const result = new Map();
22
+ let total = 0;
23
+ for (let i = 0; i < count; i++) {
24
+ if (off + 46 > buf.length || buf.readUInt32LE(off) !== 0x02014b50)
25
+ fail('ZIP_CENTRAL_INVALID');
26
+ const flags = buf.readUInt16LE(off + 8);
27
+ const method = buf.readUInt16LE(off + 10);
28
+ const expectedCrc = buf.readUInt32LE(off + 16);
29
+ const compressed = buf.readUInt32LE(off + 20), uncompressed = buf.readUInt32LE(off + 24);
30
+ const nameLen = buf.readUInt16LE(off + 28), extraLen = buf.readUInt16LE(off + 30), commentLen = buf.readUInt16LE(off + 32);
31
+ const local = buf.readUInt32LE(off + 42);
32
+ if (flags & 1)
33
+ fail('ZIP_ENCRYPTED_UNSUPPORTED');
34
+ if (uncompressed > MAX_ENTRY_BYTES)
35
+ fail('ZIP_ENTRY_TOO_LARGE');
36
+ total += uncompressed;
37
+ if (total > MAX_TOTAL_BYTES)
38
+ fail('ZIP_TOO_LARGE');
39
+ if (off + 46 + nameLen + extraLen + commentLen > buf.length)
40
+ fail('ZIP_CENTRAL_INVALID');
41
+ const name = buf.subarray(off + 46, off + 46 + nameLen).toString('utf8').replaceAll('\\', '/');
42
+ if (result.has(name))
43
+ fail('ZIP_DUPLICATE_ENTRY');
44
+ if (local + 30 > buf.length || buf.readUInt32LE(local) !== 0x04034b50)
45
+ fail('ZIP_LOCAL_INVALID');
46
+ const localName = buf.readUInt16LE(local + 26), localExtra = buf.readUInt16LE(local + 28);
47
+ const dataStart = local + 30 + localName + localExtra;
48
+ if (dataStart + compressed > buf.length)
49
+ fail('ZIP_DATA_INVALID');
50
+ const raw = buf.subarray(dataStart, dataStart + compressed);
51
+ let data;
52
+ try {
53
+ if (method === 0)
54
+ data = Buffer.from(raw);
55
+ else if (method === 8)
56
+ data = inflateRawSync(raw);
57
+ else
58
+ fail(`ZIP_METHOD_UNSUPPORTED:${method}`);
59
+ }
60
+ catch (error) {
61
+ if (error?.code)
62
+ throw error;
63
+ fail('ZIP_DEFLATE_INVALID');
64
+ }
65
+ if (data.length !== uncompressed)
66
+ fail('ZIP_SIZE_MISMATCH');
67
+ if (crc32(data) !== expectedCrc)
68
+ fail('ZIP_CRC_MISMATCH');
69
+ result.set(name, data);
70
+ off += 46 + nameLen + extraLen + commentLen;
71
+ }
72
+ return result;
73
+ }
package/dist/args.js ADDED
@@ -0,0 +1,97 @@
1
+ import { parseArgs } from 'node:util';
2
+ const MODES = new Set(['default', 'acceptEdits', 'plan', 'auto', 'dontAsk', 'bypassPermissions']);
3
+ const FORMATS = new Set(['text', 'json', 'stream-json']);
4
+ const PROTOCOLS = new Set(['v1', 'v2']);
5
+ const SUBCOMMANDS = new Set(['project', 'config', 'provider', 'model', 'session', 'mcp', 'hook', 'plugin', 'command', 'memory', 'notes', 'tasks', 'library', 'research', 'automation', 'forge', 'checkpoint', 'doctor', 'logs', 'diagnostic', 'update', 'init']);
6
+ function positiveInt(raw, flag) {
7
+ if (raw === undefined)
8
+ return undefined;
9
+ if (!/^\d+$/u.test(raw) || Number(raw) <= 0)
10
+ throw new Error(flag + ' must be a positive integer');
11
+ return Number(raw);
12
+ }
13
+ function firstPositionalIndex(argv) {
14
+ const needsValue = new Set(['--print', '-p', '--output-format', '--protocol', '--project', '--model', '--permission-mode', '--resume', '--fork', '--timeout']);
15
+ for (let i = 0; i < argv.length; i++) {
16
+ const token = argv[i];
17
+ if (token === '--')
18
+ return i + 1 < argv.length ? i + 1 : -1;
19
+ if (token.startsWith('--') && token.includes('='))
20
+ continue;
21
+ if (token.startsWith('-')) {
22
+ if (needsValue.has(token))
23
+ i += 1;
24
+ continue;
25
+ }
26
+ return i;
27
+ }
28
+ return -1;
29
+ }
30
+ export function parseCliArgs(argv) {
31
+ const first = firstPositionalIndex(argv);
32
+ const subcommandIndex = first >= 0 && SUBCOMMANDS.has(argv[first]) ? first : -1;
33
+ const parseArgv = subcommandIndex >= 0 ? argv.slice(0, subcommandIndex) : argv;
34
+ const { values, positionals } = parseArgs({
35
+ args: parseArgv,
36
+ allowPositionals: true,
37
+ strict: true,
38
+ options: {
39
+ print: { type: 'string', short: 'p' },
40
+ json: { type: 'boolean' },
41
+ 'output-format': { type: 'string' },
42
+ protocol: { type: 'string' },
43
+ project: { type: 'string' }, model: { type: 'string' },
44
+ 'permission-mode': { type: 'string' }, resume: { type: 'string' }, fork: { type: 'string' },
45
+ verbose: { type: 'boolean', short: 'v' }, 'no-color': { type: 'boolean' }, timeout: { type: 'string' },
46
+ version: { type: 'boolean' }, help: { type: 'boolean', short: 'h' },
47
+ }
48
+ });
49
+ if (values.resume && values.fork)
50
+ throw new Error('--resume and --fork are mutually exclusive');
51
+ const rawProtocol = values.protocol;
52
+ if (rawProtocol !== undefined && !PROTOCOLS.has(rawProtocol))
53
+ throw new Error('Invalid protocol: ' + rawProtocol);
54
+ const protocolVersion = (rawProtocol ?? 'v1');
55
+ if (values.version)
56
+ return { command: 'version', interactive: false, outputFormat: 'text', protocolVersion, verbose: false, color: true, positionals: [] };
57
+ if (values.help)
58
+ return { command: 'help', interactive: false, outputFormat: 'text', protocolVersion, verbose: false, color: true, positionals };
59
+ const rawMode = values['permission-mode'];
60
+ if (rawMode !== undefined && !MODES.has(rawMode))
61
+ throw new Error('Invalid permission mode: ' + rawMode);
62
+ let outputFormat = 'text';
63
+ if (values.json)
64
+ outputFormat = 'json';
65
+ if (values['output-format'] !== undefined) {
66
+ if (!FORMATS.has(values['output-format']))
67
+ throw new Error('Invalid output format: ' + values['output-format']);
68
+ outputFormat = values['output-format'];
69
+ }
70
+ if (protocolVersion === 'v2' && subcommandIndex >= 0)
71
+ throw new Error('--protocol v2 is only available for headless runs');
72
+ if (protocolVersion === 'v2' && outputFormat === 'text')
73
+ throw new Error('--protocol v2 requires --json or --output-format stream-json');
74
+ if (subcommandIndex >= 0) {
75
+ const timeoutSeconds = positiveInt(values.timeout, '--timeout');
76
+ return {
77
+ command: 'subcommand', interactive: false, outputFormat, protocolVersion,
78
+ ...(rawMode !== undefined ? { permissionMode: rawMode } : {}),
79
+ ...(values.project !== undefined ? { project: values.project } : {}), ...(values.model !== undefined ? { model: values.model } : {}),
80
+ ...(values.resume !== undefined ? { resume: values.resume } : {}), ...(values.fork !== undefined ? { fork: values.fork } : {}),
81
+ verbose: values.verbose ?? false, color: !(values['no-color'] ?? false), ...(timeoutSeconds !== undefined ? { timeoutSeconds } : {}),
82
+ positionals: argv.slice(subcommandIndex),
83
+ };
84
+ }
85
+ const promptParts = values.print !== undefined ? [values.print] : positionals;
86
+ const prompt = promptParts.length ? promptParts.join(' ') : undefined;
87
+ const interactive = values.print === undefined && outputFormat === 'text';
88
+ const timeoutSeconds = positiveInt(values.timeout, '--timeout');
89
+ return {
90
+ command: 'run', interactive, outputFormat, protocolVersion,
91
+ ...(prompt !== undefined ? { prompt } : {}), ...(rawMode !== undefined ? { permissionMode: rawMode } : {}),
92
+ ...(values.project !== undefined ? { project: values.project } : {}), ...(values.model !== undefined ? { model: values.model } : {}),
93
+ ...(values.resume !== undefined ? { resume: values.resume } : {}), ...(values.fork !== undefined ? { fork: values.fork } : {}),
94
+ verbose: values.verbose ?? false, color: !(values['no-color'] ?? false), ...(timeoutSeconds !== undefined ? { timeoutSeconds } : {}),
95
+ positionals: [...positionals],
96
+ };
97
+ }
@@ -0,0 +1,34 @@
1
+ import { mkdir, readFile, rename, writeFile, rm } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ function fail(code) { throw Object.assign(new Error(code), { code }); }
4
+ function safeId(id) { if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(id))
5
+ fail('AUTOMATION_ID_INVALID'); return id; }
6
+ function entry(value) {
7
+ if (!value || typeof value !== 'object' || Array.isArray(value))
8
+ fail('AUTOMATION_HISTORY_INVALID');
9
+ const outcome = value.outcome;
10
+ if (!['dispatch-started', 'dispatch-failed', 'missed-skipped'].includes(outcome))
11
+ fail('AUTOMATION_HISTORY_INVALID');
12
+ const nullable = (v) => v === null ? null : typeof v === 'string' ? v : fail('AUTOMATION_HISTORY_INVALID');
13
+ if (typeof value.attemptedAt !== 'string' || Number.isNaN(Date.parse(value.attemptedAt)))
14
+ fail('AUTOMATION_HISTORY_INVALID');
15
+ return { attemptedAt: new Date(value.attemptedAt).toISOString(), scheduledAt: nullable(value.scheduledAt), slotKey: nullable(value.slotKey), outcome, sessionId: nullable(value.sessionId), errorCode: nullable(value.errorCode), errorMessage: nullable(value.errorMessage), nextRetryAt: nullable(value.nextRetryAt) };
16
+ }
17
+ export function createAutomationHistoryStore(directory, options = {}) {
18
+ const limit = Number.isSafeInteger(options.limit) && Number(options.limit) > 0 ? Number(options.limit) : 200;
19
+ const pathFor = (id) => join(directory, safeId(id) + '.json');
20
+ async function list(id) { const path = pathFor(id); try {
21
+ const parsed = JSON.parse(await readFile(path, 'utf8'));
22
+ if (!Array.isArray(parsed))
23
+ fail('AUTOMATION_HISTORY_INVALID');
24
+ return parsed.map(entry);
25
+ }
26
+ catch (error) {
27
+ if (error?.code === 'ENOENT')
28
+ return [];
29
+ throw error;
30
+ } }
31
+ async function append(id, value) { const rows = await list(id); rows.push(entry(value)); const kept = rows.slice(-limit); await mkdir(directory, { recursive: true }); const path = pathFor(id), tmp = path + '.tmp-' + process.pid; await writeFile(tmp, JSON.stringify(kept, null, 2) + '\n', 'utf8'); await rename(tmp, path); return kept.at(-1); }
32
+ async function remove(id) { await rm(pathFor(id), { force: true }); }
33
+ return { list, append, delete: remove };
34
+ }
@@ -0,0 +1,43 @@
1
+ import { mkdir, readFile, rename, writeFile, rm } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { validateTimeZone } from "./schedule.js";
4
+ function fail(code) { throw Object.assign(new Error(code), { code }); }
5
+ function safeId(id) { if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(id))
6
+ fail('AUTOMATION_ID_INVALID'); return id; }
7
+ function positive(value, name, zero = false) { if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < (zero ? 0 : 1))
8
+ fail(name); return value; }
9
+ function normalize(id, value) {
10
+ safeId(id);
11
+ if (!value || typeof value !== 'object' || Array.isArray(value))
12
+ fail('AUTOMATION_POLICY_INVALID');
13
+ let schedule;
14
+ if (value.schedule?.kind === 'legacy')
15
+ schedule = { kind: 'legacy' };
16
+ else if (value.schedule?.kind === 'daily' && typeof value.schedule.at === 'string' && /^([01]\d|2[0-3]):[0-5]\d$/u.test(value.schedule.at) && typeof value.schedule.timezone === 'string')
17
+ schedule = { kind: 'daily', at: value.schedule.at, timezone: validateTimeZone(value.schedule.timezone) };
18
+ else
19
+ fail('AUTOMATION_POLICY_INVALID');
20
+ const mode = value.missedRun?.mode;
21
+ if (mode !== 'skip' && mode !== 'latest')
22
+ fail('AUTOMATION_POLICY_INVALID');
23
+ const missedRun = { mode, graceMinutes: positive(value.missedRun?.graceMinutes, 'AUTOMATION_POLICY_INVALID', true), catchupWindowMinutes: positive(value.missedRun?.catchupWindowMinutes, 'AUTOMATION_POLICY_INVALID', true) };
24
+ const baseSeconds = positive(value.backoff?.baseSeconds, 'AUTOMATION_POLICY_INVALID'), maxSeconds = positive(value.backoff?.maxSeconds, 'AUTOMATION_POLICY_INVALID');
25
+ if (maxSeconds < baseSeconds)
26
+ fail('AUTOMATION_POLICY_INVALID');
27
+ const consecutiveFailures = positive(value.backoff?.consecutiveFailures, 'AUTOMATION_POLICY_INVALID', true), nextRetryAt = value.backoff?.nextRetryAt === null ? null : typeof value.backoff?.nextRetryAt === 'string' && !Number.isNaN(Date.parse(value.backoff.nextRetryAt)) ? new Date(value.backoff.nextRetryAt).toISOString() : fail('AUTOMATION_POLICY_INVALID');
28
+ return { version: 1, automationId: id, schedule, missedRun, backoff: { baseSeconds, maxSeconds, consecutiveFailures, nextRetryAt }, lastHandledSlot: value.lastHandledSlot === null ? null : typeof value.lastHandledSlot === 'string' ? value.lastHandledSlot : fail('AUTOMATION_POLICY_INVALID') };
29
+ }
30
+ export function createAutomationPolicyStore(directory) {
31
+ const pathFor = (id) => join(directory, safeId(id) + '.json');
32
+ async function get(id) { const path = pathFor(id); try {
33
+ return normalize(id, JSON.parse(await readFile(path, 'utf8')));
34
+ }
35
+ catch (error) {
36
+ if (error?.code === 'ENOENT')
37
+ return null;
38
+ throw error;
39
+ } }
40
+ async function put(id, value) { const row = normalize(id, { ...value, automationId: id }); await mkdir(directory, { recursive: true }); const path = pathFor(id), tmp = path + '.tmp-' + process.pid; await writeFile(tmp, JSON.stringify(row, null, 2) + '\n', 'utf8'); await rename(tmp, path); return row; }
41
+ async function remove(id) { await rm(pathFor(id), { force: true }); }
42
+ return { get, put, delete: remove };
43
+ }
@@ -0,0 +1,107 @@
1
+ import { decideAutomationSchedule } from "./schedule.js";
2
+ export async function runDueAutomations(rows, { now = Date.now(), runtime }) { const ran = []; const failed = []; for (const r of rows) {
3
+ if (!r.enabled || Date.parse(r.nextRunAt) > now)
4
+ continue;
5
+ try {
6
+ await runtime.start({ projectRoot: r.projectRoot, prompt: r.prompt, model: r.model, permissionMode: r.permissionMode });
7
+ ran.push(r.id);
8
+ }
9
+ catch (e) {
10
+ failed.push({ id: r.id, error: e instanceof Error ? e.message : String(e) });
11
+ }
12
+ } return { ran, failed }; }
13
+ const DEFAULT_BACKOFF = { baseSeconds: 30, maxSeconds: 900, consecutiveFailures: 0, nextRetryAt: null };
14
+ const DEFAULT_MISSED = { mode: 'skip', graceMinutes: 5, catchupWindowMinutes: 0 };
15
+ function legacyDecision(row, now) {
16
+ if (!row.attiva)
17
+ return { action: 'wait', reason: 'inactive', slot: null, nextAt: row.prossimaEsecuzione ?? null };
18
+ if (!row.prossimaEsecuzione)
19
+ return { action: 'wait', reason: 'no-next-run', slot: null, nextAt: null };
20
+ const due = Date.parse(row.prossimaEsecuzione);
21
+ if (Number.isNaN(due))
22
+ return { action: 'wait', reason: 'invalid-next-run', slot: null, nextAt: null };
23
+ if (due > now)
24
+ return { action: 'wait', reason: 'future', slot: null, nextAt: new Date(due).toISOString() };
25
+ return { action: 'run', reason: 'legacy-due', slot: { slotKey: 'legacy:' + new Date(due).toISOString(), scheduledAt: new Date(due).toISOString(), adjustedForDst: false }, nextAt: null };
26
+ }
27
+ export async function dryRunAutomation(input) {
28
+ const now = input.now ?? Date.now(), row = input.row, policy = input.policy;
29
+ if (!row.attiva)
30
+ return { action: 'wait', reason: 'inactive', slot: null, nextAt: row.prossimaEsecuzione ?? null };
31
+ if (policy?.backoff.nextRetryAt && Date.parse(policy.backoff.nextRetryAt) > now)
32
+ return { action: 'wait', reason: 'backoff', slot: null, nextAt: policy.backoff.nextRetryAt };
33
+ if (policy?.schedule.kind === 'daily')
34
+ return decideAutomationSchedule({ schedule: policy.schedule, now, lastHandledSlot: policy.lastHandledSlot, policy: policy.missedRun });
35
+ return legacyDecision(row, now);
36
+ }
37
+ function errorInfo(error) { const e = error; return { code: typeof e?.code === 'string' ? e.code : 'AUTOMATION_DISPATCH_FAILED', message: error instanceof Error ? error.message : String(error) }; }
38
+ function policyForFailure(row, policy) {
39
+ return policy ?? { version: 1, automationId: row.id, schedule: { kind: 'legacy' }, missedRun: DEFAULT_MISSED, backoff: { ...DEFAULT_BACKOFF }, lastHandledSlot: null };
40
+ }
41
+ function nextBackoff(policy, now) {
42
+ const failures = policy.backoff.consecutiveFailures + 1;
43
+ const seconds = Math.min(policy.backoff.maxSeconds, policy.backoff.baseSeconds * (2 ** Math.min(failures - 1, 20)));
44
+ return { ...policy, backoff: { ...policy.backoff, consecutiveFailures: failures, nextRetryAt: new Date(now + seconds * 1000).toISOString() } };
45
+ }
46
+ function utcDay(ms) { return new Date(ms).toISOString().slice(0, 10); }
47
+ export async function runAutomationTick(input) {
48
+ const now = input.now ?? Date.now(), started = [], failed = [], skipped = [];
49
+ for (const row of input.rows) {
50
+ let policy = await input.policyFor(row.id);
51
+ const decision = await dryRunAutomation({ now, row, policy });
52
+ const count = row.giornoContatore === utcDay(now) ? Number(row.eseguiteOggi ?? 0) : 0;
53
+ if (decision.action === 'run' && typeof row.limiteAlGiorno === 'number' && Number.isFinite(row.limiteAlGiorno) && count >= row.limiteAlGiorno) {
54
+ skipped.push({ id: row.id, reason: 'daily-limit' });
55
+ continue;
56
+ }
57
+ if (decision.action === 'skip-missed' && decision.slot) {
58
+ if (policy) {
59
+ policy = { ...policy, lastHandledSlot: decision.slot.slotKey };
60
+ await input.savePolicy(row.id, policy);
61
+ }
62
+ await input.appendHistory(row.id, { attemptedAt: new Date(now).toISOString(), scheduledAt: decision.slot.scheduledAt, slotKey: decision.slot.slotKey, outcome: 'missed-skipped', sessionId: null, errorCode: null, errorMessage: null, nextRetryAt: null });
63
+ skipped.push({ id: row.id, reason: decision.reason });
64
+ continue;
65
+ }
66
+ if (decision.action !== 'run' || !decision.slot) {
67
+ skipped.push({ id: row.id, reason: decision.reason });
68
+ continue;
69
+ }
70
+ let sessionId = null;
71
+ try {
72
+ const result = await input.registry.avvia(row.taskId, {}, { kind: 'talos-cli-automation' });
73
+ if (result?.erroreAvvio)
74
+ throw Object.assign(new Error(String(result.erroreAvvio)), { code: result.code });
75
+ sessionId = typeof result === 'string' ? result : typeof result?.sessionId === 'string' ? result.sessionId : null;
76
+ if (!sessionId)
77
+ throw Object.assign(new Error('AUTOMATION_SESSION_ID_MISSING'), { code: 'AUTOMATION_SESSION_ID_MISSING' });
78
+ }
79
+ catch (error) {
80
+ policy = nextBackoff(policyForFailure(row, policy), now);
81
+ await input.savePolicy(row.id, policy);
82
+ const info = errorInfo(error);
83
+ const history = { attemptedAt: new Date(now).toISOString(), scheduledAt: decision.slot.scheduledAt, slotKey: decision.slot.slotKey, outcome: 'dispatch-failed', sessionId: null, errorCode: info.code, errorMessage: info.message, nextRetryAt: policy.backoff.nextRetryAt };
84
+ await input.appendHistory(row.id, history);
85
+ failed.push({ id: row.id, taskId: row.taskId, ...info, nextRetryAt: policy.backoff.nextRetryAt });
86
+ continue;
87
+ }
88
+ const bookkeepingErrors = [];
89
+ const bookkeeping = async (stage, operation) => { try {
90
+ await operation();
91
+ }
92
+ catch (error) {
93
+ const info = errorInfo(error);
94
+ bookkeepingErrors.push({ stage, ...info });
95
+ } };
96
+ const history = { attemptedAt: new Date(now).toISOString(), scheduledAt: decision.slot.scheduledAt, slotKey: decision.slot.slotKey, outcome: 'dispatch-started', sessionId, errorCode: null, errorMessage: null, nextRetryAt: null };
97
+ await bookkeeping('history', () => input.appendHistory(row.id, history));
98
+ if (policy) {
99
+ policy = { ...policy, lastHandledSlot: policy.schedule.kind === 'daily' ? decision.slot.slotKey : policy.lastHandledSlot, backoff: { ...policy.backoff, consecutiveFailures: 0, nextRetryAt: null } };
100
+ const saved = policy;
101
+ await bookkeeping('policy', () => input.savePolicy(row.id, saved));
102
+ }
103
+ await bookkeeping('execution-store', () => input.recordExecution(row.id));
104
+ started.push({ id: row.id, taskId: row.taskId, sessionId, slotKey: decision.slot.slotKey, bookkeepingErrors });
105
+ }
106
+ return { started, failed, skipped };
107
+ }
@@ -0,0 +1,85 @@
1
+ function fail(code) { throw Object.assign(new Error(code), { code }); }
2
+ function two(n) { return String(n).padStart(2, '0'); }
3
+ function dateKey(y, m, d) { return String(y).padStart(4, '0') + '-' + two(m) + '-' + two(d); }
4
+ function dateParts(key) { return [Number(key.slice(0, 4)), Number(key.slice(5, 7)), Number(key.slice(8, 10))]; }
5
+ function addDate(key, days) { const [y, m, d] = dateParts(key); return new Date(Date.UTC(y, m - 1, d + days)).toISOString().slice(0, 10); }
6
+ function wallMinutes(at) { if (!/^([01]\d|2[0-3]):[0-5]\d$/u.test(at))
7
+ fail('AUTOMATION_TIME_INVALID'); return Number(at.slice(0, 2)) * 60 + Number(at.slice(3, 5)); }
8
+ export function validateTimeZone(value) {
9
+ if (value !== 'UTC' && !/^[A-Za-z_]+(?:\/[A-Za-z0-9._+-]+)+$/u.test(value))
10
+ fail('AUTOMATION_TIMEZONE_INVALID');
11
+ try {
12
+ new Intl.DateTimeFormat('en-US', { timeZone: value }).format(new Date(0));
13
+ }
14
+ catch {
15
+ fail('AUTOMATION_TIMEZONE_INVALID');
16
+ }
17
+ return value;
18
+ }
19
+ function localParts(ms, timeZone) {
20
+ const parts = new Intl.DateTimeFormat('en-CA', { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hourCycle: 'h23' }).formatToParts(new Date(ms));
21
+ const value = (type) => Number(parts.find(p => p.type === type)?.value);
22
+ return { year: value('year'), month: value('month'), day: value('day'), hour: value('hour'), minute: value('minute') };
23
+ }
24
+ function localDate(ms, tz) { const p = localParts(ms, tz); return dateKey(p.year, p.month, p.day); }
25
+ function resolveLocal(date, at, timeZone) {
26
+ validateTimeZone(timeZone);
27
+ const target = wallMinutes(at);
28
+ const [y, m, d] = dateParts(date), hh = Number(at.slice(0, 2)), mm = Number(at.slice(3, 5));
29
+ const rough = Date.UTC(y, m - 1, d, hh, mm), exact = [], later = [];
30
+ for (let ms = rough - 18 * 60 * 60_000; ms <= rough + 18 * 60 * 60_000; ms += 60_000) {
31
+ const p = localParts(ms, timeZone);
32
+ if (dateKey(p.year, p.month, p.day) !== date)
33
+ continue;
34
+ const wall = p.hour * 60 + p.minute;
35
+ if (wall === target)
36
+ exact.push(ms);
37
+ else if (wall > target)
38
+ later.push({ ms, wall });
39
+ }
40
+ let chosen, adjusted = false;
41
+ if (exact.length)
42
+ chosen = Math.min(...exact);
43
+ else {
44
+ later.sort((a, b) => a.wall - b.wall || a.ms - b.ms);
45
+ if (!later.length)
46
+ fail('AUTOMATION_SCHEDULE_UNRESOLVABLE');
47
+ chosen = later[0].ms;
48
+ adjusted = true;
49
+ }
50
+ return { slotKey: date + '@' + at + '[' + timeZone + ']', scheduledAt: new Date(chosen).toISOString(), adjustedForDst: adjusted };
51
+ }
52
+ export function nextDailySlot(schedule, afterMs) {
53
+ const timezone = validateTimeZone(schedule.timezone);
54
+ wallMinutes(schedule.at);
55
+ const start = localDate(afterMs, timezone);
56
+ for (let i = 0; i < 4; i++) {
57
+ const slot = resolveLocal(addDate(start, i), schedule.at, timezone);
58
+ if (Date.parse(slot.scheduledAt) > afterMs)
59
+ return slot;
60
+ }
61
+ fail('AUTOMATION_SCHEDULE_UNRESOLVABLE');
62
+ }
63
+ function latestDailySlot(schedule, now) {
64
+ const timezone = validateTimeZone(schedule.timezone);
65
+ wallMinutes(schedule.at);
66
+ const today = localDate(now, timezone);
67
+ const slot = resolveLocal(today, schedule.at, timezone);
68
+ if (Date.parse(slot.scheduledAt) <= now)
69
+ return slot;
70
+ return resolveLocal(addDate(today, -1), schedule.at, timezone);
71
+ }
72
+ export function decideAutomationSchedule(input) {
73
+ const slot = latestDailySlot(input.schedule, input.now);
74
+ if (input.lastHandledSlot === slot.slotKey) {
75
+ const next = nextDailySlot(input.schedule, input.now);
76
+ return { action: 'wait', reason: 'slot-handled', slot: null, nextAt: next.scheduledAt };
77
+ }
78
+ const lateness = Math.max(0, (input.now - Date.parse(slot.scheduledAt)) / 60_000), grace = Math.max(0, input.policy.graceMinutes), catchup = Math.max(0, input.policy.catchupWindowMinutes);
79
+ if (lateness <= grace)
80
+ return { action: 'run', reason: 'due', slot, nextAt: null };
81
+ const next = nextDailySlot(input.schedule, input.now);
82
+ if (input.policy.mode === 'latest' && lateness <= catchup)
83
+ return { action: 'run', reason: 'latest-missed', slot, nextAt: null };
84
+ return { action: 'skip-missed', reason: input.policy.mode === 'skip' ? 'missed-policy-skip' : 'missed-window-expired', slot, nextAt: next.scheduledAt };
85
+ }