talos-code 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +111 -3
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  4. package/dist/archive/zip.js +73 -0
  5. package/dist/args.js +97 -0
  6. package/dist/automations/history-store.js +34 -0
  7. package/dist/automations/policy-store.js +43 -0
  8. package/dist/automations/runner.js +107 -0
  9. package/dist/automations/schedule.js +85 -0
  10. package/dist/automations/windows-task.js +53 -0
  11. package/dist/commands/advanced-cli.js +233 -0
  12. package/dist/commands/checkpoint-cli.js +45 -0
  13. package/dist/commands/config-cli.js +107 -0
  14. package/dist/commands/context.js +17 -0
  15. package/dist/commands/extensions-cli.js +207 -0
  16. package/dist/commands/project-cli.js +74 -0
  17. package/dist/commands/project-commands.js +143 -0
  18. package/dist/commands/provider-cli.js +185 -0
  19. package/dist/commands/services-cli.js +248 -0
  20. package/dist/commands/session-cli.js +171 -0
  21. package/dist/commands/system-cli.js +405 -0
  22. package/dist/config/commands.js +60 -0
  23. package/dist/config/load.js +382 -0
  24. package/dist/config/migrations.js +48 -0
  25. package/dist/config/types.js +11 -0
  26. package/dist/diagnostics/development-log.js +154 -0
  27. package/dist/diagnostics/doctor.js +104 -0
  28. package/dist/diagnostics/redact.js +80 -0
  29. package/dist/diagnostics/zip.js +52 -0
  30. package/dist/errors.js +156 -0
  31. package/dist/events/bridge.js +130 -0
  32. package/dist/extensions/installer.js +178 -0
  33. package/dist/extensions/package-schema.js +24 -0
  34. package/dist/headless/result.js +84 -0
  35. package/dist/headless/run.js +230 -0
  36. package/dist/i18n/en/approval.js +43 -0
  37. package/dist/i18n/en/common.js +9 -0
  38. package/dist/i18n/en/credentials.js +82 -0
  39. package/dist/i18n/en/errors.js +246 -0
  40. package/dist/i18n/en/firstrun.js +89 -0
  41. package/dist/i18n/en/providers.js +37 -0
  42. package/dist/i18n/en/screen.js +736 -0
  43. package/dist/i18n/en/tools.js +127 -0
  44. package/dist/i18n/en.js +14 -0
  45. package/dist/i18n/error-view.js +307 -0
  46. package/dist/i18n/index.js +19 -0
  47. package/dist/i18n/kernel-map.js +139 -0
  48. package/dist/io.js +45 -0
  49. package/dist/main.js +330 -0
  50. package/dist/paths.js +41 -0
  51. package/dist/protocol/v2/codec.js +9 -0
  52. package/dist/protocol/v2/events.js +555 -0
  53. package/dist/protocol/v2/index.js +4 -0
  54. package/dist/protocol/v2/replay.js +28 -0
  55. package/dist/protocol/v2/types.js +1 -0
  56. package/dist/provider/control-plane.js +135 -0
  57. package/dist/provider/environment-keys.js +275 -0
  58. package/dist/provider/health.js +110 -0
  59. package/dist/provider/missing-key.js +48 -0
  60. package/dist/provider/model-catalog.js +168 -0
  61. package/dist/provider/provider-text.js +13 -0
  62. package/dist/provider/store.js +95 -0
  63. package/dist/provider/system-keyring.js +214 -0
  64. package/dist/runtime/active-run.js +63 -0
  65. package/dist/runtime/agent-tree.js +74 -0
  66. package/dist/runtime/attachments.js +84 -0
  67. package/dist/runtime/brokered-executor.js +395 -0
  68. package/dist/runtime/context-status.js +76 -0
  69. package/dist/runtime/create-runtime.js +111 -0
  70. package/dist/runtime/model-profile.js +361 -0
  71. package/dist/runtime/output-store.js +137 -0
  72. package/dist/runtime/provider-attempts.js +185 -0
  73. package/dist/runtime/replay-buffer.js +153 -0
  74. package/dist/runtime/repo.js +95 -0
  75. package/dist/runtime/session-facade.js +135 -0
  76. package/dist/runtime/session-summary.js +125 -0
  77. package/dist/runtime/supervisor.js +262 -0
  78. package/dist/runtime/talos-composition.js +1006 -0
  79. package/dist/runtime/types.js +5 -0
  80. package/dist/runtime/usage-snapshot.js +82 -0
  81. package/dist/security/auto-classifier.js +38 -0
  82. package/dist/security/credential-free-environment.js +54 -0
  83. package/dist/security/evaluate.js +243 -0
  84. package/dist/security/execution-backends.js +236 -0
  85. package/dist/security/execution-broker.js +102 -0
  86. package/dist/security/forge-scan.js +74 -0
  87. package/dist/security/from-approval.js +39 -0
  88. package/dist/security/mxc-execution-backend.js +281 -0
  89. package/dist/security/permission-engine.js +138 -0
  90. package/dist/security/permission-explanation.js +54 -0
  91. package/dist/security/persist.js +179 -0
  92. package/dist/security/plugin-guard.js +230 -0
  93. package/dist/security/process-tree-evidence-store.js +74 -0
  94. package/dist/security/process-tree-probe.js +554 -0
  95. package/dist/security/project-resource-inventory.js +186 -0
  96. package/dist/security/project-trust-gate.js +38 -0
  97. package/dist/security/project-trust.js +367 -0
  98. package/dist/security/rule-parser.js +201 -0
  99. package/dist/security/shell-segmentation.js +68 -0
  100. package/dist/security/trust-authority.js +324 -0
  101. package/dist/security/types.js +1 -0
  102. package/dist/security/workspace-identity.js +102 -0
  103. package/dist/services/automation-facade.js +59 -0
  104. package/dist/services/forge-facade.js +77 -0
  105. package/dist/services/hook-facade.js +240 -0
  106. package/dist/services/index.js +16 -0
  107. package/dist/services/library-facade.js +174 -0
  108. package/dist/services/mcp-facade.js +348 -0
  109. package/dist/services/memory-facade.js +126 -0
  110. package/dist/services/notes-facade.js +157 -0
  111. package/dist/services/plugin-facade.js +308 -0
  112. package/dist/services/research-facade.js +110 -0
  113. package/dist/services/task-board-facade.js +236 -0
  114. package/dist/services/workflow-catalog.js +246 -0
  115. package/dist/sessions/export-format.js +98 -0
  116. package/dist/sessions/metadata-store.js +160 -0
  117. package/dist/sessions/share.js +122 -0
  118. package/dist/sessions/transfer.js +16 -0
  119. package/dist/subcommands.js +62 -0
  120. package/dist/tui/agent-roster.js +36 -0
  121. package/dist/tui/app.js +3761 -0
  122. package/dist/tui/approval.js +36 -0
  123. package/dist/tui/boot/boot-sequence.js +76 -0
  124. package/dist/tui/boot/cinematic.js +243 -0
  125. package/dist/tui/boot/desktop-logo.js +82 -0
  126. package/dist/tui/boot.js +3 -0
  127. package/dist/tui/busy-input.js +58 -0
  128. package/dist/tui/catalog-service.js +559 -0
  129. package/dist/tui/components/assistant-stream.js +1 -0
  130. package/dist/tui/components/command-menu.js +68 -0
  131. package/dist/tui/components/composer.js +219 -0
  132. package/dist/tui/components/diff.js +35 -0
  133. package/dist/tui/components/footer.js +48 -0
  134. package/dist/tui/components/header.js +6 -0
  135. package/dist/tui/components/markdown.js +305 -0
  136. package/dist/tui/components/status-indicator.js +32 -0
  137. package/dist/tui/components/terminal-shell.js +205 -0
  138. package/dist/tui/components/thinking-row.js +19 -0
  139. package/dist/tui/components/tool-row.js +97 -0
  140. package/dist/tui/components/transcript-virtualizer.js +165 -0
  141. package/dist/tui/components/transcript.js +43 -0
  142. package/dist/tui/diff-model.js +77 -0
  143. package/dist/tui/editor-history.js +21 -0
  144. package/dist/tui/editor.js +210 -0
  145. package/dist/tui/event-adapter.js +436 -0
  146. package/dist/tui/exit-output.js +58 -0
  147. package/dist/tui/external-editor.js +53 -0
  148. package/dist/tui/file-completion.js +89 -0
  149. package/dist/tui/focus-manager.js +5 -0
  150. package/dist/tui/highlight.js +30 -0
  151. package/dist/tui/input-router.js +18 -0
  152. package/dist/tui/interrupt.js +99 -0
  153. package/dist/tui/keybindings.js +194 -0
  154. package/dist/tui/keymap-resolver.js +91 -0
  155. package/dist/tui/launch-state.js +139 -0
  156. package/dist/tui/line-diff.js +57 -0
  157. package/dist/tui/live-activity.js +45 -0
  158. package/dist/tui/metrics.js +123 -0
  159. package/dist/tui/onboarding.js +36 -0
  160. package/dist/tui/overlays/agent-tree.js +39 -0
  161. package/dist/tui/overlays/approval-dialog.js +640 -0
  162. package/dist/tui/overlays/automation-center.js +51 -0
  163. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  164. package/dist/tui/overlays/context-inspector.js +36 -0
  165. package/dist/tui/overlays/effort-line.js +110 -0
  166. package/dist/tui/overlays/forge-center.js +46 -0
  167. package/dist/tui/overlays/help-dialog.js +16 -0
  168. package/dist/tui/overlays/history-picker.js +37 -0
  169. package/dist/tui/overlays/hook-center.js +70 -0
  170. package/dist/tui/overlays/library-center.js +55 -0
  171. package/dist/tui/overlays/mcp-center.js +60 -0
  172. package/dist/tui/overlays/memory-center.js +63 -0
  173. package/dist/tui/overlays/model-picker.js +72 -0
  174. package/dist/tui/overlays/notes-center.js +53 -0
  175. package/dist/tui/overlays/overlay-host.js +8 -0
  176. package/dist/tui/overlays/plugin-center.js +76 -0
  177. package/dist/tui/overlays/provider-picker.js +145 -0
  178. package/dist/tui/overlays/queue-editor.js +32 -0
  179. package/dist/tui/overlays/research-center.js +59 -0
  180. package/dist/tui/overlays/scroll-window.js +234 -0
  181. package/dist/tui/overlays/session-picker.js +115 -0
  182. package/dist/tui/overlays/tasks-center.js +83 -0
  183. package/dist/tui/overlays/theme-picker.js +21 -0
  184. package/dist/tui/overlays/transcript-search.js +58 -0
  185. package/dist/tui/overlays/trust-center.js +29 -0
  186. package/dist/tui/overlays/workflow-center.js +46 -0
  187. package/dist/tui/project-file-index.js +214 -0
  188. package/dist/tui/project-references.js +85 -0
  189. package/dist/tui/project-trust-prompt.js +287 -0
  190. package/dist/tui/prompt-history-store.js +116 -0
  191. package/dist/tui/queue-store.js +110 -0
  192. package/dist/tui/regions/budget.js +59 -0
  193. package/dist/tui/regions/views.js +96 -0
  194. package/dist/tui/render-coordinator.js +148 -0
  195. package/dist/tui/render-scheduler.js +4 -0
  196. package/dist/tui/run.js +69 -0
  197. package/dist/tui/selection-list.js +29 -0
  198. package/dist/tui/session-controller.js +778 -0
  199. package/dist/tui/session-export.js +54 -0
  200. package/dist/tui/shell-input.js +35 -0
  201. package/dist/tui/shell-layout.js +48 -0
  202. package/dist/tui/shell-model.js +98 -0
  203. package/dist/tui/slash-commands.js +80 -0
  204. package/dist/tui/state.js +151 -0
  205. package/dist/tui/status-bar.js +125 -0
  206. package/dist/tui/status-view.js +40 -0
  207. package/dist/tui/terminal-capabilities.js +9 -0
  208. package/dist/tui/terminal-session.js +11 -0
  209. package/dist/tui/text-width.js +66 -0
  210. package/dist/tui/theme-catalog.js +25 -0
  211. package/dist/tui/theme-store.js +23 -0
  212. package/dist/tui/theme.js +23 -0
  213. package/dist/tui/tool-display.js +135 -0
  214. package/dist/tui/tool-facts.js +1 -0
  215. package/dist/tui/tools/bash-renderer.js +32 -0
  216. package/dist/tui/tools/change.js +61 -0
  217. package/dist/tui/tools/edit-renderer.js +17 -0
  218. package/dist/tui/tools/generic-renderer.js +13 -0
  219. package/dist/tui/tools/list-renderer.js +14 -0
  220. package/dist/tui/tools/read-renderer.js +13 -0
  221. package/dist/tui/tools/registry.js +20 -0
  222. package/dist/tui/tools/row-format.js +187 -0
  223. package/dist/tui/tools/search-renderer.js +38 -0
  224. package/dist/tui/tools/shared.js +97 -0
  225. package/dist/tui/tools/write-renderer.js +15 -0
  226. package/dist/tui/transcript-model.js +441 -0
  227. package/dist/tui/ui-preferences.js +79 -0
  228. package/dist/tui/usage-view.js +77 -0
  229. package/dist/tui/vim-mode.js +99 -0
  230. package/dist/update/check.js +15 -0
  231. package/dist/update/npm.js +51 -0
  232. package/dist/update/run.js +129 -0
  233. package/dist/version.js +2 -0
  234. package/dist/workspace/checkpoint-store.js +210 -0
  235. package/dist/workspace/checkpoint.js +413 -0
  236. package/dist/workspace/restore.js +232 -0
  237. package/package.json +63 -5
  238. package/vendor/context-engine/package.json +11 -0
  239. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  240. package/vendor/context-engine/src/contracts.mjs +48 -0
  241. package/vendor/context-engine/src/engine.mjs +445 -0
  242. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  243. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  244. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  245. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  246. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  247. package/vendor/context-engine/src/profiles.mjs +10 -0
  248. package/vendor/context-engine/src/retrieval.mjs +104 -0
  249. package/vendor/context-engine/src/summary.mjs +97 -0
  250. package/vendor/context-engine/src/usage.mjs +34 -0
  251. package/vendor/harness-ui/package.json +38 -0
  252. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  253. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  254. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  255. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  256. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  257. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  258. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  259. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  260. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  261. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  262. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  263. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  264. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  265. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  266. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  267. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  268. package/vendor/harness-ui/src/config.mjs +697 -0
  269. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  270. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  271. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  272. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  273. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  274. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  275. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  276. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  277. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  278. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  279. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  280. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  281. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  282. package/vendor/harness-ui/src/doctor.mjs +142 -0
  283. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  284. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  285. package/vendor/harness-ui/src/document-report.mjs +331 -0
  286. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  287. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  288. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  289. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  290. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  291. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  292. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  293. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  294. package/vendor/harness-ui/src/git-service.mjs +626 -0
  295. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  296. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  297. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  298. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  299. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  300. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  301. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  302. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  303. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  304. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  305. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  306. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  307. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  308. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  309. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  310. package/vendor/harness-ui/src/library-store.mjs +652 -0
  311. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  312. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  313. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  314. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  315. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  316. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  317. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  318. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  319. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  320. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  321. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  322. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  323. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  324. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  325. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  326. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  327. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  328. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  329. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  330. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  331. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  332. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  333. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  334. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  335. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  336. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  337. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  338. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  339. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  340. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  341. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  342. package/vendor/harness-ui/src/research/card.mjs +235 -0
  343. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  344. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  345. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  346. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  347. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  348. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  349. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  350. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  351. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  352. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  353. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  354. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  355. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  356. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  357. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  358. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  359. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  360. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  361. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  362. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  363. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  364. package/vendor/harness-ui/src/research/report.mjs +203 -0
  365. package/vendor/harness-ui/src/research/run.mjs +527 -0
  366. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  367. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  368. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  369. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  370. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  371. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  372. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  373. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  374. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  375. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  376. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  377. package/vendor/harness-ui/src/session-store.mjs +220 -0
  378. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  379. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  380. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  381. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  382. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  383. package/vendor/harness-ui/src/static-files.mjs +96 -0
  384. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  385. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  386. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  387. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  388. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  389. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  390. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  391. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  392. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  393. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  394. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  395. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  396. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  397. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  398. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  399. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  400. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  401. package/vendor/manifest.json +170 -0
@@ -0,0 +1,445 @@
1
+ /**
2
+ * browser-stream.mjs — M2 (07/09/2026). Trasmette lo schermo di un Chromium di
3
+ * sistema dentro la nostra pagina, e riporta indietro i gesti della persona.
4
+ *
5
+ * È il ripiego B della vista Browser: quando la pagina vieta la cornice
6
+ * (`X-Frame-Options`, `frame-ancestors`) non c'è niente da riscrivere, si
7
+ * guarda il browser vero. Lo schermo esce dal compositor già compresso
8
+ * (`Page.startScreencast`) invece di serializzare il DOM a ogni scatto: è la
9
+ * stessa strada di Browserbase, Steel e Cloudflare Browser Rendering, e la
10
+ * stessa che il pannello «Screencast» di DevTools usa da sempre.
11
+ *
12
+ * ⛔ La pagina di terzi è SEMPRE contenuto non affidabile: qui dentro non c'è
13
+ * nessuna nostra API, solo byte di immagine in uscita e coordinate in entrata.
14
+ * Il client CDP arriva come parametro (`cdp`), non lo costruisce questo modulo:
15
+ * chi apre il browser (M1) decide profilo, porta e filtro degli indirizzi.
16
+ *
17
+ * FONTI, lette il 07/09/2026:
18
+ * - CDP «Page» (chromedevtools.github.io/devtools-protocol/tot/Page/):
19
+ * `Page.startScreencast{format,quality,maxWidth,maxHeight,everyNthFrame,maxFramesInFlight}`;
20
+ * `maxFramesInFlight` vale 3 di default — è il numero di fotogrammi che
21
+ * Chrome manda PRIMA di pretendere una conferma, quindi senza
22
+ * `Page.screencastFrameAck` il flusso si ferma dopo pochi fotogrammi.
23
+ * `ScreencastFrameMetadata{offsetTop,pageScaleFactor,deviceWidth,deviceHeight,scrollOffsetX,scrollOffsetY,timestamp}`:
24
+ * le prime quattro in pixel indipendenti dal dispositivo (DIP), lo scorrimento
25
+ * in pixel CSS.
26
+ * - CDP «Input»: `dispatchMouseEvent{type,x,y,button,buttons,clickCount,deltaX,deltaY,modifiers,pointerType}`
27
+ * con x/y «relative to the main frame's viewport in CSS pixels»; bit dei
28
+ * modificatori Alt=1, Ctrl=2, Meta=4, Shift=8; `buttons` sinistro=1, destro=2,
29
+ * centrale=4.
30
+ * - CDP «Emulation»: `setDeviceMetricsOverride{width,height,deviceScaleFactor,mobile,scale}`,
31
+ * width/height fra 0 e 10.000.000 dove 0 disattiva l'override;
32
+ * `clearDeviceMetricsOverride` non prende parametri.
33
+ * - devtools-frontend `panels/screencast/ScreencastView.ts` e `InputModel.ts`:
34
+ * la conversione VERA delle coordinate è
35
+ * `x = round(offsetX / screenZoom)`, `y = round(offsetY / screenZoom - screenOffsetTop)`
36
+ * con `screenZoom = larghezzaDisegnata / metadata.deviceWidth`. Nessuna
37
+ * proporzione inventata: lo scorrimento e `pageScaleFactor` NON entrano nel
38
+ * clic (li applica Chrome), servono a dire dov'è il punto nel documento.
39
+ * - chrome-debugging-protocol, thread «Dispatch key events to fill an input
40
+ * field» (Ophir Back): per scrivere un carattere servono `keyDown` → `char` →
41
+ * `keyUp`, e il campo `text` va riempito SOLO nell'evento `char` — se lo si
42
+ * mette anche su `keyDown` il carattere si scrive due volte.
43
+ * - puppeteer `USKeyboardLayout.ts`: codici Windows dei tasti non stampabili, e
44
+ * il testo di Invio che è `\r` (non `\n`).
45
+ * - chrome-remote-interface #241: `Page.screencastFrameAck` vuole un INTERO;
46
+ * il numero del fotogramma arriva nell'evento come `sessionId`, che NON è la
47
+ * sessione CDP della scheda — due cose diverse con lo stesso nome.
48
+ */
49
+
50
+ /* ─────────────────────────── i tetti ───────────────────────────
51
+ * Lo stream passa DENTRO il nostro server prima di arrivare alla pagina: un
52
+ * fotogramma non compresso a 60 al secondo lo affogherebbe. I tetti stanno qui,
53
+ * non nelle opzioni di chi chiama, così nessuna chiamata può alzarli.
54
+ */
55
+ export const QUALITA_PREDEFINITA = 60;
56
+ export const QUALITA_MASSIMA = 85;
57
+ export const QUALITA_MINIMA = 10;
58
+ /* ⛔ 08/09/2026: questi due erano 1280 e 800, e finivano dritti in `maxWidth`/`maxHeight` di
59
+ * `Page.startScreencast`. Ma quei due parametri sono un TETTO sul fotogramma, non la misura della
60
+ * pagina: la misura la decide il viewport (`Emulation.setDeviceMetricsOverride`). Con un tetto a
61
+ * 800 un riquadro alto 830 riceveva un fotogramma 893×800 — misurato sul 4174 — e restava una
62
+ * banda scoperta che nessun ridimensionamento poteva togliere, perche' `startScreencast` non si
63
+ * ri-negozia da solo. ⇒ il tetto sta al tetto; a dire quanto e' grande la pagina ci pensa il
64
+ * viewport, che invece si cambia a caldo. */
65
+ export const LARGHEZZA_PREDEFINITA = 2560;
66
+ export const ALTEZZA_PREDEFINITA = 1600;
67
+ export const LARGHEZZA_MASSIMA = 2560; /* 08/9: la vista si estende quanto il riquadro, e un 1440p ci sta */
68
+ export const ALTEZZA_MASSIMA = 1600;
69
+ /* ⛔ 08/09/2026, owner: «il frame rate è bassissimo». MISURATO prima di toccare, con una pagina
70
+ * animata e tre configurazioni a confronto (C35/C35-bis nello scratchpad): il trasporto CDP su
71
+ * 127.0.0.1 consegna ~100 fotogrammi al secondo, identici con la finestra davanti, con la finestra
72
+ * COPERTA e in headless. Il collo NON era Chrome: era questo tetto a 15, che buttava l'85% dei
73
+ * fotogrammi che Chrome aveva gia' prodotto E compresso in JPEG — lavoro pagato e gettato.
74
+ *
75
+ * ⭐ La sonda e' stata provata prima di crederle: con `everyNthFrame:3` il conteggio scende a un
76
+ * terzo esatto (499 → 166) e senza conferma si ferma a 3 fotogrammi, come dice il protocollo.
77
+ * Tre numeri identici sono un allarme, non una conferma: quello era il caso.
78
+ *
79
+ * ⛔ Perche' 60 e non 100: oltre il refresh dello schermo i fotogrammi in piu' non si vedono, e
80
+ * ognuno costa una compressione JPEG lato Chrome e un disegno lato pagina. 60 e' quanto un
81
+ * monitor mostra; il tetto a 90 lascia spazio agli schermi piu' veloci senza aprire la porta a
82
+ * una richiesta che chieda l'impossibile. */
83
+ export const FOTOGRAMMI_AL_SECONDO_PREDEFINITI = 60;
84
+ export const FOTOGRAMMI_AL_SECONDO_MASSIMI = 90;
85
+ /* ⛔ 08/09/2026, owner: «alza al 60 fps il minimo del browser headless reale». Non e solo il valore
86
+ di partenza: e il PAVIMENTO. Nessuna chiamata puo chiedere una trasmissione piu lenta di quanto
87
+ uno schermo mostra — un ripiego a 15 o a 30 tornerebbe a essere la fluidita che ha fatto dire
88
+ «il frame rate e bassissimo», e stavolta arriverebbe da un parametro invece che da un tetto. */
89
+ export const FOTOGRAMMI_AL_SECONDO_MINIMI = 60;
90
+ /** Quanti fotogrammi Chrome può mandare prima di pretendere una conferma. Il default del protocollo è 3; 2 tiene la latenza più bassa a parità di banda. */
91
+ export const FOTOGRAMMI_IN_VOLO = 2;
92
+
93
+ const TASTI_MOUSE = new Map([
94
+ ['sinistro', { nome: 'left', bit: 1 }],
95
+ ['left', { nome: 'left', bit: 1 }],
96
+ ['destro', { nome: 'right', bit: 2 }],
97
+ ['right', { nome: 'right', bit: 2 }],
98
+ ['centrale', { nome: 'middle', bit: 4 }],
99
+ ['middle', { nome: 'middle', bit: 4 }],
100
+ ]);
101
+
102
+ /**
103
+ * I tasti non stampabili, coi codici virtuali Windows di `USKeyboardLayout.ts`
104
+ * (puppeteer). `testo` c'è solo dove il tasto scrive davvero qualcosa: Invio
105
+ * scrive `\r`, le frecce non scrivono niente.
106
+ */
107
+ export const TASTI_SPECIALI = new Map([
108
+ ['Enter', { codice: 13, testo: '\r' }],
109
+ ['Backspace', { codice: 8, testo: '' }],
110
+ ['Tab', { codice: 9, testo: '' }],
111
+ ['Escape', { codice: 27, testo: '' }],
112
+ ['ArrowLeft', { codice: 37, testo: '' }],
113
+ ['ArrowUp', { codice: 38, testo: '' }],
114
+ ['ArrowRight', { codice: 39, testo: '' }],
115
+ ['ArrowDown', { codice: 40, testo: '' }],
116
+ ['Delete', { codice: 46, testo: '' }],
117
+ ['Home', { codice: 36, testo: '' }],
118
+ ['End', { codice: 35, testo: '' }],
119
+ ['PageUp', { codice: 33, testo: '' }],
120
+ ['PageDown', { codice: 34, testo: '' }],
121
+ [' ', { codice: 32, testo: ' ' }],
122
+ ]);
123
+
124
+ const numeroFinito = (valore, ripiego = 0) => (Number.isFinite(Number(valore)) ? Number(valore) : ripiego);
125
+ const dentro = (valore, minimo, massimo) => Math.min(massimo, Math.max(minimo, valore));
126
+ const positivo = (valore) => {
127
+ const n = Number(valore);
128
+ return Number.isFinite(n) && n > 0 ? n : null;
129
+ };
130
+
131
+ /**
132
+ * Porta le opzioni di chi chiama dentro i tetti. Esportata perché è il punto in
133
+ * cui si legge, senza avviare niente, quanto costerà lo stream.
134
+ * @param {{qualita?:number, larghezzaMax?:number, altezzaMax?:number, ogniNFrame?:number, fotogrammiAlSecondo?:number}} [opzioni]
135
+ */
136
+ export function opzioniTrasmissione(opzioni = {}) {
137
+ const o = opzioni && typeof opzioni === 'object' ? opzioni : {};
138
+ const qualita = Math.round(dentro(numeroFinito(o.qualita, QUALITA_PREDEFINITA), QUALITA_MINIMA, QUALITA_MASSIMA));
139
+ const larghezzaMax = Math.round(dentro(numeroFinito(o.larghezzaMax, LARGHEZZA_PREDEFINITA), 64, LARGHEZZA_MASSIMA));
140
+ const altezzaMax = Math.round(dentro(numeroFinito(o.altezzaMax, ALTEZZA_PREDEFINITA), 64, ALTEZZA_MASSIMA));
141
+ const ogniNFrame = Math.round(dentro(numeroFinito(o.ogniNFrame, 1), 1, 10));
142
+ const fotogrammiAlSecondo = dentro(numeroFinito(o.fotogrammiAlSecondo, FOTOGRAMMI_AL_SECONDO_PREDEFINITI), FOTOGRAMMI_AL_SECONDO_MINIMI, FOTOGRAMMI_AL_SECONDO_MASSIMI);
143
+ return { qualita, larghezzaMax, altezzaMax, ogniNFrame, fotogrammiAlSecondo, intervalloMinimoMs: 1000 / fotogrammiAlSecondo };
144
+ }
145
+
146
+ /**
147
+ * Il numero del fotogramma da confermare, o `null` se questo evento non è un
148
+ * fotogramma. ⛔ È il campo `sessionId` dell'evento, e non ha NIENTE a che
149
+ * vedere con la sessione CDP della scheda: `Page.screencastFrameAck` vuole
150
+ * questo intero (chrome-remote-interface #241).
151
+ */
152
+ export function numeroDelFotogramma(evento) {
153
+ if (!evento || typeof evento !== 'object') return null;
154
+ const n = Number(evento.sessionId);
155
+ if (!Number.isFinite(n) || !Number.isInteger(n)) return null;
156
+ if (typeof evento.data !== 'string' || evento.data.length === 0) return null;
157
+ return n;
158
+ }
159
+
160
+ /**
161
+ * Accende la trasmissione e resta ad ascoltare i fotogrammi.
162
+ *
163
+ * ⛔ La conferma parte SEMPRE, per ogni fotogramma davvero arrivato: anche se
164
+ * `onFrame` lancia, anche se il fotogramma viene saltato dal tetto sui
165
+ * fotogrammi al secondo. Saltare una conferma significa fermare lo stream dopo
166
+ * `maxFramesInFlight` fotogrammi, cioè uno schermo che si congela senza un
167
+ * errore da nessuna parte.
168
+ *
169
+ * @param {{invia:Function, su:Function}} cdp client CDP (lo dà M1)
170
+ * @param {string|undefined} sessionId la sessione CDP della scheda
171
+ * @param {object} opzioni vedi `opzioniTrasmissione`; `orologio` solo per le prove
172
+ * @param {(fotogramma:{dati:string, formato:string, numeroFrame:number, metadati:object, quando:number})=>void} onFrame
173
+ */
174
+ export async function avviaTrasmissione(cdp, sessionId, opzioni = {}, onFrame = () => {}) {
175
+ const scelte = opzioniTrasmissione(opzioni);
176
+ const orologio = typeof opzioni?.orologio === 'function' ? opzioni.orologio : () => Date.now();
177
+ const conteggi = { arrivati: 0, consegnati: 0, saltati: 0, confermati: 0, ignorati: 0, errori: 0 };
178
+ let viva = true;
179
+ let ultimoConsegnato = -Infinity;
180
+
181
+ const gestore = async (evento, contesto) => {
182
+ if (!viva) return;
183
+ /* Un client CDP «flat» tiene TUTTE le schede su una connessione sola e passa
184
+ * la sessione dell'evento come secondo argomento: i fotogrammi di un'altra
185
+ * scheda non sono nostri e non si confermano — confermarli ruberebbe il
186
+ * credito a chi li aspetta e lascerebbe l'altro flusso fermo.
187
+ * ⛔ La forma del secondo argomento cambia da client a client: M1
188
+ * (`browser-vivo.mjs`, `creaClientCdp`) passa `{ sessionId, metodo }`, altri
189
+ * passano la stringa nuda. Si accettano tutt'e due, e quando non c'è non si
190
+ * filtra niente. */
191
+ if (sessioneAltrui(contesto, sessionId)) return;
192
+ const numeroFrame = numeroDelFotogramma(evento);
193
+ if (numeroFrame === null) { conteggi.ignorati += 1; return; } // niente conferma per ciò che non è un fotogramma
194
+ conteggi.arrivati += 1;
195
+ try {
196
+ const adesso = numeroFinito(orologio(), 0);
197
+ if (adesso - ultimoConsegnato >= scelte.intervalloMinimoMs) {
198
+ ultimoConsegnato = adesso;
199
+ conteggi.consegnati += 1;
200
+ onFrame({ dati: evento.data, formato: 'jpeg', numeroFrame, metadati: evento.metadata || {}, quando: adesso });
201
+ } else {
202
+ conteggi.saltati += 1; // il tetto sui fotogrammi al secondo: si butta l'immagine, MAI la conferma
203
+ }
204
+ } catch (errore) {
205
+ conteggi.errori += 1; // un consumatore che lancia non deve poter fermare lo stream
206
+ } finally {
207
+ try {
208
+ await cdp.invia('Page.screencastFrameAck', { sessionId: numeroFrame }, sessionId);
209
+ conteggi.confermati += 1;
210
+ } catch {
211
+ conteggi.errori += 1; // la scheda può essere già chiusa: non è un motivo per lanciare qui
212
+ }
213
+ }
214
+ };
215
+
216
+ /* Gli eventi del dominio Page arrivano solo dopo `Page.enable`, e l'ascolto si
217
+ * registra PRIMA di `startScreencast`: fra le due chiamate Chrome manda già
218
+ * fotogrammi, e uno perso è un fotogramma non confermato. */
219
+ await cdp.invia('Page.enable', {}, sessionId);
220
+ const sgancia = cdp.su('Page.screencastFrame', gestore);
221
+ await cdp.invia('Page.startScreencast', {
222
+ format: 'jpeg',
223
+ quality: scelte.qualita,
224
+ maxWidth: scelte.larghezzaMax,
225
+ maxHeight: scelte.altezzaMax,
226
+ everyNthFrame: scelte.ogniNFrame,
227
+ maxFramesInFlight: FOTOGRAMMI_IN_VOLO,
228
+ }, sessionId);
229
+
230
+ return {
231
+ opzioni: scelte,
232
+ conteggi,
233
+ /** Stacca l'ascolto senza toccare il browser (per una riconnessione). */
234
+ sgancia() {
235
+ viva = false; // ⛔ vale anche se `su` non restituisce niente: da qui il gestore è inerte
236
+ if (typeof sgancia === 'function') { try { sgancia(); } catch { /* già staccato */ } }
237
+ },
238
+ async ferma() {
239
+ this.sgancia();
240
+ return fermaTrasmissione(cdp, sessionId);
241
+ },
242
+ };
243
+ }
244
+
245
+ /**
246
+ * Spegne la trasmissione. Non lancia: si chiama anche quando la scheda è già
247
+ * morta, e in quel caso «fermata» è comunque il risultato che si voleva.
248
+ */
249
+ export async function fermaTrasmissione(cdp, sessionId) {
250
+ try {
251
+ await cdp.invia('Page.stopScreencast', {}, sessionId);
252
+ return { fermata: true, motivo: null };
253
+ } catch (errore) {
254
+ return { fermata: false, motivo: String(errore?.message || errore) };
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Dal punto toccato sul NOSTRO canvas al punto vero nella pagina.
260
+ *
261
+ * La formula è quella di DevTools (`ScreencastView.convertIntoScreenSpace`):
262
+ * si divide per lo zoom e POI si toglie `offsetTop`, perché `offsetTop` è già
263
+ * espresso in DIP dello schermo emulato (la fascia sopra la pagina), non in
264
+ * pixel del canvas. Lo zoom è il rapporto fra ciò che abbiamo disegnato e
265
+ * `deviceWidth`; si prende il minimo fra i due assi perché l'immagine si adatta
266
+ * dentro il canvas mantenendo le proporzioni, e ciò che avanza è bordo nero.
267
+ *
268
+ * ⛔ `scrollOffsetX/Y` e `pageScaleFactor` NON entrano nel clic: `Input.dispatchMouseEvent`
269
+ * vuole coordinate «relative to the main frame's viewport», e lo scorrimento lo
270
+ * applica Chrome. Servono a dire dove sta il punto nel DOCUMENTO, che è ciò che
271
+ * serve per appuntarci sopra una nota.
272
+ *
273
+ * @param {{x:number,y:number}} punto sul canvas
274
+ * @param {{larghezzaCanvas:number, altezzaCanvas:number, metadatiFrame:object}} vista
275
+ * @returns {{x:number,y:number,documentoX:number,documentoY:number,scala:number,fuoriBordo:boolean}}
276
+ */
277
+ export function coordinateVerso(punto, vista = {}) {
278
+ const m = vista.metadatiFrame && typeof vista.metadatiFrame === 'object' ? vista.metadatiFrame : {};
279
+ const larghezzaCanvas = positivo(vista.larghezzaCanvas) ?? 1;
280
+ const altezzaCanvas = positivo(vista.altezzaCanvas) ?? 1;
281
+ /* Metadati assurdi (zero, negativi, NaN, assenti) non devono produrre un clic
282
+ * fuori pagina: si ripiega sulla misura del canvas, cioè zoom 1. */
283
+ const larghezzaSchermo = positivo(m.deviceWidth) ?? larghezzaCanvas;
284
+ const altezzaSchermo = positivo(m.deviceHeight) ?? altezzaCanvas;
285
+ const offsetTop = dentro(numeroFinito(m.offsetTop, 0), 0, altezzaSchermo);
286
+ const altezzaUtile = Math.max(0, altezzaSchermo - offsetTop);
287
+
288
+ let scala = Math.min(larghezzaCanvas / larghezzaSchermo, altezzaCanvas / altezzaSchermo);
289
+ if (!Number.isFinite(scala) || scala <= 0) scala = 1;
290
+
291
+ const xCanvas = numeroFinito(punto?.x, 0);
292
+ const yCanvas = numeroFinito(punto?.y, 0);
293
+ const xGrezza = xCanvas / scala;
294
+ const yGrezza = yCanvas / scala - offsetTop;
295
+ const x = Math.round(dentro(xGrezza, 0, larghezzaSchermo));
296
+ const y = Math.round(dentro(yGrezza, 0, altezzaUtile));
297
+ /* Fuori dall'immagine disegnata (il bordo del «contain», o un tocco oltre il
298
+ * canvas): il chiamante può ignorare il gesto invece di cliccare sul bordo. */
299
+ const fuoriBordo = xGrezza < 0 || yGrezza < 0 || xGrezza > larghezzaSchermo || yGrezza > altezzaUtile;
300
+
301
+ const fattorePagina = positivo(m.pageScaleFactor) ?? 1;
302
+ const documentoX = Math.round(numeroFinito(m.scrollOffsetX, 0) + x / fattorePagina);
303
+ const documentoY = Math.round(numeroFinito(m.scrollOffsetY, 0) + y / fattorePagina);
304
+ return { x, y, documentoX, documentoY, scala, fuoriBordo };
305
+ }
306
+
307
+ /**
308
+ * L'evento è di un'ALTRA scheda? Il secondo argomento di `su` è la stringa della
309
+ * sessione in certi client e `{ sessionId }` in altri (M1 dà l'oggetto).
310
+ * Se non si sa dire di chi è, non si scarta: meglio confermare un fotogramma in
311
+ * più che congelare il proprio flusso.
312
+ */
313
+ export function sessioneAltrui(contesto, sessionId) {
314
+ if (typeof sessionId !== 'string' || !sessionId) return false;
315
+ const dellEvento = typeof contesto === 'string' ? contesto : (contesto && typeof contesto === 'object' ? contesto.sessionId : null);
316
+ if (typeof dellEvento !== 'string' || !dellEvento) return false;
317
+ return dellEvento !== sessionId;
318
+ }
319
+
320
+ /** I bit dei modificatori: Alt=1, Ctrl=2, Meta=4, Shift=8 (dominio Input). */
321
+ export function bitModificatori(modificatori) {
322
+ if (typeof modificatori === 'number' && Number.isFinite(modificatori)) return modificatori & 0b1111;
323
+ const m = modificatori && typeof modificatori === 'object' ? modificatori : {};
324
+ return (m.alt ? 1 : 0) | (m.ctrl || m.control ? 2 : 0) | (m.meta ? 4 : 0) | (m.shift ? 8 : 0);
325
+ }
326
+
327
+ /**
328
+ * Un clic vero è una COPPIA di eventi, non un evento solo: premuto e rilasciato
329
+ * con lo stesso `clickCount`. Il doppio clic sono due coppie con `clickCount`
330
+ * 1 e poi 2 — è il secondo numero che fa scattare il `dblclick` nella pagina.
331
+ * Prima si manda un `mouseMoved`, come fa puppeteer, altrimenti gli stati
332
+ * `:hover` che aprono i menù non si accendono mai.
333
+ */
334
+ export async function mandaClic(cdp, sessionId, { x, y, tasto = 'sinistro', doppio = false, modificatori = 0 } = {}) {
335
+ const scelto = TASTI_MOUSE.get(String(tasto).toLowerCase()) || TASTI_MOUSE.get('sinistro');
336
+ const modifiers = bitModificatori(modificatori);
337
+ const posizione = { x: Math.round(numeroFinito(x, 0)), y: Math.round(numeroFinito(y, 0)) };
338
+ const comune = { ...posizione, modifiers, pointerType: 'mouse' };
339
+ await cdp.invia('Input.dispatchMouseEvent', { ...comune, type: 'mouseMoved', button: 'none', buttons: 0, clickCount: 0 }, sessionId);
340
+ const conteggi = doppio ? [1, 2] : [1];
341
+ for (const clickCount of conteggi) {
342
+ await cdp.invia('Input.dispatchMouseEvent', { ...comune, type: 'mousePressed', button: scelto.nome, buttons: scelto.bit, clickCount }, sessionId);
343
+ await cdp.invia('Input.dispatchMouseEvent', { ...comune, type: 'mouseReleased', button: scelto.nome, buttons: 0, clickCount }, sessionId);
344
+ }
345
+ return { coppie: conteggi.length, tasto: scelto.nome };
346
+ }
347
+
348
+ /**
349
+ * Un tasto stampabile vuole `keyDown` → `char` → `keyUp`, e il testo va SOLO
350
+ * nell'evento `char`: metterlo anche su `keyDown` scrive il carattere due volte
351
+ * (Chrome genera lui il `char` quando `text` è pieno).
352
+ *
353
+ * ⛔ Con Ctrl, Alt o Meta premuti NON si manda il `char`: quella è una
354
+ * scorciatoia (Ctrl+A seleziona tutto), non una lettera da scrivere. Shift no:
355
+ * shift fa parte della lettera.
356
+ */
357
+ export async function mandaTasto(cdp, sessionId, { chiave, testo, modificatori = 0 } = {}) {
358
+ const key = String(chiave ?? '');
359
+ if (!key) return { eventi: 0, scritto: false };
360
+ const modifiers = bitModificatori(modificatori);
361
+ const speciale = TASTI_SPECIALI.get(key);
362
+ const testoScritto = testo !== undefined ? String(testo) : (speciale ? speciale.testo : (Array.from(key).length === 1 ? key : ''));
363
+ const codice = speciale ? speciale.codice : (Array.from(key).length === 1 ? key.toUpperCase().codePointAt(0) : 0);
364
+ const scorciatoia = (modifiers & 0b0111) !== 0; // Alt|Ctrl|Meta, ma non Shift
365
+ const scrive = testoScritto.length > 0 && !scorciatoia;
366
+ const identita = { key, code: codiceFisico(key, speciale), windowsVirtualKeyCode: codice, nativeVirtualKeyCode: codice, modifiers };
367
+
368
+ await cdp.invia('Input.dispatchKeyEvent', { ...identita, type: 'keyDown', autoRepeat: false, isKeypad: false, location: 0 }, sessionId);
369
+ if (scrive) {
370
+ await cdp.invia('Input.dispatchKeyEvent', { type: 'char', key, text: testoScritto, unmodifiedText: testoScritto.toLowerCase(), modifiers }, sessionId);
371
+ }
372
+ await cdp.invia('Input.dispatchKeyEvent', { ...identita, type: 'keyUp', location: 0 }, sessionId);
373
+ return { eventi: scrive ? 3 : 2, scritto: scrive };
374
+ }
375
+
376
+ /** Il nome del tasto FISICO: per le lettere è `KeyA`, per le cifre `Digit1`, per gli altri il nome stesso. */
377
+ function codiceFisico(key, speciale) {
378
+ if (speciale) return key === ' ' ? 'Space' : key;
379
+ if (/^[a-zA-Z]$/.test(key)) return `Key${key.toUpperCase()}`;
380
+ if (/^[0-9]$/.test(key)) return `Digit${key}`;
381
+ return '';
382
+ }
383
+
384
+ /**
385
+ * La rotella è un `mouseWheel` con i delta in pixel CSS, nel punto in cui sta il
386
+ * puntatore: la pagina scorre l'elemento sotto quel punto, non sempre il
387
+ * documento.
388
+ */
389
+ export async function mandaRotella(cdp, sessionId, { x, y, dx = 0, dy = 0, modificatori = 0 } = {}) {
390
+ await cdp.invia('Input.dispatchMouseEvent', {
391
+ type: 'mouseWheel',
392
+ x: Math.round(numeroFinito(x, 0)),
393
+ y: Math.round(numeroFinito(y, 0)),
394
+ deltaX: numeroFinito(dx, 0),
395
+ deltaY: numeroFinito(dy, 0),
396
+ modifiers: bitModificatori(modificatori),
397
+ button: 'none',
398
+ buttons: 0,
399
+ clickCount: 0,
400
+ pointerType: 'mouse',
401
+ }, sessionId);
402
+ return { dx: numeroFinito(dx, 0), dy: numeroFinito(dy, 0) };
403
+ }
404
+
405
+ /**
406
+ * La misura della finestra vista dalla pagina. `width`/`height` a 0 tolgono
407
+ * l'override (lo dice il protocollo), quindi «zero per zero» qui significa
408
+ * «torna com'eri»: si chiama `clearDeviceMetricsOverride`, che è la stessa cosa
409
+ * detta senza ambiguità.
410
+ */
411
+ export async function ridimensiona(cdp, sessionId, { larghezza, altezza, scala = 1 } = {}) {
412
+ const l = Math.round(numeroFinito(larghezza, 0));
413
+ const a = Math.round(numeroFinito(altezza, 0));
414
+ if (l <= 0 && a <= 0) {
415
+ await cdp.invia('Emulation.clearDeviceMetricsOverride', {}, sessionId);
416
+ return { azzerato: true, larghezza: 0, altezza: 0, scala: 1 };
417
+ }
418
+ const misura = {
419
+ width: dentro(l, 1, LARGHEZZA_MASSIMA),
420
+ height: dentro(a, 1, ALTEZZA_MASSIMA),
421
+ deviceScaleFactor: dentro(numeroFinito(scala, 1), 0.5, 3),
422
+ mobile: false,
423
+ };
424
+ await cdp.invia('Emulation.setDeviceMetricsOverride', misura, sessionId);
425
+ /*
426
+ * ⛔ 08/09/2026 — cambiare il viewport non basta a far arrivare un fotogramma nuovo: una pagina
427
+ * FERMA non ridisegna, e lo schermo resta quello di prima, con la forma vecchia. Visto in una
428
+ * foto: dopo il ridimensionamento la pagina restava 926×448 dentro un riquadro più alto, con
429
+ * una banda nera sotto che spariva solo appena si scorreva.
430
+ * ⇒ Si ri-chiede lo screencast con gli stessi parametri: `Page.startScreencast` e' idempotente e
431
+ * il primo fotogramma dopo la chiamata e' completo, quindi arriva subito la forma nuova.
432
+ * L'ascolto e' gia' registrato altrove: qui non si tocca, si sveglia soltanto.
433
+ */
434
+ try {
435
+ await cdp.invia('Page.startScreencast', {
436
+ format: 'jpeg',
437
+ quality: QUALITA_PREDEFINITA,
438
+ maxWidth: LARGHEZZA_MASSIMA,
439
+ maxHeight: ALTEZZA_MASSIMA,
440
+ everyNthFrame: 1,
441
+ maxFramesInFlight: FOTOGRAMMI_IN_VOLO,
442
+ }, sessionId);
443
+ } catch { /* la scheda puo' essere chiusa fra le due chiamate: il ridimensionamento resta valido */ }
444
+ return { azzerato: false, larghezza: misura.width, altezza: misura.height, scala: misura.deviceScaleFactor };
445
+ }