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,465 @@
1
+ /*
2
+ * L6 — LA CACHE DEI RISULTATI WEB, DENTRO LA CORSA.
3
+ *
4
+ * ## Il difetto che chiude, col numero
5
+ *
6
+ * Baseline vera del desktop, corsa `deep` (sessione `d2a453a8` del 4174,
7
+ * 11/09/2026): 484.171 token in ingresso, `cached_tokens: 0`, 9 ricerche e 14
8
+ * navigazioni. Le linee d'indagine di una ricerca profonda partono dalla stessa
9
+ * domanda: cercano le stesse cose e aprono le stesse pagine, e oggi ognuna paga
10
+ * per conto suo. È l'UNICO punto in cui Hermes — l'obiettivo da battere — è
11
+ * avanti a noi E al mobile (§4.2 del disegno, righe C21/C22).
12
+ *
13
+ * ## Che cosa questa cache risparmia, e che cosa NO
14
+ *
15
+ * ⛔ Va detto con precisione, perché confonderlo farebbe promettere il numero
16
+ * sbagliato:
17
+ *
18
+ * - risparmia CHIAMATE DI RETE e attese: la stessa pagina si apre una volta;
19
+ * - risparmia GIRI: un attrezzo in meno è un giro in meno, e in una
20
+ * conversazione che cresce ogni giro rispedisce TUTTO il prefisso — quindi
21
+ * il risparmio in token è più che proporzionale al risultato evitato;
22
+ * - NON risparmia da sola i token della sintesi: il testo di una pagina entra
23
+ * nel prompt anche quando arriva dalla cache. Quelli li tagliano il budget
24
+ * per pagina (`page-budget.mjs`) e la cache del PROMPT del fornitore, che è
25
+ * un'altra cosa e sta altrove.
26
+ *
27
+ * ⇒ `cached_tokens: 0` è un guasto della cache del PROMPT (prefisso esatto);
28
+ * questa cache attacca il numeratore — 484.171 — riducendo i giri. Le due si
29
+ * moltiplicano, e per moltiplicarsi vogliono la stessa cosa: che una chiamata
30
+ * identica produca byte IDENTICI. Per questo un risultato servito dalla cache
31
+ * torna uguale all'originale, e il fatto che venisse dalla cache si scrive nel
32
+ * registro — mai dentro il testo che legge il modello.
33
+ *
34
+ * ## Le regole, e da dove vengono
35
+ *
36
+ * Fonte primaria: `website/docs/user-guide/features/web-search.md:65-80` del
37
+ * clone `%LOCALAPPDATA%\Temp\talos-competitor\hermes-agent-v21` (Hermes v0.21
38
+ * «Pantheon»), letta l'11/09/2026 — «Result caching»:
39
+ *
40
+ * - `web_search`: stessa query (insensibile a maiuscole e spazi), stesso
41
+ * fornitore; i limiti richiesti sono raggruppati a 10/20/50/100 «so
42
+ * near-identical requests share one entry, with each caller receiving its
43
+ * requested count»;
44
+ * - `web_extract`: stesso URL, stesso formato, stesso fornitore;
45
+ * - ricerche identiche CONCORRENTI «are coalesced into a single backend
46
+ * request — the first caller pays; the rest share the response»;
47
+ * - «Only successful responses are cached. Failures always retry the backend»;
48
+ * - mai in cache gli indirizzi locali: «dev servers, hot-reload builds … a
49
+ * cached copy would show you a stale build».
50
+ *
51
+ * ⛔ Quest'ultima per noi non è un'ipotesi di comodo: il 4174 è `localhost`, e
52
+ * una copia vecchia di una pagina del nostro stesso prodotto è esattamente il
53
+ * genere di bugia che costa una giornata.
54
+ *
55
+ * ## Perché la scadenza, di default, è LA CORSA
56
+ *
57
+ * Hermes tiene 20 minuti. Noi no, e per una ragione che riguarda il prodotto:
58
+ * un dossier dev'essere COERENTE. Due rami che citano la stessa pagina con due
59
+ * testi diversi perché in mezzo è passata mezz'ora producono un rapporto che si
60
+ * contraddice da solo, e la contraddizione non sarebbe nemmeno visibile. La
61
+ * freschezza è il mestiere di `recheck.mjs`, che rilegge apposta e dice cos'è
62
+ * cambiato. ⇒ dentro una corsa la pagina è quella; `ttlMs` resta configurabile
63
+ * per chi vuole il comportamento di Hermes.
64
+ *
65
+ * ## Vive per corsa e sopravvive alla pausa
66
+ *
67
+ * Questo modulo NON scrive su disco: la persistenza è dell'orchestratore, che
68
+ * salva accanto al giornale. Qui si dichiara solo il contratto —
69
+ * `snapshot()`/`restore()` su un oggetto JSON-serializzabile — perché una
70
+ * ripresa che ripaga ciò che era già stato pagato è il difetto che il giornale
71
+ * esiste per impedire.
72
+ */
73
+
74
+ import { TALOS_RESEARCH_KEPT_CAP } from './page-budget.mjs';
75
+
76
+ /** La versione dell'istantanea. Un numero diverso si ignora invece di indovinare. */
77
+ export const TALOS_RESEARCH_CACHE_SNAPSHOT_VERSION = 1;
78
+
79
+ /**
80
+ * I gruppi dei limiti di ricerca, da Hermes: `limit=5` e `limit=8` condividono
81
+ * una voce, e ognuno riceve il numero che aveva chiesto.
82
+ */
83
+ export const TALOS_RESEARCH_LIMIT_BUCKETS = [10, 20, 50, 100];
84
+
85
+ /**
86
+ * L'indirizzo ridotto a ciò che identifica la PAGINA.
87
+ *
88
+ * Schema e host minuscoli, porta di default via, frammento via (`#sezione` è un
89
+ * punto della stessa pagina), query ORDINATA per chiave — `?b=2&a=1` e
90
+ * `?a=1&b=2` sono la stessa richiesta — ma MAI tolta: su moltissimi siti `?id=12`
91
+ * e `?id=13` sono due articoli diversi, e fonderli sarebbe peggio di un doppione.
92
+ *
93
+ * ⛔ La barra finale si toglie per stare d'accordo con `chiaveDi` in
94
+ * `synthesis.mjs:124-133`, che deduplica le fonti allo stesso modo: due
95
+ * identità diverse per la stessa pagina farebbero cadere la cache proprio dove
96
+ * la sintesi ha già deciso che si tratta di una pagina sola.
97
+ *
98
+ * Un indirizzo illeggibile resta sé stesso, ripulito: meglio un doppione che
99
+ * un'eccezione in mezzo a una raccolta.
100
+ *
101
+ * @param {string} grezzo
102
+ * @returns {string}
103
+ */
104
+ export function talosResearchNormalizeUrl(grezzo) {
105
+ const testo = String(grezzo ?? '').trim();
106
+ let letto;
107
+ try {
108
+ letto = new URL(testo);
109
+ } catch {
110
+ return testo;
111
+ }
112
+
113
+ letto.hash = '';
114
+ letto.protocol = letto.protocol.toLowerCase();
115
+ letto.hostname = letto.hostname.toLowerCase();
116
+ if ((letto.protocol === 'http:' && letto.port === '80') || (letto.protocol === 'https:' && letto.port === '443')) {
117
+ letto.port = '';
118
+ }
119
+
120
+ const coppie = [...letto.searchParams.entries()].sort((a, b) => (
121
+ a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0
122
+ ));
123
+ letto.search = '';
124
+ for (const [chiave, valore] of coppie) letto.searchParams.append(chiave, valore);
125
+
126
+ const finale = letto.toString();
127
+ return finale.endsWith('/') && !letto.search ? finale.slice(0, -1) : finale;
128
+ }
129
+
130
+ /**
131
+ * La query ridotta a ciò che la identifica: spazi compattati, maiuscole via.
132
+ * «Insensibile a maiuscole e spazi», come Hermes.
133
+ *
134
+ * @param {string} grezza
135
+ * @returns {string}
136
+ */
137
+ export function talosResearchNormalizeQuery(grezza) {
138
+ return String(grezza ?? '').replace(/\s+/g, ' ').trim().toLowerCase();
139
+ }
140
+
141
+ /**
142
+ * Il gruppo di appartenenza di un limite richiesto.
143
+ * @param {number} quanti
144
+ * @returns {number}
145
+ */
146
+ export function talosResearchLimitBucket(quanti) {
147
+ const n = Number(quanti);
148
+ if (!Number.isFinite(n) || n <= 0) return TALOS_RESEARCH_LIMIT_BUCKETS[0];
149
+ for (const gruppo of TALOS_RESEARCH_LIMIT_BUCKETS) if (n <= gruppo) return gruppo;
150
+ return TALOS_RESEARCH_LIMIT_BUCKETS[TALOS_RESEARCH_LIMIT_BUCKETS.length - 1];
151
+ }
152
+
153
+ /**
154
+ * @typedef {object} TalosResearchFetchDescriptor
155
+ * @property {'search' | 'extract'} kind
156
+ * @property {string} [url] Per `extract`.
157
+ * @property {string} [query] Per `search`.
158
+ * @property {number} [limit] Per `search`: raggruppato, non usato alla lettera.
159
+ * @property {string} [provider] Chi risponde. Due fornitori non danno la stessa pagina.
160
+ * @property {string} [format] Il formato chiesto a chi estrae, quando ne ha più d'uno.
161
+ */
162
+
163
+ /**
164
+ * La chiave.
165
+ *
166
+ * ⛔ Le parti a vocabolario chiuso (tipo, fornitore, formato, gruppo) stanno
167
+ * PRIMA e non contengono mai il separatore; la parte libera — URL o query — sta
168
+ * ULTIMA. Così un `|` dentro una query non può fingersi un confine: non c'è
169
+ * nessun campo dopo di lei da confondere.
170
+ *
171
+ * @param {TalosResearchFetchDescriptor} descrittore
172
+ * @returns {string}
173
+ */
174
+ export function talosResearchFetchKey(descrittore) {
175
+ const tipo = descrittore.kind === 'search' ? 'search' : 'extract';
176
+ const fornitore = String(descrittore.provider ?? '').replace(/\|/g, '').trim().toLowerCase() || '-';
177
+ const formato = String(descrittore.format ?? '').replace(/\|/g, '').trim().toLowerCase() || '-';
178
+ return tipo === 'search'
179
+ ? `search|${fornitore}|${talosResearchLimitBucket(descrittore.limit ?? 0)}|${talosResearchNormalizeQuery(descrittore.query ?? '')}`
180
+ : `extract|${fornitore}|${formato}|${talosResearchNormalizeUrl(descrittore.url ?? '')}`;
181
+ }
182
+
183
+ const IPV4 = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
184
+
185
+ /**
186
+ * Gli indirizzi che non si mettono MAI in cache: locali, di rete privata, o
187
+ * senza punti (un nome a etichetta sola è un host di LAN).
188
+ *
189
+ * ⛔ Il 4174 cade qui dentro, ed è voluto: una pagina del nostro prodotto
190
+ * servita da una copia vecchia è il modo più efficiente di perdere una giornata.
191
+ *
192
+ * @param {string} grezzo
193
+ * @returns {boolean}
194
+ */
195
+ export function talosResearchNeverCached(grezzo) {
196
+ let host;
197
+ try {
198
+ host = new URL(String(grezzo ?? '')).hostname.toLowerCase();
199
+ } catch {
200
+ // Un indirizzo che non si legge non si può nemmeno giudicare pubblico.
201
+ return true;
202
+ }
203
+ if (!host) return true;
204
+
205
+ const nudo = host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host;
206
+ if (nudo === 'localhost' || nudo === '::1' || nudo.endsWith('.localhost')) return true;
207
+ if (nudo.endsWith('.local') || nudo.endsWith('.internal') || nudo.endsWith('.home.arpa')) return true;
208
+ if (!nudo.includes('.') && !nudo.includes(':')) return true;
209
+
210
+ const quattro = IPV4.exec(nudo);
211
+ if (quattro) {
212
+ const [a, b] = [Number(quattro[1]), Number(quattro[2])];
213
+ if (a === 127 || a === 10 || a === 0) return true;
214
+ if (a === 192 && b === 168) return true;
215
+ if (a === 172 && b >= 16 && b <= 31) return true;
216
+ if (a === 169 && b === 254) return true;
217
+ }
218
+ if (nudo.startsWith('fe80:') || nudo.startsWith('fc') || nudo.startsWith('fd')) return true;
219
+ return false;
220
+ }
221
+
222
+ /**
223
+ * @typedef {object} TalosResearchCacheStats
224
+ * @property {number} calls Quante volte è stata chiesta una cosa. `calls === fetched + served + coalesced`.
225
+ * @property {number} fetched Quante volte si è dovuto chiamare davvero il produttore.
226
+ * @property {number} served Quante volte ha risposto la cache.
227
+ * @property {number} coalesced Quante si sono accodate a una chiamata identica già in volo.
228
+ * @property {number} skipped Indirizzi mai da mettere in cache (sottoinsieme di `fetched`).
229
+ * @property {number} failed Produttori che hanno lanciato o non hanno prodotto: nulla è stato conservato.
230
+ * @property {number} oversize Risposte troppo grandi per essere conservate.
231
+ * @property {number} evicted Voci sfrattate per fare posto.
232
+ * @property {number} entries Voci vive adesso.
233
+ * @property {number} chars Caratteri conservati adesso.
234
+ */
235
+
236
+ /**
237
+ * @typedef {object} TalosResearchCacheSnapshot
238
+ * @property {number} version
239
+ * @property {number | null} savedAt
240
+ * @property {readonly {key: string, storedAt: number, chars: number, value: unknown}[]} entries
241
+ */
242
+
243
+ /**
244
+ * Quanto pesa una risposta. `JSON.stringify` invece di indovinare dal campo
245
+ * `text`: una risposta di ricerca è un elenco, e il peso vero è tutto l'oggetto.
246
+ *
247
+ * @param {unknown} valore
248
+ * @returns {number}
249
+ */
250
+ function pesa(valore) {
251
+ try {
252
+ return JSON.stringify(valore)?.length ?? 0;
253
+ } catch {
254
+ // Un valore non serializzabile non è conservabile: peso infinito lo esclude
255
+ // dalla conservazione senza un ramo speciale.
256
+ return Number.POSITIVE_INFINITY;
257
+ }
258
+ }
259
+
260
+ /**
261
+ * ⛔ Il tipo è il RITORNO della fabbrica, non un'interfaccia scritta due volte:
262
+ * `harness-ui/` non ha un `tsconfig.json`, quindi un `@typedef` copiato a mano
263
+ * che si scosta dal codice non farebbe rosso nessun test — e diventerebbe una
264
+ * bugia silenziosa esattamente nel punto in cui gli altri file lo leggono.
265
+ *
266
+ * @typedef {ReturnType<typeof talosResearchFetchCache>} TalosResearchFetchCache
267
+ */
268
+
269
+ /**
270
+ * La cache di una corsa.
271
+ *
272
+ * @param {{now?: () => number, ttlMs?: number | null, maxEntries?: number, maxChars?: number, entryMaxChars?: number}} [opzioni]
273
+ */
274
+ export function talosResearchFetchCache(opzioni = {}) {
275
+ const adesso = opzioni.now ?? (() => Date.now());
276
+ const ttlMs = opzioni.ttlMs ?? null;
277
+ const maxVoci = Math.max(1, Math.trunc(opzioni.maxEntries ?? 500));
278
+ const maxCaratteri = Math.max(1, Math.trunc(opzioni.maxChars ?? 64 * 1024 * 1024));
279
+ const maxPerVoce = Math.max(1, Math.trunc(opzioni.entryMaxChars ?? TALOS_RESEARCH_KEPT_CAP));
280
+
281
+ /** @type {Map<string, {storedAt: number, chars: number, value: unknown}>} */
282
+ const voci = new Map();
283
+ /** @type {Map<string, Promise<unknown>>} */
284
+ const inVolo = new Map();
285
+ let caratteri = 0;
286
+
287
+ const conto = { calls: 0, fetched: 0, served: 0, coalesced: 0, skipped: 0, failed: 0, oversize: 0, evicted: 0 };
288
+
289
+ /** @param {string} chiave */
290
+ function scaduta(chiave) {
291
+ if (ttlMs === null) return false;
292
+ const voce = voci.get(chiave);
293
+ return voce ? adesso() - voce.storedAt >= ttlMs : false;
294
+ }
295
+
296
+ /** @param {string} chiave */
297
+ function togli(chiave) {
298
+ const voce = voci.get(chiave);
299
+ if (!voce) return;
300
+ caratteri -= voce.chars;
301
+ voci.delete(chiave);
302
+ }
303
+
304
+ function sfratta() {
305
+ // La `Map` conserva l'ordine di inserimento e ogni lettura ri-inserisce in
306
+ // fondo: la prima chiave è la meno usata di recente.
307
+ while ((voci.size > maxVoci || caratteri > maxCaratteri) && voci.size > 0) {
308
+ const primo = voci.keys().next().value;
309
+ togli(primo);
310
+ conto.evicted += 1;
311
+ }
312
+ }
313
+
314
+ /**
315
+ * @param {string} chiave
316
+ * @param {unknown} valore
317
+ */
318
+ function conserva(chiave, valore) {
319
+ const peso = pesa(valore);
320
+ if (peso > maxPerVoce) {
321
+ conto.oversize += 1;
322
+ return;
323
+ }
324
+ togli(chiave);
325
+ voci.set(chiave, { storedAt: adesso(), chars: peso, value: valore });
326
+ caratteri += peso;
327
+ sfratta();
328
+ }
329
+
330
+ return {
331
+ /** @param {TalosResearchFetchDescriptor} descrittore */
332
+ key: (descrittore) => talosResearchFetchKey(descrittore),
333
+
334
+ /**
335
+ * Il solo modo di passare di qui: si chiede il valore, e la cache decide se
336
+ * chiamare il produttore, servire quello che ha, o accodarsi a una chiamata
337
+ * identica già in volo.
338
+ *
339
+ * ⛔ `fromCache` NON deve finire nel testo che legge il modello: due giri
340
+ * identici devono produrre gli stessi byte, o la cache del prompt del
341
+ * fornitore (prefisso esatto) si azzera proprio mentre la stiamo cercando.
342
+ * Va nel registro.
343
+ *
344
+ * @template T
345
+ * @param {TalosResearchFetchDescriptor} descrittore
346
+ * @param {() => Promise<T>} produttore
347
+ * @returns {Promise<{value: T, fromCache: boolean, key: string}>}
348
+ */
349
+ async around(descrittore, produttore) {
350
+ conto.calls += 1;
351
+ const chiave = talosResearchFetchKey(descrittore);
352
+
353
+ const mai = descrittore.kind === 'extract' && talosResearchNeverCached(descrittore.url ?? '');
354
+ if (mai) {
355
+ conto.fetched += 1;
356
+ conto.skipped += 1;
357
+ try {
358
+ return { value: await produttore(), fromCache: false, key: chiave };
359
+ } catch (rotto) {
360
+ conto.failed += 1;
361
+ throw rotto;
362
+ }
363
+ }
364
+
365
+ if (scaduta(chiave)) togli(chiave);
366
+
367
+ if (voci.has(chiave)) {
368
+ const voce = voci.get(chiave);
369
+ // Ri-inserita in fondo: è la mossa che rende l'ordine una LRU.
370
+ voci.delete(chiave);
371
+ voci.set(chiave, voce);
372
+ conto.served += 1;
373
+ return { value: /** @type {T} */ (voce.value), fromCache: true, key: chiave };
374
+ }
375
+
376
+ const giaInVolo = inVolo.get(chiave);
377
+ if (giaInVolo) {
378
+ conto.coalesced += 1;
379
+ // Il primo paga, gli altri condividono la risposta. Se il primo fallisce
380
+ // falliscono anche loro: è la stessa chiamata, e fingere il contrario
381
+ // vorrebbe dire chiamare di nuovo un fornitore che ha appena detto di no.
382
+ return { value: /** @type {T} */ (await giaInVolo), fromCache: true, key: chiave };
383
+ }
384
+
385
+ conto.fetched += 1;
386
+ const promessa = (async () => produttore())();
387
+ inVolo.set(chiave, promessa);
388
+ try {
389
+ const valore = await promessa;
390
+ // Solo le risposte riuscite si conservano, come Hermes. `null`/`undefined`
391
+ // è «non si è potuto leggere»: un fallimento si ritenta, non si incide.
392
+ if (valore === null || valore === undefined) conto.failed += 1;
393
+ else conserva(chiave, valore);
394
+ return { value: /** @type {T} */ (valore), fromCache: false, key: chiave };
395
+ } catch (rotto) {
396
+ conto.failed += 1;
397
+ throw rotto;
398
+ } finally {
399
+ inVolo.delete(chiave);
400
+ }
401
+ },
402
+
403
+ /** @returns {TalosResearchCacheStats} */
404
+ stats() {
405
+ return { ...conto, entries: voci.size, chars: caratteri };
406
+ },
407
+
408
+ /**
409
+ * Il contratto per chi persiste: un oggetto JSON-serializzabile, che
410
+ * l'orchestratore salva accanto al giornale. ⛔ Questo modulo non scrive
411
+ * niente su disco.
412
+ *
413
+ * @returns {TalosResearchCacheSnapshot}
414
+ */
415
+ snapshot() {
416
+ return {
417
+ version: TALOS_RESEARCH_CACHE_SNAPSHOT_VERSION,
418
+ savedAt: adesso(),
419
+ entries: [...voci.entries()].map(([key, voce]) => ({
420
+ key,
421
+ storedAt: voce.storedAt,
422
+ chars: voce.chars,
423
+ value: voce.value,
424
+ })),
425
+ };
426
+ },
427
+
428
+ /**
429
+ * Rimette dentro ciò che una corsa in pausa aveva già pagato.
430
+ *
431
+ * ⛔ Tollerante in lettura, come il giornale: una versione che non conosce
432
+ * si ignora, una voce malformata si salta. Un formato più nuovo non deve
433
+ * impedire a una ricerca di RIPARTIRE — al massimo la fa ripagare.
434
+ *
435
+ * @param {TalosResearchCacheSnapshot | null | undefined} istantanea
436
+ * @returns {number} quante voci sono rientrate
437
+ */
438
+ restore(istantanea) {
439
+ if (!istantanea || istantanea.version !== TALOS_RESEARCH_CACHE_SNAPSHOT_VERSION) return 0;
440
+ if (!Array.isArray(istantanea.entries)) return 0;
441
+ let rientrate = 0;
442
+ for (const voce of istantanea.entries) {
443
+ if (!voce || typeof voce.key !== 'string') continue;
444
+ if (voce.value === null || voce.value === undefined) continue;
445
+ const peso = typeof voce.chars === 'number' && voce.chars >= 0 ? voce.chars : pesa(voce.value);
446
+ if (peso > maxPerVoce) { conto.oversize += 1; continue; }
447
+ togli(voce.key);
448
+ voci.set(voce.key, {
449
+ storedAt: typeof voce.storedAt === 'number' ? voce.storedAt : adesso(),
450
+ chars: peso,
451
+ value: voce.value,
452
+ });
453
+ caratteri += peso;
454
+ rientrate += 1;
455
+ }
456
+ sfratta();
457
+ return rientrate;
458
+ },
459
+
460
+ clear() {
461
+ voci.clear();
462
+ caratteri = 0;
463
+ },
464
+ };
465
+ }
@@ -0,0 +1,122 @@
1
+ import { talosResearchIndependentSources } from './independence.mjs'
2
+
3
+ /*
4
+ * PORTO FEDELE di AVM/mobile/src/lib/research/researchFidelity.ts (115 righe, 11/09/2026).
5
+ *
6
+ * ⛔ Di `verification.mjs` (porto di `researchVerification.ts`, altra sessione)
7
+ * servono qui solo i TIPI: in JSDoc non producono import a runtime, quindi
8
+ * questo file gira anche prima che quello esista.
9
+ *
10
+ * ⛔⛔ FEDELTA-05 — le quattro misure, e il divieto di darne una quando non c'è.
11
+ *
12
+ * ## Da dove vengono, misurato il 2026-08-20
13
+ *
14
+ * Ricerca sui benchmark 2026 per gli agenti di ricerca profonda — DeepResearch
15
+ * Bench, TRACE, e il lavoro sull'attribuzione delle fonti. Le dimensioni su cui
16
+ * si giudica un rapporto sono **copertura**, **fedeltà delle citazioni**,
17
+ * **ancoraggio delle affermazioni**, e quante **prove distinte** ci sono
18
+ * davvero — che conta quanto le altre tre, e nessuno la mostra.
19
+ *
20
+ * ⛔ La stessa ricerca dice perché una misura del genere invecchia: la metrica
21
+ * FACT è considerata inaffidabile per la riproducibilità **perché le pagine
22
+ * citate diventano irraggiungibili nel tempo**. Da qui due conseguenze che
23
+ * stanno nel codice e non in un commento: ogni punteggio esce con la sua
24
+ * **data**, e accanto a queste misure ci vuole la tenuta nel tempo.
25
+ *
26
+ * ## ⛔ La regola che conta più delle formule
27
+ *
28
+ * Un numero su cui nessuno ha giudicato non è un numero basso: **non è un
29
+ * numero**. Una ricerca senza giudice non produce «40%», produce «non
30
+ * verificata» — perché un 40% viene letto come una misura, e sarebbe una
31
+ * misura di niente. Per questo ogni quota è `number | null`, e il `null` non è
32
+ * un valore mancante: è l'unica risposta onesta.
33
+ *
34
+ * ⛔ Il conteggio delle fonti indipendenti fa eccezione, e la ragione è che non
35
+ * dipende dal giudice: si vede dagli indirizzi. Una ricerca non verificata può
36
+ * comunque dire quante prove distinte ha raccolto.
37
+ */
38
+
39
+ /**
40
+ * @import { TalosResearchVerifiedClaim } from './verification.mjs'
41
+ * @import { TalosResearchSourceOrigin } from './independence.mjs'
42
+ */
43
+
44
+ /**
45
+ * @typedef {object} TalosResearchFidelityInput
46
+ * @property {readonly TalosResearchVerifiedClaim[]} claims
47
+ * @property {readonly TalosResearchSourceOrigin[]} sources
48
+ */
49
+
50
+ /**
51
+ * @typedef {object} TalosResearchFidelity
52
+ * @property {boolean} verified Falso quando nessuno ha giudicato: allora le quote sono tutte `null`.
53
+ * @property {number | null} coverage Quota di affermazioni su cui un giudizio è arrivato.
54
+ * @property {number | null} citationFaithfulness Quota di affermazioni il cui passaggio è stato ritrovato nella pagina.
55
+ * @property {number | null} claimGroundedness Quanto le affermazioni giudicate reggono davvero: piena 1, parziale 0,5.
56
+ * @property {number} independentSources Prove distinte, non URL. Si conta anche senza giudice.
57
+ * @property {string | null} measuredAt ⛔ Quando: un punteggio senza data è una promessa che scade in silenzio.
58
+ */
59
+
60
+ /**
61
+ * ⛔ Una parziale vale MEZZA, e non è una convenzione arbitraria.
62
+ *
63
+ * Contarla come una sostenuta gonfierebbe il rapporto proprio dove è più
64
+ * fragile; contarla come zero cancellerebbe una verifica che è riuscita a metà,
65
+ * e spingerebbe a non usare mai «parziale» — cioè a perdere la distinzione più
66
+ * utile che abbiamo.
67
+ *
68
+ * @type {Record<string, number>}
69
+ */
70
+ const PESO = { yes: 1, partial: 0.5, no: 0, unchecked: 0 }
71
+
72
+ /**
73
+ * @param {TalosResearchFidelityInput} input
74
+ * @returns {TalosResearchFidelity}
75
+ */
76
+ export function talosResearchFidelity(input) {
77
+ const indipendenti = talosResearchIndependentSources(input.sources)
78
+ const totali = input.claims.length
79
+ const giudicate = input.claims.filter((entry) => entry.checks.judge !== null)
80
+
81
+ if (totali === 0 || giudicate.length === 0) {
82
+ return {
83
+ verified: false,
84
+ coverage: null,
85
+ citationFaithfulness: null,
86
+ claimGroundedness: null,
87
+ independentSources: indipendenti.independent,
88
+ measuredAt: null,
89
+ }
90
+ }
91
+
92
+ // ⛔ Il passaggio conta come citazione solo se è stato ritrovato NELLA
93
+ // pagina: uno preso da uno snippet di ricerca non è la fonte, è il modo in
94
+ // cui il motore l'ha riassunta, e un `missing` non è una citazione affatto.
95
+ const conPassaggio = input.claims.filter(
96
+ (entry) => entry.checks.resolved === 'page' && entry.checks.quotePresent,
97
+ ).length
98
+
99
+ const peso = giudicate.reduce(
100
+ (somma, entry) => somma + (PESO[entry.checks.claimSupported] ?? 0),
101
+ 0,
102
+ )
103
+
104
+ /*
105
+ * La data è la PIÙ RECENTE fra i giudizi: è il momento in cui questo
106
+ * punteggio ha smesso di essere aggiornato, ed è quello che serve sapere
107
+ * per decidere se rileggerlo.
108
+ */
109
+ const date = giudicate
110
+ .map((entry) => entry.checks.judgedAt)
111
+ .filter((quando) => typeof quando === 'string' && quando.length > 0)
112
+ .sort()
113
+
114
+ return {
115
+ verified: true,
116
+ coverage: giudicate.length / totali,
117
+ citationFaithfulness: conPassaggio / totali,
118
+ claimGroundedness: peso / giudicate.length,
119
+ independentSources: indipendenti.independent,
120
+ measuredAt: date.at(-1) ?? null,
121
+ }
122
+ }