talos-code 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +661 -0
  3. package/README.md +116 -3
  4. package/THIRD_PARTY_NOTICES.md +40 -0
  5. package/dist/archive/zip.js +73 -0
  6. package/dist/args.js +100 -0
  7. package/dist/automations/history-store.js +34 -0
  8. package/dist/automations/policy-store.js +43 -0
  9. package/dist/automations/runner.js +107 -0
  10. package/dist/automations/schedule.js +85 -0
  11. package/dist/automations/windows-task.js +53 -0
  12. package/dist/commands/advanced-cli.js +233 -0
  13. package/dist/commands/checkpoint-cli.js +45 -0
  14. package/dist/commands/config-cli.js +107 -0
  15. package/dist/commands/context.js +17 -0
  16. package/dist/commands/extensions-cli.js +207 -0
  17. package/dist/commands/project-cli.js +74 -0
  18. package/dist/commands/project-commands.js +143 -0
  19. package/dist/commands/provider-cli.js +244 -0
  20. package/dist/commands/services-cli.js +248 -0
  21. package/dist/commands/session-cli.js +171 -0
  22. package/dist/commands/system-cli.js +405 -0
  23. package/dist/config/commands.js +60 -0
  24. package/dist/config/load.js +382 -0
  25. package/dist/config/migrations.js +48 -0
  26. package/dist/config/types.js +11 -0
  27. package/dist/diagnostics/development-log.js +154 -0
  28. package/dist/diagnostics/doctor.js +104 -0
  29. package/dist/diagnostics/redact.js +80 -0
  30. package/dist/diagnostics/zip.js +52 -0
  31. package/dist/errors.js +156 -0
  32. package/dist/events/bridge.js +130 -0
  33. package/dist/extensions/installer.js +178 -0
  34. package/dist/extensions/package-schema.js +24 -0
  35. package/dist/headless/result.js +84 -0
  36. package/dist/headless/run.js +230 -0
  37. package/dist/i18n/en/approval.js +46 -0
  38. package/dist/i18n/en/common.js +9 -0
  39. package/dist/i18n/en/credentials.js +92 -0
  40. package/dist/i18n/en/errors.js +267 -0
  41. package/dist/i18n/en/firstrun.js +101 -0
  42. package/dist/i18n/en/providers.js +37 -0
  43. package/dist/i18n/en/screen.js +774 -0
  44. package/dist/i18n/en/tools.js +127 -0
  45. package/dist/i18n/en.js +14 -0
  46. package/dist/i18n/error-view.js +307 -0
  47. package/dist/i18n/index.js +19 -0
  48. package/dist/i18n/kernel-map.js +139 -0
  49. package/dist/io.js +45 -0
  50. package/dist/main.js +331 -0
  51. package/dist/paths.js +41 -0
  52. package/dist/protocol/v2/codec.js +9 -0
  53. package/dist/protocol/v2/events.js +555 -0
  54. package/dist/protocol/v2/index.js +4 -0
  55. package/dist/protocol/v2/replay.js +28 -0
  56. package/dist/protocol/v2/types.js +1 -0
  57. package/dist/provider/control-plane.js +135 -0
  58. package/dist/provider/environment-keys.js +275 -0
  59. package/dist/provider/health.js +110 -0
  60. package/dist/provider/missing-key.js +48 -0
  61. package/dist/provider/model-catalog.js +168 -0
  62. package/dist/provider/openrouter-login.js +172 -0
  63. package/dist/provider/provider-text.js +13 -0
  64. package/dist/provider/store.js +95 -0
  65. package/dist/provider/system-keyring.js +214 -0
  66. package/dist/runtime/active-run.js +63 -0
  67. package/dist/runtime/agent-tree.js +74 -0
  68. package/dist/runtime/attachments.js +84 -0
  69. package/dist/runtime/brokered-executor.js +395 -0
  70. package/dist/runtime/context-archive.js +69 -0
  71. package/dist/runtime/context-status.js +76 -0
  72. package/dist/runtime/create-runtime.js +111 -0
  73. package/dist/runtime/model-profile.js +361 -0
  74. package/dist/runtime/output-store.js +137 -0
  75. package/dist/runtime/provider-attempts.js +185 -0
  76. package/dist/runtime/replay-buffer.js +153 -0
  77. package/dist/runtime/repo.js +95 -0
  78. package/dist/runtime/session-facade.js +135 -0
  79. package/dist/runtime/session-summary.js +125 -0
  80. package/dist/runtime/supervisor.js +265 -0
  81. package/dist/runtime/talos-composition.js +1011 -0
  82. package/dist/runtime/types.js +5 -0
  83. package/dist/runtime/usage-snapshot.js +82 -0
  84. package/dist/security/auto-classifier.js +38 -0
  85. package/dist/security/credential-free-environment.js +54 -0
  86. package/dist/security/evaluate.js +243 -0
  87. package/dist/security/execution-backends.js +236 -0
  88. package/dist/security/execution-broker.js +102 -0
  89. package/dist/security/forge-scan.js +74 -0
  90. package/dist/security/from-approval.js +39 -0
  91. package/dist/security/mxc-execution-backend.js +281 -0
  92. package/dist/security/permission-engine.js +138 -0
  93. package/dist/security/permission-explanation.js +54 -0
  94. package/dist/security/persist.js +179 -0
  95. package/dist/security/plugin-guard.js +230 -0
  96. package/dist/security/process-tree-evidence-store.js +74 -0
  97. package/dist/security/process-tree-probe.js +554 -0
  98. package/dist/security/project-resource-inventory.js +186 -0
  99. package/dist/security/project-trust-gate.js +38 -0
  100. package/dist/security/project-trust.js +367 -0
  101. package/dist/security/rule-parser.js +201 -0
  102. package/dist/security/shell-segmentation.js +68 -0
  103. package/dist/security/trust-authority.js +324 -0
  104. package/dist/security/types.js +1 -0
  105. package/dist/security/workspace-identity.js +102 -0
  106. package/dist/services/automation-facade.js +59 -0
  107. package/dist/services/forge-facade.js +77 -0
  108. package/dist/services/hook-facade.js +240 -0
  109. package/dist/services/index.js +16 -0
  110. package/dist/services/library-facade.js +174 -0
  111. package/dist/services/mcp-facade.js +348 -0
  112. package/dist/services/memory-facade.js +126 -0
  113. package/dist/services/notes-facade.js +157 -0
  114. package/dist/services/plugin-facade.js +308 -0
  115. package/dist/services/research-facade.js +110 -0
  116. package/dist/services/task-board-facade.js +236 -0
  117. package/dist/services/workflow-catalog.js +246 -0
  118. package/dist/sessions/export-format.js +98 -0
  119. package/dist/sessions/metadata-store.js +160 -0
  120. package/dist/sessions/share.js +122 -0
  121. package/dist/sessions/transfer.js +16 -0
  122. package/dist/subcommands.js +62 -0
  123. package/dist/tui/agent-roster.js +36 -0
  124. package/dist/tui/agent-view.js +51 -0
  125. package/dist/tui/app.js +4098 -0
  126. package/dist/tui/approval.js +36 -0
  127. package/dist/tui/boot/boot-sequence.js +76 -0
  128. package/dist/tui/boot/cinematic.js +243 -0
  129. package/dist/tui/boot/desktop-logo.js +82 -0
  130. package/dist/tui/boot.js +3 -0
  131. package/dist/tui/busy-input.js +58 -0
  132. package/dist/tui/catalog-service.js +560 -0
  133. package/dist/tui/components/assistant-stream.js +1 -0
  134. package/dist/tui/components/command-menu.js +68 -0
  135. package/dist/tui/components/composer.js +219 -0
  136. package/dist/tui/components/diff.js +35 -0
  137. package/dist/tui/components/footer.js +48 -0
  138. package/dist/tui/components/header.js +6 -0
  139. package/dist/tui/components/markdown.js +305 -0
  140. package/dist/tui/components/status-indicator.js +38 -0
  141. package/dist/tui/components/terminal-shell.js +214 -0
  142. package/dist/tui/components/thinking-row.js +19 -0
  143. package/dist/tui/components/tool-row.js +97 -0
  144. package/dist/tui/components/transcript-virtualizer.js +165 -0
  145. package/dist/tui/components/transcript.js +43 -0
  146. package/dist/tui/descendant-approvals.js +104 -0
  147. package/dist/tui/diff-model.js +77 -0
  148. package/dist/tui/editor-history.js +21 -0
  149. package/dist/tui/editor.js +210 -0
  150. package/dist/tui/event-adapter.js +436 -0
  151. package/dist/tui/exit-output.js +58 -0
  152. package/dist/tui/external-editor.js +53 -0
  153. package/dist/tui/file-completion.js +89 -0
  154. package/dist/tui/focus-manager.js +5 -0
  155. package/dist/tui/highlight.js +30 -0
  156. package/dist/tui/input-router.js +18 -0
  157. package/dist/tui/interrupt.js +99 -0
  158. package/dist/tui/keybindings.js +194 -0
  159. package/dist/tui/keymap-resolver.js +91 -0
  160. package/dist/tui/launch-state.js +148 -0
  161. package/dist/tui/line-diff.js +57 -0
  162. package/dist/tui/live-activity.js +56 -0
  163. package/dist/tui/metrics.js +123 -0
  164. package/dist/tui/onboarding.js +36 -0
  165. package/dist/tui/overlays/agent-tree.js +43 -0
  166. package/dist/tui/overlays/approval-dialog.js +642 -0
  167. package/dist/tui/overlays/automation-center.js +51 -0
  168. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  169. package/dist/tui/overlays/context-inspector.js +36 -0
  170. package/dist/tui/overlays/effort-line.js +110 -0
  171. package/dist/tui/overlays/forge-center.js +46 -0
  172. package/dist/tui/overlays/help-dialog.js +16 -0
  173. package/dist/tui/overlays/history-picker.js +37 -0
  174. package/dist/tui/overlays/hook-center.js +70 -0
  175. package/dist/tui/overlays/library-center.js +55 -0
  176. package/dist/tui/overlays/mcp-center.js +60 -0
  177. package/dist/tui/overlays/memory-center.js +63 -0
  178. package/dist/tui/overlays/model-picker.js +77 -0
  179. package/dist/tui/overlays/notes-center.js +53 -0
  180. package/dist/tui/overlays/overlay-host.js +8 -0
  181. package/dist/tui/overlays/plugin-center.js +76 -0
  182. package/dist/tui/overlays/provider-picker.js +171 -0
  183. package/dist/tui/overlays/queue-editor.js +32 -0
  184. package/dist/tui/overlays/research-center.js +59 -0
  185. package/dist/tui/overlays/scroll-window.js +234 -0
  186. package/dist/tui/overlays/session-picker.js +115 -0
  187. package/dist/tui/overlays/tasks-center.js +83 -0
  188. package/dist/tui/overlays/theme-picker.js +21 -0
  189. package/dist/tui/overlays/transcript-search.js +58 -0
  190. package/dist/tui/overlays/trust-center.js +29 -0
  191. package/dist/tui/overlays/workflow-center.js +46 -0
  192. package/dist/tui/project-file-index.js +214 -0
  193. package/dist/tui/project-references.js +85 -0
  194. package/dist/tui/project-trust-prompt.js +289 -0
  195. package/dist/tui/prompt-history-store.js +116 -0
  196. package/dist/tui/queue-store.js +110 -0
  197. package/dist/tui/regions/budget.js +59 -0
  198. package/dist/tui/regions/views.js +96 -0
  199. package/dist/tui/render-coordinator.js +148 -0
  200. package/dist/tui/render-scheduler.js +4 -0
  201. package/dist/tui/run.js +69 -0
  202. package/dist/tui/selection-list.js +29 -0
  203. package/dist/tui/session-controller.js +791 -0
  204. package/dist/tui/session-export.js +54 -0
  205. package/dist/tui/setup-wizard.js +46 -0
  206. package/dist/tui/shell-input.js +35 -0
  207. package/dist/tui/shell-layout.js +48 -0
  208. package/dist/tui/shell-model.js +98 -0
  209. package/dist/tui/slash-commands.js +82 -0
  210. package/dist/tui/state.js +151 -0
  211. package/dist/tui/status-bar.js +125 -0
  212. package/dist/tui/status-view.js +40 -0
  213. package/dist/tui/terminal-capabilities.js +9 -0
  214. package/dist/tui/terminal-session.js +11 -0
  215. package/dist/tui/text-width.js +66 -0
  216. package/dist/tui/theme-catalog.js +27 -0
  217. package/dist/tui/theme-store.js +23 -0
  218. package/dist/tui/theme.js +23 -0
  219. package/dist/tui/tool-display.js +135 -0
  220. package/dist/tui/tool-facts.js +1 -0
  221. package/dist/tui/tools/bash-renderer.js +32 -0
  222. package/dist/tui/tools/change.js +61 -0
  223. package/dist/tui/tools/edit-renderer.js +17 -0
  224. package/dist/tui/tools/generic-renderer.js +13 -0
  225. package/dist/tui/tools/list-renderer.js +14 -0
  226. package/dist/tui/tools/read-renderer.js +13 -0
  227. package/dist/tui/tools/registry.js +20 -0
  228. package/dist/tui/tools/row-format.js +187 -0
  229. package/dist/tui/tools/search-renderer.js +38 -0
  230. package/dist/tui/tools/shared.js +97 -0
  231. package/dist/tui/tools/write-renderer.js +15 -0
  232. package/dist/tui/transcript-model.js +441 -0
  233. package/dist/tui/ui-preferences.js +79 -0
  234. package/dist/tui/usage-view.js +77 -0
  235. package/dist/tui/vim-mode.js +99 -0
  236. package/dist/update/check.js +15 -0
  237. package/dist/update/npm.js +51 -0
  238. package/dist/update/run.js +129 -0
  239. package/dist/version.js +2 -0
  240. package/dist/workspace/checkpoint-store.js +210 -0
  241. package/dist/workspace/checkpoint.js +413 -0
  242. package/dist/workspace/restore.js +232 -0
  243. package/package.json +64 -5
  244. package/vendor/context-engine/package.json +11 -0
  245. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  246. package/vendor/context-engine/src/contracts.mjs +48 -0
  247. package/vendor/context-engine/src/engine.mjs +445 -0
  248. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  249. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  250. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  251. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  252. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  253. package/vendor/context-engine/src/profiles.mjs +10 -0
  254. package/vendor/context-engine/src/retrieval.mjs +104 -0
  255. package/vendor/context-engine/src/summary.mjs +97 -0
  256. package/vendor/context-engine/src/usage.mjs +34 -0
  257. package/vendor/harness-ui/package.json +38 -0
  258. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  259. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  260. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  261. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  262. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  263. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  264. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  265. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  266. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  267. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  268. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  269. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  270. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  271. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  272. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  273. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  274. package/vendor/harness-ui/src/config.mjs +697 -0
  275. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  276. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  277. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  278. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  279. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  280. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  281. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  282. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  283. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  284. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  285. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  286. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  287. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  288. package/vendor/harness-ui/src/doctor.mjs +142 -0
  289. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  290. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  291. package/vendor/harness-ui/src/document-report.mjs +331 -0
  292. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  293. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  294. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  295. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  296. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  297. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  298. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  299. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  300. package/vendor/harness-ui/src/git-service.mjs +626 -0
  301. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  302. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  303. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  304. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  305. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  306. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  307. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  308. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  309. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  310. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  311. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  312. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  313. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  314. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  315. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  316. package/vendor/harness-ui/src/library-store.mjs +652 -0
  317. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  318. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  319. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  320. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  321. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  322. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  323. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  324. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  325. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  326. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  327. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  328. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  329. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  330. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  331. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  332. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  333. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  334. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  335. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  336. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  337. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  338. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  339. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  340. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  341. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  342. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  343. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  344. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  345. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  346. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  347. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  348. package/vendor/harness-ui/src/research/card.mjs +235 -0
  349. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  350. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  351. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  352. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  353. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  354. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  355. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  356. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  357. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  358. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  359. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  360. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  361. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  362. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  363. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  364. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  365. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  366. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  367. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  368. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  369. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  370. package/vendor/harness-ui/src/research/report.mjs +203 -0
  371. package/vendor/harness-ui/src/research/run.mjs +527 -0
  372. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  373. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  374. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  375. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  376. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  377. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  378. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  379. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  380. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  381. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  382. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  383. package/vendor/harness-ui/src/session-store.mjs +220 -0
  384. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  385. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  386. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  387. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  388. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  389. package/vendor/harness-ui/src/static-files.mjs +96 -0
  390. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  391. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  392. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  393. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  394. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  395. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  396. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  397. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  398. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  399. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  400. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  401. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  402. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  403. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  404. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  405. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  406. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  407. package/vendor/manifest.json +170 -0
@@ -0,0 +1,331 @@
1
+ /**
2
+ * document-report.mjs — porto VERBATIM di
3
+ * mobile/src/lib/documents/reportBuilder.ts (letto per intero il 28/8
4
+ * prima di scrivere una riga, piano elegant-spinning-dongarra.md).
5
+ *
6
+ * Solo sintassi TypeScript → JavaScript (tipi rimossi), la LOGICA è
7
+ * identica — incluse le correzioni già pagate sul mobile (canvas a
8
+ * altezza zero, barre negative appiattite, tabelle con celle mancanti,
9
+ * pagine vuote da `pb` consecutivi): riscriverle da zero le avrebbe
10
+ * fatte ripagare qui.
11
+ *
12
+ * Un documento il MODELLO descrive a blocchi semantici (niente
13
+ * coordinate, niente colori) — il layout lo decide questo file, non il
14
+ * chiamante. `pdfmake` fa il lavoro di flusso (interruzioni di pagina,
15
+ * intestazioni di tabella ripetute, piè di pagina che sa il numero).
16
+ */
17
+
18
+ export const TALOS_REPORT_THEMES = {
19
+ report: { brand: '#3E2723', accent: '#7B9C7B', ink: '#2C2320', muted: '#8A7F79', panel: '#F5F0E8' },
20
+ plain: { brand: '#1F2933', accent: '#3D5A80', ink: '#1F2933', muted: '#7B8794', panel: '#F1F3F5' },
21
+ }
22
+
23
+ const CHART_WIDTH = 460
24
+ const CHART_HEIGHT = 170
25
+ const ALIGNMENT = { l: 'left', c: 'center', r: 'right' }
26
+
27
+ /**
28
+ * Un canvas costruito solo da `path` misura altezza zero: il misuratore
29
+ * di pdfmake distingue ellisse/rettangolo/linea/polilinea ma non ha un
30
+ * caso per `path`, quindi una torta non riserva spazio e il blocco dopo
31
+ * ci viene disegnato sopra. Un rettangolo invisibile riserva lo spazio.
32
+ */
33
+ function boundingBox(width, height) {
34
+ return { type: 'rect', x: 0, y: 0, w: width, h: height, color: '#FFFFFF', fillOpacity: 0 }
35
+ }
36
+
37
+ function slicePath(cx, cy, radius, from, to) {
38
+ const x1 = cx + radius * Math.cos(from)
39
+ const y1 = cy + radius * Math.sin(from)
40
+ const x2 = cx + radius * Math.cos(to)
41
+ const y2 = cy + radius * Math.sin(to)
42
+ const largeArc = to - from > Math.PI ? 1 : 0
43
+ return `M ${cx} ${cy} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2} Z`
44
+ }
45
+
46
+ function paletteFor(theme, index) {
47
+ const wheel = [theme.accent, theme.brand, theme.muted, '#C8B49B', '#A5B8A5', '#6E5B52']
48
+ return wheel[index % wheel.length]
49
+ }
50
+
51
+ function barChart(block, theme) {
52
+ const values = block.series[0]?.data ?? []
53
+ if (values.length === 0) return { text: '', margin: [0, 0, 0, 0] }
54
+
55
+ // La scala attraversa lo zero: una barra negativa scende SOTTO
56
+ // l'asse invece di appiattirsi a un puntino — tre valori negativi
57
+ // disegnati come tre segni identici da 2pt non direbbero niente.
58
+ const low = Math.min(0, ...values)
59
+ const high = Math.max(0, ...values)
60
+ const span = high - low || 1
61
+ const plot = CHART_HEIGHT - 34
62
+ const zeroY = 8 + (high / span) * plot
63
+
64
+ // Il gap si restringe col numero di barre: oltre le 31 un gap fisso
65
+ // da 14pt rendeva la larghezza NEGATIVA — tre anni di punti mensili
66
+ // è una richiesta ordinaria.
67
+ const gap = Math.min(14, CHART_WIDTH / (values.length * 4))
68
+ const pitch = CHART_WIDTH / values.length
69
+ const barWidth = Math.max(1, pitch - gap)
70
+ const canvas = [boundingBox(CHART_WIDTH, CHART_HEIGHT)]
71
+
72
+ canvas.push({
73
+ type: 'line', x1: 0, y1: zeroY, x2: CHART_WIDTH, y2: zeroY,
74
+ lineWidth: 0.8, lineColor: theme.muted,
75
+ })
76
+ values.forEach((value, index) => {
77
+ const height = Math.abs(value / span) * plot
78
+ canvas.push({
79
+ type: 'rect',
80
+ x: index * pitch + gap / 2,
81
+ y: value >= 0 ? zeroY - height : zeroY,
82
+ w: barWidth,
83
+ h: Math.max(1, height),
84
+ r: 1,
85
+ color: value >= 0 ? paletteFor(theme, index) : theme.muted,
86
+ })
87
+ })
88
+
89
+ return {
90
+ // La riga delle etichette è misurata sulla STESSA pista delle
91
+ // barre (colonne fisse di `pitch`, non colonne '*'): su due
92
+ // piste diverse, dalla settima barra in poi l'etichetta cadeva
93
+ // fuori dalla barra a cui si riferiva.
94
+ stack: [
95
+ { canvas },
96
+ {
97
+ columns: values.map((value, index) => ({
98
+ width: pitch,
99
+ stack: [
100
+ { text: String(value), style: 'chartValue' },
101
+ { text: String(block.labels[index] ?? ''), style: 'chartLabel' },
102
+ ],
103
+ })),
104
+ columnGap: 0,
105
+ margin: [0, 2, 0, 0],
106
+ },
107
+ ],
108
+ margin: [0, 4, 0, 12],
109
+ }
110
+ }
111
+
112
+ function pieChart(block, theme) {
113
+ const values = block.series[0]?.data ?? []
114
+ // Solo la parte positiva: sommando i negativi il totale diventava
115
+ // più piccolo di una singola fetta, e due fette disegnavano ognuna
116
+ // un cerchio INTERO, uno sopra l'altro.
117
+ const total = values.reduce((sum, value) => sum + Math.max(0, value), 0)
118
+ const radius = 68
119
+ let angle = -Math.PI / 2
120
+ const slices = []
121
+
122
+ values.forEach((value, index) => {
123
+ if (total <= 0 || value <= 0) return
124
+ const sweep = (value / total) * Math.PI * 2
125
+ slices.push(`<path d="${slicePath(78, 74, radius, angle, angle + sweep)}" fill="${paletteFor(theme, index)}"/>`)
126
+ angle += sweep
127
+ })
128
+ /*
129
+ * ⛔⛔⛔ 28/8, trovato dal vivo sul PORTO Node (screenshot del PDF,
130
+ * non solo "si riapre" — la verifica automatica passava lo stesso):
131
+ * il motore pdfmake lato server (`PdfPrinter`/PDFKit, ctx7
132
+ * confermato) misura MALE un `canvas` che contiene un elemento
133
+ * `type:'path'` (le fette della torta), anche con un rettangolo
134
+ * `boundingBox` invisibile davanti come richiesto dal commento
135
+ * originale — provato isolato: un canvas con solo `rect` misura
136
+ * giusto, lo STESSO canvas con anche un `path` misura zero e il
137
+ * blocco dopo ci si sovrappone. ⛔ Una prima ipotesi (il problema
138
+ * erano due blocchi `columns` di fila) si è rivelata SBAGLIATA,
139
+ * corretta con lo stesso test — un `stack` esterno non cambiava
140
+ * niente. La causa vera è il primitivo `path` dentro `canvas`,
141
+ * non la forma del contenitore. Correlato a un difetto noto della
142
+ * libreria sul riuso di elementi canvas (issue #2123 upstream,
143
+ * non identico ma stessa famiglia).
144
+ *
145
+ * ⇒ Cura verificata: le fette diventano un vero elemento `svg`
146
+ * (markup SVG, un percorso diverso nel renderer — non passa dal
147
+ * misuratore canvas rotto). Confermato isolato: stesso scenario
148
+ * KPI→torta, altezza corretta, nessuna sovrapposizione.
149
+ */
150
+ const svg = `<svg width="170" height="150" viewBox="0 0 170 150">${slices.join('')}</svg>`
151
+
152
+ return {
153
+ stack: [{
154
+ columns: [
155
+ { width: 170, svg },
156
+ {
157
+ width: '*',
158
+ stack: values.map((value, index) => ({
159
+ columns: [
160
+ { width: 10, canvas: [{ type: 'rect', x: 0, y: 3, w: 8, h: 8, color: paletteFor(theme, index) }] },
161
+ {
162
+ width: '*',
163
+ text: `${block.labels[index] ?? ''} — ${total > 0 ? Math.round((Math.max(0, value) / total) * 100) : 0}%`,
164
+ style: 'legend',
165
+ },
166
+ ],
167
+ columnGap: 6,
168
+ margin: [0, 0, 0, 4],
169
+ })),
170
+ margin: [0, 18, 0, 0],
171
+ },
172
+ ],
173
+ }],
174
+ margin: [0, 4, 0, 12],
175
+ }
176
+ }
177
+
178
+ function renderBlock(block, theme) {
179
+ switch (block.t) {
180
+ case 'cover':
181
+ return [{
182
+ stack: [
183
+ { canvas: [{ type: 'rect', x: 0, y: 0, w: 60, h: 6, r: 3, color: theme.accent }], margin: [0, 140, 0, 18] },
184
+ { text: block.title, style: 'coverTitle' },
185
+ ...(block.subtitle ? [{ text: block.subtitle, style: 'coverSubtitle' }] : []),
186
+ ...(block.date ? [{ text: block.date, style: 'coverDate' }] : []),
187
+ ],
188
+ }]
189
+ case 'h':
190
+ return [{ text: block.x, style: `h${block.lvl ?? 1}` }]
191
+ case 'p':
192
+ return [{ text: block.x, style: 'body' }]
193
+ case 'note':
194
+ return [{ text: block.x, style: 'note' }]
195
+ case 'list':
196
+ return [{
197
+ [block.ordered ? 'ol' : 'ul']: block.items.map((item) => ({ text: item, style: 'body' })),
198
+ margin: [0, 0, 0, 10],
199
+ }]
200
+ case 'kpi':
201
+ return [{
202
+ columns: block.items.map((item) => ({
203
+ width: '*',
204
+ stack: [
205
+ { text: item.v, style: 'kpiValue' },
206
+ { text: item.l, style: 'kpiLabel' },
207
+ ...(item.d ? [{ text: item.d, style: 'kpiDelta' }] : []),
208
+ ],
209
+ margin: [8, 10, 8, 10],
210
+ })),
211
+ columnGap: 8,
212
+ margin: [0, 4, 0, 14],
213
+ }]
214
+ case 'table': {
215
+ const head = block.head ?? []
216
+ // La larghezza si decide PRIMA di costruire il corpo, e ogni
217
+ // riga viene imbottita fino a quella misura — una sola cella
218
+ // mancante in una tabella da sessanta righe lanciava
219
+ // "Malformed table row" fuori da pdfmake, dopo che il
220
+ // modello aveva già scritto l'intero report.
221
+ const columns = Math.max(
222
+ head.length,
223
+ ...block.rows.map((row) => row.length),
224
+ block.total?.length ?? 0,
225
+ 1,
226
+ )
227
+ const cells = (row, style) =>
228
+ Array.from({ length: columns }, (_, index) => ({
229
+ text: row[index] ?? '',
230
+ style,
231
+ alignment: ALIGNMENT[block.align?.[index] ?? 'l'],
232
+ }))
233
+
234
+ const body = []
235
+ if (head.length) body.push(cells(head, 'th'))
236
+ for (const row of block.rows) body.push(cells(row, 'td'))
237
+ if (block.total?.length) body.push(cells(block.total, 'tdTotal'))
238
+
239
+ return [{
240
+ table: {
241
+ // L'intestazione si ripete su ogni pagina che la
242
+ // tabella attraversa — il motivo per cui è stato
243
+ // scelto un motore di flusso.
244
+ headerRows: head.length ? 1 : 0,
245
+ widths: Array.from({ length: columns }, (_, index) => (index === 0 ? '*' : 'auto')),
246
+ body: body.length ? body : [Array.from({ length: columns }, () => '')],
247
+ },
248
+ layout: {
249
+ hLineWidth: (index) => (index === 0 || index === 1 ? 0.8 : 0.4),
250
+ vLineWidth: () => 0,
251
+ hLineColor: (index) => (index <= 1 ? theme.brand : '#E3DCD2'),
252
+ paddingTop: () => 5,
253
+ paddingBottom: () => 5,
254
+ },
255
+ margin: [0, 2, 0, 14],
256
+ }]
257
+ }
258
+ case 'chart':
259
+ return [block.kind === 'pie' ? pieChart(block, theme) : barChart(block, theme)]
260
+ case 'spacer':
261
+ return [{ text: ' ', margin: [0, 6, 0, 6] }]
262
+ case 'pb':
263
+ return [{ text: '', pageBreak: 'after' }]
264
+ default:
265
+ return []
266
+ }
267
+ }
268
+
269
+ export function buildTalosReportDefinition(spec) {
270
+ const theme = TALOS_REPORT_THEMES[spec.theme ?? 'report'] ?? TALOS_REPORT_THEMES.report
271
+ const content = []
272
+ let lastWasBreak = true // un'interruzione prima di ogni contenuto sarebbe una pagina vuota
273
+
274
+ for (const block of spec.blocks) {
275
+ if (block.t === 'pb') {
276
+ // Interruzioni consecutive sono pagine vuote che nessuno ha chiesto.
277
+ if (lastWasBreak) continue
278
+ lastWasBreak = true
279
+ }
280
+ else {
281
+ lastWasBreak = false
282
+ }
283
+ content.push(...renderBlock(block, theme))
284
+ }
285
+
286
+ const footerText = spec.footer?.text ?? ''
287
+ const showPage = spec.footer?.pageNo !== false
288
+
289
+ return {
290
+ pageSize: 'A4',
291
+ pageOrientation: 'portrait',
292
+ pageMargins: [48, 46, 48, 56],
293
+ info: {
294
+ title: spec.meta.title,
295
+ ...(spec.meta.author ? { author: spec.meta.author } : {}),
296
+ },
297
+ defaultStyle: { font: 'Roboto', fontSize: 10, color: theme.ink, lineHeight: 1.25 },
298
+ styles: {
299
+ coverTitle: { fontSize: 30, bold: true, color: theme.brand, margin: [0, 0, 0, 10] },
300
+ coverSubtitle: { fontSize: 13, color: theme.muted, margin: [0, 0, 0, 26] },
301
+ coverDate: { fontSize: 11, color: theme.accent },
302
+ h1: { fontSize: 18, bold: true, color: theme.brand, margin: [0, 14, 0, 6] },
303
+ h2: { fontSize: 14, bold: true, color: theme.brand, margin: [0, 12, 0, 5] },
304
+ h3: { fontSize: 11, bold: true, color: theme.ink, margin: [0, 10, 0, 4] },
305
+ body: { margin: [0, 0, 0, 8] },
306
+ note: { fontSize: 8.5, color: theme.muted, italics: true, margin: [0, 0, 0, 10] },
307
+ kpiValue: { fontSize: 17, bold: true, color: theme.brand },
308
+ kpiLabel: { fontSize: 8.5, color: theme.muted },
309
+ kpiDelta: { fontSize: 9, color: theme.accent, bold: true },
310
+ th: { bold: true, fontSize: 9.5, color: theme.brand },
311
+ td: { fontSize: 9.5 },
312
+ tdTotal: { fontSize: 9.5, bold: true, color: theme.brand },
313
+ chartValue: { fontSize: 8.5, bold: true, alignment: 'center', color: theme.brand },
314
+ chartLabel: { fontSize: 8.5, alignment: 'center', color: theme.muted },
315
+ legend: { fontSize: 9 },
316
+ footer: { fontSize: 8, color: theme.muted },
317
+ },
318
+ // Una funzione, perché deve sapere in che pagina si trova — cosa
319
+ // che un'API a coordinate non può dare senza contare le pagine a mano.
320
+ footer: (currentPage, pageCount) => ({
321
+ columns: [
322
+ { text: footerText, style: 'footer', width: '*' },
323
+ ...(showPage
324
+ ? [{ text: `${currentPage} / ${pageCount}`, style: 'footer', width: 'auto' }]
325
+ : []),
326
+ ],
327
+ margin: [48, 16, 48, 0],
328
+ }),
329
+ content,
330
+ }
331
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * ⭐⭐⭐ 04/9 — R-03, RICERCA WEB SENZA CHIAVE (owner: «se è possibile dare al
3
+ * modello modi per fare una ricerca web anche se una chiave non è impostata,
4
+ * fallo»).
5
+ *
6
+ * DuckDuckGo non ha un'API pubblica: si legge la pagina HTML dell'endpoint
7
+ * senza JavaScript (`html.duckduckgo.com/html/`), un approccio non ufficiale
8
+ * già usato altrove nel settore («unofficial HTML-based integration», docs 09/2026). Non è un
9
+ * accordo con DuckDuckGo: è una pagina pubblica, e sotto uso automatico può
10
+ * rispondere con un blocco o un CAPTCHA. ⇒ Fonte «senza chiave» dichiarata
11
+ * come tale nelle Impostazioni, mai spacciata per un'API; quando DuckDuckGo
12
+ * rifiuta, l'esito lo dice.
13
+ *
14
+ * Il markup è stato letto DAL VIVO il 04/09 (curl, 200, 32 KB) e la fixture
15
+ * dei test è un ritaglio di quella risposta, non un HTML scritto a memoria:
16
+ * <a class="result__a" href="//duckduckgo.com/l/?uddg=<url-codificato>&rut=…">Titolo</a>
17
+ * <a class="result__snippet" href="…">Estratto con <b>grassetti</b></a>
18
+ * L'URL vero sta nel parametro `uddg` del redirect: si decodifica, mai si
19
+ * segue il redirect di DuckDuckGo.
20
+ *
21
+ * ⛔ Nessun host scelto dal modello: la destinazione è FISSA (DuckDuckGo) e
22
+ * solo la query entra nella querystring. È lo stesso confine del kernel per
23
+ * `web_search` (endpoint fisso del provider, URL del modello mai).
24
+ */
25
+
26
+ export const DUCKDUCKGO_ENDPOINT = 'https://html.duckduckgo.com/html/';
27
+ /** Host sentinella: il kernel costruisce l'URL della fonte `custom` con questo host, e il trasporto iniettato lo riconosce. `.invalid` è riservato dallo standard: non esiste e non potrà mai risolvere. */
28
+ export const HOST_SENTINELLA_SENZA_CHIAVE = 'ricerca-senza-chiave.talos.invalid';
29
+ export const ENDPOINT_SENTINELLA_DUCKDUCKGO = `https://${HOST_SENTINELLA_SENZA_CHIAVE}/duckduckgo`;
30
+ const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) TALOS-Harness/0.1 (+https://github.com/Ninozzz95/talos)';
31
+ const MAX_BYTE = 2 * 1024 * 1024;
32
+ const TIMEOUT_MS = 15_000;
33
+
34
+ function decodificaEntita(testo) {
35
+ return String(testo)
36
+ .replace(/<[^>]+>/g, '')
37
+ .replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#x27;|&#39;/g, "'").replace(/&nbsp;/g, ' ')
38
+ .replace(/\s+/g, ' ').trim();
39
+ }
40
+
41
+ function urlDaRedirect(href) {
42
+ const grezzo = String(href).replace(/&amp;/g, '&');
43
+ const m = /[?&]uddg=([^&]+)/.exec(grezzo);
44
+ const candidato = m ? decodeURIComponent(m[1]) : (grezzo.startsWith('//') ? `https:${grezzo}` : grezzo);
45
+ try {
46
+ const u = new URL(candidato);
47
+ return u.protocol === 'http:' || u.protocol === 'https:' ? u.toString() : null;
48
+ } catch { return null; }
49
+ }
50
+
51
+ /** Puro: dal testo HTML ai risultati nella forma che il kernel già legge per `custom` ({ url, title, content }). Mai lancia. */
52
+ export function analizzaHtmlDuckDuckGo(html, maxRisultati = 8) {
53
+ const testo = typeof html === 'string' ? html : '';
54
+ const risultati = [];
55
+ const reTitolo = /<a[^>]*class="result__a"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/g;
56
+ const reSnippet = /<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g;
57
+ const snippet = [];
58
+ for (const m of testo.matchAll(reSnippet)) snippet.push(decodificaEntita(m[1]));
59
+ let indice = 0;
60
+ for (const m of testo.matchAll(reTitolo)) {
61
+ const url = urlDaRedirect(m[1]);
62
+ const title = decodificaEntita(m[2]);
63
+ const content = snippet[indice] ?? '';
64
+ indice += 1;
65
+ if (!url || !title) continue;
66
+ risultati.push({ url, title, content });
67
+ if (risultati.length >= Math.max(1, Math.min(20, Number(maxRisultati) || 8))) break;
68
+ }
69
+ return risultati;
70
+ }
71
+
72
+ /** Riconosce un blocco/CAPTCHA di DuckDuckGo: pagina senza risultati che parla di anomalia o challenge. */
73
+ export function sembraBloccoDuckDuckGo(stato, html) {
74
+ if (stato === 403 || stato === 429 || stato === 202) return true;
75
+ const t = String(html || '').toLowerCase();
76
+ return !/class="result__a"/.test(t) && /anomaly|captcha|challenge|unusual traffic|bot/.test(t);
77
+ }
78
+
79
+ /**
80
+ * Esegue una ricerca vera. `fetchFn` è iniettabile per i test (mai una
81
+ * richiesta di rete in `node --test`).
82
+ */
83
+ export async function cercaDuckDuckGo(query, maxRisultati = 8, { fetchFn = globalThis.fetch } = {}) {
84
+ const q = String(query ?? '').trim();
85
+ if (!q) return [];
86
+ const url = new URL(DUCKDUCKGO_ENDPOINT);
87
+ url.searchParams.set('q', q);
88
+ /*
89
+ * ⛔⛔ 10/09 — UN RITENTATIVO, e la ragione non è «a volte la rete fa i capricci».
90
+ *
91
+ * MISURATO oggi: la ricerca dal 4174 è fallita **tre volte** con «fetch failed», e nello stesso
92
+ * momento tre chiamate identiche da un processo appena avviato hanno dato 200 con risultati.
93
+ * Provato anche lo user-agent: quello del server funziona MEGLIO di uno da browser (200 con
94
+ * risultati contro 202, la pagina anti-bot) — quindi non era né DuckDuckGo né la nostra firma.
95
+ * La differenza è che il server gira da ore.
96
+ *
97
+ * Ricerca del 10/09/2026 (nodejs/undici issue #5450 «fetch failed under concurrent load due to
98
+ * socket reuse / keep-alive timeout mismatch», issue #3141 «Race condition at-or-near
99
+ * keep-alive expiration»): undici riusa un socket del pool nello stesso istante in cui il
100
+ * server lo chiude, e la richiesta muore sul filo come `TypeError: fetch failed`.
101
+ * ⇒ «A reset on an idle pooled socket almost always means the request **never reached** the
102
+ * application — for GET a single retry on a fresh connection is safe and clears the large
103
+ * majority of these errors.»
104
+ *
105
+ * ⛔ UNO solo, e solo per la rete: due ritentativi nasconderebbero un guasto vero dietro
106
+ * un'attesa più lunga. E MAI su un abort: se è scaduto il tempo o la persona ha fermato il
107
+ * giro, insistere è esattamente ciò che non deve succedere.
108
+ */
109
+ const chiamata = async () => {
110
+ const controller = new AbortController();
111
+ const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
112
+ try {
113
+ return await fetchFn(url, { headers: { 'user-agent': USER_AGENT, accept: 'text/html' }, signal: controller.signal, redirect: 'follow' });
114
+ } finally {
115
+ clearTimeout(timer);
116
+ }
117
+ };
118
+ let risposta;
119
+ try {
120
+ risposta = await chiamata();
121
+ } catch (primo) {
122
+ if (primo?.name === 'AbortError') {
123
+ throw Object.assign(new Error('DuckDuckGo non raggiungibile: tempo scaduto'), { code: 'SEARCH_UNREACHABLE' });
124
+ }
125
+ try {
126
+ risposta = await chiamata();
127
+ } catch (secondo) {
128
+ throw Object.assign(new Error(`DuckDuckGo non raggiungibile: ${secondo?.name === 'AbortError' ? 'tempo scaduto' : secondo?.message ?? secondo} (già ritentato una volta)`), { code: 'SEARCH_UNREACHABLE' });
129
+ }
130
+ }
131
+ const testo = (await risposta.text()).slice(0, MAX_BYTE);
132
+ if (sembraBloccoDuckDuckGo(risposta.status, testo)) {
133
+ throw Object.assign(new Error(`DuckDuckGo ha rifiutato la richiesta (HTTP ${risposta.status}): limite o verifica anti-bot. Riprova più tardi o imposta una fonte con chiave.`), { code: 'SEARCH_BLOCKED' });
134
+ }
135
+ if (!risposta.ok) throw Object.assign(new Error(`DuckDuckGo ha risposto HTTP ${risposta.status}`), { code: 'SEARCH_FAILED' });
136
+ return analizzaHtmlDuckDuckGo(testo, maxRisultati);
137
+ }
138
+
139
+ /**
140
+ * Il trasporto da iniettare al kernel come `richiediRicercaFn`: quando il
141
+ * kernel chiede la fonte `custom` con l'host sentinella, la risposta è quella
142
+ * di DuckDuckGo nella forma `{ results: [...] }` che il kernel già analizza.
143
+ * Qualunque altro host è un errore: questo trasporto vale SOLO per la fonte
144
+ * senza chiave, e non deve mai diventare un canale verso un URL arbitrario.
145
+ */
146
+ export function creaTrasportoSenzaChiave({ fetchFn = globalThis.fetch } = {}) {
147
+ return async function richiediRicercaSenzaChiave(url) {
148
+ const u = url instanceof URL ? url : new URL(String(url));
149
+ if (u.hostname !== HOST_SENTINELLA_SENZA_CHIAVE) {
150
+ throw Object.assign(new Error('TALOS_SEARCH_TRANSPORT_UNEXPECTED_HOST'), { code: 'SEARCH_FAILED' });
151
+ }
152
+ const results = await cercaDuckDuckGo(u.searchParams.get('q') ?? '', Number(u.searchParams.get('count')) || 8, { fetchFn });
153
+ return { stato: 200, corpo: JSON.stringify({ results }) };
154
+ };
155
+ }