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.
- package/LICENSE +661 -0
- package/README.md +111 -3
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/archive/zip.js +73 -0
- package/dist/args.js +97 -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 +185 -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 +43 -0
- package/dist/i18n/en/common.js +9 -0
- package/dist/i18n/en/credentials.js +82 -0
- package/dist/i18n/en/errors.js +246 -0
- package/dist/i18n/en/firstrun.js +89 -0
- package/dist/i18n/en/providers.js +37 -0
- package/dist/i18n/en/screen.js +736 -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 +330 -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/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-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 +262 -0
- package/dist/runtime/talos-composition.js +1006 -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/app.js +3761 -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 +559 -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 +32 -0
- package/dist/tui/components/terminal-shell.js +205 -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/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 +139 -0
- package/dist/tui/line-diff.js +57 -0
- package/dist/tui/live-activity.js +45 -0
- package/dist/tui/metrics.js +123 -0
- package/dist/tui/onboarding.js +36 -0
- package/dist/tui/overlays/agent-tree.js +39 -0
- package/dist/tui/overlays/approval-dialog.js +640 -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 +72 -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 +145 -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 +287 -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 +778 -0
- package/dist/tui/session-export.js +54 -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 +80 -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 +25 -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 +63 -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,96 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const MAX_STATIC_BYTES = 4_194_304;
|
|
5
|
+
/** ⭐ Riconciliazione con la copia mobile (24/8) — vedi harness-ui-due-copie-divergenti.md: stessi 10 file .woff2, stesso font/weight/subset. */
|
|
6
|
+
const FONT_FILES = Object.freeze([
|
|
7
|
+
'instrument-sans-latin-ext-400-normal.woff2',
|
|
8
|
+
'instrument-sans-latin-400-normal.woff2',
|
|
9
|
+
'instrument-sans-latin-ext-500-normal.woff2',
|
|
10
|
+
'instrument-sans-latin-500-normal.woff2',
|
|
11
|
+
'instrument-sans-latin-ext-600-normal.woff2',
|
|
12
|
+
'instrument-sans-latin-600-normal.woff2',
|
|
13
|
+
'jetbrains-mono-latin-ext-400-normal.woff2',
|
|
14
|
+
'jetbrains-mono-latin-400-normal.woff2',
|
|
15
|
+
'jetbrains-mono-latin-ext-500-normal.woff2',
|
|
16
|
+
'jetbrains-mono-latin-500-normal.woff2',
|
|
17
|
+
]);
|
|
18
|
+
const STATIC_ASSETS = Object.freeze({
|
|
19
|
+
'/': { file: 'index.html', contentType: 'text/html; charset=utf-8' },
|
|
20
|
+
'/index.html': { file: 'index.html', contentType: 'text/html; charset=utf-8' },
|
|
21
|
+
'/styles.css': { file: 'styles.css', contentType: 'text/css; charset=utf-8' },
|
|
22
|
+
'/app.js': { file: 'app.js', contentType: 'text/javascript; charset=utf-8' },
|
|
23
|
+
/*
|
|
24
|
+
* ⭐⭐⭐ 11/09 — la schermata d'avvio. È un file a parte, e non un pezzo di `app.js`, perché deve
|
|
25
|
+
* arrivare PRIMA del primo disegno: `app.js` è il bundle grosso, cioè proprio il tempo che il
|
|
26
|
+
* velo esiste per coprire.
|
|
27
|
+
* ⛔ Senza questa riga il server risponde **404** e non lo dice a nessuno: il velo resta a schermo
|
|
28
|
+
* per sempre, e sotto c'è la app che nessuno può toccare. Trovato dal vivo, non da un test —
|
|
29
|
+
* la pagina non lanciava un solo errore.
|
|
30
|
+
* ⛔ Questa mappa è cablata apposta: `file` non si costruisce MAI dal `pathname` della richiesta
|
|
31
|
+
* (vedi la nota qui sotto su DEC-053), e una voce in più è il solo modo di aggiungere un asset.
|
|
32
|
+
*/
|
|
33
|
+
'/avvio.js': { file: 'avvio.js', contentType: 'text/javascript; charset=utf-8' },
|
|
34
|
+
/*
|
|
35
|
+
* ⭐⭐⭐ 26/8, DEC-053 — MAI PIÙ una copia locale sincronizzata a mano
|
|
36
|
+
* (harness-ui-due-copie-divergenti.md era esattamente questo difetto).
|
|
37
|
+
* publicDir ora È mobile/public/harness-ui/: `talos/brand/` è FRATELLO
|
|
38
|
+
* di `harness-ui/`, non figlio — `../` risale alla radice condivisa
|
|
39
|
+
* `mobile/public/` una volta sola, verso l'UNICO file reale che l'app
|
|
40
|
+
* mobile stessa monta a runtime. `file` qui è un valore CABLATO nel
|
|
41
|
+
* sorgente, mai costruito da `pathname` della richiesta: il `..` non
|
|
42
|
+
* apre un varco di traversal, sceglie solo quale asset fisso servire.
|
|
43
|
+
*/
|
|
44
|
+
'/talos/brand/logo-short.svg': { file: 'talos/brand/logo-short.svg', contentType: 'image/svg+xml' },
|
|
45
|
+
'/talos/browser-annota.js': { file: 'talos/browser-annota.js', contentType: 'text/javascript; charset=utf-8' }, // 06/9: l'overlay iniettato dal proxy
|
|
46
|
+
...Object.fromEntries(FONT_FILES.map((name) => [
|
|
47
|
+
`/fonts/${name}`,
|
|
48
|
+
{ file: `fonts/${name}`, contentType: 'font/woff2' },
|
|
49
|
+
])),
|
|
50
|
+
/*
|
|
51
|
+
* ⭐⭐⭐ 28/8 — Terminale REALE (LEDGER-TERMINALE-REALE.md): xterm.js
|
|
52
|
+
* vendorizzato (mai una CDN, stesso principio dei font sopra). Trovato
|
|
53
|
+
* dalla verifica dal vivo — senza queste tre righe la allowlist
|
|
54
|
+
* rispondeva 404 su tutti e tre i file e la UI mostrava onestamente
|
|
55
|
+
* "xterm.js non caricato" invece di fingersi connessa.
|
|
56
|
+
*/
|
|
57
|
+
'/vendor/xterm/xterm.js': { file: 'vendor/xterm/xterm.js', contentType: 'text/javascript; charset=utf-8' },
|
|
58
|
+
'/vendor/xterm/xterm.css': { file: 'vendor/xterm/xterm.css', contentType: 'text/css; charset=utf-8' },
|
|
59
|
+
'/vendor/xterm/addon-fit.js': { file: 'vendor/xterm/addon-fit.js', contentType: 'text/javascript; charset=utf-8' },
|
|
60
|
+
/** ⭐ 28/8 — renderer WebGL: la vista Terminale ha bisogno di questo per i colori ANSI, vedi il commento in montaTerminaleSeServe() (app.js) e vendor/xterm/README.md per il perché. */
|
|
61
|
+
'/vendor/xterm/addon-webgl.js': { file: 'vendor/xterm/addon-webgl.js', contentType: 'text/javascript; charset=utf-8' },
|
|
62
|
+
/**
|
|
63
|
+
* ⭐⭐⭐ 02/9 — formattatore dei blocchi di codice: Prism 1.30.0
|
|
64
|
+
* vendorizzato (core + 19 linguaggi in un file solo, vedi
|
|
65
|
+
* `vendor/prism/README.md`), stesso principio di xterm qui sopra — mai
|
|
66
|
+
* una CDN. ⛔ Questa riga NON è facoltativa: la allowlist è esplicita, e
|
|
67
|
+
* senza risponderebbe 404 lasciando ogni blocco senza evidenziazione —
|
|
68
|
+
* esattamente il difetto già pagato con xterm il 28/8, quattro righe più
|
|
69
|
+
* su, dove è costato una verifica dal vivo per accorgersene.
|
|
70
|
+
*/
|
|
71
|
+
'/vendor/prism/prism.js': { file: 'vendor/prism/prism.js', contentType: 'text/javascript; charset=utf-8' },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export function createStaticHandler(publicDir, fsAdapter = { readFile }) {
|
|
75
|
+
return async function staticHandler(pathname) {
|
|
76
|
+
const asset = STATIC_ASSETS[pathname];
|
|
77
|
+
if (!asset) return null;
|
|
78
|
+
let body;
|
|
79
|
+
try {
|
|
80
|
+
body = await fsAdapter.readFile(join(publicDir, asset.file));
|
|
81
|
+
} catch (error) {
|
|
82
|
+
// ⭐ 26/8 — un asset MAPPATO ma fisicamente assente (percorso di
|
|
83
|
+
// sviluppo diverso, TALOS_HARNESS_UI_PUBLIC_DIR di test senza la
|
|
84
|
+
// radice condivisa accanto) è un 404 onesto, non un 500 generico:
|
|
85
|
+
// la richiesta era legittima, manca solo il file.
|
|
86
|
+
if (error?.code === 'ENOENT') return null;
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
if (body.length > MAX_STATIC_BYTES) {
|
|
90
|
+
const error = new Error('Asset statico oltre limite');
|
|
91
|
+
error.code = 'PAYLOAD_LIMIT';
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
return { statusCode: 200, contentType: asset.contentType, body };
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Partitions provider text streams before they reach the UI. Provider
|
|
3
|
+
* delimiters are transport syntax, never user-visible assistant text.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const OPEN_TAGS = Object.freeze([
|
|
7
|
+
{ tag: '<think>', mode: 'reasoning' },
|
|
8
|
+
{ tag: '<thinking>', mode: 'reasoning' },
|
|
9
|
+
{ tag: '<tool_call>', mode: 'tool' },
|
|
10
|
+
{ tag: '<tool_call_start>', mode: 'tool' },
|
|
11
|
+
]);
|
|
12
|
+
const CLOSE_TAGS = Object.freeze([
|
|
13
|
+
'</think>',
|
|
14
|
+
'</thinking>',
|
|
15
|
+
'</tool_call>',
|
|
16
|
+
'<tool_call_end>',
|
|
17
|
+
]);
|
|
18
|
+
const MAX_TAG_LENGTH = Math.max(...OPEN_TAGS.map(({ tag }) => tag.length), ...CLOSE_TAGS.map((tag) => tag.length));
|
|
19
|
+
|
|
20
|
+
function partialTagLength(value, tags) {
|
|
21
|
+
const limit = Math.min(value.length, MAX_TAG_LENGTH - 1);
|
|
22
|
+
for (let length = limit; length > 0; length -= 1) {
|
|
23
|
+
const suffix = value.slice(-length);
|
|
24
|
+
if (tags.some((tag) => tag.startsWith(suffix))) return length;
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function emitText(callback, value) {
|
|
30
|
+
if (typeof value === 'string' && value !== '') callback(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function parseToolPayload(value) {
|
|
34
|
+
const raw = String(value ?? '').trim();
|
|
35
|
+
if (!raw) return { name: 'provider_tool', arguments: '{}' };
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(raw);
|
|
38
|
+
if (parsed && typeof parsed === 'object') {
|
|
39
|
+
const name = typeof parsed.name === 'string' && parsed.name.trim() ? parsed.name.trim()
|
|
40
|
+
: typeof parsed.tool === 'string' && parsed.tool.trim() ? parsed.tool.trim() : 'provider_tool';
|
|
41
|
+
const argumentsValue = Object.hasOwn(parsed, 'arguments') ? parsed.arguments
|
|
42
|
+
: Object.hasOwn(parsed, 'args') ? parsed.args : parsed;
|
|
43
|
+
return { ...(typeof parsed.id === 'string' && parsed.id ? { id: parsed.id } : {}), name, arguments: typeof argumentsValue === 'string' ? argumentsValue : JSON.stringify(argumentsValue ?? {}) };
|
|
44
|
+
}
|
|
45
|
+
} catch { /* alcuni provider usano una sintassi chiamata non-JSON: la conserviamo come argomento */ }
|
|
46
|
+
const call = /^\[?\s*([A-Za-z][\w.-]*)\s*\((.*)\)\s*\]?$/us.exec(raw);
|
|
47
|
+
if (call) return { name: call[1], arguments: call[2].trim() || '{}' };
|
|
48
|
+
return { name: 'provider_tool', arguments: raw };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createStreamPartitioner({ onText = () => {}, onReasoning = () => {}, onToolCall = () => {} } = {}) {
|
|
52
|
+
let buffer = '';
|
|
53
|
+
let mode = 'text';
|
|
54
|
+
let toolBuffer = '';
|
|
55
|
+
let finished = false;
|
|
56
|
+
|
|
57
|
+
const emitMode = (value) => {
|
|
58
|
+
if (mode === 'text') emitText(onText, value);
|
|
59
|
+
else if (mode === 'reasoning') emitText(onReasoning, value);
|
|
60
|
+
else if (mode === 'tool') toolBuffer += value;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const drain = (final = false) => {
|
|
64
|
+
while (buffer) {
|
|
65
|
+
if (mode === 'text') {
|
|
66
|
+
let found = null;
|
|
67
|
+
for (const candidate of OPEN_TAGS) {
|
|
68
|
+
const index = buffer.indexOf(candidate.tag);
|
|
69
|
+
if (index >= 0 && (!found || index < found.index)) found = { ...candidate, index };
|
|
70
|
+
}
|
|
71
|
+
if (!found) {
|
|
72
|
+
const keep = final ? 0 : partialTagLength(buffer, OPEN_TAGS.map(({ tag }) => tag));
|
|
73
|
+
const emitLength = Math.max(0, buffer.length - keep);
|
|
74
|
+
emitMode(buffer.slice(0, emitLength));
|
|
75
|
+
buffer = buffer.slice(emitLength);
|
|
76
|
+
if (!final && buffer.length) return;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
emitMode(buffer.slice(0, found.index));
|
|
80
|
+
buffer = buffer.slice(found.index + found.tag.length);
|
|
81
|
+
mode = found.mode;
|
|
82
|
+
toolBuffer = '';
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let close = null;
|
|
87
|
+
for (const tag of CLOSE_TAGS) {
|
|
88
|
+
const index = buffer.indexOf(tag);
|
|
89
|
+
if (index >= 0 && (!close || index < close.index)) close = { tag, index };
|
|
90
|
+
}
|
|
91
|
+
if (!close) {
|
|
92
|
+
const keep = final ? 0 : partialTagLength(buffer, CLOSE_TAGS);
|
|
93
|
+
const emitLength = Math.max(0, buffer.length - keep);
|
|
94
|
+
emitMode(buffer.slice(0, emitLength));
|
|
95
|
+
buffer = buffer.slice(emitLength);
|
|
96
|
+
if (!final && buffer.length) return;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
emitMode(buffer.slice(0, close.index));
|
|
100
|
+
buffer = buffer.slice(close.index + close.tag.length);
|
|
101
|
+
if (mode === 'tool') onToolCall(parseToolPayload(toolBuffer));
|
|
102
|
+
mode = 'text';
|
|
103
|
+
toolBuffer = '';
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const push = (chunk) => {
|
|
108
|
+
if (finished || chunk === null || chunk === undefined) return;
|
|
109
|
+
buffer += String(chunk);
|
|
110
|
+
drain(false);
|
|
111
|
+
};
|
|
112
|
+
const finish = () => {
|
|
113
|
+
if (finished) return;
|
|
114
|
+
finished = true;
|
|
115
|
+
drain(true);
|
|
116
|
+
if (mode === 'tool' && toolBuffer) onToolCall(parseToolPayload(toolBuffer));
|
|
117
|
+
toolBuffer = '';
|
|
118
|
+
mode = 'text';
|
|
119
|
+
};
|
|
120
|
+
return Object.freeze({ push, finish });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export { parseToolPayload };
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subagent-orchestrator.mjs — FASE C (sub-agenti), piano
|
|
3
|
+
* `elegant-spinning-dongarra.md`. Delega isolata verso una sessione
|
|
4
|
+
* figlia — un differenziatore diretto rispetto allo stato dell'arte
|
|
5
|
+
* (vincolo persistente dell'owner). Vedi `.claude/LEDGER-FASE-C-SUBAGENTI.md`
|
|
6
|
+
* per il ledger completo, il confronto competitivo e le decisioni
|
|
7
|
+
* prese in corso d'opera.
|
|
8
|
+
*
|
|
9
|
+
* ⛔ Zero registro proprio: opera sulla STESSA `Map` `sessioni` di
|
|
10
|
+
* `session-registry.mjs`, iniettata — mai una seconda fonte di verità
|
|
11
|
+
* su quali sessioni esistono.
|
|
12
|
+
*
|
|
13
|
+
* ⭐⭐⭐ I numeri sotto sono quelli VERI trovati in ricerca, letti da un
|
|
14
|
+
* repository open source dello stesso spazio clonato il 28/8 — non
|
|
15
|
+
* inventati, non presi da doc secondari (due correzioni fatte quel
|
|
16
|
+
* giorno su claim sbagliati di doc secondari, vedi il ledger): un
|
|
17
|
+
* tetto di 10 figli concorrenti di default, e una profondità massima
|
|
18
|
+
* di delega di 2, con la nota nel codice sorgente "for parity with the
|
|
19
|
+
* original MAX_DEPTH constant".
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Fonte: ricerca su un progetto open source dello stesso spazio, letto il 28/8. */
|
|
23
|
+
import { existsSync, statSync } from 'node:fs';
|
|
24
|
+
import { parse as parsePath } from 'node:path';
|
|
25
|
+
|
|
26
|
+
export const LIMITE_FIGLI_CONCORRENTI = 10;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Fonte: la stessa ricerca sopra. A differenza dell'approccio trovato
|
|
30
|
+
* (che non ha un tetto duro oltre il default, solo un avviso in log),
|
|
31
|
+
* questa prima fetta applica un tetto DURO — scelta più prudente
|
|
32
|
+
* finché non c'è una misura reale che dica se serve di più (stesso
|
|
33
|
+
* principio "si aggiunge quando serve" già in uso per `GIRI_MASSIMI`
|
|
34
|
+
* nel kernel).
|
|
35
|
+
*/
|
|
36
|
+
export const LIMITE_PROFONDITA_DELEGA = 2;
|
|
37
|
+
|
|
38
|
+
const TOOL_ERRORE_ESPLICITO = /^(?:\s*(?:error\b|exit\s+[1-9]\d*\b)|.*\b(?:ENOENT|no such file or directory|could not|unable to|failed to|not accessible|no file matches|non riesco|problema di configurazione)\b)/i;
|
|
39
|
+
const TASK_SCRITTURA_ESPLICITA = /\b(?:scriv\w*|modific\w*|aggiorn\w*|cre\w*|aggiung\w*|elimin\w*|rinomin\w*|implement\w*|write|modify|update|create|add|delete|rename|implement)\b/i;
|
|
40
|
+
|
|
41
|
+
/** Una richiesta esplicita di modifica richiede una prova di file/artefatto, non solo una risposta tool. */
|
|
42
|
+
export function taskRichiedeEvidenzaScrittura(task) {
|
|
43
|
+
const testo = typeof task === 'string' ? task : task?.consegna ?? task?.consegnaCorta ?? '';
|
|
44
|
+
return TASK_SCRITTURA_ESPLICITA.test(String(testo));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Riassume soltanto i segnali operativi già emessi dal figlio. Il testo
|
|
49
|
+
* finale del modello non è una prova di scrittura: una delega può dichiarare
|
|
50
|
+
* "fatto" anche quando ogni terminale ha risposto con un errore.
|
|
51
|
+
*
|
|
52
|
+
* @param {Array<object>|undefined|null} eventi
|
|
53
|
+
* @returns {{scritture:number, artefatti:number, toolCalls:number, toolCallsOk:number, toolCallsFalliti:number, verificabile:boolean}|null}
|
|
54
|
+
*/
|
|
55
|
+
export function analizzaEvidenzaDelega(eventi) {
|
|
56
|
+
if (!Array.isArray(eventi)) return null;
|
|
57
|
+
let scritture = 0;
|
|
58
|
+
let artefatti = 0;
|
|
59
|
+
let toolCalls = 0;
|
|
60
|
+
let toolCallsOk = 0;
|
|
61
|
+
let toolCallsFalliti = 0;
|
|
62
|
+
for (const evento of eventi) {
|
|
63
|
+
if (evento?.type === 'ArtifactCreated') artefatti += 1;
|
|
64
|
+
if (evento?.type === 'StateDelta') {
|
|
65
|
+
const delta = Array.isArray(evento.delta) ? evento.delta : [];
|
|
66
|
+
scritture += delta.filter((voce) => typeof voce?.path === 'string' && voce.path.startsWith('/file/')).length;
|
|
67
|
+
}
|
|
68
|
+
if (evento?.type !== 'ToolCallResult') continue;
|
|
69
|
+
toolCalls += 1;
|
|
70
|
+
if (TOOL_ERRORE_ESPLICITO.test(String(evento.content ?? ''))) toolCallsFalliti += 1;
|
|
71
|
+
else toolCallsOk += 1;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
scritture,
|
|
75
|
+
artefatti,
|
|
76
|
+
toolCalls,
|
|
77
|
+
toolCallsOk,
|
|
78
|
+
toolCallsFalliti,
|
|
79
|
+
verificabile: scritture > 0 || artefatti > 0 || toolCallsOk > 0,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function motivoEvidenzaMancante(evidenza, richiestaScrittura = false) {
|
|
84
|
+
const dettaglio = richiestaScrittura
|
|
85
|
+
? 'la richiesta prevedeva una modifica ma non risultano scritture o artefatti'
|
|
86
|
+
: `${evidenza.toolCallsFalliti} tool su ${evidenza.toolCalls} hanno fallito e non risultano scritture o artefatti`;
|
|
87
|
+
return `Il sotto-agente ha dichiarato successo, ma non ha lasciato evidenza verificabile: ${dettaglio}. Il lavoro non è considerato concluso.`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Traduce il risultato di `agent-service.avviaSessione` (il "risultato"
|
|
92
|
+
* catturato dentro il `.then()`/`.catch()` di `avviaESegui`) nella
|
|
93
|
+
* forma onesta che il kernel (`onDelega`) si aspetta — mai un successo
|
|
94
|
+
* inventato quando la figlia non ha concluso per davvero.
|
|
95
|
+
*
|
|
96
|
+
* @param {{ok?: boolean, esito?: object|null, erroreInterno?: string|null}|null} risultato
|
|
97
|
+
* @param {Array<object>|undefined|null} [eventi] eventi AG-UI persistiti dalla figlia
|
|
98
|
+
* @param {{task?:string|object}} [contesto] richiesta originale, per distinguere una lettura da una modifica
|
|
99
|
+
*/
|
|
100
|
+
export function esitoDelegaDaRisultato(risultato, eventi, contesto = {}) {
|
|
101
|
+
if (risultato?.ok) {
|
|
102
|
+
const evidenza = analizzaEvidenzaDelega(eventi);
|
|
103
|
+
const richiestaScrittura = taskRichiedeEvidenzaScrittura(contesto.task);
|
|
104
|
+
// Se il figlio ha ricevuto una richiesta di modifica, una risposta tool
|
|
105
|
+
// riuscita non dimostra che il file sia stato scritto: serve StateDelta o
|
|
106
|
+
// ArtifactCreated. Per richieste puramente informative resta sufficiente
|
|
107
|
+
// una tool-call riuscita; una delega senza tool conserva il contratto.
|
|
108
|
+
if (evidenza && evidenza.toolCalls > 0 && ((!evidenza.verificabile) || (richiestaScrittura && evidenza.scritture === 0 && evidenza.artefatti === 0))) {
|
|
109
|
+
return {
|
|
110
|
+
riassunto: risultato.esito?.detto || '(il sotto-agente non ha lasciato un riassunto testuale)',
|
|
111
|
+
esito: 'fallito',
|
|
112
|
+
motivo: motivoEvidenzaMancante(evidenza, richiestaScrittura),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
riassunto: risultato.esito?.detto || '(il sotto-agente non ha lasciato un riassunto testuale)',
|
|
117
|
+
esito: 'concluso',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (risultato?.esito) {
|
|
121
|
+
// giri-esauriti / fermato: la figlia ha girato, non ha chiuso il task.
|
|
122
|
+
return {
|
|
123
|
+
riassunto: risultato.esito.detto || `Il sotto-task non si è concluso (${risultato.esito.comeFinita}).`,
|
|
124
|
+
esito: 'fallito',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
// erroreInterno: avviaSessione dichiara di non lanciare mai, ma un ripiego onesto resta necessario (stesso principio già in uso nel .catch() di avviaESegui).
|
|
128
|
+
return { riassunto: null, esito: 'fallito', motivo: risultato?.erroreInterno ?? 'errore sconosciuto nella sessione figlia' };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Ricostruisce il verdetto di una figlia dopo il riavvio del server. */
|
|
132
|
+
export function esitoDelegaDaEventi(eventi, contesto = {}) {
|
|
133
|
+
if (!Array.isArray(eventi)) return null;
|
|
134
|
+
const terminale = [...eventi].reverse().find((evento) => evento?.type === 'RunFinished' || evento?.type === 'RunError');
|
|
135
|
+
if (!terminale) return null;
|
|
136
|
+
if (terminale.type === 'RunError') return 'fallito';
|
|
137
|
+
return esitoDelegaDaRisultato({ ok: true, esito: { detto: terminale.result?.detto ?? '', comeFinita: 'concluso' } }, eventi, contesto).esito;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {Map<string, object>} sessioni — la STESSA Map di session-registry.mjs.
|
|
142
|
+
* @param {Function} avviaESeguiFn — la funzione interna avviaESegui di session-registry.mjs, non una sua copia.
|
|
143
|
+
*/
|
|
144
|
+
/** Uno dei due controlli sul percorso che il kernel non può fare: esiste, ed è una cartella. */
|
|
145
|
+
export function esisteCartella(percorso, { esiste = existsSync, stato = statSync } = {}) {
|
|
146
|
+
const p = String(percorso || '');
|
|
147
|
+
if (!p.trim()) return false;
|
|
148
|
+
try { return esiste(p) && stato(p).isDirectory(); } catch { return false; }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* La FORMA di un percorso: come è ancorato, non dove porta. È la sola cosa che distingue
|
|
153
|
+
* «C:\progetto» da «/mnt/c/progetto» PRIMA di toccare il disco.
|
|
154
|
+
*
|
|
155
|
+
* ⛔⛔⛔ 13/09/2026 — MISURATO SU QUESTA MACCHINA (Windows 11, Node v24.18.0), non dedotto.
|
|
156
|
+
* `esisteCartella` da sola NON ferma un percorso di un altro sistema operativo, perché su
|
|
157
|
+
* Windows un percorso che comincia con `/` è ANCORATO ALL'UNITÀ CORRENTE, non rifiutato:
|
|
158
|
+
* esisteCartella('/tmp') → true (il disco risponde per C:\tmp)
|
|
159
|
+
* esisteCartella('/Users') → true (il disco risponde per C:\Users)
|
|
160
|
+
* esisteCartella('src') → true (relativo: risolto sulla cartella del SERVER, non su
|
|
161
|
+
* quella della madre — la figlia finirebbe in harness-ui)
|
|
162
|
+
* Cioè: tre forme storte ACCETTATE IN SILENZIO, e la figlia parte in una cartella che nessuno
|
|
163
|
+
* ha scelto. Le due che il difetto dell'08/09 nominava (`/mnt/c/…`, `/home/user/app`) venivano
|
|
164
|
+
* fermate solo per caso — perché `C:\mnt` e `C:\home` non esistono su QUESTA macchina.
|
|
165
|
+
*
|
|
166
|
+
* Fonte (documentazione ufficiale Node v24, modulo `path` e modulo `fs`, letta il 13/09/2026 via
|
|
167
|
+
* ctx7): `path.isAbsolute('//server')` e `path.isAbsolute('\\\\server')` sono `true` su Windows, e
|
|
168
|
+
* «On Windows, Node.js follows the concept of per-drive working directory» — cioè `isAbsolute` da
|
|
169
|
+
* solo NON distingue le due forme, mentre `path.parse().root` sì: `'/'` per un percorso ancorato
|
|
170
|
+
* alla sola radice, `'C:\'` per un'unità, `'\\server\share\'` per la rete, `''` per un relativo.
|
|
171
|
+
* ⛔ Ricerca web NON disponibile in questa sessione (budget esaurito, 200/200): la citazione è la
|
|
172
|
+
* documentazione ufficiale del runtime, che per questa domanda è la fonte primaria.
|
|
173
|
+
*
|
|
174
|
+
* @returns {'assente'|'relativo'|'radice-sola'|'unita'|'unita-senza-radice'|'rete'}
|
|
175
|
+
*/
|
|
176
|
+
export function formaDelPercorso(percorso) {
|
|
177
|
+
const p = String(percorso ?? '');
|
|
178
|
+
if (!p.trim()) return 'assente';
|
|
179
|
+
const radice = parsePath(p).root;
|
|
180
|
+
if (radice === '') return 'relativo';
|
|
181
|
+
if (/^[A-Za-z]:$/u.test(radice)) return 'unita-senza-radice'; // «C:progetto»: relativo alla cartella corrente DI QUELL'UNITÀ
|
|
182
|
+
if (/^[A-Za-z]:[\\/]$/u.test(radice)) return 'unita';
|
|
183
|
+
if (radice === '/' || radice === '\\') return 'radice-sola';
|
|
184
|
+
return 'rete';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Il percorso che il MODELLO ha proposto per la figlia è utilizzabile su questo computer?
|
|
189
|
+
*
|
|
190
|
+
* ⛔ La misura NON è «assomiglia a Windows»: è «ha la STESSA FORMA della cartella in cui la madre
|
|
191
|
+
* sta già lavorando». Quella cartella l'ha scelta una persona ed è vera per costruzione, quindi
|
|
192
|
+
* è il metro giusto — e si tara da sé, senza una riga che nomini un sistema operativo. Il kernel
|
|
193
|
+
* non può farlo: non sa in che forma è il disco (`talosHarness.mjs`, `delega_sottotask`, che per
|
|
194
|
+
* questo delega il no a `onDelega`).
|
|
195
|
+
*
|
|
196
|
+
* ⛔ Percorso assente ⇒ nessun giudizio: si lavora dove lavora la madre, ed è il caso NORMALE
|
|
197
|
+
* (stato dell'arte letto il 06/09/2026: i sotto-agenti condividono la cartella del padre).
|
|
198
|
+
*
|
|
199
|
+
* @returns {{ok:true}|{ok:false, motivo:string}} mai un'eccezione: un rifiuto è un esito.
|
|
200
|
+
*/
|
|
201
|
+
export function percorsoDellaFigliaUsabile(proposto, cartellaMadre) {
|
|
202
|
+
const forma = formaDelPercorso(proposto);
|
|
203
|
+
if (forma === 'assente') return { ok: true };
|
|
204
|
+
const formaMadre = formaDelPercorso(cartellaMadre);
|
|
205
|
+
if (forma === formaMadre) return { ok: true };
|
|
206
|
+
/*
|
|
207
|
+
* ⛔ Il motivo PORTA la cartella giusta, scritta per esteso. Un rifiuto che dice solo «no»
|
|
208
|
+
* lascia il modello a indovinare, ed è esattamente così che sono morte tre deleghe di fila:
|
|
209
|
+
* vedeva un REFUSED, inventava un'altra forma, ne vedeva un altro. Chi rifiuta e conosce la
|
|
210
|
+
* risposta la dice.
|
|
211
|
+
*/
|
|
212
|
+
const spiegazione = forma === 'relativo' || forma === 'unita-senza-radice'
|
|
213
|
+
? `la cartella «${proposto}» non è un percorso assoluto`
|
|
214
|
+
: `la cartella «${proposto}» è scritta nella forma di un altro sistema operativo`;
|
|
215
|
+
if (formaMadre === 'assente') {
|
|
216
|
+
return { ok: false, motivo: `${spiegazione}. Ometti la cartella per lavorare dove lavora chi ti ha delegato.` };
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
ok: false,
|
|
220
|
+
motivo: `${spiegazione}: su questo computer i percorsi si scrivono come «${cartellaMadre}». `
|
|
221
|
+
+ `Ometti la cartella per lavorare dove lavora chi ti ha delegato, oppure usa esattamente «${cartellaMadre}».`,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/*
|
|
226
|
+
* `cartellaEsisteFn` si inietta: le prove costruiscono sessioni con cartelle che sul disco non
|
|
227
|
+
* esistono, e il controllo vero (quello che ferma un percorso in forma WSL) resta acceso in produzione.
|
|
228
|
+
*/
|
|
229
|
+
/**
|
|
230
|
+
* Il COMPITO dentro il prompt che il kernel costruisce per una figlia.
|
|
231
|
+
* ⛔ `Compito:` è il marcatore del kernel dell'owner (`mobile/scripts/harness-talos`), che non è di questa
|
|
232
|
+
* lane: se un giorno cambia, il nome torna a essere il preambolo — brutto e visibile, mai un silenzio.
|
|
233
|
+
* Senza marcatore si restituisce la stringa intera: non si indovina dove finisce un preambolo che non c'è.
|
|
234
|
+
*/
|
|
235
|
+
export function compitoDaPromptDiDelega(prompt) {
|
|
236
|
+
const testo = typeof prompt === 'string' ? prompt : prompt?.consegna ?? '';
|
|
237
|
+
const marcatore = new RegExp(String.raw`(?:^|[.` + String.fromCharCode(10) + String.raw`])\s*Compito\s*:\s*`, 'u').exec(testo);
|
|
238
|
+
if (!marcatore) return testo;
|
|
239
|
+
const dopo = testo.slice(marcatore.index + marcatore[0].length).trim();
|
|
240
|
+
return dopo || testo;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function creaSubagentOrchestrator({ sessioni, avviaESeguiFn, cartellaEsisteFn = esisteCartella }) {
|
|
244
|
+
function contaFigliAttivi(sessionPadreId) {
|
|
245
|
+
let n = 0;
|
|
246
|
+
for (const voce of sessioni.values()) {
|
|
247
|
+
if (voce.padreId === sessionPadreId && !voce.conclusa) n += 1;
|
|
248
|
+
}
|
|
249
|
+
return n;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Per il foglio "Albero sessione" (C.3) — ordinati per avvio, il più vecchio prima. */
|
|
253
|
+
function elencaFigli(sessionPadreId) {
|
|
254
|
+
const figli = [];
|
|
255
|
+
for (const [sessionId, voce] of sessioni.entries()) {
|
|
256
|
+
if (voce.padreId === sessionPadreId) {
|
|
257
|
+
figli.push({
|
|
258
|
+
sessionId,
|
|
259
|
+
task: voce.task?.consegna ?? null,
|
|
260
|
+
/*
|
|
261
|
+
* ⛔ 09/09, visto nella FOTO della scheda «Agenti» dopo il giro vero della delega (D2): le due
|
|
262
|
+
* schede si chiamavano ENTRAMBE «Sei una sessione di lavoro autonoma; non hai altro …», cioè
|
|
263
|
+
* il preambolo del kernel, che è identico per ogni figlia. La barra era già stata curata poche
|
|
264
|
+
* ore prima; qui no, perché la scheda legge QUESTA funzione e non `elenca()`. Stesso difetto,
|
|
265
|
+
* secondo consumatore — la cura non si copia, si espone il dato una volta sola.
|
|
266
|
+
* ⛔ `task` resta la consegna INTERA: il foglio «Albero sessione» la mostra per esteso, e
|
|
267
|
+
* togliere informazione a un consumatore per aggiustarne un altro è esattamente il modo di
|
|
268
|
+
* rifare il giro fra un mese. Il nome corto viaggia accanto.
|
|
269
|
+
*/
|
|
270
|
+
taskCorto: voce.task?.consegnaCorta ?? (voce.task?.consegna ? compitoDaPromptDiDelega(voce.task.consegna) : null),
|
|
271
|
+
/*
|
|
272
|
+
* ⛔ D3 — i file che QUESTA figlia ha scritto e che anche un'altra sorella ha toccato. La
|
|
273
|
+
* lista sta sulla madre (il registro la scrive mentre gli eventi passano); qui esce filtrata
|
|
274
|
+
* per la figlia, perché la scheda «Agenti» parla di una delega alla volta. Vuota quasi
|
|
275
|
+
* sempre: se non lo è, due deleghe si sono pestate i piedi e va detto.
|
|
276
|
+
*/
|
|
277
|
+
collisioni: (sessioni.get(voce.padreId)?.collisioniDiScrittura ?? [])
|
|
278
|
+
.filter((c) => c.prima === sessionId || c.poi === sessionId)
|
|
279
|
+
.map((c) => ({ percorso: c.percorso, primaDi: c.prima === sessionId ? null : c.prima, dopoDi: c.poi === sessionId ? null : c.poi })),
|
|
280
|
+
conclusa: voce.conclusa,
|
|
281
|
+
/*
|
|
282
|
+
* ⛔ 06/9, T05-D3 un piano più sotto: senza questo campo un sotto-agente ucciso dalla
|
|
283
|
+
* morte del processo restava «In corso» per sempre nella scheda Agenti e nel foglio
|
|
284
|
+
* dell'albero — e il frontend non aveva NIENTE con cui dire il vero, perché il dato
|
|
285
|
+
* non usciva da qui. Il registro la conosce (`interrotta: !conclusa` al ripristino).
|
|
286
|
+
*/
|
|
287
|
+
interrotta: voce.interrotta === true,
|
|
288
|
+
esitoDelega: voce.esitoDelega ?? null,
|
|
289
|
+
evidenzaDelega: voce.evidenzaDelega ?? null,
|
|
290
|
+
avviataAlle: voce.avviataAlle ?? null,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
figli.sort((a, b) => String(a.avviataAlle).localeCompare(String(b.avviataAlle)));
|
|
295
|
+
return figli;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* @returns {Promise<{riassunto?: string, esito: 'concluso'|'fallito'|'rifiutato', motivo?: string}>}
|
|
300
|
+
* Non lancia MAI — un rifiuto (cartella invalida, tetto raggiunto,
|
|
301
|
+
* padre scomparso) è un `esito:'rifiutato'` con `motivo`, non
|
|
302
|
+
* un'eccezione: il dispatcher del kernel lo traduce in un REFUSED
|
|
303
|
+
* onesto per il modello, stessa disciplina di ogni altro cancello.
|
|
304
|
+
*/
|
|
305
|
+
function delegaSottoTask({ sessionPadreId, task, cartella }) {
|
|
306
|
+
return new Promise((resolve) => {
|
|
307
|
+
const padre = sessioni.get(sessionPadreId);
|
|
308
|
+
if (!padre) {
|
|
309
|
+
resolve({ esito: 'rifiutato', motivo: 'la sessione padre non esiste più' });
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
/*
|
|
313
|
+
* ⛔⛔⛔ 06/9 — questa guardia diceva «la cartella della delega deve essere diversa da quella
|
|
314
|
+
* del padre», e insieme alla gemella nel kernel produceva il difetto misurato dal vivo: un
|
|
315
|
+
* giro con UNA delega, quattro sessioni figlie, otto giri, 76,8k token, tutte fallite. Il
|
|
316
|
+
* modello vedeva un rifiuto sul caso normale — delegare un pezzo dello STESSO progetto — e
|
|
317
|
+
* aggirava riscrivendo il percorso in forma WSL (`/mnt/c/…`), che qui passava e su Windows
|
|
318
|
+
* non esiste: il figlio partiva con una cartella inesistente e moriva.
|
|
319
|
+
* Stato dell'arte (letto 06/09/2026): per difetto i
|
|
320
|
+
* sotto-agenti CONDIVIDONO la cartella del padre; l'isolamento vero, quando serve, si fa con
|
|
321
|
+
* un worktree, non con una cartella diversa a caso.
|
|
322
|
+
* ⇒ Restano DUE controlli, quelli che il kernel non può fare: la FORMA del percorso e la sua
|
|
323
|
+
* ESISTENZA.
|
|
324
|
+
* ⛔⛔ 13/09/2026 — la seconda metà di questa cura MANCAVA, e il difetto è misurato nella doc
|
|
325
|
+
* di `formaDelPercorso`: su Windows `/tmp`, `/Users` e `src` passavano `esisteCartella`
|
|
326
|
+
* (rispettivamente `C:\tmp`, `C:\Users` e la cartella del SERVER) e la figlia partiva in
|
|
327
|
+
* una cartella che nessuno aveva scelto. `/mnt/c/…` veniva fermato solo perché `C:\mnt`
|
|
328
|
+
* non esiste QUI: una guardia che dipende da quali cartelle ha la macchina non è una
|
|
329
|
+
* guardia. La forma si controlla PRIMA del disco, e il rifiuto dice quale sia la giusta.
|
|
330
|
+
*/
|
|
331
|
+
const proposta = typeof cartella === 'string' && cartella.trim() !== '' ? cartella : null;
|
|
332
|
+
const dove = proposta ?? padre.cartella;
|
|
333
|
+
const forma = percorsoDellaFigliaUsabile(proposta, padre.cartella);
|
|
334
|
+
if (!forma.ok) {
|
|
335
|
+
resolve({ esito: 'rifiutato', motivo: forma.motivo });
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (!cartellaEsisteFn(dove)) {
|
|
339
|
+
/* ⛔ Anche qui il motivo porta la cartella della madre — tranne quando è LEI a non esistere:
|
|
340
|
+
consigliare la cartella che ha appena fallito sarebbe un consiglio falso. */
|
|
341
|
+
/* ⛔⛔ 13/09/2026, revisione avversariale: il commento qui sopra prometteva questo, il
|
|
342
|
+
codice NON lo faceva. `dove === padre.cartella` riconosce solo il caso in cui il modello
|
|
343
|
+
RIPETE la cartella della madre; se ne propone un'altra e la cartella della madre nel
|
|
344
|
+
frattempo è sparita (cancellata a sessione viva), il rifiuto consigliava una cartella
|
|
345
|
+
inesistente — il consiglio falso che la riga sopra dice di evitare. Ora la condizione è
|
|
346
|
+
quella dichiarata: si consiglia solo una cartella che il disco conferma. */
|
|
347
|
+
const madreConsigliabile = dove !== padre.cartella && cartellaEsisteFn(padre.cartella);
|
|
348
|
+
const invece = madreConsigliabile
|
|
349
|
+
? ` Ometti la cartella per lavorare dove lavora chi ti ha delegato, oppure usa esattamente «${padre.cartella}».`
|
|
350
|
+
: '';
|
|
351
|
+
resolve({ esito: 'rifiutato', motivo: `la cartella ${dove} non esiste su questo computer.${invece}` });
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const profonditaVoluta = (padre.profonditaDelega ?? 0) + 1;
|
|
355
|
+
if (profonditaVoluta > LIMITE_PROFONDITA_DELEGA) {
|
|
356
|
+
resolve({ esito: 'rifiutato', motivo: `profondità di delega massima raggiunta (limite ${LIMITE_PROFONDITA_DELEGA})` });
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (contaFigliAttivi(sessionPadreId) >= LIMITE_FIGLI_CONCORRENTI) {
|
|
360
|
+
resolve({ esito: 'rifiutato', motivo: `limite di ${LIMITE_FIGLI_CONCORRENTI} figli concorrenti raggiunto` });
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
let figlioId = null;
|
|
364
|
+
let conclusioneRicevuta = null;
|
|
365
|
+
let conclusioneGestita = false;
|
|
366
|
+
const completaConclusione = (risultatoSessione) => {
|
|
367
|
+
if (conclusioneGestita) return;
|
|
368
|
+
if (!figlioId) {
|
|
369
|
+
conclusioneRicevuta = risultatoSessione;
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
conclusioneGestita = true;
|
|
373
|
+
const voceFiglia = sessioni.get(figlioId);
|
|
374
|
+
const eventi = voceFiglia?.eventi;
|
|
375
|
+
const esito = esitoDelegaDaRisultato(risultatoSessione, eventi, { task });
|
|
376
|
+
if (voceFiglia) {
|
|
377
|
+
voceFiglia.esitoDelega = esito.esito;
|
|
378
|
+
voceFiglia.evidenzaDelega = analizzaEvidenzaDelega(eventi);
|
|
379
|
+
}
|
|
380
|
+
resolve(esito);
|
|
381
|
+
};
|
|
382
|
+
/*
|
|
383
|
+
* ⛔⛔⛔ 06/9, stessa misura: i figli partivano con `glm-4.7-flash` mentre la sessione madre
|
|
384
|
+
* aveva scelto `glm-5.3-flash`, e nessuna riga a schermo lo diceva. Un sotto-agente eredita
|
|
385
|
+
* gli strumenti del padre (stesso principio trovato in ricerca: i sotto-agenti ereditano
|
|
386
|
+
* gli strumenti abilitati del padre); a
|
|
387
|
+
* maggior ragione deve ereditare il MODELLO, altrimenti chi paga non sa cosa sta pagando.
|
|
388
|
+
* Si eredita anche lo sforzo di ragionamento e i permessi: il figlio non è più libero del padre.
|
|
389
|
+
*/
|
|
390
|
+
const risultatoAvvio = avviaESeguiFn({
|
|
391
|
+
taskId: `delega:${sessionPadreId}`,
|
|
392
|
+
cartella: dove,
|
|
393
|
+
/*
|
|
394
|
+
* ⛔⛔⛔ 08/09/2026 — SENZA QUESTA RIGA LA FIGLIA LAVORA IN `C:\`, LA RADICE DEL DISCO.
|
|
395
|
+
*
|
|
396
|
+
* Misurato sulla run vera dell'owner (tre sessioni in `.sessions-store/`): l'intestazione
|
|
397
|
+
* della figlia porta la cartella giusta, e il `contesto` di `RunStarted` porta `C:\`. La
|
|
398
|
+
* cartella corretta viene passata qui, scritta su disco, e allargata un istante dopo da
|
|
399
|
+
* `cartellaEffettivaPerPermessi` (session-registry), che senza `cartellaGiaScelta` traduce
|
|
400
|
+
* «Full access» in `parsePath(cartella).root`. La figlia eredita Full access dalla madre —
|
|
401
|
+
* ed è giusto che lo erediti — quindi finiva nella radice.
|
|
402
|
+
*
|
|
403
|
+
* ⇒ Il difetto non è l'eredità dei permessi: è che una FIGLIA NON HA NIENTE DA CUI
|
|
404
|
+
* ALLARGARSI. La sua cartella è per definizione esattamente quella della madre, già
|
|
405
|
+
* scelta da una persona. È il caso (d) della famiglia documentata sopra
|
|
406
|
+
* `cartellaEffettivaPerPermessi` (a: allowlist — l'unico che deve allargare; b:
|
|
407
|
+
* avviaLibero, curato 03/9; c: avvia() dei task di catalogo, curato 04/9): la delega non
|
|
408
|
+
* era mai stata considerata.
|
|
409
|
+
*
|
|
410
|
+
* Il danno misurato prima della cura, su 37 chiamate delle due figlie: `scrivi` →
|
|
411
|
+
* `EPERM mkdir 'C:\'`; `document_create` → sei tentativi tutti EPERM; `leggi package.json`
|
|
412
|
+
* → `ENOENT 'C:\package.json'`. Zero file scritti nel workspace, e la delega ha consegnato
|
|
413
|
+
* un artefatto al posto del documento chiesto senza che nessuno protestasse.
|
|
414
|
+
*
|
|
415
|
+
* Ricerca 08/09/2026 — dev.to «Giving an AI agent permission to spawn sub-agents (without
|
|
416
|
+
* losing control)»: il wrapper della delega «resolves the workspace **against the parent's
|
|
417
|
+
* root**», e l'eredità dev'essere «explicit and **downgraded by default**: parent can
|
|
418
|
+
* delegate only permissions it actually has» — «if every subagent inherits the parent
|
|
419
|
+
* token, it recreates sudo with better branding». Qui la cartella è la prima delega da
|
|
420
|
+
* restringere.
|
|
421
|
+
*/
|
|
422
|
+
cartellaGiaScelta: true,
|
|
423
|
+
/*
|
|
424
|
+
* ⛔ 09/09/2026 — trovato dal giro vero sul 4174: nella barra e nella scheda «Agenti» le due figlie
|
|
425
|
+
* si chiamavano entrambe «Sei una sessione di lavoro autonoma; non hai altro …». Il kernel non
|
|
426
|
+
* passa il compito nudo: passa il PROMPT INTERO della figlia (825 caratteri, letti dal JSONL),
|
|
427
|
+
* che comincia con un preambolo di sistema e mette il compito dopo «Compito:». Chi legge la barra
|
|
428
|
+
* vedeva due righe identiche e doveva aprirle per sapere quale fosse quale.
|
|
429
|
+
* ⇒ La forma corta si costruisce QUI, dove si sa che quella stringa è il prompt di una delega:
|
|
430
|
+
* `session-registry` non può saperlo, e il kernel dell'owner non è mio.
|
|
431
|
+
*/
|
|
432
|
+
task: { consegna: task, consegnaCorta: compitoDaPromptDiDelega(task) },
|
|
433
|
+
padreId: sessionPadreId,
|
|
434
|
+
profonditaDelega: profonditaVoluta,
|
|
435
|
+
modelloRichiesta: padre.modello ?? null,
|
|
436
|
+
reasoningRichiesto: padre.reasoning ?? null,
|
|
437
|
+
permessiRichiesti: padre.permessi ?? null,
|
|
438
|
+
permessiPerAttrezzoRichiesti: padre.permessiPerAttrezzo ?? null,
|
|
439
|
+
onConclusioneFn: (risultatoSessione) => {
|
|
440
|
+
completaConclusione(risultatoSessione);
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
figlioId = risultatoAvvio?.sessionId ?? null;
|
|
444
|
+
if (conclusioneRicevuta) completaConclusione(conclusioneRicevuta);
|
|
445
|
+
// ⛔ AL CONTRARIO: avviaESeguiFn può rifiutare PRIMA di avviare (es. chiave API non configurata) — mai una Promise appesa in eterno se onConclusioneFn non scatterà mai.
|
|
446
|
+
if (!conclusioneGestita && !conclusioneRicevuta && risultatoAvvio?.erroreAvvio) {
|
|
447
|
+
resolve({ esito: 'rifiutato', motivo: risultatoAvvio.erroreAvvio });
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return Object.freeze({ delegaSottoTask, contaFigliAttivi, elencaFigli });
|
|
453
|
+
}
|