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.
- package/CHANGELOG.md +87 -0
- package/LICENSE +661 -0
- package/README.md +116 -3
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/archive/zip.js +73 -0
- package/dist/args.js +100 -0
- package/dist/automations/history-store.js +34 -0
- package/dist/automations/policy-store.js +43 -0
- package/dist/automations/runner.js +107 -0
- package/dist/automations/schedule.js +85 -0
- package/dist/automations/windows-task.js +53 -0
- package/dist/commands/advanced-cli.js +233 -0
- package/dist/commands/checkpoint-cli.js +45 -0
- package/dist/commands/config-cli.js +107 -0
- package/dist/commands/context.js +17 -0
- package/dist/commands/extensions-cli.js +207 -0
- package/dist/commands/project-cli.js +74 -0
- package/dist/commands/project-commands.js +143 -0
- package/dist/commands/provider-cli.js +244 -0
- package/dist/commands/services-cli.js +248 -0
- package/dist/commands/session-cli.js +171 -0
- package/dist/commands/system-cli.js +405 -0
- package/dist/config/commands.js +60 -0
- package/dist/config/load.js +382 -0
- package/dist/config/migrations.js +48 -0
- package/dist/config/types.js +11 -0
- package/dist/diagnostics/development-log.js +154 -0
- package/dist/diagnostics/doctor.js +104 -0
- package/dist/diagnostics/redact.js +80 -0
- package/dist/diagnostics/zip.js +52 -0
- package/dist/errors.js +156 -0
- package/dist/events/bridge.js +130 -0
- package/dist/extensions/installer.js +178 -0
- package/dist/extensions/package-schema.js +24 -0
- package/dist/headless/result.js +84 -0
- package/dist/headless/run.js +230 -0
- package/dist/i18n/en/approval.js +46 -0
- package/dist/i18n/en/common.js +9 -0
- package/dist/i18n/en/credentials.js +92 -0
- package/dist/i18n/en/errors.js +267 -0
- package/dist/i18n/en/firstrun.js +101 -0
- package/dist/i18n/en/providers.js +37 -0
- package/dist/i18n/en/screen.js +774 -0
- package/dist/i18n/en/tools.js +127 -0
- package/dist/i18n/en.js +14 -0
- package/dist/i18n/error-view.js +307 -0
- package/dist/i18n/index.js +19 -0
- package/dist/i18n/kernel-map.js +139 -0
- package/dist/io.js +45 -0
- package/dist/main.js +331 -0
- package/dist/paths.js +41 -0
- package/dist/protocol/v2/codec.js +9 -0
- package/dist/protocol/v2/events.js +555 -0
- package/dist/protocol/v2/index.js +4 -0
- package/dist/protocol/v2/replay.js +28 -0
- package/dist/protocol/v2/types.js +1 -0
- package/dist/provider/control-plane.js +135 -0
- package/dist/provider/environment-keys.js +275 -0
- package/dist/provider/health.js +110 -0
- package/dist/provider/missing-key.js +48 -0
- package/dist/provider/model-catalog.js +168 -0
- package/dist/provider/openrouter-login.js +172 -0
- package/dist/provider/provider-text.js +13 -0
- package/dist/provider/store.js +95 -0
- package/dist/provider/system-keyring.js +214 -0
- package/dist/runtime/active-run.js +63 -0
- package/dist/runtime/agent-tree.js +74 -0
- package/dist/runtime/attachments.js +84 -0
- package/dist/runtime/brokered-executor.js +395 -0
- package/dist/runtime/context-archive.js +69 -0
- package/dist/runtime/context-status.js +76 -0
- package/dist/runtime/create-runtime.js +111 -0
- package/dist/runtime/model-profile.js +361 -0
- package/dist/runtime/output-store.js +137 -0
- package/dist/runtime/provider-attempts.js +185 -0
- package/dist/runtime/replay-buffer.js +153 -0
- package/dist/runtime/repo.js +95 -0
- package/dist/runtime/session-facade.js +135 -0
- package/dist/runtime/session-summary.js +125 -0
- package/dist/runtime/supervisor.js +265 -0
- package/dist/runtime/talos-composition.js +1011 -0
- package/dist/runtime/types.js +5 -0
- package/dist/runtime/usage-snapshot.js +82 -0
- package/dist/security/auto-classifier.js +38 -0
- package/dist/security/credential-free-environment.js +54 -0
- package/dist/security/evaluate.js +243 -0
- package/dist/security/execution-backends.js +236 -0
- package/dist/security/execution-broker.js +102 -0
- package/dist/security/forge-scan.js +74 -0
- package/dist/security/from-approval.js +39 -0
- package/dist/security/mxc-execution-backend.js +281 -0
- package/dist/security/permission-engine.js +138 -0
- package/dist/security/permission-explanation.js +54 -0
- package/dist/security/persist.js +179 -0
- package/dist/security/plugin-guard.js +230 -0
- package/dist/security/process-tree-evidence-store.js +74 -0
- package/dist/security/process-tree-probe.js +554 -0
- package/dist/security/project-resource-inventory.js +186 -0
- package/dist/security/project-trust-gate.js +38 -0
- package/dist/security/project-trust.js +367 -0
- package/dist/security/rule-parser.js +201 -0
- package/dist/security/shell-segmentation.js +68 -0
- package/dist/security/trust-authority.js +324 -0
- package/dist/security/types.js +1 -0
- package/dist/security/workspace-identity.js +102 -0
- package/dist/services/automation-facade.js +59 -0
- package/dist/services/forge-facade.js +77 -0
- package/dist/services/hook-facade.js +240 -0
- package/dist/services/index.js +16 -0
- package/dist/services/library-facade.js +174 -0
- package/dist/services/mcp-facade.js +348 -0
- package/dist/services/memory-facade.js +126 -0
- package/dist/services/notes-facade.js +157 -0
- package/dist/services/plugin-facade.js +308 -0
- package/dist/services/research-facade.js +110 -0
- package/dist/services/task-board-facade.js +236 -0
- package/dist/services/workflow-catalog.js +246 -0
- package/dist/sessions/export-format.js +98 -0
- package/dist/sessions/metadata-store.js +160 -0
- package/dist/sessions/share.js +122 -0
- package/dist/sessions/transfer.js +16 -0
- package/dist/subcommands.js +62 -0
- package/dist/tui/agent-roster.js +36 -0
- package/dist/tui/agent-view.js +51 -0
- package/dist/tui/app.js +4098 -0
- package/dist/tui/approval.js +36 -0
- package/dist/tui/boot/boot-sequence.js +76 -0
- package/dist/tui/boot/cinematic.js +243 -0
- package/dist/tui/boot/desktop-logo.js +82 -0
- package/dist/tui/boot.js +3 -0
- package/dist/tui/busy-input.js +58 -0
- package/dist/tui/catalog-service.js +560 -0
- package/dist/tui/components/assistant-stream.js +1 -0
- package/dist/tui/components/command-menu.js +68 -0
- package/dist/tui/components/composer.js +219 -0
- package/dist/tui/components/diff.js +35 -0
- package/dist/tui/components/footer.js +48 -0
- package/dist/tui/components/header.js +6 -0
- package/dist/tui/components/markdown.js +305 -0
- package/dist/tui/components/status-indicator.js +38 -0
- package/dist/tui/components/terminal-shell.js +214 -0
- package/dist/tui/components/thinking-row.js +19 -0
- package/dist/tui/components/tool-row.js +97 -0
- package/dist/tui/components/transcript-virtualizer.js +165 -0
- package/dist/tui/components/transcript.js +43 -0
- package/dist/tui/descendant-approvals.js +104 -0
- package/dist/tui/diff-model.js +77 -0
- package/dist/tui/editor-history.js +21 -0
- package/dist/tui/editor.js +210 -0
- package/dist/tui/event-adapter.js +436 -0
- package/dist/tui/exit-output.js +58 -0
- package/dist/tui/external-editor.js +53 -0
- package/dist/tui/file-completion.js +89 -0
- package/dist/tui/focus-manager.js +5 -0
- package/dist/tui/highlight.js +30 -0
- package/dist/tui/input-router.js +18 -0
- package/dist/tui/interrupt.js +99 -0
- package/dist/tui/keybindings.js +194 -0
- package/dist/tui/keymap-resolver.js +91 -0
- package/dist/tui/launch-state.js +148 -0
- package/dist/tui/line-diff.js +57 -0
- package/dist/tui/live-activity.js +56 -0
- package/dist/tui/metrics.js +123 -0
- package/dist/tui/onboarding.js +36 -0
- package/dist/tui/overlays/agent-tree.js +43 -0
- package/dist/tui/overlays/approval-dialog.js +642 -0
- package/dist/tui/overlays/automation-center.js +51 -0
- package/dist/tui/overlays/checkpoint-picker.js +47 -0
- package/dist/tui/overlays/context-inspector.js +36 -0
- package/dist/tui/overlays/effort-line.js +110 -0
- package/dist/tui/overlays/forge-center.js +46 -0
- package/dist/tui/overlays/help-dialog.js +16 -0
- package/dist/tui/overlays/history-picker.js +37 -0
- package/dist/tui/overlays/hook-center.js +70 -0
- package/dist/tui/overlays/library-center.js +55 -0
- package/dist/tui/overlays/mcp-center.js +60 -0
- package/dist/tui/overlays/memory-center.js +63 -0
- package/dist/tui/overlays/model-picker.js +77 -0
- package/dist/tui/overlays/notes-center.js +53 -0
- package/dist/tui/overlays/overlay-host.js +8 -0
- package/dist/tui/overlays/plugin-center.js +76 -0
- package/dist/tui/overlays/provider-picker.js +171 -0
- package/dist/tui/overlays/queue-editor.js +32 -0
- package/dist/tui/overlays/research-center.js +59 -0
- package/dist/tui/overlays/scroll-window.js +234 -0
- package/dist/tui/overlays/session-picker.js +115 -0
- package/dist/tui/overlays/tasks-center.js +83 -0
- package/dist/tui/overlays/theme-picker.js +21 -0
- package/dist/tui/overlays/transcript-search.js +58 -0
- package/dist/tui/overlays/trust-center.js +29 -0
- package/dist/tui/overlays/workflow-center.js +46 -0
- package/dist/tui/project-file-index.js +214 -0
- package/dist/tui/project-references.js +85 -0
- package/dist/tui/project-trust-prompt.js +289 -0
- package/dist/tui/prompt-history-store.js +116 -0
- package/dist/tui/queue-store.js +110 -0
- package/dist/tui/regions/budget.js +59 -0
- package/dist/tui/regions/views.js +96 -0
- package/dist/tui/render-coordinator.js +148 -0
- package/dist/tui/render-scheduler.js +4 -0
- package/dist/tui/run.js +69 -0
- package/dist/tui/selection-list.js +29 -0
- package/dist/tui/session-controller.js +791 -0
- package/dist/tui/session-export.js +54 -0
- package/dist/tui/setup-wizard.js +46 -0
- package/dist/tui/shell-input.js +35 -0
- package/dist/tui/shell-layout.js +48 -0
- package/dist/tui/shell-model.js +98 -0
- package/dist/tui/slash-commands.js +82 -0
- package/dist/tui/state.js +151 -0
- package/dist/tui/status-bar.js +125 -0
- package/dist/tui/status-view.js +40 -0
- package/dist/tui/terminal-capabilities.js +9 -0
- package/dist/tui/terminal-session.js +11 -0
- package/dist/tui/text-width.js +66 -0
- package/dist/tui/theme-catalog.js +27 -0
- package/dist/tui/theme-store.js +23 -0
- package/dist/tui/theme.js +23 -0
- package/dist/tui/tool-display.js +135 -0
- package/dist/tui/tool-facts.js +1 -0
- package/dist/tui/tools/bash-renderer.js +32 -0
- package/dist/tui/tools/change.js +61 -0
- package/dist/tui/tools/edit-renderer.js +17 -0
- package/dist/tui/tools/generic-renderer.js +13 -0
- package/dist/tui/tools/list-renderer.js +14 -0
- package/dist/tui/tools/read-renderer.js +13 -0
- package/dist/tui/tools/registry.js +20 -0
- package/dist/tui/tools/row-format.js +187 -0
- package/dist/tui/tools/search-renderer.js +38 -0
- package/dist/tui/tools/shared.js +97 -0
- package/dist/tui/tools/write-renderer.js +15 -0
- package/dist/tui/transcript-model.js +441 -0
- package/dist/tui/ui-preferences.js +79 -0
- package/dist/tui/usage-view.js +77 -0
- package/dist/tui/vim-mode.js +99 -0
- package/dist/update/check.js +15 -0
- package/dist/update/npm.js +51 -0
- package/dist/update/run.js +129 -0
- package/dist/version.js +2 -0
- package/dist/workspace/checkpoint-store.js +210 -0
- package/dist/workspace/checkpoint.js +413 -0
- package/dist/workspace/restore.js +232 -0
- package/package.json +64 -5
- package/vendor/context-engine/package.json +11 -0
- package/vendor/context-engine/src/compaction-planner.mjs +57 -0
- package/vendor/context-engine/src/contracts.mjs +48 -0
- package/vendor/context-engine/src/engine.mjs +445 -0
- package/vendor/context-engine/src/node/context-export.mjs +164 -0
- package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
- package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
- package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
- package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
- package/vendor/context-engine/src/profiles.mjs +10 -0
- package/vendor/context-engine/src/retrieval.mjs +104 -0
- package/vendor/context-engine/src/summary.mjs +97 -0
- package/vendor/context-engine/src/usage.mjs +34 -0
- package/vendor/harness-ui/package.json +38 -0
- package/vendor/harness-ui/src/acp-agent.mjs +350 -0
- package/vendor/harness-ui/src/agent-service.mjs +2188 -0
- package/vendor/harness-ui/src/agui-events.mjs +452 -0
- package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
- package/vendor/harness-ui/src/artifact-store.mjs +39 -0
- package/vendor/harness-ui/src/assistenza.mjs +123 -0
- package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
- package/vendor/harness-ui/src/automation-store.mjs +145 -0
- package/vendor/harness-ui/src/browser-annota.mjs +639 -0
- package/vendor/harness-ui/src/browser-frame.mjs +211 -0
- package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
- package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
- package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
- package/vendor/harness-ui/src/browser-stream.mjs +445 -0
- package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
- package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
- package/vendor/harness-ui/src/config.mjs +697 -0
- package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
- package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
- package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
- package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
- package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
- package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
- package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
- package/vendor/harness-ui/src/context-runtime.mjs +118 -0
- package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
- package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
- package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
- package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
- package/vendor/harness-ui/src/custom-task.mjs +171 -0
- package/vendor/harness-ui/src/doctor.mjs +142 -0
- package/vendor/harness-ui/src/document-filename.mjs +97 -0
- package/vendor/harness-ui/src/document-generator.mjs +493 -0
- package/vendor/harness-ui/src/document-report.mjs +331 -0
- package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
- package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
- package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
- package/vendor/harness-ui/src/forge-contract.mjs +221 -0
- package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
- package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
- package/vendor/harness-ui/src/generation-idle.mjs +332 -0
- package/vendor/harness-ui/src/gguf-header.mjs +207 -0
- package/vendor/harness-ui/src/git-service.mjs +626 -0
- package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
- package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
- package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
- package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
- package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
- package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
- package/vendor/harness-ui/src/hook-registry.mjs +186 -0
- package/vendor/harness-ui/src/http-app.mjs +6259 -0
- package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
- package/vendor/harness-ui/src/id-archivio.mjs +27 -0
- package/vendor/harness-ui/src/image-generator.mjs +143 -0
- package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
- package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
- package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
- package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
- package/vendor/harness-ui/src/library-store.mjs +652 -0
- package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
- package/vendor/harness-ui/src/local-model-store.mjs +339 -0
- package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
- package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
- package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
- package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
- package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
- package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
- package/vendor/harness-ui/src/mcp-client.mjs +98 -0
- package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
- package/vendor/harness-ui/src/mcp-session.mjs +177 -0
- package/vendor/harness-ui/src/memory-store.mjs +227 -0
- package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
- package/vendor/harness-ui/src/model-catalog.mjs +129 -0
- package/vendor/harness-ui/src/model-destination.mjs +189 -0
- package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
- package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
- package/vendor/harness-ui/src/notes-store.mjs +250 -0
- package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
- package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
- package/vendor/harness-ui/src/path-policy.mjs +442 -0
- package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
- package/vendor/harness-ui/src/plugin-session.mjs +180 -0
- package/vendor/harness-ui/src/process-policy.mjs +345 -0
- package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
- package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
- package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
- package/vendor/harness-ui/src/provider-probe.mjs +582 -0
- package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
- package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
- package/vendor/harness-ui/src/public-problem.mjs +109 -0
- package/vendor/harness-ui/src/research/card.mjs +235 -0
- package/vendor/harness-ui/src/research/citations.mjs +142 -0
- package/vendor/harness-ui/src/research/collector.mjs +275 -0
- package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
- package/vendor/harness-ui/src/research/dossier.mjs +114 -0
- package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
- package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
- package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
- package/vendor/harness-ui/src/research/independence.mjs +159 -0
- package/vendor/harness-ui/src/research/ledger.mjs +166 -0
- package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
- package/vendor/harness-ui/src/research/narration.mjs +181 -0
- package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
- package/vendor/harness-ui/src/research/opposing.mjs +305 -0
- package/vendor/harness-ui/src/research/outline.mjs +111 -0
- package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
- package/vendor/harness-ui/src/research/pdf.mjs +291 -0
- package/vendor/harness-ui/src/research/plan.mjs +301 -0
- package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
- package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
- package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
- package/vendor/harness-ui/src/research/recheck.mjs +194 -0
- package/vendor/harness-ui/src/research/report.mjs +203 -0
- package/vendor/harness-ui/src/research/run.mjs +527 -0
- package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
- package/vendor/harness-ui/src/research/verification.mjs +572 -0
- package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
- package/vendor/harness-ui/src/research-store.mjs +1133 -0
- package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
- package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
- package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
- package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
- package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
- package/vendor/harness-ui/src/search-source-store.mjs +172 -0
- package/vendor/harness-ui/src/session-registry.mjs +6095 -0
- package/vendor/harness-ui/src/session-store.mjs +220 -0
- package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
- package/vendor/harness-ui/src/setup-stato.mjs +31 -0
- package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
- package/vendor/harness-ui/src/skill-registry.mjs +120 -0
- package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
- package/vendor/harness-ui/src/static-files.mjs +96 -0
- package/vendor/harness-ui/src/stream-partition.mjs +123 -0
- package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
- package/vendor/harness-ui/src/task-catalog.mjs +65 -0
- package/vendor/harness-ui/src/tasks-store.mjs +220 -0
- package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
- package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
- package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
- package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
- package/vendor/harness-ui/src/usage-cache.mjs +315 -0
- package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
- package/vendor/harness-ui/src/workspace-context.mjs +124 -0
- package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
- package/vendor/harness-ui/src/workspace-files.mjs +589 -0
- package/vendor/harness-ui/src/workspace-info.mjs +189 -0
- package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
- package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
- package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
- package/vendor/manifest.json +170 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agui-events.mjs — traduttori PURI da forme interne di talosHarness.mjs
|
|
3
|
+
* allo schema pubblico AG-UI (Agent User Interaction Protocol).
|
|
4
|
+
*
|
|
5
|
+
* ⛔ Zero dipendenze da talosLavora: ogni funzione qui prende dati già
|
|
6
|
+
* pronti (la risposta OpenAI-shaped, un id, un esito) e restituisce
|
|
7
|
+
* SOLO oggetti piatti — nessuna chiamata di rete, nessun I/O, nessuno
|
|
8
|
+
* stato. Per questo si prova con un evento finto per riga, senza mai
|
|
9
|
+
* far girare un vero talosLavora (vedi il piano, §1.6, punto 1).
|
|
10
|
+
*
|
|
11
|
+
* Schema verificato il 24/8 su docs.ag-ui.com/concepts/events — nomi di
|
|
12
|
+
* campo esatti, non inventati. Vedi il piano (elegant-spinning-dongarra.md),
|
|
13
|
+
* §1.2, per la tabella completa evento-per-evento con la fonte, e §0.1
|
|
14
|
+
* per il perché SSE (non WebSocket) è il trasporto scelto: la ricerca
|
|
15
|
+
* del 24/8 conferma che la maggioranza delle implementazioni AG-UI usa
|
|
16
|
+
* SSE per il canale server→client, e l'unico segnale client→server che
|
|
17
|
+
* questa fase richiede ("stop") è raro e non a bassa latenza, quindi
|
|
18
|
+
* viaggia come POST separato invece di aprire un canale bidirezionale.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { ContextEventV1 } from '../../context-engine/src/contracts.mjs';
|
|
22
|
+
|
|
23
|
+
/** AG-UI CUSTOM ufficiale; l'identita persistita resta nel payload TALOS v1. */
|
|
24
|
+
export function contextEngineEvent(input) {
|
|
25
|
+
const value = ContextEventV1.parse(structuredClone(input));
|
|
26
|
+
return { type: 'CUSTOM', name: 'talos.context', timestamp: Date.parse(value.createdAt), value };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function runStarted({ threadId, runId, input, contesto }) {
|
|
30
|
+
const evento = { type: 'RunStarted', threadId, runId }
|
|
31
|
+
if (input !== undefined) evento.input = input
|
|
32
|
+
/*
|
|
33
|
+
* ⭐ `contesto` — {progetto, cartella, branch} da workspace-context.mjs —
|
|
34
|
+
* non fa parte dello schema pubblico AG-UI (che non prevede un campo per
|
|
35
|
+
* "dove sta girando", solo "cosa sta facendo"): è un'estensione
|
|
36
|
+
* dichiarata, nello spirito di "loose event format matching" che AG-UI
|
|
37
|
+
* stesso permette (ricerca del piano, §0.1). Solo se presente: il primo
|
|
38
|
+
* chiamante di questa funzione (i test) non deve saperne niente.
|
|
39
|
+
*/
|
|
40
|
+
if (contesto !== undefined) evento.contesto = contesto
|
|
41
|
+
return evento
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function runFinished({ threadId, runId, outcome, result }) {
|
|
45
|
+
const evento = { type: 'RunFinished', threadId, runId }
|
|
46
|
+
if (outcome !== undefined) evento.outcome = outcome
|
|
47
|
+
if (result !== undefined) evento.result = result
|
|
48
|
+
return evento
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function runError({ message, code }) {
|
|
52
|
+
const evento = { type: 'RunError', message }
|
|
53
|
+
if (code !== undefined) evento.code = code
|
|
54
|
+
return evento
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Lifecycle AVM-owned del reindirizzamento di un giro attivo. AG-UI non
|
|
59
|
+
* definisce ancora un contratto equivalente per il reindirizzamento di
|
|
60
|
+
* un turno attivo: questi eventi restano quindi estensioni dichiarate, come ApprovalRequested e
|
|
61
|
+
* QueuedMessageDelivered. `redirectId` correla richiesta ed esito senza
|
|
62
|
+
* affidarsi alla posizione nel buffer; `testo` compare solo negli eventi
|
|
63
|
+
* che rappresentano un input utente effettivo.
|
|
64
|
+
*/
|
|
65
|
+
export function runRedirectRequested({ redirectId, testo }) {
|
|
66
|
+
return { type: 'RunRedirectRequested', redirectId, testo }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function runRedirectApplied({ redirectId, testo, immagini = [] }) {
|
|
70
|
+
return { type: 'RunRedirectApplied', redirectId, testo, ...(immagini.length ? { immagini } : {}) }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function runRedirectCancelled({ redirectId }) {
|
|
74
|
+
return { type: 'RunRedirectCancelled', redirectId }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function runRedirectFailed({ redirectId, message, code }) {
|
|
78
|
+
const evento = { type: 'RunRedirectFailed', redirectId, message }
|
|
79
|
+
if (code !== undefined) evento.code = code
|
|
80
|
+
return evento
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function textMessageStart({ messageId, role = 'assistant' }) {
|
|
84
|
+
return { type: 'TextMessageStart', messageId, role }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function textMessageContent({ messageId, delta }) {
|
|
88
|
+
return { type: 'TextMessageContent', messageId, delta }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function textMessageEnd({ messageId }) {
|
|
92
|
+
return { type: 'TextMessageEnd', messageId }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* ⭐⭐⭐ 27/8, piano sezione "RICOGNIZIONE COMPETITIVA" (R1) — verificato
|
|
97
|
+
* su docs.ag-ui.com/concepts/events (WebFetch, non assunto): questi TRE
|
|
98
|
+
* eventi esistono davvero nello schema pubblico, stesso schema
|
|
99
|
+
* Start/Content/End di TextMessage*, `role:'reasoning'` fisso. La doc
|
|
100
|
+
* segnala che i vecchi eventi `THINKING_*` sono deprecati a favore di
|
|
101
|
+
* questi — REASONING_* è la forma corrente.
|
|
102
|
+
*/
|
|
103
|
+
export function reasoningMessageStart({ messageId }) {
|
|
104
|
+
return { type: 'ReasoningMessageStart', messageId, role: 'reasoning' }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function reasoningMessageContent({ messageId, delta }) {
|
|
108
|
+
return { type: 'ReasoningMessageContent', messageId, delta }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function reasoningMessageEnd({ messageId }) {
|
|
112
|
+
return { type: 'ReasoningMessageEnd', messageId }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* ⛔⛔ OSS-1 (17/09/2026) — UNA DURATA MISURATA SULL'OSSERVATORE NON E' UNA DURATA.
|
|
117
|
+
*
|
|
118
|
+
* Nella scheda «Processi» ogni riga diceva «0 s» al REPLAY di una sessione, e il conto era
|
|
119
|
+
* giusto: il client sottraeva due `ricevutoA`, cioe' due ore di ARRIVO dell'evento, e al replay
|
|
120
|
+
* tutti gli eventi arrivano insieme. Il tempo va misurato dove succede — nel kernel, intorno
|
|
121
|
+
* all'esecuzione — e viaggiare dentro l'evento.
|
|
122
|
+
*
|
|
123
|
+
* ⛔ `avviatoA` (epoch ms del SERVER) e `durataMs` (interi) sono campi ADDITIVI, fuori dallo
|
|
124
|
+
* schema pubblico AG-UI come gia' `contesto` su RunStarted e `prima`/`allegato` su StateDelta:
|
|
125
|
+
* la spec dichiara «loose event format matching», e un consumer che non li conosce li ignora.
|
|
126
|
+
* ⛔⛔ E si OMETTONO quando non ci sono. Uno zero al posto di «non misurato» e' indistinguibile
|
|
127
|
+
* da «istantaneo» — cioe' esattamente il difetto che questa riga cura, riportato da un'altra
|
|
128
|
+
* porta. Stessa disciplina di `usage`/`totali` nel kernel: «mai un contatore che dice zero dove
|
|
129
|
+
* la verita' e' ignoto».
|
|
130
|
+
*/
|
|
131
|
+
function oraValida(valore) {
|
|
132
|
+
return typeof valore === 'number' && Number.isFinite(valore)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** ⛔ Una durata e' un intero di millisecondi >= 0: un decimale si arrotonda, tutto il resto sparisce. */
|
|
136
|
+
function durataValida(valore) {
|
|
137
|
+
return typeof valore === 'number' && Number.isFinite(valore) && valore >= 0
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function toolCallStart({ toolCallId, toolCallName, parentMessageId, avviatoA }) {
|
|
141
|
+
const evento = { type: 'ToolCallStart', toolCallId, toolCallName }
|
|
142
|
+
if (parentMessageId !== undefined) evento.parentMessageId = parentMessageId
|
|
143
|
+
if (oraValida(avviatoA)) evento.avviatoA = Math.round(avviatoA)
|
|
144
|
+
return evento
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function toolCallArgs({ toolCallId, delta }) {
|
|
148
|
+
return { type: 'ToolCallArgs', toolCallId, delta }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* ⭐⭐⭐ D-10B — l'uscita di un comando MENTRE esce.
|
|
153
|
+
*
|
|
154
|
+
* ⛔ Non e' un `ToolCallResult` parziale: quello e' l'esito, arriva una volta sola e ha un
|
|
155
|
+
* `messageId` perche' entra nella conversazione come messaggio di ruolo `tool`. Questo invece e'
|
|
156
|
+
* avanzamento — si mostra e si dimentica, e il testo definitivo resta quello del risultato.
|
|
157
|
+
* Tenerli distinti e' la ragione per cui un consumer vecchio, che non conosce questo tipo, lo
|
|
158
|
+
* ignora e continua a vedere esattamente cio' che vedeva prima.
|
|
159
|
+
* Ricerca 10/09/2026: AG-UI definisce «a vocabulary of typed events that agents emit to frontends»
|
|
160
|
+
* e tiene separati i chunk di avanzamento dai messaggi finali; Vercel Academy, «Streaming and Tool
|
|
161
|
+
* Rendering», per la stessa distinzione lato resa.
|
|
162
|
+
*/
|
|
163
|
+
/**
|
|
164
|
+
* ⭐⭐⭐ D-10D — UN COMANDO SCRITTO DALLA PERSONA NON È UN GIRO DEL MODELLO.
|
|
165
|
+
*
|
|
166
|
+
* ⛔ Prima si travestiva da giro: `eseguiComandoDiretto` emetteva `RunStarted`/`RunFinished`, e
|
|
167
|
+
* `shell()` metteva `voce.conclusa = false` per la sua durata. Da lì **sette lettori del registro
|
|
168
|
+
* credevano a una bugia** — il watcher del workspace si spegneva a metà scrittura,
|
|
169
|
+
* `resume`/`fork`/`compatta` diventavano leciti su una sessione viva, `reindirizza` rifiutava, la
|
|
170
|
+
* barra dava la sessione per finita. E il prezzo più alto lo pagava chi scrive: col modello al
|
|
171
|
+
* lavoro il `!` veniva respinto («la sessione è ancora in corso»), perché due giri insieme non si
|
|
172
|
+
* possono raccontare con un vocabolario che ne conosce uno solo.
|
|
173
|
+
*
|
|
174
|
+
* ⇒ Due operazioni distinte sulla stessa sessione, ognuna col suo vocabolario. È la forma che usa
|
|
175
|
+
* AWS Bedrock AgentCore (docs.aws.amazon.com, «Execute shell commands in AgentCore Runtime
|
|
176
|
+
* sessions», letto il 10/09/2026): `InvokeAgentRuntime` per il ragionamento e
|
|
177
|
+
* `InvokeAgentRuntimeCommand` per la shell deterministica, con la garanzia dichiarata che
|
|
178
|
+
* «command execution doesn't block agent invocations, and you can invoke the agent and run
|
|
179
|
+
* commands concurrently on the same session».
|
|
180
|
+
*
|
|
181
|
+
* ⛔ `comandoId` e non `runId`: sono due spazi di nomi diversi, e confonderli riporterebbe il
|
|
182
|
+
* difetto da un'altra porta.
|
|
183
|
+
*/
|
|
184
|
+
export function comandoUtenteIniziato({ comandoId, comando }) {
|
|
185
|
+
return { type: 'ComandoUtenteIniziato', comandoId, comando: String(comando ?? '') }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function comandoUtenteFinito({ comandoId, codice, enforcement, errore }) {
|
|
189
|
+
const evento = { type: 'ComandoUtenteFinito', comandoId }
|
|
190
|
+
if (codice !== undefined) evento.codice = codice
|
|
191
|
+
if (enforcement !== undefined) evento.enforcement = enforcement
|
|
192
|
+
/* ⛔ Un comando che non è nemmeno partito lo DICE qui: senza, resterebbe indistinguibile da uno
|
|
193
|
+
finito bene e muto — la stessa confusione che `codice: null` faceva in D-10G. */
|
|
194
|
+
if (errore !== undefined) evento.errore = String(errore)
|
|
195
|
+
return evento
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function toolCallOutput({ toolCallId, delta }) {
|
|
199
|
+
return { type: 'ToolCallOutput', toolCallId, delta: String(delta ?? '') }
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* ⭐ OSS-1 — `durataMs`: i millisecondi misurati nel kernel INTORNO all'esecuzione dell'attrezzo
|
|
204
|
+
* (`performance.now()`, un orologio monotono: non torna indietro se l'ora di sistema cambia a
|
|
205
|
+
* meta' comando). Assente per gli attrezzi che non misuriamo — vedi `oraValida`/`durataValida`.
|
|
206
|
+
*
|
|
207
|
+
* ⭐ OSS-2 — `comando` e `cwd`: `prova` non compariva fra i processi perche' i suoi
|
|
208
|
+
* `ToolCallArgs` sono `{}` — il comando eseguito non e' un argomento del modello, e' una
|
|
209
|
+
* impostazione della sessione (`comandoProva`). Senza questi due campi chi guarda gli eventi
|
|
210
|
+
* non poteva sapere CHE COSA e' stato eseguito ne' DOVE. Per `shell` `cwd` e' la cartella
|
|
211
|
+
* EFFETTIVA (quella che il comando ha visto davvero), non quella richiesta.
|
|
212
|
+
*/
|
|
213
|
+
export function toolCallResult({ messageId, toolCallId, content, role = 'tool', durataMs, comando, cwd, receipt, outcome }) {
|
|
214
|
+
const evento = { type: 'ToolCallResult', messageId, toolCallId, content, role }
|
|
215
|
+
if (durataValida(durataMs)) evento.durataMs = Math.round(durataMs)
|
|
216
|
+
if (typeof comando === 'string' && comando !== '') evento.comando = comando
|
|
217
|
+
if (typeof cwd === 'string' && cwd !== '') evento.cwd = cwd
|
|
218
|
+
if (receipt && typeof receipt === 'object' && !Array.isArray(receipt)) evento.receipt = receipt
|
|
219
|
+
if (outcome === 'cancelled') evento.outcome = outcome
|
|
220
|
+
return evento
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function stateDelta({ delta }) {
|
|
224
|
+
return { type: 'StateDelta', delta }
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* ⭐⭐⭐ 28/8 — `ArtifactCreated`. ⛔ NON è nello schema pubblico AG-UI
|
|
229
|
+
* (verificato il 24/8 su docs.ag-ui.com/concepts/events per gli eventi
|
|
230
|
+
* sopra: non esiste un evento per "un documento HTML autosufficiente da
|
|
231
|
+
* mostrare"): stessa estensione dichiarata di `contesto` su RunStarted,
|
|
232
|
+
* stesso spirito "loose event format matching".
|
|
233
|
+
*
|
|
234
|
+
* ⛔⛔ NIENTE `html` qui dentro — cambiato dopo la prima versione,
|
|
235
|
+
* misurato dal vivo: `html` viaggiava nell'evento SSE e il frontend lo
|
|
236
|
+
* passava a `iframe.srcdoc`, ma un `srcdoc` eredita la CSP della pagina
|
|
237
|
+
* (vedi artifact-store.mjs) — lo script del modello non partiva mai.
|
|
238
|
+
* La cura è servire l'HTML da una rotta HTTP vera
|
|
239
|
+
* (`GET /api/v1/artifacts/:id`, la sua CSP dedicata), quindi qui basta
|
|
240
|
+
* l'`id`: il frontend punta `iframe.src` lì, il browser fa il resto.
|
|
241
|
+
*/
|
|
242
|
+
export function artifactCreated({ messageId, id, titolo }) {
|
|
243
|
+
return { type: 'ArtifactCreated', messageId, id, titolo }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* ⭐⭐⭐ 28/8 — workspace-watcher.mjs: i file sono cambiati FUORI
|
|
248
|
+
* dall'app (Explorer, un editor, git...), owner 27/8: "se muovo i
|
|
249
|
+
* file il work tree non si aggiorna automaticamente". Fuori dallo
|
|
250
|
+
* schema pubblico AG-UI (stessa estensione già dichiarata per
|
|
251
|
+
* `ArtifactCreated`) — `percorsi` sono i percorsi RELATIVI coinvolti,
|
|
252
|
+
* già debounced/deduplicati dal watcher; il frontend oggi li usa solo
|
|
253
|
+
* per decidere SE invalidare (mai un diff fine, vedi app.js), ma sono
|
|
254
|
+
* inoltrati comunque: costano poco e un consumo più preciso è lavoro
|
|
255
|
+
* futuro, non una riscrittura del contratto.
|
|
256
|
+
*/
|
|
257
|
+
export function workspaceChanged({ percorsi }) {
|
|
258
|
+
return { type: 'WorkspaceChanged', percorsi }
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* ⭐⭐⭐ 28/8 — la pillola permessi, livello "On request": il kernel chiama
|
|
263
|
+
* `chiediApprovazioneFn(azione)` PRIMA di scrivi/shell/document_create
|
|
264
|
+
* (talosHarness.mjs, `verificaPermessoScrittura`) e resta in attesa —
|
|
265
|
+
* questo evento è come quell'attesa diventa visibile a chi guarda la
|
|
266
|
+
* sessione dal vivo. Fuori dallo schema pubblico AG-UI (stessa estensione
|
|
267
|
+
* già dichiarata per ArtifactCreated/WorkspaceChanged): non esiste un
|
|
268
|
+
* evento AG-UI per "il run è in pausa in attesa di un umano".
|
|
269
|
+
*
|
|
270
|
+
* `requestId` è come il frontend risponde (`POST .../approve`, vedi
|
|
271
|
+
* http-app.mjs) — necessario perché una risposta in ritardo/duplicata non
|
|
272
|
+
* deve mai risolvere la richiesta SUCCESSIVA per errore (session-registry.mjs
|
|
273
|
+
* verifica che l'id combaci prima di risolvere la Promise in attesa).
|
|
274
|
+
* `azione` è esattamente ciò che talosHarness.mjs passa al callback:
|
|
275
|
+
* `{tipo, percorso?, comando?, formato?}` — abbastanza per mostrare
|
|
276
|
+
* all'owner COSA sta per succedere prima che lui decida.
|
|
277
|
+
*/
|
|
278
|
+
export function approvalRequested({ requestId, azione }) {
|
|
279
|
+
return { type: 'ApprovalRequested', requestId, azione }
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* ⭐⭐⭐ FASE D (28/8) — coda messaggi, piano elegant-spinning-dongarra.md,
|
|
284
|
+
* LEDGER-FASE-D-CODA.md. Il kernel chiama `codaMessaggiFn()` SOLO nel
|
|
285
|
+
* punto in cui avrebbe altrimenti concluso il run (zero tool-call
|
|
286
|
+
* nell'ultima risposta) — se torna un testo, quel testo diventa un
|
|
287
|
+
* nuovo turno utente e il ciclo continua. Questo evento è il SOLO modo
|
|
288
|
+
* onesto per il frontend di sapere ESATTAMENTE quando questo è successo:
|
|
289
|
+
* un'euristica lato client (es. "un nuovo ToolCallStart dopo una
|
|
290
|
+
* risposta di solo testo") è ambigua — la stessa sequenza succede anche
|
|
291
|
+
* quando il modello risponde con testo+tool_calls nello stesso giro,
|
|
292
|
+
* senza che la coda c'entri nulla. Fuori dallo schema pubblico AG-UI
|
|
293
|
+
* (stessa estensione già dichiarata per ArtifactCreated/WorkspaceChanged/
|
|
294
|
+
* ApprovalRequested).
|
|
295
|
+
*/
|
|
296
|
+
export function queuedMessageDelivered({ testo }) {
|
|
297
|
+
return { type: 'QueuedMessageDelivered', testo }
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* ⭐⭐⭐ 28/8 — chiude la richiesta sopra: emesso SUBITO dopo che l'owner ha
|
|
302
|
+
* risposto, così un secondo tab/client con la stessa sessione aperta
|
|
303
|
+
* smette di mostrare il prompt invece di restare bloccato per sempre.
|
|
304
|
+
*/
|
|
305
|
+
export function approvalResolved({ requestId, approvato }) {
|
|
306
|
+
return { type: 'ApprovalResolved', requestId, approvato }
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* ⭐⭐⭐ 28/8 — FASE A (hook), piano `elegant-spinning-dongarra.md`. Emesso
|
|
311
|
+
* da `costruisciHookFn` (session-registry.mjs) DOPO ogni esecuzione VERA
|
|
312
|
+
* di un hook fidato — mai per un hook non fidato (quello non gira
|
|
313
|
+
* affatto, non c'è niente da mostrare) né per una sessione senza hook
|
|
314
|
+
* (il ramo veloce `hooksCache.length === 0` non chiama mai questo).
|
|
315
|
+
* `tipo`/`azione` sono l'evento passato all'hook (pre_tool_call/
|
|
316
|
+
* post_tool_call/session_start/session_end, più l'azione se presente);
|
|
317
|
+
* `esito` è ESATTAMENTE ciò che l'hook ha risposto (o il rifiuto
|
|
318
|
+
* sintetico se l'hook è fallito nell'esecuzione) — il pannello
|
|
319
|
+
* Control-plane mostra questo, non una sua interpretazione.
|
|
320
|
+
*/
|
|
321
|
+
export function hookInvoked({ hookId, tipo, azione, esito }) {
|
|
322
|
+
return { type: 'HookInvoked', hookId, tipo, azione: azione ?? null, esito }
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* ⭐ Da una risposta grezza del modello (la stessa forma OpenAI che
|
|
327
|
+
* talosLavora già costruisce — {role, content, tool_calls}, vedi
|
|
328
|
+
* talosHarness.mjs riga ~761) all'elenco ORDINATO di eventi AG-UI per
|
|
329
|
+
* quel giro.
|
|
330
|
+
*
|
|
331
|
+
* ⛔ Zero eventi di streaming a chunk QUI: questa funzione traduce la
|
|
332
|
+
* risposta GIÀ COMPLETA che `onGiro` riceve a fine giro (talosHarness.mjs),
|
|
333
|
+
* quindi ogni messaggio di testo resta uno Start+Content+End con UN SOLO
|
|
334
|
+
* delta. ⭐ 27/8 — lo streaming vero (testo E ragionamento, a pezzi,
|
|
335
|
+
* PRIMA che il giro finisca) esiste ora come canale SEPARATO: vedi
|
|
336
|
+
* `reasoningMessageStart/Content/End` sopra e `onDelta` in
|
|
337
|
+
* agent-service.mjs — non sostituisce questa funzione, la precede nel
|
|
338
|
+
* tempo (i delta arrivano durante il giro, questa traduce cosa resta a
|
|
339
|
+
* fine giro).
|
|
340
|
+
*
|
|
341
|
+
* `messageId` è responsabilità del CHIAMANTE (chi ha lo stato per
|
|
342
|
+
* generarne uno univoco, es. agent-service.mjs con crypto.randomUUID) —
|
|
343
|
+
* questa funzione resta pura e deterministica per essere provata senza
|
|
344
|
+
* mock di generatori casuali.
|
|
345
|
+
*
|
|
346
|
+
* ⛔ `testoGiaStreamato` — ⭐ 27/8, R1: quando `onDelta` ha già mandato il
|
|
347
|
+
* testo di QUESTO giro a pezzi (Start, N Content, End — dal vivo, prima
|
|
348
|
+
* ancora che il giro finisse — vedi agent-service.mjs), rimandarlo qui INTERO
|
|
349
|
+
* duplicherebbe il messaggio in chat — stessa famiglia di difetto già
|
|
350
|
+
* trovata e chiusa stanotte per RunFinished.
|
|
351
|
+
*
|
|
352
|
+
* ⛔ `toolCallsGiaStreamate` — Piano procedi-col-generare-un-snoopy-neumann.md,
|
|
353
|
+
* Fase 4: STESSA famiglia di difetto, applicata alle tool-call. Prima
|
|
354
|
+
* di questa fase erano dichiarate "non ancora streamate" (vedi il
|
|
355
|
+
* commento che questa riga sostituisce) — ora che `onDelta` le manda a
|
|
356
|
+
* pezzi (agent-service.mjs), rimandarle qui INTERE le duplicherebbe. Un
|
|
357
|
+
* `Set`/array di `toolCallId` (non un booleano unico: un giro può avere
|
|
358
|
+
* PIÙ tool-call, a differenza del testo/ragionamento che ne hanno al
|
|
359
|
+
* più uno) — ogni tool-call il cui id è dentro viene saltata qui,
|
|
360
|
+
* l'altre (fornitori/percorsi che non passano da `onDelta`, es. la
|
|
361
|
+
* risposta non-streaming) restano emesse come sempre.
|
|
362
|
+
*/
|
|
363
|
+
export function eventiPerRisposta(risposta, { messageId, parentMessageId, testoGiaStreamato = false, toolCallsGiaStreamate } = {}) {
|
|
364
|
+
const eventi = []
|
|
365
|
+
if (risposta?.content && !testoGiaStreamato) {
|
|
366
|
+
eventi.push(textMessageStart({ messageId, role: risposta.role ?? 'assistant' }))
|
|
367
|
+
eventi.push(textMessageContent({ messageId, delta: String(risposta.content) }))
|
|
368
|
+
eventi.push(textMessageEnd({ messageId }))
|
|
369
|
+
}
|
|
370
|
+
const streamate = toolCallsGiaStreamate ?? new Set()
|
|
371
|
+
for (const chiamata of risposta?.tool_calls ?? []) {
|
|
372
|
+
if (streamate.has(chiamata.id)) continue
|
|
373
|
+
eventi.push(toolCallStart({
|
|
374
|
+
toolCallId: chiamata.id,
|
|
375
|
+
toolCallName: chiamata.function?.name,
|
|
376
|
+
parentMessageId,
|
|
377
|
+
}))
|
|
378
|
+
eventi.push(toolCallArgs({
|
|
379
|
+
toolCallId: chiamata.id,
|
|
380
|
+
delta: chiamata.function?.arguments ?? '',
|
|
381
|
+
}))
|
|
382
|
+
}
|
|
383
|
+
return eventi
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* ⭐ Dall'esito già calcolato di un attrezzo (la stessa stringa che
|
|
388
|
+
* talosLavora mette in `messaggi.push({role:'tool', tool_call_id,
|
|
389
|
+
* content})`, talosHarness.mjs riga ~836) a ToolCallResult.
|
|
390
|
+
*/
|
|
391
|
+
export function eventoPerEsitoTool({ messageId, toolCallId, content, durataMs, comando, cwd, receipt, outcome }) {
|
|
392
|
+
/* ⭐ OSS-1/OSS-2/M4-E — inoltro puro: la decisione su COSA entra nell'evento sta tutta in
|
|
393
|
+
`toolCallResult` qui sopra, un posto solo. Chi non passa i campi opzionali ottiene l'oggetto
|
|
394
|
+
identico di prima, byte per byte. */
|
|
395
|
+
return toolCallResult({ messageId, toolCallId, content: String(content), durataMs, comando, cwd, receipt, outcome })
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* ⭐ Dal prima/dopo che `scrivi` già costruisce internamente (vedi
|
|
400
|
+
* `premessaDellaScrittura` in talosHarness.mjs — `prima` e `dopo` sono
|
|
401
|
+
* già array di {percorso, testo}) a UNA operazione JSON Patch RFC 6902:
|
|
402
|
+
* `replace` se il file esisteva già in `prima`, `add` se è nuovo.
|
|
403
|
+
* Formato scelto dalla ricerca del piano §0.1 (`StateDelta` — RFC 6902
|
|
404
|
+
* JSON Patch), non inventato qui.
|
|
405
|
+
*
|
|
406
|
+
* ⭐⭐⭐ 27/8, owner: "un vero formattatore diff, importantissimo".
|
|
407
|
+
* `contenutoPrima` — quinto campo, NON standard RFC 6902 (la spec non lo
|
|
408
|
+
* vieta: un consumer che non lo conosce lo ignora) — è il testo del file
|
|
409
|
+
* un istante prima di questa scrittura, ora tornato da
|
|
410
|
+
* `premessaDellaScrittura` (vedi AVM-harness). ⛔ Aggiunto SOLO quando
|
|
411
|
+
* presente (`contenutoPrima !== undefined`): un chiamante vecchio che non
|
|
412
|
+
* lo passa produce l'identico oggetto di prima, byte per byte — nessuna
|
|
413
|
+
* chiave fantasma `prima: undefined` che romperebbe un
|
|
414
|
+
* `assert.deepStrictEqual` già scritto altrove.
|
|
415
|
+
*/
|
|
416
|
+
/*
|
|
417
|
+
* ⛔⛔ PO-05, owner: «ogni file generato deve avere un collegamento diretto per scaricarlo con un
|
|
418
|
+
* clic; nome, formato, dimensione e disponibilità REALI». `allegato` — sesto campo, come `prima`
|
|
419
|
+
* fuori dalla RFC 6902 e come `prima` innocuo per chi non lo conosce — porta ciò che serve a
|
|
420
|
+
* costruire quel collegamento e a scrivere l'etichetta: nome, formato e byte.
|
|
421
|
+
* ⛔ NON porta i byte: quelli si prendono dalla rotta, uno per uno, quando la persona clicca. Un
|
|
422
|
+
* `.docx` dentro un evento SSE andrebbe ricodificato, cioè spedito due volte e corrotto una.
|
|
423
|
+
* ⛔ E si aggiunge SOLO quando c'è (`allegato !== undefined`): un chiamante che non lo passa produce
|
|
424
|
+
* l'oggetto identico di prima, byte per byte — stessa disciplina di `prima`, e per lo stesso
|
|
425
|
+
* motivo (un `assert.deepStrictEqual` già scritto altrove non deve diventare rosso da solo).
|
|
426
|
+
*/
|
|
427
|
+
export function eventoPerScrittura({ percorso, contenuto, esisteva, contenutoPrima, allegato }) {
|
|
428
|
+
return stateDelta({
|
|
429
|
+
delta: [{
|
|
430
|
+
op: esisteva ? 'replace' : 'add',
|
|
431
|
+
path: `/file/${percorso}`,
|
|
432
|
+
value: contenuto,
|
|
433
|
+
...(contenutoPrima !== undefined ? { prima: contenutoPrima } : {}),
|
|
434
|
+
...(allegato !== undefined ? { allegato } : {}),
|
|
435
|
+
}],
|
|
436
|
+
})
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* ⭐⭐⭐ Piano procedi-col-generare-un-snoopy-neumann.md, Fase 3 — il
|
|
441
|
+
* contatore costo/token per una sessione VIVA (oggi esiste solo per le
|
|
442
|
+
* righe storiche della Board campagne). Stesso formato StateDelta di
|
|
443
|
+
* `eventoPerScrittura` sopra, stesso path-prefix `/usage` (mai
|
|
444
|
+
* `/file/*`): `replace` sempre, perché `totali` da `talosHarness.mjs`
|
|
445
|
+
* è già una SOMMA cumulativa a ogni giro, non un delta da sommare qui —
|
|
446
|
+
* un secondo consumer che sommasse di nuovo raddoppierebbe il conto.
|
|
447
|
+
*/
|
|
448
|
+
export function eventoPerUsage(totali) {
|
|
449
|
+
return stateDelta({
|
|
450
|
+
delta: [{ op: 'replace', path: '/usage', value: totali }],
|
|
451
|
+
})
|
|
452
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ambiente-solo-server.mjs — le variabili che il SERVER TALOS ha addosso solo perché gliele ha
|
|
3
|
+
* messe il desktop, e che un processo lanciato PER LA PERSONA non deve ereditare.
|
|
4
|
+
*
|
|
5
|
+
* ⛔⛔⛔ CLI-REQ-04 (17/09/2026) + D1 del secondo giro. Nasce come costante dentro
|
|
6
|
+
* `pty-terminal.mjs`, e si sposta qui perché adesso i clienti sono DUE: la shell della scheda
|
|
7
|
+
* Terminale e il browser di sistema che `browser-vivo.mjs` avvia per la persona. Una copia per
|
|
8
|
+
* cliente sarebbe due elenchi che divergono al primo segreto nuovo — e nessuno se ne
|
|
9
|
+
* accorgerebbe, perché il risultato sbagliato (una variabile che passa) ha lo stesso aspetto di
|
|
10
|
+
* quello giusto.
|
|
11
|
+
*
|
|
12
|
+
* ⛔ E non basta esportarlo da `pty-terminal.mjs`: quel modulo importa `node-pty`, un modulo
|
|
13
|
+
* NATIVO, in cima. Farlo importare a `browser-vivo.mjs` legherebbe l'avvio del browser alla
|
|
14
|
+
* presenza di un binding compilato che lì non serve. Un file senza dipendenze è la forma che
|
|
15
|
+
* permette di riusare l'elenco invece di copiarlo.
|
|
16
|
+
*
|
|
17
|
+
* ⛔⛔ PERCHÉ UN ELENCO CHIUSO E NON IL FILTRO A FORMA del kernel (`ambienteSenzaCredenziali`,
|
|
18
|
+
* D-10E) — decisione dell'owner, 17/09/2026. Questi processi sono della PERSONA: la scheda
|
|
19
|
+
* Terminale è «un terminale vero e proprio [...] che non ha limiti» (intestazione di
|
|
20
|
+
* `pty-terminal.mjs`), e il browser è il suo browser. Un filtro che toglie «tutto ciò che sembra
|
|
21
|
+
* una credenziale» porterebbe via anche `GH_TOKEN`, `NPM_TOKEN`, `ANTHROPIC_API_KEY`,
|
|
22
|
+
* `AWS_SECRET_ACCESS_KEY`: `gh` e `npm publish` funzionerebbero nella Git Bash della stessa
|
|
23
|
+
* macchina e fallirebbero dentro TALOS. Si toglie SOLO ciò che esiste perché ce l'ha messo TALOS.
|
|
24
|
+
*
|
|
25
|
+
* ⛔⛔⛔ E IL KERNEL NON COPRE GIÀ QUESTI NOMI: il commit del primo giro lo affermava, ed era
|
|
26
|
+
* FALSO. Misurato il 17/09/2026 chiamando `eUnaCredenziale()` di `kernel/talosHarness.mjs` sui
|
|
27
|
+
* quattro nomi:
|
|
28
|
+
* TALOS_HARNESS_UI_TOKEN → true (D-10E lo toglie)
|
|
29
|
+
* TALOS_HARNESS_RECEIPT_PRIVATE_KEY_B64 → true (D-10E lo toglie)
|
|
30
|
+
* TALOS_HARNESS_RECEIPT_KEY_ID → **false**
|
|
31
|
+
* ELECTRON_RUN_AS_NODE → **false**
|
|
32
|
+
* TALOS_HARNESS_SEARCH_API_KEY → true
|
|
33
|
+
* Causa: `FORMA_DI_CREDENZIALE` (`talosHarness.mjs:3705`) ha `_KEY$` e `^KEY_` ma non `_KEY_`,
|
|
34
|
+
* e `ELECTRON_RUN_AS_NODE` non ha forma di credenziale perché non è un segreto — è un cambio
|
|
35
|
+
* di comportamento. ⇒ Quei due arrivano ancora all'attrezzo `shell` e a `prova` del modello.
|
|
36
|
+
* ⛔ NON è curato qui: il filtro del kernel è fuori dal perimetro di questa riga. È DICHIARATO,
|
|
37
|
+
* perché una cosa non curata e non scritta è una cosa dimenticata.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/** ⛔ Le variabili che esistono solo perché TALOS le ha messe. Elenco CHIUSO, deciso dall'owner. */
|
|
41
|
+
export const VARIABILI_SOLO_DEL_SERVER = Object.freeze([
|
|
42
|
+
// Il token di loopback: chi ce l'ha parla con la nostra API con l'autorità dell'interfaccia.
|
|
43
|
+
'TALOS_HARNESS_UI_TOKEN',
|
|
44
|
+
/*
|
|
45
|
+
* ⛔ La coppia della firma ricevute va tolta INTERA, mai a metà: `parseFirmaRicevute`
|
|
46
|
+
* (`config.mjs:627-634`) fallisce l'avvio quando ne trova una sola. Lasciare l'id addosso al
|
|
47
|
+
* processo farebbe morire con ConfigurationError un TALOS lanciato da lì.
|
|
48
|
+
*/
|
|
49
|
+
'TALOS_HARNESS_RECEIPT_KEY_ID',
|
|
50
|
+
'TALOS_HARNESS_RECEIPT_PRIVATE_KEY_B64',
|
|
51
|
+
/*
|
|
52
|
+
* ⛔ Aggiunta nel secondo giro (B3): è la chiave della fonte di ricerca web, che il server legge
|
|
53
|
+
* da `config.mjs:685` e tiene per sé. Sta nel NOSTRO spazio di nomi `TALOS_*`, cioè è nostra e
|
|
54
|
+
* non della persona: è esattamente il criterio dell'owner («si toglie ciò che esiste perché
|
|
55
|
+
* TALOS lo usa, non le credenziali della persona»). Nel primo giro non era stata decisa per
|
|
56
|
+
* nome, ed è la ragione per cui la guardia qui sotto adesso legge anche `config.mjs`.
|
|
57
|
+
*/
|
|
58
|
+
'TALOS_HARNESS_SEARCH_API_KEY',
|
|
59
|
+
/*
|
|
60
|
+
* Non è un segreto, è un cambio di comportamento: `runtime.mjs:56` la mette per far partire il
|
|
61
|
+
* server come Node dentro l'eseguibile Electron. Ereditata, farebbe partire come Node semplice
|
|
62
|
+
* QUALUNQUE programma Electron lanciato da lì.
|
|
63
|
+
*/
|
|
64
|
+
'ELECTRON_RUN_AS_NODE',
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
* ⛔ CLI-REQ-04, punto (a): le altre variabili che `runtime.mjs` mette nel figlio, dichiarate
|
|
69
|
+
* innocue PER NOME invece che dimenticate in silenzio. La prova legge la sorgente di
|
|
70
|
+
* `runtime.mjs` e di `config.mjs` e pretende che ogni nome stia in uno dei due elenchi.
|
|
71
|
+
*
|
|
72
|
+
* Perché innocue: host e porta sono un indirizzo di loopback, non una credenziale — senza il
|
|
73
|
+
* token non aprono niente, e chi lavora nel terminale ha buoni motivi per sapere dove ascolta il
|
|
74
|
+
* server. Il file di handshake contiene `{host, port}` e nient'altro (`server.mjs:775-777`). Le
|
|
75
|
+
* tre cartelle dei dati e i due percorsi del motore locale sono percorsi sul disco della persona,
|
|
76
|
+
* che dal terminale può già leggere.
|
|
77
|
+
*/
|
|
78
|
+
export const VARIABILI_DEL_SERVER_DICHIARATE_INNOCUE = Object.freeze([
|
|
79
|
+
'TALOS_HARNESS_UI_HOST',
|
|
80
|
+
'TALOS_HARNESS_UI_PORT',
|
|
81
|
+
'TALOS_HARNESS_UI_REPORT_FILE',
|
|
82
|
+
'TALOS_DESKTOP_DATA_DIR',
|
|
83
|
+
'TALOS_HARNESS_UI_SESSIONS_DIR',
|
|
84
|
+
'TALOS_LLAMA_SERVER_PATH',
|
|
85
|
+
'TALOS_LLAMA_SERVER_FALLBACK_PATH',
|
|
86
|
+
/*
|
|
87
|
+
* ⛔⛔⛔ B-1 del terzo giro (17/09/2026) — DUE CREDENZIALI CHE RESTANO, DECISE PER NOME.
|
|
88
|
+
*
|
|
89
|
+
* `config.mjs:590-591` legge anche `OPENROUTER_API_KEY` e `HF_TOKEN`, e il primo giro non le
|
|
90
|
+
* aveva decise: passavano perché la guardia guardava solo `runtime.mjs` e solo i nomi `TALOS_*`.
|
|
91
|
+
* Passare per distrazione e passare per decisione si somigliano, e proprio per questo vanno
|
|
92
|
+
* separati.
|
|
93
|
+
*
|
|
94
|
+
* ⇒ RESTANO, ed è la stessa regola dell'owner applicata dritta: sono credenziali della PERSONA,
|
|
95
|
+
* non cose che esistono perché ce le ha messe TALOS. Stanno nello spazio di nomi dei loro
|
|
96
|
+
* fornitori — come `GH_TOKEN`, `NPM_TOKEN`, `ANTHROPIC_API_KEY` — e chi apre il terminale se le
|
|
97
|
+
* aspetta: `huggingface-cli`, `curl` verso OpenRouter, la CLI di un altro agente. Toglierle
|
|
98
|
+
* sarebbe il filtro a forma che l'owner ha rifiutato, travestito da elenco.
|
|
99
|
+
* ⛔ Il fatto che il server le LEGGA non le rende sue: le legge dall'ambiente della persona,
|
|
100
|
+
* non le mette lui. Il criterio è l'ORIGINE, non chi le usa.
|
|
101
|
+
*/
|
|
102
|
+
'OPENROUTER_API_KEY',
|
|
103
|
+
'HF_TOKEN',
|
|
104
|
+
]);
|
|
105
|
+
|
|
106
|
+
const NOMI_SOLO_DEL_SERVER = new Set(VARIABILI_SOLO_DEL_SERVER.map((nome) => nome.toUpperCase()));
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* L'ambiente da dare a un processo lanciato PER LA PERSONA: tutto il suo, meno ciò che è solo del
|
|
110
|
+
* server.
|
|
111
|
+
*
|
|
112
|
+
* ⛔ Confronto senza distinzione di maiuscole: su Windows i nomi delle variabili d'ambiente lo
|
|
113
|
+
* sono, e `runtime.mjs:47` filtra già i suoi con una regexp `/i`.
|
|
114
|
+
* ⛔ Gli `undefined` si scartano: `IPtyForkOptions.env` di node-pty 1.1.0 è
|
|
115
|
+
* `{[key:string]: string|undefined}`, e `runtime.mjs:47` fa già lo stesso per il figlio.
|
|
116
|
+
*/
|
|
117
|
+
export function ambienteSenzaVariabiliDelServer(env = process.env) {
|
|
118
|
+
return Object.fromEntries(
|
|
119
|
+
Object.entries(env).filter(([nome, valore]) => valore !== undefined && !NOMI_SOLO_DEL_SERVER.has(nome.toUpperCase())),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* artifact-store.mjs — l'HTML degli artefatti (attrezzo `artifact_create`
|
|
3
|
+
* in talosHarness.mjs), tenuto in memoria per essere servito via GET con
|
|
4
|
+
* la SUA propria Content-Security-Policy, permissiva SOLO per quella
|
|
5
|
+
* risposta (vedi la rotta in http-app.mjs).
|
|
6
|
+
*
|
|
7
|
+
* ⛔⛔⛔ 28/8 — PERCHÉ NON `srcdoc`, misurato dal vivo e non ipotizzato: un
|
|
8
|
+
* documento `about:srcdoc` EREDITA la Content-Security-Policy della
|
|
9
|
+
* pagina che lo crea (regola dello standard, non un bug del browser). Con
|
|
10
|
+
* lo `script-src 'self'` di tutto il resto di Harness UI
|
|
11
|
+
* (`SECURITY_HEADERS`, http-app.mjs), un `<meta>` CSP permissivo scritto
|
|
12
|
+
* DENTRO il srcdoc veniva ignorato: lo script del modello non partiva
|
|
13
|
+
* mai, nessuno `<style>` si applicava — verificato con una sonda
|
|
14
|
+
* cross-frame via `postMessage` (zero eseguiti, in tre varianti diverse,
|
|
15
|
+
* anche senza alcun sandbox). Una risposta HTTP VERA, con la SUA propria
|
|
16
|
+
* intestazione, non eredita niente dalla pagina che la incorpora — è la
|
|
17
|
+
* stessa architettura di un pattern noto (bloom.security, 28/8):
|
|
18
|
+
* un'origine/risposta separata, non un frammento incollato nella pagina
|
|
19
|
+
* principale.
|
|
20
|
+
*
|
|
21
|
+
* ⛔ Solo in memoria, stesso principio di session-registry.mjs
|
|
22
|
+
* (sessioni): non sopravvive a un riavvio del server — accettabile per
|
|
23
|
+
* uno strumento locale owner-only, dichiarato qui perché non diventi
|
|
24
|
+
* un'assunzione silenziosa.
|
|
25
|
+
*/
|
|
26
|
+
const artefatti = new Map();
|
|
27
|
+
|
|
28
|
+
export function salvaArtefatto(id, html) {
|
|
29
|
+
artefatti.set(id, html);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function leggiArtefatto(id) {
|
|
33
|
+
return artefatti.get(id) ?? null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Solo per i test: azzera lo store fra un test e l'altro (Map globale al modulo). */
|
|
37
|
+
export function svuotaArtefattiPerTest() {
|
|
38
|
+
artefatti.clear();
|
|
39
|
+
}
|