@vascend/talos 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/README.md +202 -0
- package/dist/backend/asset-events.d.ts +31 -0
- package/dist/backend/asset-events.js +149 -0
- package/dist/backend/assets.d.ts +31 -0
- package/dist/backend/assets.js +210 -0
- package/dist/backend/auth.d.ts +18 -0
- package/dist/backend/auth.js +59 -0
- package/dist/backend/config.d.ts +14 -0
- package/dist/backend/config.js +41 -0
- package/dist/backend/conversations.d.ts +21 -0
- package/dist/backend/conversations.js +141 -0
- package/dist/backend/crypto.d.ts +9 -0
- package/dist/backend/crypto.js +68 -0
- package/dist/backend/engine.d.ts +13 -0
- package/dist/backend/engine.js +78 -0
- package/dist/backend/http.d.ts +25 -0
- package/dist/backend/http.js +112 -0
- package/dist/backend/index.d.ts +1 -0
- package/dist/backend/index.js +24 -0
- package/dist/backend/routes.d.ts +14 -0
- package/dist/backend/routes.js +169 -0
- package/dist/backend/sdk.d.ts +12 -0
- package/dist/backend/sdk.js +11 -0
- package/dist/backend/server.d.ts +12 -0
- package/dist/backend/server.js +91 -0
- package/dist/backend/temp-image-store.d.ts +46 -0
- package/dist/backend/temp-image-store.js +197 -0
- package/dist/backend/types.d.ts +103 -0
- package/dist/backend/types.js +29 -0
- package/dist/backend/users.d.ts +13 -0
- package/dist/backend/users.js +76 -0
- package/dist/backend/ws-handler.d.ts +14 -0
- package/dist/backend/ws-handler.js +72 -0
- package/dist/backend/ws.d.ts +19 -0
- package/dist/backend/ws.js +146 -0
- package/dist/core/agent.d.ts +56 -0
- package/dist/core/agent.js +1783 -0
- package/dist/core/background.d.ts +45 -0
- package/dist/core/background.js +140 -0
- package/dist/core/bootstrap.d.ts +45 -0
- package/dist/core/bootstrap.js +294 -0
- package/dist/core/cli-args.d.ts +41 -0
- package/dist/core/cli-args.js +282 -0
- package/dist/core/collapsible-output.d.ts +38 -0
- package/dist/core/collapsible-output.js +143 -0
- package/dist/core/compaction-checkpoint.d.ts +9 -0
- package/dist/core/compaction-checkpoint.js +58 -0
- package/dist/core/compaction.d.ts +42 -0
- package/dist/core/compaction.js +270 -0
- package/dist/core/config.d.ts +49 -0
- package/dist/core/config.js +417 -0
- package/dist/core/context-ledger.d.ts +99 -0
- package/dist/core/context-ledger.js +222 -0
- package/dist/core/context-policy.d.ts +17 -0
- package/dist/core/context-policy.js +81 -0
- package/dist/core/continuation-review.d.ts +23 -0
- package/dist/core/continuation-review.js +64 -0
- package/dist/core/crash-report.d.ts +3 -0
- package/dist/core/crash-report.js +27 -0
- package/dist/core/credentials.d.ts +11 -0
- package/dist/core/credentials.js +183 -0
- package/dist/core/doctor.d.ts +24 -0
- package/dist/core/doctor.js +125 -0
- package/dist/core/effort.d.ts +5 -0
- package/dist/core/effort.js +42 -0
- package/dist/core/env-paths.d.ts +3 -0
- package/dist/core/env-paths.js +38 -0
- package/dist/core/execution-guidance.d.ts +9 -0
- package/dist/core/execution-guidance.js +73 -0
- package/dist/core/execution-target.d.ts +41 -0
- package/dist/core/execution-target.js +69 -0
- package/dist/core/file-coordination.d.ts +66 -0
- package/dist/core/file-coordination.js +176 -0
- package/dist/core/file-lease-store.d.ts +14 -0
- package/dist/core/file-lease-store.js +89 -0
- package/dist/core/image-limits.d.ts +26 -0
- package/dist/core/image-limits.js +205 -0
- package/dist/core/interruptible-completion.d.ts +3 -0
- package/dist/core/interruptible-completion.js +42 -0
- package/dist/core/kingdoms-mode-state.d.ts +24 -0
- package/dist/core/kingdoms-mode-state.js +139 -0
- package/dist/core/licenza.d.ts +38 -0
- package/dist/core/licenza.js +125 -0
- package/dist/core/model-limits.d.ts +2 -0
- package/dist/core/model-limits.js +36 -0
- package/dist/core/output-lifecycle.d.ts +44 -0
- package/dist/core/output-lifecycle.js +190 -0
- package/dist/core/package-update.d.ts +15 -0
- package/dist/core/package-update.js +121 -0
- package/dist/core/permission-queue.d.ts +2 -0
- package/dist/core/permission-queue.js +20 -0
- package/dist/core/prompt-attachment.d.ts +21 -0
- package/dist/core/prompt-attachment.js +123 -0
- package/dist/core/request-plan.d.ts +16 -0
- package/dist/core/request-plan.js +36 -0
- package/dist/core/run-timing.d.ts +17 -0
- package/dist/core/run-timing.js +123 -0
- package/dist/core/self-update.d.ts +17 -0
- package/dist/core/self-update.js +54 -0
- package/dist/core/session-refs.d.ts +27 -0
- package/dist/core/session-refs.js +126 -0
- package/dist/core/session-storage.d.ts +4 -0
- package/dist/core/session-storage.js +48 -0
- package/dist/core/session-title.d.ts +1 -0
- package/dist/core/session-title.js +21 -0
- package/dist/core/session-usage.d.ts +17 -0
- package/dist/core/session-usage.js +74 -0
- package/dist/core/session.d.ts +58 -0
- package/dist/core/session.js +296 -0
- package/dist/core/settings.d.ts +17 -0
- package/dist/core/settings.js +107 -0
- package/dist/core/storage-retention.d.ts +21 -0
- package/dist/core/storage-retention.js +227 -0
- package/dist/core/text-sanitize.d.ts +1 -0
- package/dist/core/text-sanitize.js +35 -0
- package/dist/core/tool-artifacts.d.ts +6 -0
- package/dist/core/tool-artifacts.js +51 -0
- package/dist/core/tool-compress.d.ts +8 -0
- package/dist/core/tool-compress.js +111 -0
- package/dist/core/tool-executor.d.ts +16 -0
- package/dist/core/tool-executor.js +97 -0
- package/dist/core/tool-result-index.d.ts +52 -0
- package/dist/core/tool-result-index.js +327 -0
- package/dist/core/tool-result-store.d.ts +38 -0
- package/dist/core/tool-result-store.js +190 -0
- package/dist/core/tool-scheduler.d.ts +16 -0
- package/dist/core/tool-scheduler.js +35 -0
- package/dist/core/trust.d.ts +21 -0
- package/dist/core/trust.js +95 -0
- package/dist/core/types.d.ts +402 -0
- package/dist/core/types.js +1 -0
- package/dist/core/update-check.d.ts +26 -0
- package/dist/core/update-check.js +89 -0
- package/dist/core/update-process.d.ts +10 -0
- package/dist/core/update-process.js +31 -0
- package/dist/core/user-inbox.d.ts +23 -0
- package/dist/core/user-inbox.js +56 -0
- package/dist/core/user-input.d.ts +10 -0
- package/dist/core/user-input.js +35 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/version.js +10 -0
- package/dist/core/vibe-modes.d.ts +38 -0
- package/dist/core/vibe-modes.js +383 -0
- package/dist/core/workspace-roots.d.ts +13 -0
- package/dist/core/workspace-roots.js +91 -0
- package/dist/core/workspace-sessions.d.ts +51 -0
- package/dist/core/workspace-sessions.js +243 -0
- package/dist/cowork/client.d.ts +29 -0
- package/dist/cowork/client.js +49 -0
- package/dist/cowork/engine-bridge.d.ts +22 -0
- package/dist/cowork/engine-bridge.js +98 -0
- package/dist/cowork/index.d.ts +11 -0
- package/dist/cowork/index.js +16 -0
- package/dist/cowork/ipc.d.ts +97 -0
- package/dist/cowork/ipc.js +96 -0
- package/dist/cowork/manager.d.ts +66 -0
- package/dist/cowork/manager.js +325 -0
- package/dist/cowork/store.d.ts +23 -0
- package/dist/cowork/store.js +182 -0
- package/dist/cowork/sync.d.ts +20 -0
- package/dist/cowork/sync.js +164 -0
- package/dist/cowork/types.d.ts +78 -0
- package/dist/cowork/types.js +21 -0
- package/dist/extensions/ext-tools.d.ts +3 -0
- package/dist/extensions/ext-tools.js +73 -0
- package/dist/extensions/loader.d.ts +91 -0
- package/dist/extensions/loader.js +474 -0
- package/dist/extensions/settings.d.ts +20 -0
- package/dist/extensions/settings.js +86 -0
- package/dist/extensions/types.d.ts +219 -0
- package/dist/extensions/types.js +1 -0
- package/dist/horizon/async-queue.d.ts +9 -0
- package/dist/horizon/async-queue.js +46 -0
- package/dist/horizon/engine.d.ts +85 -0
- package/dist/horizon/engine.js +603 -0
- package/dist/horizon/index.d.ts +4 -0
- package/dist/horizon/index.js +2 -0
- package/dist/horizon/main-team.d.ts +163 -0
- package/dist/horizon/main-team.js +774 -0
- package/dist/horizon/types.d.ts +233 -0
- package/dist/horizon/types.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +233 -0
- package/dist/mcp/protocol.d.ts +81 -0
- package/dist/mcp/protocol.js +122 -0
- package/dist/package.json +1 -0
- package/dist/packages/packages.d.ts +12 -0
- package/dist/packages/packages.js +323 -0
- package/dist/prompts/templates.d.ts +13 -0
- package/dist/prompts/templates.js +139 -0
- package/dist/providers/anthropic-oauth.d.ts +13 -0
- package/dist/providers/anthropic-oauth.js +124 -0
- package/dist/providers/anthropic.d.ts +27 -0
- package/dist/providers/anthropic.js +526 -0
- package/dist/providers/catalog.d.ts +15 -0
- package/dist/providers/catalog.js +166 -0
- package/dist/providers/effort.d.ts +12 -0
- package/dist/providers/effort.js +102 -0
- package/dist/providers/model-catalog.d.ts +43 -0
- package/dist/providers/model-catalog.js +70 -0
- package/dist/providers/model-effort.d.ts +5 -0
- package/dist/providers/model-effort.js +43 -0
- package/dist/providers/model-registry.d.ts +39 -0
- package/dist/providers/model-registry.js +142 -0
- package/dist/providers/models-dev.d.ts +9 -0
- package/dist/providers/models-dev.js +97 -0
- package/dist/providers/oauth-callback-server.d.ts +28 -0
- package/dist/providers/oauth-callback-server.js +184 -0
- package/dist/providers/oauth-orchestrator.d.ts +58 -0
- package/dist/providers/oauth-orchestrator.js +159 -0
- package/dist/providers/oauth-store.d.ts +12 -0
- package/dist/providers/oauth-store.js +139 -0
- package/dist/providers/open-browser.d.ts +20 -0
- package/dist/providers/open-browser.js +92 -0
- package/dist/providers/openai-compat.d.ts +14 -0
- package/dist/providers/openai-compat.js +523 -0
- package/dist/providers/openai-oauth.d.ts +15 -0
- package/dist/providers/openai-oauth.js +382 -0
- package/dist/providers/openrouter-auth.d.ts +73 -0
- package/dist/providers/openrouter-auth.js +321 -0
- package/dist/providers/openrouter-manual-fallback.d.ts +25 -0
- package/dist/providers/openrouter-manual-fallback.js +161 -0
- package/dist/providers/openrouter.d.ts +15 -0
- package/dist/providers/openrouter.js +107 -0
- package/dist/providers/plan-limits.d.ts +6 -0
- package/dist/providers/plan-limits.js +175 -0
- package/dist/providers/provider-reset.d.ts +4 -0
- package/dist/providers/provider-reset.js +83 -0
- package/dist/providers/quota-limits.d.ts +4 -0
- package/dist/providers/quota-limits.js +33 -0
- package/dist/providers/registry.d.ts +33 -0
- package/dist/providers/registry.js +213 -0
- package/dist/providers/retry.d.ts +37 -0
- package/dist/providers/retry.js +347 -0
- package/dist/rpc/server.d.ts +23 -0
- package/dist/rpc/server.js +222 -0
- package/dist/sdk.d.ts +67 -0
- package/dist/sdk.js +64 -0
- package/dist/skills/skills.d.ts +17 -0
- package/dist/skills/skills.js +155 -0
- package/dist/text-sanitize.js +28 -0
- package/dist/tools/ask-user.d.ts +2 -0
- package/dist/tools/ask-user.js +60 -0
- package/dist/tools/builtin.d.ts +48 -0
- package/dist/tools/builtin.js +2494 -0
- package/dist/tools/capabilities.d.ts +5 -0
- package/dist/tools/capabilities.js +55 -0
- package/dist/tools/computer-capture.d.ts +2 -0
- package/dist/tools/computer-capture.js +91 -0
- package/dist/tools/computer-posix.d.ts +5 -0
- package/dist/tools/computer-posix.js +136 -0
- package/dist/tools/computer-use.d.ts +14 -0
- package/dist/tools/computer-use.js +108 -0
- package/dist/tools/discovery.d.ts +12 -0
- package/dist/tools/discovery.js +205 -0
- package/dist/tools/execute.d.ts +2 -0
- package/dist/tools/execute.js +73 -0
- package/dist/tools/normalize-input.d.ts +17 -0
- package/dist/tools/normalize-input.js +174 -0
- package/dist/tools/output-artifact.d.ts +3 -0
- package/dist/tools/output-artifact.js +80 -0
- package/dist/tools/pagination.d.ts +15 -0
- package/dist/tools/pagination.js +93 -0
- package/dist/tools/plan-status.d.ts +2 -0
- package/dist/tools/plan-status.js +109 -0
- package/dist/tools/program-input.d.ts +3 -0
- package/dist/tools/program-input.js +19 -0
- package/dist/tools/program.d.ts +3 -0
- package/dist/tools/program.js +567 -0
- package/dist/tools/protocol-catalog.d.ts +12 -0
- package/dist/tools/protocol-catalog.js +46 -0
- package/dist/tools/ramification-tools.d.ts +12 -0
- package/dist/tools/ramification-tools.js +528 -0
- package/dist/tools/regex-compat.d.ts +9 -0
- package/dist/tools/regex-compat.js +96 -0
- package/dist/tools/registry.d.ts +51 -0
- package/dist/tools/registry.js +185 -0
- package/dist/tools/resolve.d.ts +2 -0
- package/dist/tools/resolve.js +107 -0
- package/dist/tools/shell-env.d.ts +2 -0
- package/dist/tools/shell-env.js +7 -0
- package/dist/tools/team-input.d.ts +3 -0
- package/dist/tools/team-input.js +129 -0
- package/dist/tools/team-tools.d.ts +7 -0
- package/dist/tools/team-tools.js +348 -0
- package/dist/tools/workspace-sessions.d.ts +2 -0
- package/dist/tools/workspace-sessions.js +35 -0
- package/dist/tui/account-entry.d.ts +1 -0
- package/dist/tui/account-entry.js +93 -0
- package/dist/tui/attachment-highlight.d.ts +1 -0
- package/dist/tui/attachment-highlight.js +24 -0
- package/dist/tui/attachment-refs.d.ts +2 -0
- package/dist/tui/attachment-refs.js +3 -0
- package/dist/tui/bottom-input.d.ts +219 -0
- package/dist/tui/bottom-input.js +1958 -0
- package/dist/tui/branding.d.ts +107 -0
- package/dist/tui/branding.js +750 -0
- package/dist/tui/clipboard-image.d.ts +10 -0
- package/dist/tui/clipboard-image.js +163 -0
- package/dist/tui/clipboard-text.d.ts +9 -0
- package/dist/tui/clipboard-text.js +51 -0
- package/dist/tui/clipboard-windows.d.ts +8 -0
- package/dist/tui/clipboard-windows.js +84 -0
- package/dist/tui/collapsible-command.d.ts +15 -0
- package/dist/tui/collapsible-command.js +48 -0
- package/dist/tui/command-feedback.d.ts +10 -0
- package/dist/tui/command-feedback.js +46 -0
- package/dist/tui/command-output-registry.d.ts +28 -0
- package/dist/tui/command-output-registry.js +103 -0
- package/dist/tui/command-transcript.d.ts +12 -0
- package/dist/tui/command-transcript.js +90 -0
- package/dist/tui/commands.d.ts +20 -0
- package/dist/tui/commands.js +131 -0
- package/dist/tui/context-bar.d.ts +4 -0
- package/dist/tui/context-bar.js +74 -0
- package/dist/tui/context-meter.d.ts +25 -0
- package/dist/tui/context-meter.js +81 -0
- package/dist/tui/cost-binding.d.ts +8 -0
- package/dist/tui/cost-binding.js +43 -0
- package/dist/tui/cost-tracker.d.ts +49 -0
- package/dist/tui/cost-tracker.js +122 -0
- package/dist/tui/diff.d.ts +9 -0
- package/dist/tui/diff.js +119 -0
- package/dist/tui/i18n-catalog.d.ts +5 -0
- package/dist/tui/i18n-catalog.js +184 -0
- package/dist/tui/i18n.d.ts +6 -0
- package/dist/tui/i18n.js +10 -0
- package/dist/tui/image-attachments.d.ts +46 -0
- package/dist/tui/image-attachments.js +167 -0
- package/dist/tui/images.d.ts +12 -0
- package/dist/tui/images.js +87 -0
- package/dist/tui/intro.d.ts +13 -0
- package/dist/tui/intro.js +109 -0
- package/dist/tui/language-preference.d.ts +6 -0
- package/dist/tui/language-preference.js +24 -0
- package/dist/tui/live-output.d.ts +2 -0
- package/dist/tui/live-output.js +18 -0
- package/dist/tui/locales.d.ts +19 -0
- package/dist/tui/locales.js +22 -0
- package/dist/tui/login-menu.d.ts +17 -0
- package/dist/tui/login-menu.js +58 -0
- package/dist/tui/logo.d.ts +8 -0
- package/dist/tui/logo.js +305 -0
- package/dist/tui/markdown-inline.d.ts +3 -0
- package/dist/tui/markdown-inline.js +99 -0
- package/dist/tui/markdown-table.d.ts +4 -0
- package/dist/tui/markdown-table.js +63 -0
- package/dist/tui/markdown.d.ts +11 -0
- package/dist/tui/markdown.js +257 -0
- package/dist/tui/mcp-transcript.d.ts +7 -0
- package/dist/tui/mcp-transcript.js +40 -0
- package/dist/tui/model-details.d.ts +2 -0
- package/dist/tui/model-details.js +21 -0
- package/dist/tui/model-selection.d.ts +7 -0
- package/dist/tui/model-selection.js +41 -0
- package/dist/tui/native-scrollback.d.ts +27 -0
- package/dist/tui/native-scrollback.js +134 -0
- package/dist/tui/onboarding.d.ts +72 -0
- package/dist/tui/onboarding.js +207 -0
- package/dist/tui/paste-collapse.d.ts +39 -0
- package/dist/tui/paste-collapse.js +117 -0
- package/dist/tui/perm-mode.d.ts +8 -0
- package/dist/tui/perm-mode.js +41 -0
- package/dist/tui/prompt-queue-store.d.ts +26 -0
- package/dist/tui/prompt-queue-store.js +87 -0
- package/dist/tui/prompt-queue.d.ts +47 -0
- package/dist/tui/prompt-queue.js +187 -0
- package/dist/tui/provider-menu.d.ts +33 -0
- package/dist/tui/provider-menu.js +175 -0
- package/dist/tui/question.d.ts +24 -0
- package/dist/tui/question.js +32 -0
- package/dist/tui/queue-screen.d.ts +25 -0
- package/dist/tui/queue-screen.js +152 -0
- package/dist/tui/queue-team.d.ts +3 -0
- package/dist/tui/queue-team.js +28 -0
- package/dist/tui/queued-questions.d.ts +20 -0
- package/dist/tui/queued-questions.js +163 -0
- package/dist/tui/quick-help.d.ts +1 -0
- package/dist/tui/quick-help.js +53 -0
- package/dist/tui/repl.d.ts +78 -0
- package/dist/tui/repl.js +4130 -0
- package/dist/tui/restore-queued-input.d.ts +3 -0
- package/dist/tui/restore-queued-input.js +20 -0
- package/dist/tui/review-detail.d.ts +6 -0
- package/dist/tui/review-detail.js +56 -0
- package/dist/tui/review-files.d.ts +3 -0
- package/dist/tui/review-files.js +22 -0
- package/dist/tui/review-render.d.ts +22 -0
- package/dist/tui/review-render.js +98 -0
- package/dist/tui/review-screen.d.ts +38 -0
- package/dist/tui/review-screen.js +358 -0
- package/dist/tui/review-store.d.ts +60 -0
- package/dist/tui/review-store.js +270 -0
- package/dist/tui/review-team.d.ts +2 -0
- package/dist/tui/review-team.js +27 -0
- package/dist/tui/selector-mouse.d.ts +26 -0
- package/dist/tui/selector-mouse.js +65 -0
- package/dist/tui/selector.d.ts +51 -0
- package/dist/tui/selector.js +299 -0
- package/dist/tui/session-replay.d.ts +10 -0
- package/dist/tui/session-replay.js +78 -0
- package/dist/tui/session-usage.d.ts +22 -0
- package/dist/tui/session-usage.js +55 -0
- package/dist/tui/skill-transcript.d.ts +5 -0
- package/dist/tui/skill-transcript.js +31 -0
- package/dist/tui/startup.d.ts +5 -0
- package/dist/tui/startup.js +61 -0
- package/dist/tui/status-line-loader.d.ts +8 -0
- package/dist/tui/status-line-loader.js +33 -0
- package/dist/tui/status-line.d.ts +38 -0
- package/dist/tui/status-line.js +213 -0
- package/dist/tui/system-language.d.ts +8 -0
- package/dist/tui/system-language.js +41 -0
- package/dist/tui/task-labels.d.ts +2 -0
- package/dist/tui/task-labels.js +7 -0
- package/dist/tui/term-bg.d.ts +4 -0
- package/dist/tui/term-bg.js +67 -0
- package/dist/tui/terminal-screen.d.ts +12 -0
- package/dist/tui/terminal-screen.js +1 -0
- package/dist/tui/terminal-text.d.ts +7 -0
- package/dist/tui/terminal-text.js +123 -0
- package/dist/tui/theme.d.ts +25 -0
- package/dist/tui/theme.js +383 -0
- package/dist/tui/tool-style.d.ts +7 -0
- package/dist/tui/tool-style.js +119 -0
- package/dist/tui/update-prompt.d.ts +14 -0
- package/dist/tui/update-prompt.js +104 -0
- package/dist/tui/usage-footer.d.ts +9 -0
- package/dist/tui/usage-footer.js +123 -0
- package/dist/tui/vascend-login.d.ts +68 -0
- package/dist/tui/vascend-login.js +355 -0
- package/dist/tui/web-login.d.ts +28 -0
- package/dist/tui/web-login.js +115 -0
- package/dist/vascend/activity-status.d.ts +12 -0
- package/dist/vascend/activity-status.js +68 -0
- package/dist/vascend/architecture-map.d.ts +73 -0
- package/dist/vascend/architecture-map.js +424 -0
- package/dist/vascend/attention-layout.d.ts +19 -0
- package/dist/vascend/attention-layout.js +141 -0
- package/dist/vascend/budget-allocator.d.ts +31 -0
- package/dist/vascend/budget-allocator.js +79 -0
- package/dist/vascend/candidate-collector.d.ts +20 -0
- package/dist/vascend/candidate-collector.js +220 -0
- package/dist/vascend/code-events.d.ts +24 -0
- package/dist/vascend/code-events.js +304 -0
- package/dist/vascend/code-graph-memory.d.ts +38 -0
- package/dist/vascend/code-graph-memory.js +334 -0
- package/dist/vascend/code-graph-runtime.d.ts +19 -0
- package/dist/vascend/code-graph-runtime.js +190 -0
- package/dist/vascend/code-graph-types.d.ts +58 -0
- package/dist/vascend/code-graph-types.js +50 -0
- package/dist/vascend/code-parser.d.ts +4 -0
- package/dist/vascend/code-parser.js +257 -0
- package/dist/vascend/competitor-knowledge.d.ts +53 -0
- package/dist/vascend/competitor-knowledge.js +262 -0
- package/dist/vascend/completeness.d.ts +16 -0
- package/dist/vascend/completeness.js +90 -0
- package/dist/vascend/context-autotuner.d.ts +45 -0
- package/dist/vascend/context-autotuner.js +231 -0
- package/dist/vascend/context-candidate.d.ts +45 -0
- package/dist/vascend/context-candidate.js +150 -0
- package/dist/vascend/context-capsule.d.ts +51 -0
- package/dist/vascend/context-capsule.js +133 -0
- package/dist/vascend/context-fabric.d.ts +108 -0
- package/dist/vascend/context-fabric.js +480 -0
- package/dist/vascend/context-feedback-loop.d.ts +56 -0
- package/dist/vascend/context-feedback-loop.js +204 -0
- package/dist/vascend/context-learning-identity.d.ts +4 -0
- package/dist/vascend/context-learning-identity.js +8 -0
- package/dist/vascend/context-links.d.ts +14 -0
- package/dist/vascend/context-links.js +83 -0
- package/dist/vascend/context-lint.d.ts +22 -0
- package/dist/vascend/context-lint.js +91 -0
- package/dist/vascend/context-market-selection.d.ts +17 -0
- package/dist/vascend/context-market-selection.js +50 -0
- package/dist/vascend/context-metrics.d.ts +25 -0
- package/dist/vascend/context-metrics.js +57 -0
- package/dist/vascend/context-pack-render.d.ts +16 -0
- package/dist/vascend/context-pack-render.js +52 -0
- package/dist/vascend/context-pareto.d.ts +33 -0
- package/dist/vascend/context-pareto.js +165 -0
- package/dist/vascend/context-pattern-explorer.d.ts +41 -0
- package/dist/vascend/context-pattern-explorer.js +276 -0
- package/dist/vascend/context-regret.d.ts +32 -0
- package/dist/vascend/context-regret.js +93 -0
- package/dist/vascend/context-retriever.d.ts +22 -0
- package/dist/vascend/context-retriever.js +243 -0
- package/dist/vascend/context-scope-index.d.ts +5 -0
- package/dist/vascend/context-scope-index.js +96 -0
- package/dist/vascend/context-scorer.d.ts +35 -0
- package/dist/vascend/context-scorer.js +162 -0
- package/dist/vascend/context-search-index.d.ts +12 -0
- package/dist/vascend/context-search-index.js +25 -0
- package/dist/vascend/context-snapshot.d.ts +22 -0
- package/dist/vascend/context-snapshot.js +135 -0
- package/dist/vascend/context-window-compiler.d.ts +42 -0
- package/dist/vascend/context-window-compiler.js +237 -0
- package/dist/vascend/contract-memory.d.ts +61 -0
- package/dist/vascend/contract-memory.js +435 -0
- package/dist/vascend/council.d.ts +58 -0
- package/dist/vascend/council.js +337 -0
- package/dist/vascend/decision-promotion.d.ts +48 -0
- package/dist/vascend/decision-promotion.js +410 -0
- package/dist/vascend/delta-context.d.ts +12 -0
- package/dist/vascend/delta-context.js +36 -0
- package/dist/vascend/dev-context-compiler.d.ts +27 -0
- package/dist/vascend/dev-context-compiler.js +133 -0
- package/dist/vascend/dev-context-layout.d.ts +30 -0
- package/dist/vascend/dev-context-layout.js +262 -0
- package/dist/vascend/evidence-slots.d.ts +14 -0
- package/dist/vascend/evidence-slots.js +55 -0
- package/dist/vascend/expansion-levels.d.ts +15 -0
- package/dist/vascend/expansion-levels.js +178 -0
- package/dist/vascend/file-lock.d.ts +7 -0
- package/dist/vascend/file-lock.js +95 -0
- package/dist/vascend/granular-kingdom.d.ts +25 -0
- package/dist/vascend/granular-kingdom.js +259 -0
- package/dist/vascend/granular-launcher.d.ts +48 -0
- package/dist/vascend/granular-launcher.js +202 -0
- package/dist/vascend/kingdom-bus.d.ts +25 -0
- package/dist/vascend/kingdom-bus.js +54 -0
- package/dist/vascend/kingdom-channel.d.ts +22 -0
- package/dist/vascend/kingdom-channel.js +180 -0
- package/dist/vascend/kingdom-kpi.d.ts +48 -0
- package/dist/vascend/kingdom-kpi.js +172 -0
- package/dist/vascend/kingdom-live.d.ts +28 -0
- package/dist/vascend/kingdom-live.js +61 -0
- package/dist/vascend/kingdom-run.d.ts +18 -0
- package/dist/vascend/kingdom-run.js +506 -0
- package/dist/vascend/kingdom-scribe.d.ts +20 -0
- package/dist/vascend/kingdom-scribe.js +52 -0
- package/dist/vascend/kingdom.d.ts +79 -0
- package/dist/vascend/kingdom.js +870 -0
- package/dist/vascend/lexical-index.d.ts +10 -0
- package/dist/vascend/lexical-index.js +99 -0
- package/dist/vascend/lexical-search.d.ts +29 -0
- package/dist/vascend/lexical-search.js +262 -0
- package/dist/vascend/long-term-context.d.ts +51 -0
- package/dist/vascend/long-term-context.js +194 -0
- package/dist/vascend/mandate.d.ts +33 -0
- package/dist/vascend/mandate.js +107 -0
- package/dist/vascend/memory-packet.d.ts +13 -0
- package/dist/vascend/memory-packet.js +155 -0
- package/dist/vascend/memory-status.d.ts +22 -0
- package/dist/vascend/memory-status.js +73 -0
- package/dist/vascend/memory-store.d.ts +62 -0
- package/dist/vascend/memory-store.js +273 -0
- package/dist/vascend/objective-revision.d.ts +69 -0
- package/dist/vascend/objective-revision.js +319 -0
- package/dist/vascend/patch-plan-store.d.ts +33 -0
- package/dist/vascend/patch-plan-store.js +240 -0
- package/dist/vascend/patch-plan.d.ts +97 -0
- package/dist/vascend/patch-plan.js +345 -0
- package/dist/vascend/plan-progress.d.ts +11 -0
- package/dist/vascend/plan-progress.js +68 -0
- package/dist/vascend/plan-store.d.ts +64 -0
- package/dist/vascend/plan-store.js +460 -0
- package/dist/vascend/proof-chains.d.ts +19 -0
- package/dist/vascend/proof-chains.js +120 -0
- package/dist/vascend/ramification-store.d.ts +25 -0
- package/dist/vascend/ramification-store.js +94 -0
- package/dist/vascend/ramification.d.ts +193 -0
- package/dist/vascend/ramification.js +583 -0
- package/dist/vascend/recall-planner.d.ts +17 -0
- package/dist/vascend/recall-planner.js +109 -0
- package/dist/vascend/requirements.d.ts +31 -0
- package/dist/vascend/requirements.js +151 -0
- package/dist/vascend/reviewer.d.ts +9 -0
- package/dist/vascend/reviewer.js +93 -0
- package/dist/vascend/room-graph.d.ts +29 -0
- package/dist/vascend/room-graph.js +242 -0
- package/dist/vascend/room-memory.d.ts +57 -0
- package/dist/vascend/room-memory.js +631 -0
- package/dist/vascend/runtime.d.ts +84 -0
- package/dist/vascend/runtime.js +286 -0
- package/dist/vascend/self-improve.d.ts +104 -0
- package/dist/vascend/self-improve.js +396 -0
- package/dist/vascend/session-search.d.ts +52 -0
- package/dist/vascend/session-search.js +349 -0
- package/dist/vascend/supersession-graph.d.ts +14 -0
- package/dist/vascend/supersession-graph.js +70 -0
- package/dist/vascend/team-areas.d.ts +9 -0
- package/dist/vascend/team-areas.js +28 -0
- package/dist/vascend/team-handoff.d.ts +24 -0
- package/dist/vascend/team-handoff.js +37 -0
- package/dist/vascend/team-scheduler.d.ts +13 -0
- package/dist/vascend/team-scheduler.js +74 -0
- package/dist/vascend/team-session.d.ts +42 -0
- package/dist/vascend/team-session.js +142 -0
- package/dist/vascend/test-failure-memory.d.ts +76 -0
- package/dist/vascend/test-failure-memory.js +354 -0
- package/dist/vascend/token-market.d.ts +42 -0
- package/dist/vascend/token-market.js +144 -0
- package/dist/vascend/tuner-baseline-store.d.ts +52 -0
- package/dist/vascend/tuner-baseline-store.js +446 -0
- package/dist/vascend/user-profile.d.ts +44 -0
- package/dist/vascend/user-profile.js +131 -0
- package/dist/vascend/vision.d.ts +94 -0
- package/dist/vascend/vision.js +375 -0
- package/dist/vascend/work-agent.d.ts +12 -0
- package/dist/vascend/work-agent.js +83 -0
- package/dist/vascend/work-queue.d.ts +62 -0
- package/dist/vascend/work-queue.js +255 -0
- package/dist/vascend/work-runner.d.ts +64 -0
- package/dist/vascend/work-runner.js +137 -0
- package/dist/vascend/worktree.d.ts +38 -0
- package/dist/vascend/worktree.js +206 -0
- package/dist/vendor/computer-use/README.md +7 -0
- package/dist/vendor/computer-use/computer-desktop.js +211 -0
- package/dist/vendor/computer-use/computer-observe.js +315 -0
- package/dist/vendor/computer-use/computer-scripts.js +1230 -0
- package/dist/vendor/computer-use/computer-tools.js +2136 -0
- package/dist/vendor/computer-use/package.json +1 -0
- package/dist/vendor/computer-use/rac/atomic-input.js +91 -0
- package/dist/vendor/computer-use/rac/grammatica.js +101 -0
- package/dist/vendor/computer-use/rac/parser.js +185 -0
- package/dist/vendor/computer-use/rac/protocol.js +136 -0
- package/install.ps1 +30 -0
- package/install.sh +50 -0
- package/package.json +56 -0
|
@@ -0,0 +1,774 @@
|
|
|
1
|
+
import { AsyncQueue } from "./async-queue.js";
|
|
2
|
+
import { HorizonEngine } from "./engine.js";
|
|
3
|
+
import { FileCoordinationHub, fileActor, withFileActor } from "../core/file-coordination.js";
|
|
4
|
+
import { normalizeExecutionTarget } from "../core/execution-target.js";
|
|
5
|
+
class MainExchangeBus {
|
|
6
|
+
onExchange;
|
|
7
|
+
sequence = 0;
|
|
8
|
+
messages = [];
|
|
9
|
+
waiters = new Set();
|
|
10
|
+
constructor(onExchange) {
|
|
11
|
+
this.onExchange = onExchange;
|
|
12
|
+
}
|
|
13
|
+
post(from, to, text) {
|
|
14
|
+
const exchange = {
|
|
15
|
+
seq: ++this.sequence,
|
|
16
|
+
from,
|
|
17
|
+
to,
|
|
18
|
+
text: String(text || "").trim().slice(0, 8_000),
|
|
19
|
+
at: Date.now(),
|
|
20
|
+
};
|
|
21
|
+
if (!exchange.text)
|
|
22
|
+
throw new TypeError("il messaggio tra agenti non puo' essere vuoto");
|
|
23
|
+
this.messages.push(exchange);
|
|
24
|
+
if (this.messages.length > 500)
|
|
25
|
+
this.messages.splice(0, this.messages.length - 500);
|
|
26
|
+
this.onExchange(exchange);
|
|
27
|
+
this.flushWaiters();
|
|
28
|
+
return exchange;
|
|
29
|
+
}
|
|
30
|
+
recall(agent, from, limit = 12) {
|
|
31
|
+
const cap = Math.max(1, Math.min(50, Math.trunc(limit) || 12));
|
|
32
|
+
return this.messages
|
|
33
|
+
.filter((message) => message.from !== agent
|
|
34
|
+
&& (message.to === "all" || message.to === agent)
|
|
35
|
+
&& (!from || message.from === from))
|
|
36
|
+
.slice(-cap);
|
|
37
|
+
}
|
|
38
|
+
wait(agent, from, timeoutMs = 15_000) {
|
|
39
|
+
const ready = this.recall(agent, from);
|
|
40
|
+
if (ready.length)
|
|
41
|
+
return Promise.resolve(ready);
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const waiter = {
|
|
44
|
+
agent,
|
|
45
|
+
...(from ? { from } : {}),
|
|
46
|
+
resolve,
|
|
47
|
+
timer: setTimeout(() => {
|
|
48
|
+
this.waiters.delete(waiter);
|
|
49
|
+
resolve([]);
|
|
50
|
+
}, Math.max(100, Math.min(60_000, Math.trunc(timeoutMs) || 15_000))),
|
|
51
|
+
};
|
|
52
|
+
this.waiters.add(waiter);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
history() {
|
|
56
|
+
return this.messages.slice();
|
|
57
|
+
}
|
|
58
|
+
close() {
|
|
59
|
+
for (const waiter of this.waiters) {
|
|
60
|
+
clearTimeout(waiter.timer);
|
|
61
|
+
waiter.resolve([]);
|
|
62
|
+
}
|
|
63
|
+
this.waiters.clear();
|
|
64
|
+
}
|
|
65
|
+
flushWaiters() {
|
|
66
|
+
for (const waiter of [...this.waiters]) {
|
|
67
|
+
const ready = this.recall(waiter.agent, waiter.from);
|
|
68
|
+
if (!ready.length)
|
|
69
|
+
continue;
|
|
70
|
+
clearTimeout(waiter.timer);
|
|
71
|
+
this.waiters.delete(waiter);
|
|
72
|
+
waiter.resolve(ready);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const DEFAULT_RUNTIME = undefined;
|
|
77
|
+
export class HorizonMainTeam {
|
|
78
|
+
options;
|
|
79
|
+
runtime;
|
|
80
|
+
engines = new Map();
|
|
81
|
+
activeTurns = new Map();
|
|
82
|
+
config;
|
|
83
|
+
sequence = 0;
|
|
84
|
+
decisionSequence = 0;
|
|
85
|
+
guideDecisionTail = Promise.resolve();
|
|
86
|
+
supervision = null;
|
|
87
|
+
closed = false;
|
|
88
|
+
constructor(options, config, runtime) {
|
|
89
|
+
this.options = options;
|
|
90
|
+
this.runtime = runtime;
|
|
91
|
+
this.config = normalizeMainTeamConfig(config);
|
|
92
|
+
}
|
|
93
|
+
static async create(options, config = {}, runtime = DEFAULT_RUNTIME) {
|
|
94
|
+
const cwd = String(options.cwd || process.cwd());
|
|
95
|
+
const coordinated = options.fileCoordination ? options : {
|
|
96
|
+
...options,
|
|
97
|
+
fileCoordination: {
|
|
98
|
+
hub: new FileCoordinationHub(cwd, normalizeExecutionTarget(options.executionTarget)),
|
|
99
|
+
actor: fileActor(`horizon:team:${Date.now().toString(36)}`, "Horizon", "main"),
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
const team = new HorizonMainTeam(coordinated, config, runtime);
|
|
103
|
+
try {
|
|
104
|
+
await team.initialize();
|
|
105
|
+
return team;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
// Se r2/guida non riescono a riprendere la propria sessione, r1 puo'
|
|
109
|
+
// essere gia' stato creato. Chiudilo prima di propagare l'errore: il
|
|
110
|
+
// Terminal fara' un solo recovery controllato senza lasciare engine
|
|
111
|
+
// orfani nel processo.
|
|
112
|
+
await team.close();
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
startTurn(input) {
|
|
117
|
+
if (this.closed)
|
|
118
|
+
throw new Error("main team Horizon chiuso");
|
|
119
|
+
if (this.activeTurns.size)
|
|
120
|
+
throw new Error("un turno main team e' gia' in corso");
|
|
121
|
+
const teamId = `mt-${Date.now().toString(36)}-${(++this.sequence).toString(36)}`;
|
|
122
|
+
const id = `${teamId}:turn`;
|
|
123
|
+
const queue = new AsyncQueue();
|
|
124
|
+
const mains = this.mainRefs();
|
|
125
|
+
let aborted = false;
|
|
126
|
+
let bus;
|
|
127
|
+
const emit = (event) => queue.push(event);
|
|
128
|
+
bus = new MainExchangeBus((exchange) => emit({ type: "exchange", teamId, exchange }));
|
|
129
|
+
this.bindTeamTools(bus);
|
|
130
|
+
const supervision = { original: input, emit, bus, decisions: [] };
|
|
131
|
+
if (this.config.guide)
|
|
132
|
+
this.supervision = supervision;
|
|
133
|
+
const done = (async () => {
|
|
134
|
+
emit({ type: "team_start", teamId, agents: mains, names: this.config.names, guide: this.config.guide });
|
|
135
|
+
const outputs = {};
|
|
136
|
+
let plan;
|
|
137
|
+
let review;
|
|
138
|
+
let status = "completed";
|
|
139
|
+
let error;
|
|
140
|
+
try {
|
|
141
|
+
if (this.config.guide) {
|
|
142
|
+
plan = await this.plan(input, mains, 0, emit);
|
|
143
|
+
supervision.plan = plan;
|
|
144
|
+
emit({ type: "plan", round: 0, plan });
|
|
145
|
+
}
|
|
146
|
+
const first = await Promise.all(mains.map(async (agent) => {
|
|
147
|
+
const assignedInput = plan
|
|
148
|
+
? assignmentPrompt(input, plan, agent, this.config.names)
|
|
149
|
+
: input;
|
|
150
|
+
const result = await this.runAgent(agent, assignedInput, 0, emit);
|
|
151
|
+
outputs[agent] = result.text;
|
|
152
|
+
return result;
|
|
153
|
+
}));
|
|
154
|
+
const failed = first.find((item) => item.result.status !== "completed");
|
|
155
|
+
if (failed) {
|
|
156
|
+
status = failed.result.status;
|
|
157
|
+
error = failed.result.error;
|
|
158
|
+
}
|
|
159
|
+
if (!aborted && status === "completed" && mains.length === 2) {
|
|
160
|
+
const consolidated = await this.runAgent("r1", consolidationPrompt(outputs.r1 || "", outputs.r2 || "", bus.history()), 0, emit);
|
|
161
|
+
outputs.r1 = completedAgentText(consolidated, "consolidamento r1");
|
|
162
|
+
}
|
|
163
|
+
for (let round = 1; !aborted && status === "completed" && this.config.guide && round <= this.config.reviewRounds + 1; round += 1) {
|
|
164
|
+
review = await this.review(input, outputs, bus.history(), round, emit);
|
|
165
|
+
emit({ type: "review", round, verdict: review });
|
|
166
|
+
if (review.approved)
|
|
167
|
+
break;
|
|
168
|
+
if (round > this.config.reviewRounds) {
|
|
169
|
+
status = "failed";
|
|
170
|
+
error = `Revisione della guida non approvata: budget esaurito al round ${round}. ${review.summary}`;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
const corrections = mains.filter((agent) => String(review?.actions[agent] || "").trim());
|
|
174
|
+
if (!corrections.length) {
|
|
175
|
+
status = "failed";
|
|
176
|
+
error = `Revisione della guida non approvata: nessuna azione correttiva eseguibile. ${review.summary}`;
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
const corrected = await Promise.all(corrections.map(async (agent) => {
|
|
180
|
+
const action = review?.actions[agent] || review?.summary || "Verifica e completa il lavoro.";
|
|
181
|
+
const result = await this.runAgent(agent, correctionPrompt(action, review?.summary || "", bus.history()), round, emit);
|
|
182
|
+
outputs[agent] = result.text;
|
|
183
|
+
return result;
|
|
184
|
+
}));
|
|
185
|
+
const failedCorrection = corrected.find((item) => item.result.status !== "completed");
|
|
186
|
+
if (failedCorrection) {
|
|
187
|
+
status = failedCorrection.result.status;
|
|
188
|
+
error = failedCorrection.result.error;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
if (mains.length === 2) {
|
|
192
|
+
const consolidated = await this.runAgent("r1", consolidationPrompt(outputs.r1 || "", outputs.r2 || "", bus.history()), round, emit);
|
|
193
|
+
outputs.r1 = completedAgentText(consolidated, "consolidamento r1");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (cause) {
|
|
198
|
+
status = aborted ? "aborted" : "failed";
|
|
199
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
bus.close();
|
|
203
|
+
if (this.supervision === supervision)
|
|
204
|
+
this.supervision = null;
|
|
205
|
+
this.activeTurns.clear();
|
|
206
|
+
emit({ type: "team_end", teamId, status });
|
|
207
|
+
queue.close();
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
id,
|
|
211
|
+
teamId,
|
|
212
|
+
status,
|
|
213
|
+
text: outputs.r1 || outputs.r2 || "",
|
|
214
|
+
sessions: {
|
|
215
|
+
r1: this.engines.get("r1")?.session.id || null,
|
|
216
|
+
r2: this.engines.get("r2")?.session.id || null,
|
|
217
|
+
},
|
|
218
|
+
names: this.config.names,
|
|
219
|
+
outputs,
|
|
220
|
+
exchanges: bus.history(),
|
|
221
|
+
decisions: supervision.decisions.slice(),
|
|
222
|
+
...(plan ? { plan } : {}),
|
|
223
|
+
...(review ? { review } : {}),
|
|
224
|
+
...(error ? { error } : {}),
|
|
225
|
+
};
|
|
226
|
+
})();
|
|
227
|
+
return {
|
|
228
|
+
id,
|
|
229
|
+
teamId,
|
|
230
|
+
events: queue,
|
|
231
|
+
done,
|
|
232
|
+
abort: () => {
|
|
233
|
+
if (aborted || !this.activeTurns.size)
|
|
234
|
+
return false;
|
|
235
|
+
aborted = true;
|
|
236
|
+
for (const turn of this.activeTurns.values())
|
|
237
|
+
turn.abort();
|
|
238
|
+
return true;
|
|
239
|
+
},
|
|
240
|
+
send: (message, messageId) => this.activeTurns.get("r1")?.send(message, messageId) ?? null,
|
|
241
|
+
prioritize: (messageId) => this.activeTurns.get("r1")?.prioritize(messageId) ?? false,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
modelCatalog() {
|
|
245
|
+
const engine = this.engines.get("r1");
|
|
246
|
+
if (!engine)
|
|
247
|
+
throw new Error("main agent r1 non disponibile");
|
|
248
|
+
return engine.modelCatalog();
|
|
249
|
+
}
|
|
250
|
+
contextStatus() {
|
|
251
|
+
const engine = this.engines.get("r1");
|
|
252
|
+
if (!engine)
|
|
253
|
+
throw new Error("main agent r1 non disponibile");
|
|
254
|
+
return engine.contextStatus();
|
|
255
|
+
}
|
|
256
|
+
async close() {
|
|
257
|
+
if (this.closed)
|
|
258
|
+
return;
|
|
259
|
+
this.closed = true;
|
|
260
|
+
for (const turn of this.activeTurns.values())
|
|
261
|
+
turn.abort();
|
|
262
|
+
await Promise.all([...this.engines.values()].map((engine) => engine.close()));
|
|
263
|
+
this.activeTurns.clear();
|
|
264
|
+
this.engines.clear();
|
|
265
|
+
}
|
|
266
|
+
async initialize() {
|
|
267
|
+
for (const ref of this.mainRefs()) {
|
|
268
|
+
this.engines.set(ref, await this.createEngine(ref));
|
|
269
|
+
}
|
|
270
|
+
if (this.config.guide)
|
|
271
|
+
this.engines.set("guide", await this.createEngine("guide"));
|
|
272
|
+
}
|
|
273
|
+
async createEngine(ref) {
|
|
274
|
+
const originalConfigure = this.options.configureHarness;
|
|
275
|
+
const originalConfirm = this.options.confirm;
|
|
276
|
+
const engineOptions = {
|
|
277
|
+
...this.options,
|
|
278
|
+
...(this.options.fileCoordination ? {
|
|
279
|
+
fileCoordination: withFileActor(this.options.fileCoordination, fileActor(`${this.options.fileCoordination.actor.id}:${ref}`, ref === "guide" ? "Guida" : this.config.names[ref], "main")),
|
|
280
|
+
} : {}),
|
|
281
|
+
...(ref !== "r1" ? {
|
|
282
|
+
model: ref === "r2" && this.config.peerModel ? this.config.peerModel : this.options.model,
|
|
283
|
+
sessionId: ref === "r2" && this.config.peerSessionId ? this.config.peerSessionId : undefined,
|
|
284
|
+
continueLast: false,
|
|
285
|
+
sessionName: `Horizon ${ref}`,
|
|
286
|
+
} : {}),
|
|
287
|
+
...(ref === "guide" ? {
|
|
288
|
+
confirm: async (action, detail) => {
|
|
289
|
+
if (GUIDE_MUTATION_TOOLS.has(action))
|
|
290
|
+
return false;
|
|
291
|
+
return originalConfirm ? originalConfirm(action, detail) : false;
|
|
292
|
+
},
|
|
293
|
+
} : ref === "r1" || ref === "r2" ? {
|
|
294
|
+
confirm: async (action, detail) => {
|
|
295
|
+
if (this.config.guide && needsGuideArbitration(action, detail)) {
|
|
296
|
+
const decision = await this.arbitrate(ref, action, detail, "automatic-gate");
|
|
297
|
+
if (!decision.approved)
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
return originalConfirm ? originalConfirm(action, detail) : false;
|
|
301
|
+
},
|
|
302
|
+
} : {}),
|
|
303
|
+
configureHarness: async (harness) => {
|
|
304
|
+
await originalConfigure?.(harness);
|
|
305
|
+
if (ref === "guide") {
|
|
306
|
+
for (const name of GUIDE_MUTATION_TOOLS)
|
|
307
|
+
harness.tools.remove(name);
|
|
308
|
+
}
|
|
309
|
+
harness.config = {
|
|
310
|
+
...harness.config,
|
|
311
|
+
system: `${harness.config.system}\n\n${teamSystemBlock(ref, this.config.agents, this.config.names, this.config.guide)}`,
|
|
312
|
+
};
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
return this.runtime
|
|
316
|
+
? HorizonEngine.create(engineOptions, this.runtime)
|
|
317
|
+
: HorizonEngine.create(engineOptions);
|
|
318
|
+
}
|
|
319
|
+
bindTeamTools(bus) {
|
|
320
|
+
for (const ref of this.mainRefs()) {
|
|
321
|
+
const engine = this.engines.get(ref);
|
|
322
|
+
const harness = engine ? engineHarness(engine) : null;
|
|
323
|
+
if (!harness)
|
|
324
|
+
continue;
|
|
325
|
+
registerTeamTools(harness, ref, bus, this.config.guide
|
|
326
|
+
? (proposal) => this.arbitrate(ref, proposal.action, proposal.proposal, "agent-request")
|
|
327
|
+
: undefined);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
mainRefs() {
|
|
331
|
+
return this.config.agents === 2 ? ["r1", "r2"] : ["r1"];
|
|
332
|
+
}
|
|
333
|
+
async runAgent(agent, input, round, emit, purpose = "work") {
|
|
334
|
+
const engine = this.engines.get(agent);
|
|
335
|
+
if (!engine)
|
|
336
|
+
throw new Error(`engine ${agent} non disponibile`);
|
|
337
|
+
const name = agent === "guide" ? "Guida" : this.config.names[agent];
|
|
338
|
+
emit({ type: "agent_start", agent, name, round, purpose });
|
|
339
|
+
// Ogni main riceve una capability filesystem propria e mutabile per il
|
|
340
|
+
// singolo turno. Il bootstrap conserva invece una snapshot readonly:
|
|
341
|
+
// con due engine non va condivisa né mutata durante i grant dinamici.
|
|
342
|
+
const turn = engine.startTurn(input, {
|
|
343
|
+
...(this.options.fsRoots !== undefined ? { fsRoots: [...this.options.fsRoots] } : {}),
|
|
344
|
+
});
|
|
345
|
+
this.activeTurns.set(agent, turn);
|
|
346
|
+
let text = "";
|
|
347
|
+
for await (const event of turn.events) {
|
|
348
|
+
if (event.type === "text")
|
|
349
|
+
text += event.delta;
|
|
350
|
+
emit({ type: "agent_event", agent, round, purpose, event });
|
|
351
|
+
}
|
|
352
|
+
const result = await turn.done;
|
|
353
|
+
this.activeTurns.delete(agent);
|
|
354
|
+
emit({ type: "agent_end", agent, name, round, status: result.status, output: text.trim().slice(0, 16_000) });
|
|
355
|
+
return { text: text.trim(), result };
|
|
356
|
+
}
|
|
357
|
+
async review(original, outputs, exchanges, round, emit) {
|
|
358
|
+
const raw = await this.runAgent("guide", guidePrompt(original, outputs, exchanges), round, emit, "review");
|
|
359
|
+
return parseGuideVerdict(completedAgentText(raw, "review della guida"));
|
|
360
|
+
}
|
|
361
|
+
async plan(original, mains, round, emit) {
|
|
362
|
+
const raw = await this.runAgent("guide", guidePlanningPrompt(original, mains, this.config.names), round, emit, "plan");
|
|
363
|
+
return parseGuidePlan(completedAgentText(raw, "pianificazione della guida"), mains);
|
|
364
|
+
}
|
|
365
|
+
arbitrate(agent, action, proposal, source) {
|
|
366
|
+
const run = async () => {
|
|
367
|
+
const active = this.supervision;
|
|
368
|
+
const request = {
|
|
369
|
+
id: `gd-${(++this.decisionSequence).toString(36)}`,
|
|
370
|
+
agent,
|
|
371
|
+
agentName: this.config.names[agent],
|
|
372
|
+
action: cleanPlanText(action, "decisione operativa", 160),
|
|
373
|
+
proposal: cleanPlanText(proposal, "", 8_000),
|
|
374
|
+
source,
|
|
375
|
+
at: Date.now(),
|
|
376
|
+
};
|
|
377
|
+
if (!active || !this.config.guide) {
|
|
378
|
+
return {
|
|
379
|
+
requestId: request.id,
|
|
380
|
+
approved: false,
|
|
381
|
+
risk: "high",
|
|
382
|
+
reason: "La Guida non e' disponibile nel turno corrente.",
|
|
383
|
+
guidance: "Non procedere e chiedere indicazioni all'utente.",
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
active.emit({ type: "decision", phase: "requested", request });
|
|
387
|
+
const raw = await this.runAgent("guide", guideDecisionPrompt(active.original, active.plan, active.bus.history(), request), 1000 + this.decisionSequence, active.emit, "decision");
|
|
388
|
+
const decision = parseGuideDecision(completedAgentText(raw, "decisione della guida"), request.id);
|
|
389
|
+
active.decisions.push({ request, decision });
|
|
390
|
+
if (active.decisions.length > 100)
|
|
391
|
+
active.decisions.splice(0, active.decisions.length - 100);
|
|
392
|
+
active.emit({ type: "decision", phase: "resolved", request, decision });
|
|
393
|
+
return decision;
|
|
394
|
+
};
|
|
395
|
+
const result = this.guideDecisionTail.then(run, run);
|
|
396
|
+
this.guideDecisionTail = result.then(() => undefined, () => undefined);
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function completedAgentText(run, phase) {
|
|
401
|
+
if (run.result.status === "completed")
|
|
402
|
+
return run.text;
|
|
403
|
+
throw new Error(run.result.error?.trim()
|
|
404
|
+
|| `${phase} interrotto (${run.result.status}); il risultato parziale non e' valido`);
|
|
405
|
+
}
|
|
406
|
+
const GUIDE_MUTATION_TOOLS = new Set([
|
|
407
|
+
"bash",
|
|
408
|
+
"write_file",
|
|
409
|
+
"edit_file",
|
|
410
|
+
"apply_patch",
|
|
411
|
+
"image_generate",
|
|
412
|
+
"kingdoms_warm",
|
|
413
|
+
"vascend_plan",
|
|
414
|
+
"vascend_addtasks",
|
|
415
|
+
"vascend_mark",
|
|
416
|
+
]);
|
|
417
|
+
function normalizeMainTeamConfig(config) {
|
|
418
|
+
return {
|
|
419
|
+
agents: config.agents === 2 ? 2 : 1,
|
|
420
|
+
guide: config.guide === true,
|
|
421
|
+
reviewRounds: Math.max(0, Math.min(2, Math.trunc(config.reviewRounds ?? 1))),
|
|
422
|
+
peerSessionId: String(config.peerSessionId || "").trim(),
|
|
423
|
+
peerModel: String(config.peerModel || "").trim(),
|
|
424
|
+
names: {
|
|
425
|
+
r1: normalizeAgentName(config.names?.r1, "Main 1"),
|
|
426
|
+
r2: normalizeAgentName(config.names?.r2, "Main 2"),
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function normalizeAgentName(value, fallback) {
|
|
431
|
+
const clean = String(value || "").replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim();
|
|
432
|
+
return clean ? clean.slice(0, 48) : fallback;
|
|
433
|
+
}
|
|
434
|
+
// HorizonEngine mantiene intenzionalmente l'harness privato. Il team e' parte
|
|
435
|
+
// dello stesso facade core e usa questo accesso confinato solo per registrare i
|
|
436
|
+
// tre tool di coordinamento dopo aver creato il bus del singolo turno.
|
|
437
|
+
function engineHarness(engine) {
|
|
438
|
+
return engine.harness ?? null;
|
|
439
|
+
}
|
|
440
|
+
function registerTeamTools(harness, self, bus, askGuide) {
|
|
441
|
+
const peer = self === "r1" ? "r2" : "r1";
|
|
442
|
+
const requestGuideDecision = askGuide;
|
|
443
|
+
if (requestGuideDecision)
|
|
444
|
+
harness.tools.register({
|
|
445
|
+
name: "main_team_send",
|
|
446
|
+
description: `Invia un aggiornamento al main agent ${peer}. Usalo per dichiarare ownership, decisioni, blocchi e risultati prima di modifiche potenzialmente sovrapposte.`,
|
|
447
|
+
schema: {
|
|
448
|
+
type: "object",
|
|
449
|
+
properties: {
|
|
450
|
+
to: { type: "string", enum: [peer, "all"] },
|
|
451
|
+
message: { type: "string" },
|
|
452
|
+
},
|
|
453
|
+
required: ["to", "message"],
|
|
454
|
+
},
|
|
455
|
+
handler: async (input) => JSON.stringify(bus.post(self, input["to"] === "all" ? "all" : peer, String(input["message"] || ""))),
|
|
456
|
+
});
|
|
457
|
+
harness.tools.register({
|
|
458
|
+
name: "main_team_recall",
|
|
459
|
+
description: `Richiama gli ultimi messaggi scambiati con ${peer}. Il riferimento stabile di questo agente e' ${self}.`,
|
|
460
|
+
schema: {
|
|
461
|
+
type: "object",
|
|
462
|
+
properties: {
|
|
463
|
+
agent: { type: "string", enum: [peer] },
|
|
464
|
+
limit: { type: "number" },
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
handler: async (input) => JSON.stringify(bus.recall(self, peer, Number(input["limit"]) || 12), null, 2),
|
|
468
|
+
});
|
|
469
|
+
harness.tools.register({
|
|
470
|
+
name: "main_team_wait",
|
|
471
|
+
description: `Attende un aggiornamento di ${peer} senza importare la sua cronologia completa.`,
|
|
472
|
+
schema: {
|
|
473
|
+
type: "object",
|
|
474
|
+
properties: {
|
|
475
|
+
agent: { type: "string", enum: [peer] },
|
|
476
|
+
timeout_ms: { type: "number" },
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
handler: async (input) => JSON.stringify(await bus.wait(self, peer, Number(input["timeout_ms"]) || 15_000), null, 2),
|
|
480
|
+
});
|
|
481
|
+
harness.tools.register({
|
|
482
|
+
name: "main_team_ask_guide",
|
|
483
|
+
description: "Sottopone alla Guida una scelta operativa prima di agire. Obbligatorio per azioni distruttive, deviazioni dal piano, takeover del lavoro del peer, processi pesanti o alternative con trade-off rilevanti.",
|
|
484
|
+
schema: {
|
|
485
|
+
type: "object",
|
|
486
|
+
properties: {
|
|
487
|
+
action: { type: "string", description: "Nome breve della decisione" },
|
|
488
|
+
proposal: { type: "string", description: "Cosa vuoi fare, perche', impatto, alternative e rollback" },
|
|
489
|
+
},
|
|
490
|
+
required: ["action", "proposal"],
|
|
491
|
+
},
|
|
492
|
+
handler: async (input) => JSON.stringify(await requestGuideDecision({
|
|
493
|
+
action: String(input["action"] || "decisione operativa"),
|
|
494
|
+
proposal: String(input["proposal"] || ""),
|
|
495
|
+
}), null, 2),
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
function teamSystemBlock(ref, agents, names, guide) {
|
|
499
|
+
if (ref === "guide") {
|
|
500
|
+
return [
|
|
501
|
+
"[HORIZON_GUIDE]",
|
|
502
|
+
"role=autonomous-supervisor; first design and assign precise work, later review evidence and the actual workspace",
|
|
503
|
+
"policy=do not implement or execute shell commands yourself; use read/search/browser tools and agent evidence to plan, arbitrate or verify",
|
|
504
|
+
"output=return only the JSON schema explicitly requested by the current planning or review prompt",
|
|
505
|
+
"[/HORIZON_GUIDE]",
|
|
506
|
+
].join("\n");
|
|
507
|
+
}
|
|
508
|
+
const peer = ref === "r1" ? "r2" : "r1";
|
|
509
|
+
return [
|
|
510
|
+
"[HORIZON_MAIN_TEAM]",
|
|
511
|
+
`identity=${ref}; display_name=${names[ref]}; class=main-agent; peer_count=${agents}; peer=${agents === 2 ? peer : "none"}; peer_name=${agents === 2 ? names[peer] : "none"}`,
|
|
512
|
+
"hierarchy=peer; you are a team member",
|
|
513
|
+
agents === 2
|
|
514
|
+
? "coordination=before overlapping edits send ownership and plan with main_team_send; use main_team_recall/main_team_wait instead of assuming peer state"
|
|
515
|
+
: "coordination=single main agent",
|
|
516
|
+
...(guide ? [
|
|
517
|
+
"supervision=before destructive actions, high-resource local jobs, plan deviations, peer takeover or material trade-offs call main_team_ask_guide and obey its verdict",
|
|
518
|
+
"safety=the guide can deny or redirect an action; never disguise or split a denied action to bypass supervision",
|
|
519
|
+
] : []),
|
|
520
|
+
"context_policy=only explicit bus exchanges are shared; never assume access to the peer private transcript",
|
|
521
|
+
ref === "r1"
|
|
522
|
+
? "delivery=you own the single final response after incorporating useful peer evidence"
|
|
523
|
+
: "delivery=work as an equal main agent; send findings, changed files, tests and blockers to r1",
|
|
524
|
+
"[/HORIZON_MAIN_TEAM]",
|
|
525
|
+
].join("\n");
|
|
526
|
+
}
|
|
527
|
+
function exchangeDigest(exchanges) {
|
|
528
|
+
const maxChars = 24_000;
|
|
529
|
+
const rows = [];
|
|
530
|
+
let used = 0;
|
|
531
|
+
// Gli scambi completi restano nella sessione/UI; ai prompt successivi passa
|
|
532
|
+
// un working set recente e bounded, altrimenti 40 messaggi da 8k possono
|
|
533
|
+
// aggiungere ~80k token a ogni revisione della Guida.
|
|
534
|
+
for (const item of exchanges.slice(-40).reverse()) {
|
|
535
|
+
const body = item.text.length > 1_200 ? `${item.text.slice(0, 1_200)}…` : item.text;
|
|
536
|
+
const row = `[${item.seq}] ${item.from}->${item.to}: ${body}`;
|
|
537
|
+
if (used + row.length + 1 > maxChars)
|
|
538
|
+
break;
|
|
539
|
+
rows.push(row);
|
|
540
|
+
used += row.length + 1;
|
|
541
|
+
}
|
|
542
|
+
return rows.reverse().join("\n") || "(nessuno scambio)";
|
|
543
|
+
}
|
|
544
|
+
function consolidationPrompt(r1, r2, exchanges) {
|
|
545
|
+
return [
|
|
546
|
+
"Consolida ora il lavoro dei due main agent. Verifica lo stato reale del workspace e completa soltanto cio' che manca.",
|
|
547
|
+
"Restituisci una singola risposta finale all'utente, concreta e senza parlare di transcript interni.",
|
|
548
|
+
`OUTPUT R1:\n${r1.slice(-24_000)}`,
|
|
549
|
+
`OUTPUT R2:\n${r2.slice(-24_000)}`,
|
|
550
|
+
`SCAMBI ESPLICITI:\n${exchangeDigest(exchanges)}`,
|
|
551
|
+
].join("\n\n");
|
|
552
|
+
}
|
|
553
|
+
function correctionPrompt(action, summary, exchanges) {
|
|
554
|
+
return [
|
|
555
|
+
"La guida autonoma ha rilevato lavoro incompleto. Continua sul workspace reale, applica le correzioni e verifica con test proporzionati.",
|
|
556
|
+
`AZIONE ASSEGNATA:\n${action}`,
|
|
557
|
+
`VERDETTO:\n${summary}`,
|
|
558
|
+
`SCAMBI MAIN:\n${exchangeDigest(exchanges)}`,
|
|
559
|
+
].join("\n\n");
|
|
560
|
+
}
|
|
561
|
+
function guidePrompt(original, outputs, exchanges) {
|
|
562
|
+
const goal = typeof original === "string"
|
|
563
|
+
? original
|
|
564
|
+
: original.map((part) => part.type === "text" ? part.text : `[${part.type}]`).join("\n");
|
|
565
|
+
return [
|
|
566
|
+
"Revisiona autonomamente l'operato dei main agent rispetto alla richiesta.",
|
|
567
|
+
"Controlla il workspace con strumenti read-only e valuta gli esiti dei test prodotti dai main agent. Non fidarti soltanto dei loro riassunti.",
|
|
568
|
+
"Se il lavoro non e' completo, assegna un'azione concreta a r1 e/o r2. Rispondi esclusivamente nel JSON richiesto dal system.",
|
|
569
|
+
`RICHIESTA:\n${goal.slice(-30_000)}`,
|
|
570
|
+
`OUTPUT R1:\n${String(outputs.r1 || "").slice(-20_000)}`,
|
|
571
|
+
`OUTPUT R2:\n${String(outputs.r2 || "").slice(-20_000)}`,
|
|
572
|
+
`SCAMBI:\n${exchangeDigest(exchanges)}`,
|
|
573
|
+
].join("\n\n");
|
|
574
|
+
}
|
|
575
|
+
function guideDecisionPrompt(original, plan, exchanges, request) {
|
|
576
|
+
const goal = typeof original === "string"
|
|
577
|
+
? original
|
|
578
|
+
: original.map((part) => part.type === "text" ? part.text : `[${part.type}]`).join("\n");
|
|
579
|
+
const assigned = plan?.assignments[request.agent] ?? [];
|
|
580
|
+
return [
|
|
581
|
+
"Agisci come supervisore umano del run: valuta questa scelta PRIMA che venga eseguita.",
|
|
582
|
+
"Non limitarti a verificare se il comando e' tecnicamente possibile. Rifletti su necessita', proporzionalita', coerenza col piano, ownership, perdita dati, costo di CPU/RAM/tempo, concorrenza, rollback e alternative piu' sicure.",
|
|
583
|
+
"Nega idee bizzarre, non motivate, distruttive o duplicate. Approva solo quando l'azione serve davvero all'obiettivo ed e' confinata e recuperabile. Se mancano evidenze, nega e indica quali controlli read-only fare prima.",
|
|
584
|
+
"L'approvazione non sostituisce mai i permessi dell'utente.",
|
|
585
|
+
"Rispondi esclusivamente con JSON: {\"approved\":boolean,\"risk\":\"low|medium|high|critical\",\"reason\":string,\"guidance\":string}",
|
|
586
|
+
`OBIETTIVO UTENTE:\n${goal.slice(-24_000)}`,
|
|
587
|
+
`AGENTE PROPONENTE: ${request.agentName} (${request.agent})`,
|
|
588
|
+
`AZIONE: ${request.action}`,
|
|
589
|
+
`PROPOSTA E MOTIVAZIONE:\n${request.proposal}`,
|
|
590
|
+
`TASK ASSEGNATI:\n${assigned.length
|
|
591
|
+
? assigned.map((task) => `- ${task.id}: ${task.title}; ${task.details}`).join("\n")
|
|
592
|
+
: "- nessun task assegnato"}`,
|
|
593
|
+
`SCAMBI RECENTI:\n${exchangeDigest(exchanges)}`,
|
|
594
|
+
].join("\n\n");
|
|
595
|
+
}
|
|
596
|
+
function guidePlanningPrompt(original, mains, names) {
|
|
597
|
+
const goal = typeof original === "string"
|
|
598
|
+
? original
|
|
599
|
+
: original.map((part) => part.type === "text" ? part.text : `[${part.type}]`).join("\n");
|
|
600
|
+
return [
|
|
601
|
+
"Progetta il lavoro PRIMA che i main agent inizino. Ispeziona il workspace con tool read-only quando serve.",
|
|
602
|
+
"Assegna task precisi e non sovrapposti a ciascun main. Per i task che richiedono entrambi, dichiara lead, support e protocollo di handoff.",
|
|
603
|
+
"Non implementare. Rispondi esclusivamente con questo JSON:",
|
|
604
|
+
"{\"summary\":string,\"assignments\":{\"r1\":[{\"id\":string,\"title\":string,\"details\":string,\"cooperateWith\":\"r2\"?}],\"r2\":[{\"id\":string,\"title\":string,\"details\":string,\"cooperateWith\":\"r1\"?}]},\"cooperation\":[{\"id\":string,\"title\":string,\"lead\":\"r1|r2\",\"support\":\"r1|r2\",\"protocol\":string}]}",
|
|
605
|
+
`AGENTI ATTIVI:\n${mains.map((ref) => `${ref}=${names[ref]}`).join("\n")}`,
|
|
606
|
+
`RICHIESTA:\n${goal.slice(-30_000)}`,
|
|
607
|
+
].join("\n\n");
|
|
608
|
+
}
|
|
609
|
+
function assignmentPrompt(original, plan, self, names) {
|
|
610
|
+
const goal = typeof original === "string"
|
|
611
|
+
? original
|
|
612
|
+
: original.map((part) => part.type === "text" ? part.text : `[${part.type}]`).join("\n");
|
|
613
|
+
const tasks = plan.assignments[self];
|
|
614
|
+
const cooperation = plan.cooperation.filter((item) => item.lead === self || item.support === self);
|
|
615
|
+
return [
|
|
616
|
+
`La Guida ha assegnato il seguente perimetro a ${names[self]} (${self}).`,
|
|
617
|
+
"Esegui i task assegnati sul workspace reale. Non duplicare il lavoro del peer.",
|
|
618
|
+
"Per ogni cooperazione usa main_team_send prima dell'area condivisa e al completamento dell'handoff.",
|
|
619
|
+
`OBIETTIVO UTENTE:\n${goal.slice(-24_000)}`,
|
|
620
|
+
`PIANO:\n${plan.summary}`,
|
|
621
|
+
`TASK ASSEGNATI:\n${tasks.length
|
|
622
|
+
? tasks.map((task) => `- ${task.id}: ${task.title}\n ${task.details}${task.cooperateWith ? `\n coopera con ${names[task.cooperateWith]} (${task.cooperateWith})` : ""}`).join("\n")
|
|
623
|
+
: "- Nessun task operativo: verifica il peer e segnala eventuali blocchi."}`,
|
|
624
|
+
`COOPERAZIONI:\n${cooperation.length
|
|
625
|
+
? cooperation.map((item) => `- ${item.id}: ${item.title}; lead=${names[item.lead]}; support=${names[item.support]}; handoff=${item.protocol}`).join("\n")
|
|
626
|
+
: "- Nessuna"}`,
|
|
627
|
+
].join("\n\n");
|
|
628
|
+
}
|
|
629
|
+
function parseGuidePlan(text, mains) {
|
|
630
|
+
const empty = { r1: [], r2: [] };
|
|
631
|
+
const match = String(text || "").match(/\{[\s\S]*\}/);
|
|
632
|
+
if (!match)
|
|
633
|
+
return fallbackGuidePlan(mains, "La Guida non ha prodotto un piano valido.");
|
|
634
|
+
try {
|
|
635
|
+
const raw = JSON.parse(match[0]);
|
|
636
|
+
const assignmentsRaw = raw["assignments"] && typeof raw["assignments"] === "object"
|
|
637
|
+
? raw["assignments"]
|
|
638
|
+
: {};
|
|
639
|
+
for (const ref of mains) {
|
|
640
|
+
const rows = Array.isArray(assignmentsRaw[ref]) ? assignmentsRaw[ref] : [];
|
|
641
|
+
empty[ref] = rows.slice(0, 24).map((item, index) => {
|
|
642
|
+
const row = item && typeof item === "object" ? item : {};
|
|
643
|
+
const peer = row["cooperateWith"] === "r1" || row["cooperateWith"] === "r2"
|
|
644
|
+
? row["cooperateWith"]
|
|
645
|
+
: undefined;
|
|
646
|
+
return {
|
|
647
|
+
id: cleanPlanText(row["id"], `T${String(index + 1).padStart(2, "0")}`, 32),
|
|
648
|
+
title: cleanPlanText(row["title"], "Task assegnato", 240),
|
|
649
|
+
details: cleanPlanText(row["details"], "", 2_000),
|
|
650
|
+
...(peer && peer !== ref ? { cooperateWith: peer } : {}),
|
|
651
|
+
};
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
const cooperationRaw = Array.isArray(raw["cooperation"]) ? raw["cooperation"] : [];
|
|
655
|
+
const cooperation = cooperationRaw.slice(0, 24).map((item, index) => {
|
|
656
|
+
const row = item && typeof item === "object" ? item : {};
|
|
657
|
+
const lead = row["lead"] === "r2" ? "r2" : "r1";
|
|
658
|
+
const support = row["support"] === "r1" ? "r1" : "r2";
|
|
659
|
+
if (lead === support || !mains.includes(lead) || !mains.includes(support))
|
|
660
|
+
return null;
|
|
661
|
+
return {
|
|
662
|
+
id: cleanPlanText(row["id"], `C${String(index + 1).padStart(2, "0")}`, 32),
|
|
663
|
+
title: cleanPlanText(row["title"], "Cooperazione", 240),
|
|
664
|
+
lead,
|
|
665
|
+
support,
|
|
666
|
+
protocol: cleanPlanText(row["protocol"], "Condividere stato e risultato tramite main_team_send.", 2_000),
|
|
667
|
+
};
|
|
668
|
+
}).filter((item) => item !== null);
|
|
669
|
+
if (!empty.r1.length && mains.includes("r1"))
|
|
670
|
+
return fallbackGuidePlan(mains, cleanPlanText(raw["summary"], "Piano operativo", 4_000));
|
|
671
|
+
return {
|
|
672
|
+
summary: cleanPlanText(raw["summary"], "Piano operativo della Guida", 4_000),
|
|
673
|
+
assignments: empty,
|
|
674
|
+
cooperation,
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
catch {
|
|
678
|
+
return fallbackGuidePlan(mains, "La Guida ha restituito un piano JSON non valido.");
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
function fallbackGuidePlan(mains, summary) {
|
|
682
|
+
return {
|
|
683
|
+
summary,
|
|
684
|
+
assignments: {
|
|
685
|
+
r1: mains.includes("r1") ? [{ id: "T01", title: "Analizzare e completare la richiesta", details: "Operare sul workspace e verificare il risultato." }] : [],
|
|
686
|
+
r2: mains.includes("r2") ? [{ id: "T02", title: "Verificare evidenze e integrazione", details: "Controllare il lavoro, coprire i gap e comunicare risultati a r1.", cooperateWith: "r1" }] : [],
|
|
687
|
+
},
|
|
688
|
+
cooperation: mains.length === 2
|
|
689
|
+
? [{ id: "C01", title: "Integrazione finale", lead: "r1", support: "r2", protocol: "r2 invia evidenze e blocchi; r1 consolida e verifica." }]
|
|
690
|
+
: [],
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
function cleanPlanText(value, fallback, max) {
|
|
694
|
+
const clean = String(value || "").replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim();
|
|
695
|
+
return (clean || fallback).slice(0, max);
|
|
696
|
+
}
|
|
697
|
+
export function needsGuideArbitration(action, detail) {
|
|
698
|
+
const kind = String(action || "").toLowerCase();
|
|
699
|
+
const text = String(detail || "").toLowerCase();
|
|
700
|
+
if (kind === "kingdoms_warm")
|
|
701
|
+
return true;
|
|
702
|
+
if (kind !== "bash")
|
|
703
|
+
return false;
|
|
704
|
+
return [
|
|
705
|
+
/\b(?:rm|rmdir|del|erase)\b/,
|
|
706
|
+
/\bremove-item\b/,
|
|
707
|
+
/\b(?:rmtree|rimraf|rmsync|unlinksync|removedirectory)\b/,
|
|
708
|
+
/\b(?:shutil|fs)\s*\.\s*(?:rmtree|rm|unlink)\b/,
|
|
709
|
+
/\bos\s*\.\s*(?:remove|unlink|removedirs)\b/,
|
|
710
|
+
/\b(?:format|mkfs|diskpart|cipher\s+\/w)\b/,
|
|
711
|
+
/\b(?:drop|truncate)\s+(?:table|database|schema)\b/,
|
|
712
|
+
/\bgit\s+(?:clean|reset\s+--hard|checkout\s+--|restore\s+--source)\b/,
|
|
713
|
+
/\b(?:taskkill|stop-process|kill|pkill|killall)\b/,
|
|
714
|
+
/\b(?:docker|podman)\s+(?:system\s+prune|rm|rmi|volume\s+rm)\b/,
|
|
715
|
+
/\b(?:start-process|nohup)\b/,
|
|
716
|
+
/(?:^|\s)(?:&|start\s+\/b)(?:\s|$)/,
|
|
717
|
+
/\b(?:whisper|multiprocessing|threadpoolexecutor|processpoolexecutor)\b/,
|
|
718
|
+
/--workers(?:=|\s+)\d+/,
|
|
719
|
+
/(?:^|\s)-(?:j|jobs)(?:=|\s*)\d+/,
|
|
720
|
+
].some((pattern) => pattern.test(text));
|
|
721
|
+
}
|
|
722
|
+
function parseGuideDecision(text, requestId) {
|
|
723
|
+
const fallback = {
|
|
724
|
+
requestId,
|
|
725
|
+
approved: false,
|
|
726
|
+
risk: "high",
|
|
727
|
+
reason: "La Guida non ha prodotto una decisione strutturata valida.",
|
|
728
|
+
guidance: "Non procedere; raccogli evidenze read-only o chiedi all'utente.",
|
|
729
|
+
};
|
|
730
|
+
const match = String(text || "").match(/\{[\s\S]*\}/);
|
|
731
|
+
if (!match)
|
|
732
|
+
return fallback;
|
|
733
|
+
try {
|
|
734
|
+
const raw = JSON.parse(match[0]);
|
|
735
|
+
const risk = ["low", "medium", "high", "critical"].includes(String(raw["risk"]))
|
|
736
|
+
? String(raw["risk"])
|
|
737
|
+
: (raw["approved"] === true ? "medium" : "high");
|
|
738
|
+
return {
|
|
739
|
+
requestId,
|
|
740
|
+
approved: raw["approved"] === true,
|
|
741
|
+
risk,
|
|
742
|
+
reason: cleanPlanText(raw["reason"], fallback.reason, 4_000),
|
|
743
|
+
guidance: cleanPlanText(raw["guidance"], raw["approved"] === true ? "Procedere entro il perimetro approvato." : fallback.guidance, 4_000),
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
catch {
|
|
747
|
+
return fallback;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
function parseGuideVerdict(text) {
|
|
751
|
+
const match = String(text || "").match(/\{[\s\S]*\}/);
|
|
752
|
+
if (!match)
|
|
753
|
+
return { approved: false, summary: "La guida non ha prodotto un verdetto valido.", actions: { r1: "Verifica e completa il lavoro." } };
|
|
754
|
+
try {
|
|
755
|
+
const raw = JSON.parse(match[0]);
|
|
756
|
+
const actionsRaw = raw["actions"] && typeof raw["actions"] === "object"
|
|
757
|
+
? raw["actions"]
|
|
758
|
+
: {};
|
|
759
|
+
const actions = {};
|
|
760
|
+
for (const ref of ["r1", "r2"]) {
|
|
761
|
+
const value = String(actionsRaw[ref] || "").trim().slice(0, 8_000);
|
|
762
|
+
if (value)
|
|
763
|
+
actions[ref] = value;
|
|
764
|
+
}
|
|
765
|
+
return {
|
|
766
|
+
approved: raw["approved"] === true,
|
|
767
|
+
summary: String(raw["summary"] || "").trim().slice(0, 8_000) || "Nessun riepilogo della guida.",
|
|
768
|
+
actions,
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
catch {
|
|
772
|
+
return { approved: false, summary: "La guida ha restituito JSON non valido.", actions: { r1: "Verifica e completa il lavoro." } };
|
|
773
|
+
}
|
|
774
|
+
}
|