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,168 @@
1
+ import { REASONING_EFFORTS } from "../config/types.js";
2
+ const SOURCE_RANK = Object.freeze({
3
+ unknown: 0, documented: 1, configured: 2, live: 3,
4
+ });
5
+ const CAPABILITY_RANK = Object.freeze({
6
+ unknown: 0, configured: 1, documented: 2, live: 3,
7
+ });
8
+ export function catalogSourceFromKernel(source, { successfulCatalogBoundary = false } = {}) {
9
+ const value = String(source ?? '').trim().toLowerCase().replace(/[_ ]+/gu, '-');
10
+ if (['config', 'configured', 'configurazione'].includes(value))
11
+ return 'configured';
12
+ if (['documented', 'documentation', 'documentazione', 'riserva', 'fallback'].includes(value))
13
+ return 'documented';
14
+ if (['live', 'fornitore', 'provider', 'remote', 'runtime', 'runtime-locale'].includes(value))
15
+ return 'live';
16
+ if (!value && successfulCatalogBoundary)
17
+ return 'live';
18
+ return 'unknown';
19
+ }
20
+ function effortsFrom(...values) {
21
+ let observed = false;
22
+ const out = [];
23
+ for (const value of values) {
24
+ if (!Array.isArray(value))
25
+ continue;
26
+ observed = true;
27
+ for (const item of value) {
28
+ if (typeof item !== 'string' || !REASONING_EFFORTS.includes(item))
29
+ continue;
30
+ const effort = item;
31
+ if (!out.includes(effort))
32
+ out.push(effort);
33
+ }
34
+ }
35
+ return observed ? out : null;
36
+ }
37
+ function evidenceMeta(row) {
38
+ const url = [row?.fonteMetadati, row?.fonteDichiarazione, row?.metadataSource, row?.declarationSource, row?.fonte]
39
+ .find(value => typeof value === 'string' && /^(?:https?:\/\/|urn:)/u.test(value)) ?? null;
40
+ const date = [row?.dataMetadati, row?.dataDichiarazione, row?.metadataDate, row?.declarationDate, row?.data]
41
+ .find(value => typeof value === 'string' && value.trim() !== '') ?? null;
42
+ return { url, date };
43
+ }
44
+ function evidence(value, source, meta = { url: null, date: null }) {
45
+ if (value === null)
46
+ return { value: null, source: 'unknown', evidenceUrl: null, evidenceDate: null };
47
+ return { value, source, evidenceUrl: meta.url, evidenceDate: meta.date };
48
+ }
49
+ function documentedCapabilitySource(row, rowSource, kind) {
50
+ if (rowSource === 'documented')
51
+ return 'documented';
52
+ const hasDocumentedMeta = typeof row?.fonteMetadati === 'string' || typeof row?.fonteDichiarazione === 'string'
53
+ || typeof row?.dataMetadati === 'string' || typeof row?.dataDichiarazione === 'string';
54
+ return hasDocumentedMeta && (kind === 'context' || kind === 'reasoning') ? 'documented' : rowSource;
55
+ }
56
+ export function normalizeModelRows(rows, provider, source) {
57
+ const seen = new Set();
58
+ const out = [];
59
+ for (const row of rows) {
60
+ const raw = String(row?.id ?? row?.modelId ?? row?.model ?? '').trim();
61
+ if (!raw)
62
+ continue;
63
+ const id = raw.startsWith(`${provider}:`) ? raw : `${provider}:${raw}`;
64
+ if (seen.has(id))
65
+ continue;
66
+ seen.add(id);
67
+ const explicitSource = catalogSourceFromKernel(row?.fonte);
68
+ const rowSource = explicitSource === 'unknown' ? source : explicitSource;
69
+ const caps = row?.capacita ?? row?.capabilities ?? {};
70
+ const supportedParameters = Array.isArray(row?.supported_parameters) ? row.supported_parameters : Array.isArray(row?.supportedParameters) ? row.supportedParameters : null;
71
+ const supportedParameterSet = supportedParameters ? new Set(supportedParameters.filter((value) => typeof value === 'string').map((value) => value.toLowerCase())) : null;
72
+ const ownReasoning = row?.reasoning && typeof row.reasoning === 'object' && !Array.isArray(row.reasoning) ? row.reasoning : null;
73
+ const capReasoning = caps?.reasoning && typeof caps.reasoning === 'object' && !Array.isArray(caps.reasoning) ? caps.reasoning : null;
74
+ const reasoningEfforts = effortsFrom(row?.reasoningEfforts, row?.livelliRagionamento, row?.ragionamento?.livelli, ownReasoning?.supportedEfforts, ownReasoning?.supported_efforts, ownReasoning?.allowed_options, capReasoning?.supportedEfforts, capReasoning?.supported_efforts, capReasoning?.allowed_options, caps?.ragionamento?.livelli);
75
+ const structuredReasoning = Boolean(ownReasoning || capReasoning || row?.ragionamento && typeof row.ragionamento === 'object' || caps?.ragionamento && typeof caps.ragionamento === 'object');
76
+ const reasoning = typeof row?.reasoning === 'boolean' ? row.reasoning
77
+ : typeof row?.supportsReasoning === 'boolean' ? row.supportsReasoning
78
+ : typeof caps?.reasoning === 'boolean' ? caps.reasoning
79
+ : structuredReasoning || reasoningEfforts !== null || supportedParameterSet?.has('reasoning') === true || supportedParameterSet?.has('include_reasoning') === true ? true : null;
80
+ const contextWindow = Number.isFinite(row?.contextLength) ? Number(row.contextLength)
81
+ : Number.isFinite(row?.contextWindow) ? Number(row.contextWindow)
82
+ : Number.isFinite(row?.finestraContesto) ? Number(row.finestraContesto)
83
+ : Number.isFinite(row?.context_length) ? Number(row.context_length) : null;
84
+ const toolCalling = typeof row?.toolCalling === 'boolean' ? row.toolCalling
85
+ : typeof row?.supportsTools === 'boolean' ? row.supportsTools
86
+ : typeof caps?.toolCall === 'boolean' ? caps.toolCall
87
+ : typeof caps?.tools === 'boolean' ? caps.tools
88
+ : supportedParameterSet?.has('tools') || supportedParameterSet?.has('tool_choice') ? true : null;
89
+ const explicitModalities = Array.isArray(row?.inputModalities) ? row.inputModalities
90
+ : Array.isArray(row?.input_modalities) ? row.input_modalities
91
+ : Array.isArray(row?.architecture?.input_modalities) ? row.architecture.input_modalities
92
+ : Array.isArray(row?.architecture?.inputModalities) ? row.architecture.inputModalities : null;
93
+ const images = explicitModalities ? explicitModalities.includes('image')
94
+ : typeof row?.images === 'boolean' ? row.images
95
+ : typeof caps?.images === 'boolean' ? caps.images
96
+ : typeof caps?.imageInput === 'boolean' ? caps.imageInput : null;
97
+ const meta = evidenceMeta(row);
98
+ const contextSource = documentedCapabilitySource(row, rowSource, 'context');
99
+ const reasoningSource = documentedCapabilitySource(row, rowSource, 'reasoning');
100
+ const capabilityEvidence = {
101
+ contextWindow: evidence(contextWindow, contextSource, contextSource === 'documented' ? meta : { url: null, date: null }),
102
+ toolCalling: evidence(toolCalling, rowSource, rowSource === 'documented' ? meta : { url: null, date: null }),
103
+ reasoning: evidence(reasoning, reasoningSource, reasoningSource === 'documented' ? meta : { url: null, date: null }),
104
+ reasoningEfforts: evidence(reasoningEfforts, reasoningSource, reasoningSource === 'documented' ? meta : { url: null, date: null }),
105
+ images: evidence(images, rowSource, rowSource === 'documented' ? meta : { url: null, date: null }),
106
+ };
107
+ out.push({
108
+ id, provider, name: String(row?.nome ?? row?.name ?? raw),
109
+ source: rowSource, available: rowSource, availabilityVerified: rowSource === 'live',
110
+ contextWindow, toolCalling, reasoning, reasoningEfforts, images,
111
+ capabilityEvidence,
112
+ });
113
+ }
114
+ return out;
115
+ }
116
+ function preferredCapability(left, right) {
117
+ if (left.value === null)
118
+ return right;
119
+ if (right.value === null)
120
+ return left;
121
+ return CAPABILITY_RANK[right.source] > CAPABILITY_RANK[left.source] ? right : left;
122
+ }
123
+ function withFlatCapabilities(row) {
124
+ const evidence = row.capabilityEvidence;
125
+ const reasoningEfforts = evidence.reasoningEfforts.value;
126
+ const reasoning = evidence.reasoning.value ?? (reasoningEfforts !== null ? true : null);
127
+ return {
128
+ ...row,
129
+ contextWindow: evidence.contextWindow.value,
130
+ toolCalling: evidence.toolCalling.value,
131
+ reasoning,
132
+ reasoningEfforts,
133
+ images: evidence.images.value,
134
+ };
135
+ }
136
+ function mergeTwo(left, right) {
137
+ const preferred = SOURCE_RANK[right.source] > SOURCE_RANK[left.source] ? right : left;
138
+ const capabilityEvidence = {
139
+ contextWindow: preferredCapability(left.capabilityEvidence.contextWindow, right.capabilityEvidence.contextWindow),
140
+ toolCalling: preferredCapability(left.capabilityEvidence.toolCalling, right.capabilityEvidence.toolCalling),
141
+ reasoning: preferredCapability(left.capabilityEvidence.reasoning, right.capabilityEvidence.reasoning),
142
+ reasoningEfforts: preferredCapability(left.capabilityEvidence.reasoningEfforts, right.capabilityEvidence.reasoningEfforts),
143
+ images: preferredCapability(left.capabilityEvidence.images, right.capabilityEvidence.images),
144
+ };
145
+ return withFlatCapabilities({
146
+ id: left.id,
147
+ provider: left.provider,
148
+ name: preferred.name,
149
+ source: preferred.source,
150
+ available: preferred.source,
151
+ availabilityVerified: preferred.source === 'live',
152
+ capabilityEvidence,
153
+ });
154
+ }
155
+ export function mergeModelRows(...rows) {
156
+ const byId = new Map();
157
+ const order = [];
158
+ for (const row of rows) {
159
+ const previous = byId.get(row.id);
160
+ if (!previous) {
161
+ byId.set(row.id, row);
162
+ order.push(row.id);
163
+ continue;
164
+ }
165
+ byId.set(row.id, mergeTwo(previous, row));
166
+ }
167
+ return order.map(id => byId.get(id));
168
+ }
@@ -0,0 +1,13 @@
1
+ /*
2
+ * R2 (D-05, gate E1/E4): the one place a provider's label and description reach the screen or `talos provider list`. Mapped
3
+ * by provider ID, never by the kernel's words; the kernel registry (and what the model or the kernel receives) is untouched.
4
+ */
5
+ import { en, t } from "../i18n/index.js";
6
+ function entry(id, field) {
7
+ const key = `provider.${id}.${field}`;
8
+ return Object.hasOwn(en, key) ? t(key) : null;
9
+ }
10
+ /** The English label for provider `id`, or `fallback` (the registry text) when the registry label is already English. */
11
+ export function providerLabelText(id, fallback) { return entry(id, 'label') ?? fallback; }
12
+ /** The English description for provider `id`, or `fallback` (the registry text). */
13
+ export function providerDescriptionText(id, fallback) { return entry(id, 'description') ?? fallback; }
@@ -0,0 +1,95 @@
1
+ import { loadTalosSystemKeyring, systemKeyringAdapter } from "./system-keyring.js";
2
+ import { t } from "../i18n/index.js";
3
+ import { CliRuntimeError } from "../runtime/types.js";
4
+ import { CREDENTIAL_STORES } from "../config/types.js";
5
+ const SERVICE = 'talos-cli-provider';
6
+ function cleanKey(v) { const x = v.trim(); if (!x || x.length > 4096 || /[\r\n\0]/u.test(x))
7
+ throw new Error('PROVIDER_KEY_INVALID'); return x; }
8
+ export function createCliProviderStore({ env, keyring, definitions }) {
9
+ const def = (id) => { const d = definitions[id]; if (!d)
10
+ throw new Error('PROVIDER_INVALID'); return d; };
11
+ const envKey = (id) => { for (const n of def(id).env) {
12
+ const v = env[n];
13
+ if (v?.trim())
14
+ return cleanKey(v);
15
+ } return null; };
16
+ return {
17
+ async getKey(id) { const e = envKey(id); if (e)
18
+ return e; const v = await keyring.get(SERVICE, id); return v ? cleanKey(v) : null; },
19
+ async setKey(id, value) { def(id); await keyring.set(SERVICE, id, cleanKey(value)); },
20
+ async removeKey(id) { def(id); await keyring.remove(SERVICE, id); },
21
+ async listPublic() { const rows = []; for (const [id, d] of Object.entries(definitions)) {
22
+ rows.push({ id, label: d.label ?? id, requiresKey: d.requiresKey, configured: d.requiresKey ? Boolean(await this.getKey(id)) : true });
23
+ } return rows; },
24
+ };
25
+ }
26
+ export const CREDENTIAL_STORE_VARIABLE = 'TALOS_CREDENTIAL_STORE';
27
+ export const TEST_PROFILE_VARIABLE = 'TALOS_TEST_PROFILE';
28
+ export function isTestProfile(env) {
29
+ return env[TEST_PROFILE_VARIABLE] === '1' || (typeof env.NODE_TEST_CONTEXT === 'string' && env.NODE_TEST_CONTEXT !== '');
30
+ }
31
+ export function chooseCredentialStore({ env, config, ownLoader = false }) {
32
+ const testProfile = isTestProfile(env);
33
+ const raw = env[CREDENTIAL_STORE_VARIABLE];
34
+ if (typeof raw === 'string' && raw.trim() !== '') {
35
+ const kind = raw.trim().toLowerCase();
36
+ if (!CREDENTIAL_STORES.includes(kind))
37
+ throw new CliRuntimeError('CREDENTIAL_STORE_INVALID', t('store.invalid', { value: raw.trim(), variable: CREDENTIAL_STORE_VARIABLE }), { variable: CREDENTIAL_STORE_VARIABLE });
38
+ return { kind: kind, source: 'environment', testProfile };
39
+ }
40
+ const configured = config?.credentials?.store;
41
+ if (configured === 'system' || configured === 'memory')
42
+ return { kind: configured, source: 'config', testProfile };
43
+ return testProfile && !ownLoader ? { kind: 'memory', source: 'test-profile', testProfile } : { kind: 'system', source: 'default', testProfile };
44
+ }
45
+ /** The name `doctor` and the refusal give the store: the OS store's own name on this platform. */
46
+ export function credentialStoreName(kind, platform = process.platform) {
47
+ if (kind === 'memory')
48
+ return t('store.name.memory');
49
+ return t(platform === 'win32' ? 'store.name.system.win32' : platform === 'darwin' ? 'store.name.system.darwin' : 'store.name.system.other');
50
+ }
51
+ export function credentialStoreSourceText(choice) {
52
+ return choice.source === 'environment' ? t('store.source.environment', { variable: CREDENTIAL_STORE_VARIABLE })
53
+ : choice.source === 'config' ? t('store.source.config') : choice.source === 'test-profile' ? t('store.source.testProfile') : t('store.source.default');
54
+ }
55
+ /* Per profile (Codex keys its ephemeral store by `compute_store_key(codex_home)`): a runtime rebuilt in the same process (the
56
+ supervisor's restart) still sees a key saved a minute ago, and two profiles in one test process do not share keys. */
57
+ const MEMORY_STORES = new Map();
58
+ export function createMemoryKeyring(scope) {
59
+ let values = MEMORY_STORES.get(scope);
60
+ if (!values) {
61
+ values = new Map();
62
+ MEMORY_STORES.set(scope, values);
63
+ }
64
+ const map = values;
65
+ const key = (service, account) => `${service}\u0000${account}`;
66
+ return { get: (service, account) => map.get(key(service, account)) ?? null, set: (service, account, value) => { map.set(key(service, account), value); }, remove: (service, account) => { map.delete(key(service, account)); } };
67
+ }
68
+ let active = null;
69
+ /** The store the last resolution in this process chose (for the sentences that name it), or null before any. */
70
+ export function activeCredentialStore() { return active; }
71
+ /** What `/provider` says after a key passed its test and was saved: where it now lives. */
72
+ export function keySavedText() { return t(active?.kind === 'memory' ? 'store.saved.memory' : 'store.saved.system'); }
73
+ /**
74
+ * Resolves and opens the store. `scope` separates memory stores (the profile's data root). Throws `CREDENTIAL_STORE_INVALID` or
75
+ * `CREDENTIAL_STORE_REAL_IN_TEST`; a system store that cannot be loaded is `keyring: null` with its `problem`, as before R2.
76
+ */
77
+ export function openCredentialStore({ repoRoot, scope, env = process.env, config, loader }) {
78
+ const ownLoader = typeof loader?.load === 'function';
79
+ const choice = chooseCredentialStore({ env, config: config ?? null, ownLoader });
80
+ if (choice.kind === 'system' && choice.testProfile && !ownLoader) {
81
+ throw new CliRuntimeError('CREDENTIAL_STORE_REAL_IN_TEST', t('store.refusedInTest', { store: credentialStoreName('system'), variable: CREDENTIAL_STORE_VARIABLE }), { store: 'system', source: choice.source });
82
+ }
83
+ active = choice;
84
+ if (choice.kind === 'memory')
85
+ return { ...choice, keyring: createMemoryKeyring(scope), problem: null };
86
+ const loaded = loadTalosSystemKeyring(repoRoot, loader ?? {});
87
+ return loaded.ok ? { ...choice, keyring: systemKeyringAdapter(loaded.Entry), problem: null } : { ...choice, keyring: null, problem: loaded };
88
+ }
89
+ /** R2 (E13): through the resolver, so a test profile never reaches the OS store from here either. */
90
+ export async function createSystemKeyring(repoRoot, { scope = repoRoot, env = process.env, config } = {}) {
91
+ const opened = openCredentialStore({ repoRoot, scope, env, config: config ?? null });
92
+ if (!opened.keyring)
93
+ throw new Error('PROVIDER_STORE_UNAVAILABLE');
94
+ return opened.keyring;
95
+ }
@@ -0,0 +1,214 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { lstatSync, readlinkSync, realpathSync } from 'node:fs';
3
+ import { createRequire } from 'node:module';
4
+ import { basename, dirname, isAbsolute, join, parse, relative, resolve, sep } from 'node:path';
5
+ import { t } from "../i18n/index.js";
6
+ /*
7
+ * ⛔⛔⛔ WHY THE APPROVED-ROOTS GUARD EXISTS — read for B1 slice 19. The file arrived whole with the gold
8
+ * baseline (7e5b048b, "restore verified gold baseline"), and no commit records the reason, so it is read
9
+ * from the code, from its test (a fake module in an ANCESTOR `node_modules` must be refused) and from
10
+ * this host:
11
+ *
12
+ * - Node's resolution does not stop at TALOS's own folders. From `harness-ui/package.json` it walks every
13
+ * ancestor `node_modules` up to the drive root, then `~/.node_modules`, `~/.node_libraries` and
14
+ * `<prefix>/lib/node`.
15
+ * - On Windows the drive root lets any signed-in account create a folder (`icacls C:\` on this host:
16
+ * `NT AUTHORITY\Authenticated Users:(AD)`, and Modify on what they create). Anyone with a local account
17
+ * can therefore create `C:\node_modules`.
18
+ * - `@napi-rs/keyring` is native code that is handed every provider key TALOS stores. Loaded from such a
19
+ * folder, it would run with the owner's rights and could read or send the keys anywhere.
20
+ *
21
+ * On this host that is what happened, harmlessly: `C:\node_modules` is a junction into another
22
+ * checkout's `harness-ui\node_modules`, and a worktree without `harness-ui\node_modules` resolved the
23
+ * keyring there. The guard refused it, correctly; `doctor` just could not say so.
24
+ *
25
+ * ⛔ THE CURE: the module must be resolvable INSIDE the approved roots.
26
+ * - Installed: `cli/scripts/stage-windows.mjs` copies the dependency trees to `app/node_modules` and
27
+ * `app/vendor/harness-ui/node_modules`, both approved (read in code, not staged).
28
+ * - CI: `npm --prefix harness-ui ci`, inside the checkout.
29
+ * - Development: a `harness-ui\node_modules` inside the checkout — a real install, or ONE junction like the
30
+ * `cli\node_modules` every worktree here already has. Node reports the REAL path behind a junction, so
31
+ * the lexical roots alone refuse even that.
32
+ *
33
+ * ⛔⛔ Round 2, after adversarial review: "the real path of an approved root is approved" was too wide. A
34
+ * link at the root can be trusted as far as whoever placed it, but not further: the reviewer loaded an
35
+ * attacker module through a second link someone else could re-point (A2), through a junction into the real
36
+ * `C:\node_modules` (A3), into an ancestor folder (E), and into the drive root itself (E2). A real path is
37
+ * approved now only when ALL of these hold:
38
+ * 1. the approved root is at most a single link, and its target is not a link and not below one — checked
39
+ * as realpath(target) equal to the target, which fails for both;
40
+ * 2. the target is not a drive root;
41
+ * 3. the target is not an ancestor of the checkout;
42
+ * 4. the target is not inside a `node_modules` folder of an ancestor of the checkout — the folders Node's
43
+ * own lookup reaches, and exactly what `C:\node_modules` is; without this, A3 passes 1-3 on any host
44
+ * where that folder is a plain directory instead of a junction;
45
+ * 5. the module lies under `<target>\@napi-rs\keyring\`.
46
+ * ⛔ The verdict is reached BEFORE anything is loaded: a refused module never runs a line of code.
47
+ * ⛔ What this does NOT judge: who may write to the target. A junction to a folder other accounts can write
48
+ * into (a shared temporary folder, another drive's subfolder) passes when it satisfies 1-5. The guard
49
+ * reads no ACLs.
50
+ * ⛔ REFUSED as a design: recognising a junction ABOVE the checkout because its target looks like a TALOS
51
+ * location. Whoever creates `C:\node_modules` chooses where it points.
52
+ */
53
+ function inside(root, candidate) {
54
+ const rel = relative(resolve(root), resolve(candidate));
55
+ return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel));
56
+ }
57
+ function strictlyInside(root, candidate) { return inside(root, candidate) && relative(resolve(root), resolve(candidate)) !== ''; }
58
+ function samePath(a, b) { return relative(resolve(a), resolve(b)) === ''; }
59
+ function approvedModuleRoots(repoRoot) {
60
+ const roots = [join(repoRoot, 'harness-ui', 'node_modules'), join(repoRoot, 'node_modules')];
61
+ if (basename(repoRoot).toLowerCase() === 'vendor')
62
+ roots.push(join(dirname(repoRoot), 'node_modules'));
63
+ return roots;
64
+ }
65
+ /** Every folder above the checkout, nearest first, up to the drive root. */
66
+ function ancestorsOf(path) {
67
+ const out = [];
68
+ let current = dirname(resolve(path));
69
+ for (;;) {
70
+ out.push(current);
71
+ const next = dirname(current);
72
+ if (next === current)
73
+ break;
74
+ current = next;
75
+ }
76
+ return out;
77
+ }
78
+ /** One line, bounded: an error's later lines are stack frames, and doctor prints one line per check. */
79
+ function firstLine(error) {
80
+ const text = error instanceof Error ? error.message : String(error);
81
+ return (text.split(/\r?\n/u)[0] ?? '').slice(0, 300);
82
+ }
83
+ /**
84
+ * The keyring folder a single link at an approved root may stand for, or null. Rules 1-4 of the block
85
+ * above; rule 5 is the caller's containment check against the folder returned here.
86
+ */
87
+ function linkedKeyringFolder(root, repoRoot, fs) {
88
+ try {
89
+ if (!fs.lstat(root).isSymbolicLink())
90
+ return null;
91
+ const target = resolve(dirname(root), fs.readlink(root));
92
+ if (!fs.lstat(target).isDirectory())
93
+ return null;
94
+ const real = fs.realpath(target);
95
+ if (!samePath(real, target))
96
+ return null; /* 1 */
97
+ if (samePath(parse(real).root, real))
98
+ return null; /* 2 */
99
+ if (inside(real, repoRoot))
100
+ return null; /* 3 */
101
+ if (ancestorsOf(repoRoot).some(ancestor => inside(join(ancestor, 'node_modules'), real)))
102
+ return null; /* 4 */
103
+ return join(real, '@napi-rs', 'keyring');
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
109
+ /*
110
+ * R2 (gate E13): how many times this process tried to LOAD the native module (after resolution and the approved-roots check, the
111
+ * step that runs its code). `doctor` reports whether its own run moved it (`nativeModuleLoaded`): the observable by which the
112
+ * acceptance scenario s16 proves that a memory profile never opened the OS store.
113
+ */
114
+ let moduleLoads = 0;
115
+ export function systemKeyringModuleLoads() { return moduleLoads; }
116
+ export function loadTalosSystemKeyring(repoRoot, deps = {}) {
117
+ /* Created on first use and inside the try below: a repoRoot Node refuses as an anchor is a reason, never a throw. */
118
+ let requireFromTalos;
119
+ const talosRequire = () => requireFromTalos ??= createRequire(join(repoRoot, 'harness-ui', 'package.json'));
120
+ const resolveModule = deps.resolve ?? ((request) => talosRequire().resolve(request));
121
+ const loadModule = deps.load ?? ((file) => talosRequire()(file));
122
+ const fs = {
123
+ lstat: deps.lstat ?? ((path) => lstatSync(path)),
124
+ readlink: deps.readlink ?? ((path) => readlinkSync(path)),
125
+ realpath: deps.realpath ?? ((path) => realpathSync(path)),
126
+ };
127
+ const roots = approvedModuleRoots(repoRoot);
128
+ let location;
129
+ try {
130
+ location = resolveModule('@napi-rs/keyring');
131
+ }
132
+ catch (error) {
133
+ if (error?.code === 'MODULE_NOT_FOUND')
134
+ return { ok: false, reason: 'module-missing', approvedRoots: roots };
135
+ return { ok: false, reason: 'load-failed', detail: firstLine(error) };
136
+ }
137
+ const lexical = roots.some(root => inside(root, location));
138
+ const linked = roots.map(root => linkedKeyringFolder(root, repoRoot, fs)).filter((folder) => folder !== null);
139
+ if (!lexical && !linked.some(folder => strictlyInside(folder, location)))
140
+ return { ok: false, reason: 'outside-approved-roots', location, approvedRoots: roots }; /* 5 */
141
+ let mod;
142
+ moduleLoads++;
143
+ try {
144
+ mod = loadModule(location);
145
+ }
146
+ catch (error) {
147
+ return { ok: false, reason: 'load-failed', location, detail: firstLine(error) };
148
+ }
149
+ return typeof mod?.Entry === 'function' ? { ok: true, Entry: mod.Entry, location } : { ok: false, reason: 'invalid-module', location };
150
+ }
151
+ export function keyringModuleAvailable(repoRoot, deps = {}) { return loadTalosSystemKeyring(repoRoot, deps).ok; }
152
+ export async function diagnoseKeyringProbe(keyring, account = randomUUID()) {
153
+ const service = 'talos-cli-doctor';
154
+ const value = `probe-${randomUUID()}`;
155
+ try {
156
+ try {
157
+ await keyring.set(service, account, value);
158
+ }
159
+ catch (error) {
160
+ return { ok: false, stage: 'write', detail: firstLine(error) };
161
+ }
162
+ let read;
163
+ try {
164
+ read = await keyring.get(service, account);
165
+ }
166
+ catch (error) {
167
+ return { ok: false, stage: 'read', detail: firstLine(error) };
168
+ }
169
+ return read === value ? { ok: true } : { ok: false, stage: 'mismatch' };
170
+ }
171
+ finally {
172
+ try {
173
+ await keyring.remove(service, account);
174
+ }
175
+ catch { /* diagnostic cleanup is best effort */ }
176
+ }
177
+ }
178
+ export async function probeSystemKeyring(keyring, account = randomUUID()) { return (await diagnoseKeyringProbe(keyring, account)).ok; }
179
+ /*
180
+ * R2 (gate E1): `KEYRING_TEXT` moved into the dictionary (`i18n/en/credentials.ts`, `store.keyring.*`), words unchanged. These
181
+ * two functions stay the only place that picks them: `doctor` prints them, and the next surface that needs the reason reuses them.
182
+ */
183
+ export function describeKeyringProblem(problem) {
184
+ switch (problem.reason) {
185
+ case 'module-missing': return t('store.keyring.moduleMissing', { roots: problem.approvedRoots.join('; ') });
186
+ case 'outside-approved-roots': return t('store.keyring.outsideApprovedRoots', { location: problem.location, roots: problem.approvedRoots.join('; ') });
187
+ case 'load-failed': return problem.location === undefined ? t('store.keyring.unresolved', { detail: problem.detail }) : t('store.keyring.loadFailed', { location: problem.location, detail: problem.detail });
188
+ case 'invalid-module': return t('store.keyring.invalidModule', { location: problem.location });
189
+ }
190
+ }
191
+ export function describeKeyringProbeFailure(outcome) {
192
+ if (outcome.stage === 'mismatch')
193
+ return t('store.keyring.probeMismatch');
194
+ return t(outcome.stage === 'write' ? 'store.keyring.probeWriteFailed' : 'store.keyring.probeReadFailed', { detail: outcome.detail });
195
+ }
196
+ export function systemKeyringAdapter(Entry) {
197
+ return {
198
+ get(service, account) { try {
199
+ return new Entry(service, account).getPassword() || null;
200
+ }
201
+ catch {
202
+ return null;
203
+ } },
204
+ set(service, account, value) { new Entry(service, account).setPassword(value); },
205
+ remove(service, account) { try {
206
+ new Entry(service, account).deletePassword();
207
+ }
208
+ catch { /* idempotent removal */ } },
209
+ };
210
+ }
211
+ export function createTalosSystemKeyring(repoRoot, deps = {}) {
212
+ const loaded = loadTalosSystemKeyring(repoRoot, deps);
213
+ return loaded.ok ? systemKeyringAdapter(loaded.Entry) : null;
214
+ }
@@ -0,0 +1,63 @@
1
+ import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { join, resolve } from 'node:path';
3
+ function dir(paths) { return join(paths.dataRoot, 'active-runs'); }
4
+ function marker(paths, pid = process.pid) { return join(dir(paths), `${pid}.json`); }
5
+ function alive(pid) { try {
6
+ process.kill(pid, 0);
7
+ return true;
8
+ }
9
+ catch (error) {
10
+ return error?.code === 'EPERM';
11
+ } }
12
+ export async function registerActiveRun(paths, info = {}) {
13
+ const root = dir(paths);
14
+ await mkdir(root, { recursive: true, mode: 0o700 });
15
+ const file = marker(paths);
16
+ const record = { pid: process.pid, startedAt: new Date().toISOString(), ...info };
17
+ await writeFile(file, `${JSON.stringify(record)}\n`, { encoding: 'utf8', mode: 0o600 });
18
+ let released = false;
19
+ return async () => { if (released)
20
+ return; released = true; await rm(file, { force: true }); };
21
+ }
22
+ /* R5b D3: `exceptPid` leaves out a process (the TUI asking about the others: main.ts registers it for its whole life) and
23
+ `projectRoot` counts only the runs of that project; a marker that does not name its project still counts. */
24
+ function sameRoot(a, b) { const x = resolve(a), y = resolve(b); return process.platform === 'win32' ? x.toLowerCase() === y.toLowerCase() : x === y; }
25
+ export async function hasActiveRuns(paths, deps = {}) {
26
+ const isProcessAlive = deps.isProcessAlive ?? alive;
27
+ let names;
28
+ try {
29
+ names = await readdir(dir(paths));
30
+ }
31
+ catch (error) {
32
+ if (error?.code === 'ENOENT')
33
+ return false;
34
+ throw error;
35
+ }
36
+ let any = false;
37
+ for (const name of names) {
38
+ if (!/^\d+\.json$/u.test(name))
39
+ continue;
40
+ const file = join(dir(paths), name);
41
+ let pid = 0;
42
+ let root = null;
43
+ try {
44
+ const data = JSON.parse(await readFile(file, 'utf8'));
45
+ pid = Number(data?.pid);
46
+ root = data?.projectRoot;
47
+ }
48
+ catch {
49
+ await rm(file, { force: true });
50
+ continue;
51
+ }
52
+ if (!Number.isSafeInteger(pid) || pid <= 0 || !isProcessAlive(pid)) {
53
+ await rm(file, { force: true });
54
+ continue;
55
+ }
56
+ if (deps.exceptPid === pid)
57
+ continue;
58
+ if (deps.projectRoot && typeof root === 'string' && root && !sameRoot(root, deps.projectRoot))
59
+ continue;
60
+ any = true;
61
+ }
62
+ return any;
63
+ }
@@ -0,0 +1,74 @@
1
+ export class CliAgentTreeError extends Error {
2
+ code = 'AGENT_TREE_INVALID';
3
+ constructor(message = 'Agent tree input is invalid.') { super(message); this.name = 'CliAgentTreeError'; }
4
+ }
5
+ function copyUsage(value) { return value ? { ...value } : null; }
6
+ function copyCollisions(value) { return value.map(row => ({ ...row })); }
7
+ function copyEvidence(value) { return value ? { ...value } : null; }
8
+ function nodeOf(row, children) {
9
+ return {
10
+ id: row.id,
11
+ parentId: row.parentId,
12
+ nativeDepth: row.depth,
13
+ name: row.name,
14
+ task: row.delegatedTask,
15
+ model: row.model,
16
+ outcome: row.outcome,
17
+ interrupted: row.interrupted,
18
+ startedAt: row.startedAt,
19
+ updatedAt: row.updatedAt,
20
+ endedAt: row.endedAt,
21
+ usage: copyUsage(row.usage),
22
+ collisions: copyCollisions(row.collisions),
23
+ delegationOutcome: row.delegationOutcome,
24
+ delegationEvidence: copyEvidence(row.delegationEvidence),
25
+ children,
26
+ };
27
+ }
28
+ export function buildAgentTree(rows, focusId) {
29
+ const byId = new Map();
30
+ for (const row of rows) {
31
+ if (typeof row.id !== 'string' || !row.id)
32
+ throw new CliAgentTreeError('Agent tree contains an empty session id.');
33
+ if (byId.has(row.id))
34
+ throw new CliAgentTreeError('Agent tree contains duplicate session ids.');
35
+ byId.set(row.id, row);
36
+ }
37
+ const focus = byId.get(focusId);
38
+ if (!focus)
39
+ return null;
40
+ const validParent = new Map();
41
+ const childIds = new Map();
42
+ for (const row of rows) {
43
+ if (!row.parentId)
44
+ continue;
45
+ const parent = byId.get(row.parentId);
46
+ if (!parent || row.depth !== parent.depth + 1)
47
+ continue;
48
+ validParent.set(row.id, parent.id);
49
+ const siblings = childIds.get(parent.id);
50
+ if (siblings)
51
+ siblings.push(row.id);
52
+ else
53
+ childIds.set(parent.id, [row.id]);
54
+ }
55
+ let root = focus;
56
+ const climbSeen = new Set();
57
+ while (validParent.has(root.id)) {
58
+ if (climbSeen.has(root.id))
59
+ throw new CliAgentTreeError('Agent tree contains a delegation cycle.');
60
+ climbSeen.add(root.id);
61
+ const parent = byId.get(validParent.get(root.id));
62
+ if (!parent)
63
+ break;
64
+ root = parent;
65
+ }
66
+ const build = (id) => {
67
+ const row = byId.get(id);
68
+ if (!row)
69
+ throw new CliAgentTreeError('Agent tree references a missing session.');
70
+ const children = (childIds.get(id) ?? []).map(build);
71
+ return nodeOf(row, children);
72
+ };
73
+ return { focusId: focus.id, root: build(root.id) };
74
+ }