talos-code 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +111 -3
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  4. package/dist/archive/zip.js +73 -0
  5. package/dist/args.js +97 -0
  6. package/dist/automations/history-store.js +34 -0
  7. package/dist/automations/policy-store.js +43 -0
  8. package/dist/automations/runner.js +107 -0
  9. package/dist/automations/schedule.js +85 -0
  10. package/dist/automations/windows-task.js +53 -0
  11. package/dist/commands/advanced-cli.js +233 -0
  12. package/dist/commands/checkpoint-cli.js +45 -0
  13. package/dist/commands/config-cli.js +107 -0
  14. package/dist/commands/context.js +17 -0
  15. package/dist/commands/extensions-cli.js +207 -0
  16. package/dist/commands/project-cli.js +74 -0
  17. package/dist/commands/project-commands.js +143 -0
  18. package/dist/commands/provider-cli.js +185 -0
  19. package/dist/commands/services-cli.js +248 -0
  20. package/dist/commands/session-cli.js +171 -0
  21. package/dist/commands/system-cli.js +405 -0
  22. package/dist/config/commands.js +60 -0
  23. package/dist/config/load.js +382 -0
  24. package/dist/config/migrations.js +48 -0
  25. package/dist/config/types.js +11 -0
  26. package/dist/diagnostics/development-log.js +154 -0
  27. package/dist/diagnostics/doctor.js +104 -0
  28. package/dist/diagnostics/redact.js +80 -0
  29. package/dist/diagnostics/zip.js +52 -0
  30. package/dist/errors.js +156 -0
  31. package/dist/events/bridge.js +130 -0
  32. package/dist/extensions/installer.js +178 -0
  33. package/dist/extensions/package-schema.js +24 -0
  34. package/dist/headless/result.js +84 -0
  35. package/dist/headless/run.js +230 -0
  36. package/dist/i18n/en/approval.js +43 -0
  37. package/dist/i18n/en/common.js +9 -0
  38. package/dist/i18n/en/credentials.js +82 -0
  39. package/dist/i18n/en/errors.js +246 -0
  40. package/dist/i18n/en/firstrun.js +89 -0
  41. package/dist/i18n/en/providers.js +37 -0
  42. package/dist/i18n/en/screen.js +736 -0
  43. package/dist/i18n/en/tools.js +127 -0
  44. package/dist/i18n/en.js +14 -0
  45. package/dist/i18n/error-view.js +307 -0
  46. package/dist/i18n/index.js +19 -0
  47. package/dist/i18n/kernel-map.js +139 -0
  48. package/dist/io.js +45 -0
  49. package/dist/main.js +330 -0
  50. package/dist/paths.js +41 -0
  51. package/dist/protocol/v2/codec.js +9 -0
  52. package/dist/protocol/v2/events.js +555 -0
  53. package/dist/protocol/v2/index.js +4 -0
  54. package/dist/protocol/v2/replay.js +28 -0
  55. package/dist/protocol/v2/types.js +1 -0
  56. package/dist/provider/control-plane.js +135 -0
  57. package/dist/provider/environment-keys.js +275 -0
  58. package/dist/provider/health.js +110 -0
  59. package/dist/provider/missing-key.js +48 -0
  60. package/dist/provider/model-catalog.js +168 -0
  61. package/dist/provider/provider-text.js +13 -0
  62. package/dist/provider/store.js +95 -0
  63. package/dist/provider/system-keyring.js +214 -0
  64. package/dist/runtime/active-run.js +63 -0
  65. package/dist/runtime/agent-tree.js +74 -0
  66. package/dist/runtime/attachments.js +84 -0
  67. package/dist/runtime/brokered-executor.js +395 -0
  68. package/dist/runtime/context-status.js +76 -0
  69. package/dist/runtime/create-runtime.js +111 -0
  70. package/dist/runtime/model-profile.js +361 -0
  71. package/dist/runtime/output-store.js +137 -0
  72. package/dist/runtime/provider-attempts.js +185 -0
  73. package/dist/runtime/replay-buffer.js +153 -0
  74. package/dist/runtime/repo.js +95 -0
  75. package/dist/runtime/session-facade.js +135 -0
  76. package/dist/runtime/session-summary.js +125 -0
  77. package/dist/runtime/supervisor.js +262 -0
  78. package/dist/runtime/talos-composition.js +1006 -0
  79. package/dist/runtime/types.js +5 -0
  80. package/dist/runtime/usage-snapshot.js +82 -0
  81. package/dist/security/auto-classifier.js +38 -0
  82. package/dist/security/credential-free-environment.js +54 -0
  83. package/dist/security/evaluate.js +243 -0
  84. package/dist/security/execution-backends.js +236 -0
  85. package/dist/security/execution-broker.js +102 -0
  86. package/dist/security/forge-scan.js +74 -0
  87. package/dist/security/from-approval.js +39 -0
  88. package/dist/security/mxc-execution-backend.js +281 -0
  89. package/dist/security/permission-engine.js +138 -0
  90. package/dist/security/permission-explanation.js +54 -0
  91. package/dist/security/persist.js +179 -0
  92. package/dist/security/plugin-guard.js +230 -0
  93. package/dist/security/process-tree-evidence-store.js +74 -0
  94. package/dist/security/process-tree-probe.js +554 -0
  95. package/dist/security/project-resource-inventory.js +186 -0
  96. package/dist/security/project-trust-gate.js +38 -0
  97. package/dist/security/project-trust.js +367 -0
  98. package/dist/security/rule-parser.js +201 -0
  99. package/dist/security/shell-segmentation.js +68 -0
  100. package/dist/security/trust-authority.js +324 -0
  101. package/dist/security/types.js +1 -0
  102. package/dist/security/workspace-identity.js +102 -0
  103. package/dist/services/automation-facade.js +59 -0
  104. package/dist/services/forge-facade.js +77 -0
  105. package/dist/services/hook-facade.js +240 -0
  106. package/dist/services/index.js +16 -0
  107. package/dist/services/library-facade.js +174 -0
  108. package/dist/services/mcp-facade.js +348 -0
  109. package/dist/services/memory-facade.js +126 -0
  110. package/dist/services/notes-facade.js +157 -0
  111. package/dist/services/plugin-facade.js +308 -0
  112. package/dist/services/research-facade.js +110 -0
  113. package/dist/services/task-board-facade.js +236 -0
  114. package/dist/services/workflow-catalog.js +246 -0
  115. package/dist/sessions/export-format.js +98 -0
  116. package/dist/sessions/metadata-store.js +160 -0
  117. package/dist/sessions/share.js +122 -0
  118. package/dist/sessions/transfer.js +16 -0
  119. package/dist/subcommands.js +62 -0
  120. package/dist/tui/agent-roster.js +36 -0
  121. package/dist/tui/app.js +3761 -0
  122. package/dist/tui/approval.js +36 -0
  123. package/dist/tui/boot/boot-sequence.js +76 -0
  124. package/dist/tui/boot/cinematic.js +243 -0
  125. package/dist/tui/boot/desktop-logo.js +82 -0
  126. package/dist/tui/boot.js +3 -0
  127. package/dist/tui/busy-input.js +58 -0
  128. package/dist/tui/catalog-service.js +559 -0
  129. package/dist/tui/components/assistant-stream.js +1 -0
  130. package/dist/tui/components/command-menu.js +68 -0
  131. package/dist/tui/components/composer.js +219 -0
  132. package/dist/tui/components/diff.js +35 -0
  133. package/dist/tui/components/footer.js +48 -0
  134. package/dist/tui/components/header.js +6 -0
  135. package/dist/tui/components/markdown.js +305 -0
  136. package/dist/tui/components/status-indicator.js +32 -0
  137. package/dist/tui/components/terminal-shell.js +205 -0
  138. package/dist/tui/components/thinking-row.js +19 -0
  139. package/dist/tui/components/tool-row.js +97 -0
  140. package/dist/tui/components/transcript-virtualizer.js +165 -0
  141. package/dist/tui/components/transcript.js +43 -0
  142. package/dist/tui/diff-model.js +77 -0
  143. package/dist/tui/editor-history.js +21 -0
  144. package/dist/tui/editor.js +210 -0
  145. package/dist/tui/event-adapter.js +436 -0
  146. package/dist/tui/exit-output.js +58 -0
  147. package/dist/tui/external-editor.js +53 -0
  148. package/dist/tui/file-completion.js +89 -0
  149. package/dist/tui/focus-manager.js +5 -0
  150. package/dist/tui/highlight.js +30 -0
  151. package/dist/tui/input-router.js +18 -0
  152. package/dist/tui/interrupt.js +99 -0
  153. package/dist/tui/keybindings.js +194 -0
  154. package/dist/tui/keymap-resolver.js +91 -0
  155. package/dist/tui/launch-state.js +139 -0
  156. package/dist/tui/line-diff.js +57 -0
  157. package/dist/tui/live-activity.js +45 -0
  158. package/dist/tui/metrics.js +123 -0
  159. package/dist/tui/onboarding.js +36 -0
  160. package/dist/tui/overlays/agent-tree.js +39 -0
  161. package/dist/tui/overlays/approval-dialog.js +640 -0
  162. package/dist/tui/overlays/automation-center.js +51 -0
  163. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  164. package/dist/tui/overlays/context-inspector.js +36 -0
  165. package/dist/tui/overlays/effort-line.js +110 -0
  166. package/dist/tui/overlays/forge-center.js +46 -0
  167. package/dist/tui/overlays/help-dialog.js +16 -0
  168. package/dist/tui/overlays/history-picker.js +37 -0
  169. package/dist/tui/overlays/hook-center.js +70 -0
  170. package/dist/tui/overlays/library-center.js +55 -0
  171. package/dist/tui/overlays/mcp-center.js +60 -0
  172. package/dist/tui/overlays/memory-center.js +63 -0
  173. package/dist/tui/overlays/model-picker.js +72 -0
  174. package/dist/tui/overlays/notes-center.js +53 -0
  175. package/dist/tui/overlays/overlay-host.js +8 -0
  176. package/dist/tui/overlays/plugin-center.js +76 -0
  177. package/dist/tui/overlays/provider-picker.js +145 -0
  178. package/dist/tui/overlays/queue-editor.js +32 -0
  179. package/dist/tui/overlays/research-center.js +59 -0
  180. package/dist/tui/overlays/scroll-window.js +234 -0
  181. package/dist/tui/overlays/session-picker.js +115 -0
  182. package/dist/tui/overlays/tasks-center.js +83 -0
  183. package/dist/tui/overlays/theme-picker.js +21 -0
  184. package/dist/tui/overlays/transcript-search.js +58 -0
  185. package/dist/tui/overlays/trust-center.js +29 -0
  186. package/dist/tui/overlays/workflow-center.js +46 -0
  187. package/dist/tui/project-file-index.js +214 -0
  188. package/dist/tui/project-references.js +85 -0
  189. package/dist/tui/project-trust-prompt.js +287 -0
  190. package/dist/tui/prompt-history-store.js +116 -0
  191. package/dist/tui/queue-store.js +110 -0
  192. package/dist/tui/regions/budget.js +59 -0
  193. package/dist/tui/regions/views.js +96 -0
  194. package/dist/tui/render-coordinator.js +148 -0
  195. package/dist/tui/render-scheduler.js +4 -0
  196. package/dist/tui/run.js +69 -0
  197. package/dist/tui/selection-list.js +29 -0
  198. package/dist/tui/session-controller.js +778 -0
  199. package/dist/tui/session-export.js +54 -0
  200. package/dist/tui/shell-input.js +35 -0
  201. package/dist/tui/shell-layout.js +48 -0
  202. package/dist/tui/shell-model.js +98 -0
  203. package/dist/tui/slash-commands.js +80 -0
  204. package/dist/tui/state.js +151 -0
  205. package/dist/tui/status-bar.js +125 -0
  206. package/dist/tui/status-view.js +40 -0
  207. package/dist/tui/terminal-capabilities.js +9 -0
  208. package/dist/tui/terminal-session.js +11 -0
  209. package/dist/tui/text-width.js +66 -0
  210. package/dist/tui/theme-catalog.js +25 -0
  211. package/dist/tui/theme-store.js +23 -0
  212. package/dist/tui/theme.js +23 -0
  213. package/dist/tui/tool-display.js +135 -0
  214. package/dist/tui/tool-facts.js +1 -0
  215. package/dist/tui/tools/bash-renderer.js +32 -0
  216. package/dist/tui/tools/change.js +61 -0
  217. package/dist/tui/tools/edit-renderer.js +17 -0
  218. package/dist/tui/tools/generic-renderer.js +13 -0
  219. package/dist/tui/tools/list-renderer.js +14 -0
  220. package/dist/tui/tools/read-renderer.js +13 -0
  221. package/dist/tui/tools/registry.js +20 -0
  222. package/dist/tui/tools/row-format.js +187 -0
  223. package/dist/tui/tools/search-renderer.js +38 -0
  224. package/dist/tui/tools/shared.js +97 -0
  225. package/dist/tui/tools/write-renderer.js +15 -0
  226. package/dist/tui/transcript-model.js +441 -0
  227. package/dist/tui/ui-preferences.js +79 -0
  228. package/dist/tui/usage-view.js +77 -0
  229. package/dist/tui/vim-mode.js +99 -0
  230. package/dist/update/check.js +15 -0
  231. package/dist/update/npm.js +51 -0
  232. package/dist/update/run.js +129 -0
  233. package/dist/version.js +2 -0
  234. package/dist/workspace/checkpoint-store.js +210 -0
  235. package/dist/workspace/checkpoint.js +413 -0
  236. package/dist/workspace/restore.js +232 -0
  237. package/package.json +63 -5
  238. package/vendor/context-engine/package.json +11 -0
  239. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  240. package/vendor/context-engine/src/contracts.mjs +48 -0
  241. package/vendor/context-engine/src/engine.mjs +445 -0
  242. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  243. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  244. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  245. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  246. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  247. package/vendor/context-engine/src/profiles.mjs +10 -0
  248. package/vendor/context-engine/src/retrieval.mjs +104 -0
  249. package/vendor/context-engine/src/summary.mjs +97 -0
  250. package/vendor/context-engine/src/usage.mjs +34 -0
  251. package/vendor/harness-ui/package.json +38 -0
  252. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  253. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  254. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  255. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  256. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  257. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  258. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  259. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  260. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  261. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  262. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  263. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  264. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  265. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  266. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  267. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  268. package/vendor/harness-ui/src/config.mjs +697 -0
  269. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  270. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  271. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  272. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  273. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  274. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  275. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  276. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  277. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  278. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  279. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  280. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  281. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  282. package/vendor/harness-ui/src/doctor.mjs +142 -0
  283. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  284. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  285. package/vendor/harness-ui/src/document-report.mjs +331 -0
  286. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  287. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  288. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  289. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  290. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  291. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  292. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  293. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  294. package/vendor/harness-ui/src/git-service.mjs +626 -0
  295. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  296. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  297. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  298. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  299. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  300. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  301. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  302. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  303. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  304. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  305. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  306. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  307. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  308. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  309. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  310. package/vendor/harness-ui/src/library-store.mjs +652 -0
  311. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  312. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  313. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  314. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  315. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  316. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  317. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  318. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  319. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  320. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  321. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  322. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  323. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  324. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  325. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  326. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  327. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  328. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  329. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  330. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  331. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  332. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  333. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  334. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  335. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  336. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  337. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  338. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  339. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  340. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  341. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  342. package/vendor/harness-ui/src/research/card.mjs +235 -0
  343. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  344. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  345. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  346. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  347. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  348. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  349. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  350. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  351. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  352. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  353. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  354. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  355. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  356. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  357. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  358. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  359. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  360. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  361. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  362. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  363. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  364. package/vendor/harness-ui/src/research/report.mjs +203 -0
  365. package/vendor/harness-ui/src/research/run.mjs +527 -0
  366. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  367. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  368. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  369. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  370. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  371. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  372. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  373. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  374. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  375. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  376. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  377. package/vendor/harness-ui/src/session-store.mjs +220 -0
  378. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  379. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  380. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  381. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  382. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  383. package/vendor/harness-ui/src/static-files.mjs +96 -0
  384. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  385. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  386. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  387. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  388. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  389. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  390. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  391. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  392. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  393. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  394. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  395. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  396. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  397. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  398. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  399. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  400. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  401. package/vendor/manifest.json +170 -0
@@ -0,0 +1,527 @@
1
+ /*
2
+ * PORTO FEDELE di AVM/mobile/src/lib/research/researchRun.ts (492 righe, 11/09/2026).
3
+ *
4
+ * Un giro di ricerca che può essere ucciso e ripreso.
5
+ *
6
+ * Questo è R-1, e la specifica lo mette per primo per una ragione che
7
+ * sopravvive al contatto con la piattaforma: su un telefono il processo VERRÀ
8
+ * ucciso. Doze lo ferma a schermo spento, i servizi in primo piano `dataSync`
9
+ * hanno sei ore ogni ventiquattro e poi qualche secondo di preavviso, e il
10
+ * produttore di questo dispositivo — OnePlus, oggi su ColorOS — è documentato
11
+ * come uno dei più aggressivi sul mercato nell'uccidere il lavoro in secondo
12
+ * piano, coi permessi che l'utente concede azzerati dagli aggiornamenti di
13
+ * firmware.
14
+ *
15
+ * Quindi essere interrotti non è una modalità di guasto qui. È il caso normale,
16
+ * e tutto quello che sta sotto ne prende la forma.
17
+ *
18
+ * La forma è quella su cui il campo si è assestato per l'esecuzione durevole:
19
+ * un giornale a sola aggiunta di quello che È SUCCESSO, con lo stato corrente
20
+ * ricavato rigiocandolo — non un oggetto mutabile salvato sopra sé stesso. La
21
+ * differenza si vede esattamente quando conta: uno stato sovrascritto sul posto
22
+ * ti dice cosa crede sia vero adesso, e un giornale ti dice che un passo era
23
+ * finito prima che il processo morisse, che è la differenza fra pagare una
24
+ * ricerca una volta e pagarla due.
25
+ *
26
+ * Compra anche tre cose gratis, ed è la ragione per cui vale più di una colonna
27
+ * `status`: il giro si può biforcare, si può controllare, e un giro registrato
28
+ * si può rigiocare come test.
29
+ *
30
+ * Quello che fa la concorrenza qui vale la pena nominarlo, perché è il «+1».
31
+ * Fermare un giro di Deep Research su ChatGPT vuol dire ricominciarlo da zero;
32
+ * i suoi forum sono pieni di giri bloccati su «Researching…» senza alcun
33
+ * recupero. Loro se lo possono permettere: girano su un server. Noi no, e il
34
+ * vincolo è quello che produce la capacità.
35
+ *
36
+ * Niente in questo file tocca Android, la rete, un database o un modello. È
37
+ * aritmetica su una lista, che è ciò che lo rende provabile senza un
38
+ * dispositivo — e ciò che permette allo stesso giro di migrare più tardi su un
39
+ * server (R1b), visto che uno stato che si serializza è uno stato che si può
40
+ * spostare.
41
+ */
42
+
43
+ /** @typedef {'quick' | 'deep' | 'exhaustive'} TalosResearchDepth */
44
+
45
+ /**
46
+ * `pause_requested` e `paused` sono due stati, non uno, e la ragione è il
47
+ * denaro.
48
+ *
49
+ * Una pausa può arrivare mentre un passo è IN VOLO e già pagato. Buttare via
50
+ * quella risposta per onorare subito la parola «pausa» spenderebbe il denaro
51
+ * dell'utente per niente, quindi il motore drena il passo che ha cominciato, lo
52
+ * mette a registro, e solo allora riposa — la ricerca del 2026-08-03 lo chiama
53
+ * «drain then checkpoint». `pause_requested` è l'intervallo in mezzo:
54
+ * l'intenzione è registrata e nessun passo nuovo verrà prenotato, ma il punto
55
+ * sicuro non è ancora stato raggiunto. Collassare i due farebbe mentire lo
56
+ * schermo in una direzione o nell'altra.
57
+ *
58
+ * `paused` NON è `cancelled`. Cancellato è terminale — il WorkManager di
59
+ * Android non ha uno stato PAUSED e il suo CANCELLED non si può riprendere —
60
+ * quindi scriverne uno quando la persona ha chiesto l'altro butterebbe via una
61
+ * ricerca che aveva pagato.
62
+ *
63
+ * @typedef {'planning' | 'awaiting_plan_approval' | 'collecting' | 'synthesising' | 'verifying' | 'pause_requested' | 'paused' | 'done' | 'cancelled' | 'failed'} TalosResearchStatus
64
+ */
65
+
66
+ /**
67
+ * Gli stati da cui non succederà mai più niente.
68
+ *
69
+ * @type {readonly TalosResearchStatus[]}
70
+ */
71
+ export const TALOS_RESEARCH_TERMINAL = Object.freeze([
72
+ 'done', 'cancelled', 'failed',
73
+ ]);
74
+
75
+ /**
76
+ * @param {TalosResearchStatus} status
77
+ * @returns {boolean}
78
+ */
79
+ export function talosResearchIsTerminal(status) {
80
+ return TALOS_RESEARCH_TERMINAL.includes(status);
81
+ }
82
+
83
+ /**
84
+ * Fermo, ma con del lavoro ancora dovuto: il motore non deve prenotare, il giro
85
+ * si può riprendere.
86
+ *
87
+ * @param {TalosResearchStatus} status
88
+ * @returns {boolean}
89
+ */
90
+ export function talosResearchIsResting(status) {
91
+ return status === 'paused' || status === 'pause_requested';
92
+ }
93
+
94
+ /**
95
+ * Dove il giro sta girando. Tutto il punto di R1b è che questo può cambiare.
96
+ *
97
+ * @typedef {'device' | 'cloud'} TalosResearchEngine
98
+ */
99
+
100
+ /** @typedef {'search' | 'read' | 'synthesise' | 'verify'} TalosResearchStepKind */
101
+
102
+ /**
103
+ * `interrupted` non è la stessa cosa di `failed`, e la distinzione È la
104
+ * funzione.
105
+ *
106
+ * Un passo fallito ha provato e non ce l'ha fatta; uno interrotto stava ancora
107
+ * girando quando il processo è stato ucciso, quindi nessuno sa se sia finito.
108
+ * Il primo è un risultato, il secondo è una domanda — e solo il secondo vale la
109
+ * pena di riprovare.
110
+ *
111
+ * @typedef {'pending' | 'running' | 'done' | 'failed' | 'interrupted'} TalosResearchStepState
112
+ */
113
+
114
+ /**
115
+ * Solo e soltanto quello che è stato davvero osservato. Le stime vivono sul ramo.
116
+ *
117
+ * @typedef {object} TalosResearchSpend
118
+ * @property {number} tokens
119
+ * @property {number} searches
120
+ * @property {number} pages
121
+ */
122
+
123
+ /** @type {TalosResearchSpend} */
124
+ export const TALOS_RESEARCH_NO_SPEND = Object.freeze({
125
+ tokens: 0,
126
+ searches: 0,
127
+ pages: 0,
128
+ });
129
+
130
+ /**
131
+ * @typedef {object} TalosResearchBranch
132
+ * @property {string} id
133
+ * @property {string} question
134
+ * @property {TalosResearchSpend} estimate Quello che il pianificatore ha INDOVINATO. Mai confuso con quello che è stato speso.
135
+ */
136
+
137
+ /**
138
+ * @typedef {object} TalosResearchStep
139
+ * @property {string} id
140
+ * @property {string} branchId
141
+ * @property {TalosResearchStepKind} kind
142
+ * @property {TalosResearchStepState} state
143
+ * @property {number} attempts Quante volte questo passo è stato avviato. Prova, non identità.
144
+ * @property {string | null} startedAt
145
+ * @property {string | null} finishedAt
146
+ * @property {TalosResearchSpend} spend
147
+ * @property {string | null} resultRef
148
+ * Dove vive il carico — mai il carico. Un giornale che porta cento kilobyte
149
+ * di testo di pagina per riga è un giornale che nessuno può rigiocare su un
150
+ * telefono, e il testo appartiene al caveau con tutto il resto che l'app
151
+ * conserva.
152
+ * @property {string | null} error
153
+ */
154
+
155
+ /**
156
+ * @typedef {object} TalosResearchRun
157
+ * @property {string} id
158
+ * @property {string} sessionId
159
+ * @property {string} question
160
+ * @property {TalosResearchDepth} depth
161
+ * @property {TalosResearchEngine} engine
162
+ * @property {TalosResearchStatus} status
163
+ * @property {string | null} title
164
+ * L'etichetta che la lista mostra, quando qualcuno ne ha scelta una. `null`
165
+ * vuol dire «usa la domanda» — che è il default onesto, perché la domanda È
166
+ * il nome di una ricerca finché una persona non decide altrimenti.
167
+ * @property {readonly TalosResearchBranch[]} plan
168
+ * @property {readonly TalosResearchStep[]} steps
169
+ * @property {string} startedAt
170
+ * @property {string} updatedAt
171
+ */
172
+
173
+ /**
174
+ * Gli undici eventi del giornale.
175
+ *
176
+ * @typedef {{kind:'run_started', at:string, id:string, sessionId:string, question:string, depth:TalosResearchDepth, engine:TalosResearchEngine}
177
+ * | {kind:'plan_proposed', at:string, branches:readonly TalosResearchBranch[]}
178
+ * | {kind:'plan_approved', at:string, branches:readonly TalosResearchBranch[]}
179
+ * | {kind:'step_started', at:string, stepId:string, branchId:string, stepKind:TalosResearchStepKind}
180
+ * | {kind:'step_finished', at:string, stepId:string, spend:TalosResearchSpend, resultRef:string|null}
181
+ * | {kind:'step_failed', at:string, stepId:string, error:string}
182
+ * | {kind:'run_pause_requested', at:string}
183
+ * | {kind:'run_paused', at:string}
184
+ * | {kind:'run_resumed', at:string}
185
+ * | {kind:'run_renamed', at:string, title:string|null}
186
+ * | {kind:'run_cancelled', at:string}
187
+ * | {kind:'run_finished', at:string}} TalosResearchEvent
188
+ */
189
+
190
+ /**
191
+ * Il nome a cui un passo risponde, attraverso ogni tentativo.
192
+ *
193
+ * La letteratura lo ricava da giro + attività + NUMERO DI TENTATIVO. Il
194
+ * tentativo è lasciato fuori di proposito qui, perché i due contesti vogliono
195
+ * cose opposte. Là la chiave separa i tentativi proprio perché il secondo giri.
196
+ * Qui l'utente paga di tasca sua — ogni ricerca è denaro — quindi due tentativi
197
+ * dello stesso passo logico devono essere riconoscibili come LO STESSO, e un
198
+ * fornitore che sa deduplicare dev'essere messo in condizione di farlo. Il
199
+ * conteggio dei tentativi è registrato accanto al passo come prova, mai piegato
200
+ * dentro il suo nome.
201
+ *
202
+ * @param {string} runId
203
+ * @param {string} stepId
204
+ * @returns {string}
205
+ */
206
+ export function talosResearchIdempotencyKey(runId, stepId) {
207
+ return `${runId}:${stepId}`;
208
+ }
209
+
210
+ /**
211
+ * @param {TalosResearchSpend} left
212
+ * @param {TalosResearchSpend} right
213
+ * @returns {TalosResearchSpend}
214
+ */
215
+ function addSpend(left, right) {
216
+ return {
217
+ tokens: left.tokens + right.tokens,
218
+ searches: left.searches + right.searches,
219
+ pages: left.pages + right.pages,
220
+ };
221
+ }
222
+
223
+ /**
224
+ * Quanto il giro è davvero costato finora, sommato dai passi che sono girati.
225
+ *
226
+ * @param {TalosResearchRun} run
227
+ * @returns {TalosResearchSpend}
228
+ */
229
+ export function talosResearchSpent(run) {
230
+ return run.steps.reduce((total, step) => addSpend(total, step.spend), TALOS_RESEARCH_NO_SPEND);
231
+ }
232
+
233
+ /**
234
+ * @param {readonly TalosResearchStep[]} steps
235
+ * @param {string} stepId
236
+ * @param {(step: TalosResearchStep) => TalosResearchStep} change
237
+ * @returns {readonly TalosResearchStep[]}
238
+ */
239
+ function replaceStep(steps, stepId, change) {
240
+ return steps.map((step) => (step.id === stepId ? change(step) : step));
241
+ }
242
+
243
+ /**
244
+ * Un evento, ripiegato dentro lo stato.
245
+ *
246
+ * Gli eventi che non hanno senso contro lo stato a cui arrivano vengono
247
+ * IGNORATI invece di lanciare. Un giornale si legge dal magazzino dopo
248
+ * un'uccisione, e l'unica cosa che non deve fare mai è rifiutarsi di caricare:
249
+ * un giro che non si può rigiocare è un giro il cui lavoro pagato è perso, che
250
+ * è esattamente il guasto per cui questo disegno esiste. I duplicati sono il
251
+ * caso comune — un'aggiunta scritta due volte perché il processo è morto fra la
252
+ * scrittura e la conferma — e contarne uno due volte riporterebbe denaro che
253
+ * non è mai stato speso.
254
+ *
255
+ * @param {TalosResearchRun | null} run
256
+ * @param {TalosResearchEvent} event
257
+ * @returns {TalosResearchRun | null}
258
+ */
259
+ export function talosResearchApply(run, event) {
260
+ if (event.kind === 'run_started') {
261
+ // Solo il primo. Un avvio ripetuto azzererebbe un giro che ha già speso
262
+ // denaro.
263
+ if (run) return run;
264
+ return {
265
+ id: event.id,
266
+ sessionId: event.sessionId,
267
+ question: event.question,
268
+ depth: event.depth,
269
+ engine: event.engine,
270
+ status: 'planning',
271
+ title: null,
272
+ plan: [],
273
+ steps: [],
274
+ startedAt: event.at,
275
+ updatedAt: event.at,
276
+ };
277
+ }
278
+ if (!run) return null;
279
+
280
+ /**
281
+ * @param {Partial<TalosResearchRun>} next
282
+ * @returns {TalosResearchRun}
283
+ */
284
+ const touched = (next) => ({
285
+ ...run,
286
+ ...next,
287
+ updatedAt: event.at,
288
+ });
289
+
290
+ switch (event.kind) {
291
+ case 'plan_proposed':
292
+ return touched({ plan: event.branches, status: 'awaiting_plan_approval' });
293
+
294
+ case 'plan_approved':
295
+ // I rami APPROVATI, non quelli proposti: l'utente ha il permesso di
296
+ // togliere, aggiungere e riformulare, e quello che ha approvato è quello
297
+ // che gira.
298
+ return touched({ plan: event.branches, status: 'collecting' });
299
+
300
+ case 'step_started': {
301
+ const existing = run.steps.find((step) => step.id === event.stepId);
302
+ if (existing?.state === 'done') {
303
+ // Già pagato. Ricominciarlo è l'errore che tutto questo file esiste per
304
+ // rendere impossibile.
305
+ return run;
306
+ }
307
+ if (existing) {
308
+ return touched({
309
+ steps: replaceStep(run.steps, event.stepId, (step) => ({
310
+ ...step,
311
+ state: 'running',
312
+ attempts: step.attempts + 1,
313
+ startedAt: event.at,
314
+ error: null,
315
+ })),
316
+ });
317
+ }
318
+ return touched({
319
+ steps: [...run.steps, {
320
+ id: event.stepId,
321
+ branchId: event.branchId,
322
+ kind: event.stepKind,
323
+ state: 'running',
324
+ attempts: 1,
325
+ startedAt: event.at,
326
+ finishedAt: null,
327
+ spend: TALOS_RESEARCH_NO_SPEND,
328
+ resultRef: null,
329
+ error: null,
330
+ }],
331
+ });
332
+ }
333
+
334
+ case 'step_finished': {
335
+ const existing = run.steps.find((step) => step.id === event.stepId);
336
+ if (!existing || existing.state === 'done') return run;
337
+ return touched({
338
+ steps: replaceStep(run.steps, event.stepId, (step) => ({
339
+ ...step,
340
+ state: 'done',
341
+ finishedAt: event.at,
342
+ // Registrato una volta, sulla transizione. Sommarlo alla cifra
343
+ // precedente conterebbe due volte un passo riprovato che aveva già
344
+ // riportato una parte del suo costo.
345
+ spend: event.spend,
346
+ resultRef: event.resultRef,
347
+ error: null,
348
+ })),
349
+ });
350
+ }
351
+
352
+ case 'step_failed': {
353
+ const existing = run.steps.find((step) => step.id === event.stepId);
354
+ if (!existing || existing.state === 'done') return run;
355
+ return touched({
356
+ steps: replaceStep(run.steps, event.stepId, (step) => ({
357
+ ...step,
358
+ state: 'failed',
359
+ finishedAt: event.at,
360
+ error: event.error,
361
+ })),
362
+ });
363
+ }
364
+
365
+ /*
366
+ * Chiedere due volte non è chiedere più forte: la seconda richiesta non
367
+ * deve riportare a «mi sto fermando» un giro che ha già raggiunto il punto
368
+ * sicuro. E un giro che è finito non è affatto mettibile in pausa — il
369
+ * giornale si legge dopo un'uccisione, e una richiesta vecchia che arriva
370
+ * in ritardo non deve resuscitare un giro terminale.
371
+ */
372
+ case 'run_pause_requested':
373
+ if (talosResearchIsTerminal(run.status) || run.status === 'paused') return run;
374
+ return touched({ status: 'pause_requested' });
375
+
376
+ case 'run_paused':
377
+ if (talosResearchIsTerminal(run.status)) return run;
378
+ return touched({ status: 'paused' });
379
+
380
+ /*
381
+ * Di nuovo a raccogliere, che è dove vive il punto di ripresa. Rifiutato da
382
+ * uno stato terminale per lo stesso motivo: cancellato vuol dire
383
+ * cancellato, e una ripresa che lo riaprisse spenderebbe denaro su un giro
384
+ * che la persona ha chiuso.
385
+ */
386
+ case 'run_resumed':
387
+ if (talosResearchIsTerminal(run.status)) return run;
388
+ return touched({ status: 'collecting' });
389
+
390
+ case 'run_renamed': {
391
+ // Lo spazio bianco non è un titolo. Vuoto ripristina la domanda, che è
392
+ // anche quello che scrive «Ripristina il titolo originale».
393
+ const title = event.title === null ? null : event.title.trim();
394
+ return touched({ title: title === null || title.length === 0 ? null : title });
395
+ }
396
+
397
+ case 'run_cancelled':
398
+ return touched({ status: 'cancelled' });
399
+
400
+ case 'run_finished':
401
+ return touched({ status: 'done' });
402
+
403
+ default:
404
+ return run;
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Lo stato di un giro, da tutta la sua storia. Deterministico per costruzione.
410
+ *
411
+ * @param {readonly TalosResearchEvent[]} events
412
+ * @returns {TalosResearchRun | null}
413
+ */
414
+ export function talosResearchReplay(events) {
415
+ return events.reduce(talosResearchApply, /** @type {TalosResearchRun | null} */ (null));
416
+ }
417
+
418
+ /**
419
+ * Quello che il processo non ha potuto dirci, ricavato sulla via del ritorno.
420
+ *
421
+ * Un passo lasciato `running` era in volo quando il processo è stato ucciso.
422
+ * Nessuno l'ha scritto, perché la cosa che l'avrebbe scritto è quella che è
423
+ * morta — quindi si deduce qui, nell'unico momento in cui qualcuno può: il
424
+ * prossimo avvio. È per questo che non esiste un evento `process_died`; un
425
+ * evento che nessuno è vivo per aggiungere è una bugia nel giornale.
426
+ *
427
+ * @param {TalosResearchRun} run
428
+ * @param {string} at
429
+ * @returns {TalosResearchRun}
430
+ */
431
+ export function talosResearchRecover(run, at) {
432
+ if (!run.steps.some((step) => step.state === 'running')) return run;
433
+ return {
434
+ ...run,
435
+ steps: run.steps.map((step) => (
436
+ step.state === 'running' ? { ...step, state: 'interrupted' } : step
437
+ )),
438
+ updatedAt: at,
439
+ };
440
+ }
441
+
442
+ /**
443
+ * Il passo da fare dopo, o niente.
444
+ *
445
+ * I passi interrotti vengono prima di quelli intatti: finire quello che era
446
+ * stato cominciato mantiene l'ordine del giro, ed è il passo che più
447
+ * probabilmente è già stato pagato in parte.
448
+ *
449
+ * @param {TalosResearchRun} run
450
+ * @returns {TalosResearchStep | null}
451
+ */
452
+ export function talosResearchNextStep(run) {
453
+ if (talosResearchIsTerminal(run.status)) return null;
454
+ // La pausa si fa rispettare QUI, nell'unica funzione che decide cosa fare
455
+ // dopo, invece che a ogni punto di chiamata che potrebbe dimenticarsene.
456
+ // «Nessun passo nuovo viene prenotato» non è un consiglio al motore — è il
457
+ // motore che non ha niente da prenotare.
458
+ if (talosResearchIsResting(run.status)) return null;
459
+ return run.steps.find((step) => step.state === 'interrupted')
460
+ ?? run.steps.find((step) => step.state === 'pending')
461
+ ?? null;
462
+ }
463
+
464
+ /**
465
+ * Quanto è avanti un giro — una definizione sola, così niente può essere in
466
+ * disaccordo con sé stesso.
467
+ *
468
+ * La sintesi è un passo come gli altri e conta fra quelli finiti, quindi un
469
+ * totale preso dal solo piano annunciava «3 di 2» nel momento in cui il
470
+ * rapporto veniva scritto. Si aggiunge al totale una volta che il giro ha
471
+ * davvero un passo del genere, e non prima: un denominatore che conta lavoro
472
+ * che potrebbe non essere mai tentato è la stessa bugia nell'altra direzione.
473
+ *
474
+ * @param {TalosResearchRun} run
475
+ * @returns {{done: number, total: number}}
476
+ */
477
+ export function talosResearchProgressOf(run) {
478
+ return {
479
+ done: run.steps.filter((step) => step.state === 'done').length,
480
+ total: run.plan.length + (run.steps.some((step) => step.kind === 'synthesise') ? 1 : 0),
481
+ };
482
+ }
483
+
484
+ /**
485
+ * Il nome a cui risponde il passo di un ramo. Derivato, mai inventato.
486
+ *
487
+ * Un id di passo che venisse da un contatore o da una sorgente casuale sarebbe
488
+ * un nome nuovo a ogni tentativo, e un nome nuovo è un passo che nessuno può
489
+ * riconoscere come già fatto — che è il modo in cui un giro ripreso paga due
490
+ * volte la stessa ricerca.
491
+ *
492
+ * @param {string} branchId
493
+ * @param {TalosResearchStepKind} kind
494
+ * @returns {string}
495
+ */
496
+ export function talosResearchStepIdFor(branchId, kind) {
497
+ return `${branchId}:${kind}`;
498
+ }
499
+
500
+ /**
501
+ * Quello che deve ancora succedere, dal PIANO invece che dal giornale.
502
+ *
503
+ * I due rispondono a domande diverse e servono entrambi. Il giornale registra
504
+ * quello che è successo; solo il piano sa quello che avrebbe dovuto succedere.
505
+ * Un giro ucciso prima che il suo terzo ramo partisse non ha niente nel
506
+ * giornale su quel ramo — il lavoro manca, non è registrato come mancante —
507
+ * quindi chiedere al solo giornale chiamerebbe il giro finito.
508
+ *
509
+ * Un ramo è in sospeso quando il suo passo è assente, interrotto o fallito.
510
+ * Fatto è fatto: non viene mai offerto di nuovo, qualunque cosa sia successa
511
+ * dopo.
512
+ *
513
+ * @param {TalosResearchRun} run
514
+ * @param {TalosResearchStepKind} [kind='search']
515
+ * @returns {readonly TalosResearchBranch[]}
516
+ */
517
+ export function talosResearchWorkLeft(run, kind = 'search') {
518
+ // Solo terminale. Un giro in pausa DEVE ancora questo lavoro — dire il
519
+ // contrario disegnerebbe un piano vuoto per una cosa che la persona sta per
520
+ // riprendere, ed è la domanda opposta rispetto a «cosa dovrebbe fare il
521
+ // motore proprio adesso».
522
+ if (talosResearchIsTerminal(run.status)) return [];
523
+ return run.plan.filter((branch) => {
524
+ const step = run.steps.find((candidate) => candidate.id === talosResearchStepIdFor(branch.id, kind));
525
+ return !step || step.state !== 'done';
526
+ });
527
+ }