@andorra-labs/code 0.0.0-stage → 0.1.5
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.md +38 -0
- package/README.md +231 -3
- package/THIRD_PARTY_NOTICES.md +56 -0
- package/dist/src/account-presentation.d.ts +53 -0
- package/dist/src/account-presentation.js +99 -0
- package/dist/src/activity.d.ts +41 -0
- package/dist/src/activity.js +79 -0
- package/dist/src/agent-definitions.d.ts +61 -0
- package/dist/src/agent-definitions.js +303 -0
- package/dist/src/agent-execution.d.ts +4 -0
- package/dist/src/agent-execution.js +1198 -0
- package/dist/src/agent-mcp.d.ts +105 -0
- package/dist/src/agent-mcp.js +859 -0
- package/dist/src/agent-modifiers.d.ts +8 -0
- package/dist/src/agent-modifiers.js +333 -0
- package/dist/src/analytics.d.ts +81 -0
- package/dist/src/analytics.js +81 -0
- package/dist/src/anthropic-console-auth.d.ts +68 -0
- package/dist/src/anthropic-console-auth.js +318 -0
- package/dist/src/anthropic-credentials.d.ts +41 -0
- package/dist/src/anthropic-credentials.js +107 -0
- package/dist/src/app-server/protocol.d.ts +500 -0
- package/dist/src/app-server/protocol.js +106 -0
- package/dist/src/app-server/reasoning.d.ts +43 -0
- package/dist/src/app-server/reasoning.js +173 -0
- package/dist/src/app-server/terminal.d.ts +77 -0
- package/dist/src/app-server/terminal.js +177 -0
- package/dist/src/app-server/workspace.d.ts +247 -0
- package/dist/src/app-server/workspace.js +1098 -0
- package/dist/src/app-server.d.ts +1039 -0
- package/dist/src/app-server.js +6594 -0
- package/dist/src/artifacts.d.ts +27 -0
- package/dist/src/artifacts.js +103 -0
- package/dist/src/attachments.d.ts +158 -0
- package/dist/src/attachments.js +466 -0
- package/dist/src/auth/AuthManager.d.ts +110 -0
- package/dist/src/auth/AuthManager.js +435 -0
- package/dist/src/auth/callback.d.ts +10 -0
- package/dist/src/auth/callback.js +96 -0
- package/dist/src/auth/deployment.d.ts +18 -0
- package/dist/src/auth/deployment.js +18 -0
- package/dist/src/auth/index.d.ts +31 -0
- package/dist/src/auth/index.js +27 -0
- package/dist/src/auth/lock.d.ts +2 -0
- package/dist/src/auth/lock.js +29 -0
- package/dist/src/auth/store.d.ts +20 -0
- package/dist/src/auth/store.js +93 -0
- package/dist/src/auth/types.d.ts +24 -0
- package/dist/src/auth/types.js +8 -0
- package/dist/src/auth-commands.d.ts +5 -0
- package/dist/src/auth-commands.js +28 -0
- package/dist/src/automation-runner.d.ts +7 -0
- package/dist/src/automation-runner.js +113 -0
- package/dist/src/automation-service.d.ts +28 -0
- package/dist/src/automation-service.js +299 -0
- package/dist/src/automation-tool.d.ts +2 -0
- package/dist/src/automation-tool.js +49 -0
- package/dist/src/automation-worker-shutdown.d.ts +3 -0
- package/dist/src/automation-worker-shutdown.js +13 -0
- package/dist/src/automations.d.ts +63 -0
- package/dist/src/automations.js +265 -0
- package/dist/src/boot-trace.d.ts +15 -0
- package/dist/src/boot-trace.js +25 -0
- package/dist/src/browser-activity.d.ts +4 -0
- package/dist/src/browser-activity.js +18 -0
- package/dist/src/browser-bridge.d.ts +56 -0
- package/dist/src/browser-bridge.js +372 -0
- package/dist/src/browser-observation.d.ts +24 -0
- package/dist/src/browser-observation.js +104 -0
- package/dist/src/browser-panel-tool.d.ts +39 -0
- package/dist/src/browser-panel-tool.js +227 -0
- package/dist/src/browser-runner.d.ts +16 -0
- package/dist/src/browser-runner.js +302 -0
- package/dist/src/browser-server.d.ts +31 -0
- package/dist/src/browser-server.js +1189 -0
- package/dist/src/browser-session.d.ts +19 -0
- package/dist/src/browser-session.js +649 -0
- package/dist/src/browser-ui/andorra-logo.png +0 -0
- package/dist/src/browser-ui/app.js +419 -0
- package/dist/src/browser-ui/index.html +13 -0
- package/dist/src/browser-ui/style.css +243 -0
- package/dist/src/browser-view.d.ts +348 -0
- package/dist/src/browser-view.js +1487 -0
- package/dist/src/capabilities.d.ts +9 -0
- package/dist/src/capabilities.js +135 -0
- package/dist/src/clarification-ui.d.ts +23 -0
- package/dist/src/clarification-ui.js +59 -0
- package/dist/src/claude-executable.d.ts +6 -0
- package/dist/src/claude-executable.js +56 -0
- package/dist/src/claude-provider.d.ts +35 -0
- package/dist/src/claude-provider.js +391 -0
- package/dist/src/cli.d.ts +85 -0
- package/dist/src/cli.js +2564 -0
- package/dist/src/code-intelligence/CodeIntelligenceManager.d.ts +108 -0
- package/dist/src/code-intelligence/CodeIntelligenceManager.js +616 -0
- package/dist/src/code-intelligence/ContextLedger.d.ts +32 -0
- package/dist/src/code-intelligence/ContextLedger.js +77 -0
- package/dist/src/code-intelligence/ContextRouter.d.ts +8 -0
- package/dist/src/code-intelligence/ContextRouter.js +18 -0
- package/dist/src/code-intelligence/codegraph/CodeGraphProjectSession.d.ts +82 -0
- package/dist/src/code-intelligence/codegraph/CodeGraphProjectSession.js +444 -0
- package/dist/src/code-intelligence/codegraph/CodeGraphProvider.d.ts +40 -0
- package/dist/src/code-intelligence/codegraph/CodeGraphProvider.js +84 -0
- package/dist/src/code-intelligence/codegraph/CodeGraphSyncBarrier.d.ts +22 -0
- package/dist/src/code-intelligence/codegraph/CodeGraphSyncBarrier.js +71 -0
- package/dist/src/code-intelligence/codegraph/repoExploreTool.d.ts +9 -0
- package/dist/src/code-intelligence/codegraph/repoExploreTool.js +26 -0
- package/dist/src/code-intelligence/repository.d.ts +13 -0
- package/dist/src/code-intelligence/repository.js +48 -0
- package/dist/src/code-intelligence/types.d.ts +78 -0
- package/dist/src/code-intelligence/types.js +3 -0
- package/dist/src/codex-auth.d.ts +83 -0
- package/dist/src/codex-auth.js +168 -0
- package/dist/src/codex-browser-auth.d.ts +74 -0
- package/dist/src/codex-browser-auth.js +429 -0
- package/dist/src/codex-errors.d.ts +3 -0
- package/dist/src/codex-errors.js +50 -0
- package/dist/src/codex-executable.d.ts +12 -0
- package/dist/src/codex-executable.js +154 -0
- package/dist/src/codex-provider.d.ts +25 -0
- package/dist/src/codex-provider.js +211 -0
- package/dist/src/codex-rpc.d.ts +43 -0
- package/dist/src/codex-rpc.js +136 -0
- package/dist/src/coding-tools.d.ts +19 -0
- package/dist/src/coding-tools.js +875 -0
- package/dist/src/command-metrics.d.ts +17 -0
- package/dist/src/command-metrics.js +34 -0
- package/dist/src/command-screens.d.ts +44 -0
- package/dist/src/command-screens.js +601 -0
- package/dist/src/commands.d.ts +111 -0
- package/dist/src/commands.js +550 -0
- package/dist/src/completion.d.ts +45 -0
- package/dist/src/completion.js +195 -0
- package/dist/src/config.d.ts +163 -0
- package/dist/src/config.js +663 -0
- package/dist/src/context-budget.d.ts +32 -0
- package/dist/src/context-budget.js +151 -0
- package/dist/src/context-compaction.d.ts +43 -0
- package/dist/src/context-compaction.js +269 -0
- package/dist/src/context-selection.d.ts +65 -0
- package/dist/src/context-selection.js +130 -0
- package/dist/src/dashboard-view.d.ts +37 -0
- package/dist/src/dashboard-view.js +254 -0
- package/dist/src/dashboard.d.ts +41 -0
- package/dist/src/dashboard.js +160 -0
- package/dist/src/deadline.d.ts +55 -0
- package/dist/src/deadline.js +164 -0
- package/dist/src/decision/ContinuationAdapter.d.ts +6 -0
- package/dist/src/decision/ContinuationAdapter.js +11 -0
- package/dist/src/decision/DecisionEngine.d.ts +23 -0
- package/dist/src/decision/DecisionEngine.js +1 -0
- package/dist/src/decision/DecisionManager.d.ts +47 -0
- package/dist/src/decision/DecisionManager.js +280 -0
- package/dist/src/decision/DecisionPolicy.d.ts +8 -0
- package/dist/src/decision/DecisionPolicy.js +54 -0
- package/dist/src/decision/FactContinuations.d.ts +147 -0
- package/dist/src/decision/FactContinuations.js +472 -0
- package/dist/src/decision/FactServiceGate.d.ts +12 -0
- package/dist/src/decision/FactServiceGate.js +37 -0
- package/dist/src/decision/PreparedSteps.d.ts +51 -0
- package/dist/src/decision/PreparedSteps.js +147 -0
- package/dist/src/decision/applyToolMenu.d.ts +3 -0
- package/dist/src/decision/applyToolMenu.js +61 -0
- package/dist/src/decision/checks.d.ts +13 -0
- package/dist/src/decision/checks.js +104 -0
- package/dist/src/decision/facts.d.ts +64 -0
- package/dist/src/decision/facts.js +90 -0
- package/dist/src/decision/guidancePolicy.d.ts +3 -0
- package/dist/src/decision/guidancePolicy.js +10 -0
- package/dist/src/decision/hostedPolicy.d.ts +14 -0
- package/dist/src/decision/hostedPolicy.js +21 -0
- package/dist/src/decision/index.d.ts +6 -0
- package/dist/src/decision/index.js +6 -0
- package/dist/src/decision/optimizationPolicy.d.ts +26 -0
- package/dist/src/decision/optimizationPolicy.js +38 -0
- package/dist/src/decision/providers/AndorraDecisionProvider.d.ts +17 -0
- package/dist/src/decision/providers/AndorraDecisionProvider.js +251 -0
- package/dist/src/decision/providers/HttpDecisionProvider.d.ts +16 -0
- package/dist/src/decision/providers/HttpDecisionProvider.js +105 -0
- package/dist/src/decision/providers/NoOpDecisionProvider.d.ts +4 -0
- package/dist/src/decision/providers/NoOpDecisionProvider.js +3 -0
- package/dist/src/decision/providers/index.d.ts +3 -0
- package/dist/src/decision/providers/index.js +13 -0
- package/dist/src/decision/providers/questions.d.ts +3 -0
- package/dist/src/decision/providers/questions.js +31 -0
- package/dist/src/decision/routeTools.d.ts +59 -0
- package/dist/src/decision/routeTools.js +131 -0
- package/dist/src/decision/toolFamilies.d.ts +7 -0
- package/dist/src/decision/toolFamilies.js +55 -0
- package/dist/src/decision/toolMenu.d.ts +35 -0
- package/dist/src/decision/toolMenu.js +73 -0
- package/dist/src/decision/types.d.ts +99 -0
- package/dist/src/decision/types.js +1 -0
- package/dist/src/diff-preview.d.ts +6 -0
- package/dist/src/diff-preview.js +120 -0
- package/dist/src/duration.d.ts +44 -0
- package/dist/src/duration.js +72 -0
- package/dist/src/efficiency.d.ts +101 -0
- package/dist/src/efficiency.js +104 -0
- package/dist/src/engine/protocol.d.ts +11 -0
- package/dist/src/engine/protocol.js +51 -0
- package/dist/src/extensions.d.ts +46 -0
- package/dist/src/extensions.js +846 -0
- package/dist/src/favicons.d.ts +37 -0
- package/dist/src/favicons.js +216 -0
- package/dist/src/file-read-state.d.ts +8 -0
- package/dist/src/file-read-state.js +31 -0
- package/dist/src/git-summary.d.ts +67 -0
- package/dist/src/git-summary.js +461 -0
- package/dist/src/goal-completion-verification.d.ts +18 -0
- package/dist/src/goal-completion-verification.js +43 -0
- package/dist/src/graph-account.d.ts +31 -0
- package/dist/src/graph-account.js +57 -0
- package/dist/src/graph-editor-session.d.ts +15 -0
- package/dist/src/graph-editor-session.js +70 -0
- package/dist/src/graph-health.d.ts +88 -0
- package/dist/src/graph-health.js +243 -0
- package/dist/src/graph-provider-portability.d.ts +30 -0
- package/dist/src/graph-provider-portability.js +197 -0
- package/dist/src/graph-quota.d.ts +55 -0
- package/dist/src/graph-quota.js +131 -0
- package/dist/src/graph-runner.d.ts +4 -0
- package/dist/src/graph-runner.js +1356 -0
- package/dist/src/graph-selection.d.ts +17 -0
- package/dist/src/graph-selection.js +31 -0
- package/dist/src/graph-server.d.ts +13 -0
- package/dist/src/graph-server.js +483 -0
- package/dist/src/graph-studio-features.d.ts +61 -0
- package/dist/src/graph-studio-features.js +348 -0
- package/dist/src/graph-sync.d.ts +76 -0
- package/dist/src/graph-sync.js +619 -0
- package/dist/src/graph-ui/andorra-logo.png +0 -0
- package/dist/src/graph-ui/app.js +1803 -0
- package/dist/src/graph-ui/compat.js +43 -0
- package/dist/src/graph-ui/controls.css +190 -0
- package/dist/src/graph-ui/controls.js +567 -0
- package/dist/src/graph-ui/edge-router.js +117 -0
- package/dist/src/graph-ui/embed.js +324 -0
- package/dist/src/graph-ui/fonts/geist-mono-latin-400-normal.woff2 +0 -0
- package/dist/src/graph-ui/fonts/geist-sans-latin-400-normal.woff2 +0 -0
- package/dist/src/graph-ui/fonts/geist-sans-latin-500-normal.woff2 +0 -0
- package/dist/src/graph-ui/icons.js +117 -0
- package/dist/src/graph-ui/index.html +7 -0
- package/dist/src/graph-ui/library.css +26 -0
- package/dist/src/graph-ui/sidebar.js +61 -0
- package/dist/src/graph-ui/studio-canvas.js +454 -0
- package/dist/src/graph-ui/studio.css +110 -0
- package/dist/src/graph-ui/studio.js +720 -0
- package/dist/src/graph-ui/style.css +477 -0
- package/dist/src/graph-ui/theme.js +92 -0
- package/dist/src/graph-ui/tokens.css +187 -0
- package/dist/src/graphs.d.ts +270 -0
- package/dist/src/graphs.js +1102 -0
- package/dist/src/grep-regex-worker.d.ts +1 -0
- package/dist/src/grep-regex-worker.js +20 -0
- package/dist/src/grep-regex.d.ts +11 -0
- package/dist/src/grep-regex.js +64 -0
- package/dist/src/handoffs.d.ts +34 -0
- package/dist/src/handoffs.js +229 -0
- package/dist/src/hardened-runtime.d.ts +14 -0
- package/dist/src/hardened-runtime.js +264 -0
- package/dist/src/limits.d.ts +77 -0
- package/dist/src/limits.js +88 -0
- package/dist/src/markdown.d.ts +31 -0
- package/dist/src/markdown.js +553 -0
- package/dist/src/mcp.d.ts +11 -0
- package/dist/src/mcp.js +175 -0
- package/dist/src/membership-errors.d.ts +4 -0
- package/dist/src/membership-errors.js +4 -0
- package/dist/src/membership.d.ts +81 -0
- package/dist/src/membership.js +247 -0
- package/dist/src/memory/LocalToolMemory.d.ts +20 -0
- package/dist/src/memory/LocalToolMemory.js +114 -0
- package/dist/src/memory/MemoryDistiller.d.ts +35 -0
- package/dist/src/memory/MemoryDistiller.js +216 -0
- package/dist/src/memory/MemoryManager.d.ts +76 -0
- package/dist/src/memory/MemoryManager.js +386 -0
- package/dist/src/memory/MemoryPolicy.d.ts +30 -0
- package/dist/src/memory/MemoryPolicy.js +96 -0
- package/dist/src/memory/MemoryProvider.d.ts +18 -0
- package/dist/src/memory/MemoryProvider.js +1 -0
- package/dist/src/memory/MemoryRetriever.d.ts +27 -0
- package/dist/src/memory/MemoryRetriever.js +149 -0
- package/dist/src/memory/PermissionMemoryProvider.d.ts +22 -0
- package/dist/src/memory/PermissionMemoryProvider.js +50 -0
- package/dist/src/memory/ToolFailureLessons.d.ts +39 -0
- package/dist/src/memory/ToolFailureLessons.js +167 -0
- package/dist/src/memory/index.d.ts +12 -0
- package/dist/src/memory/index.js +11 -0
- package/dist/src/memory/providers/NoOpMemoryProvider.d.ts +13 -0
- package/dist/src/memory/providers/NoOpMemoryProvider.js +15 -0
- package/dist/src/memory/providers/graphiti/GraphitiClient.d.ts +27 -0
- package/dist/src/memory/providers/graphiti/GraphitiClient.js +76 -0
- package/dist/src/memory/providers/graphiti/GraphitiMapper.d.ts +6 -0
- package/dist/src/memory/providers/graphiti/GraphitiMapper.js +116 -0
- package/dist/src/memory/providers/graphiti/GraphitiMemoryProvider.d.ts +27 -0
- package/dist/src/memory/providers/graphiti/GraphitiMemoryProvider.js +137 -0
- package/dist/src/memory/providers/graphiti/GraphitiTypes.d.ts +57 -0
- package/dist/src/memory/providers/graphiti/GraphitiTypes.js +2 -0
- package/dist/src/memory/redaction.d.ts +11 -0
- package/dist/src/memory/redaction.js +58 -0
- package/dist/src/memory/repository.d.ts +11 -0
- package/dist/src/memory/repository.js +74 -0
- package/dist/src/memory/tools/memorySearchTool.d.ts +4 -0
- package/dist/src/memory/tools/memorySearchTool.js +77 -0
- package/dist/src/memory/types.d.ts +112 -0
- package/dist/src/memory/types.js +7 -0
- package/dist/src/model-metadata.d.ts +28 -0
- package/dist/src/model-metadata.js +274 -0
- package/dist/src/model-override.d.ts +60 -0
- package/dist/src/model-override.js +146 -0
- package/dist/src/model-tiers.d.ts +61 -0
- package/dist/src/model-tiers.js +109 -0
- package/dist/src/opencode-catalog.d.ts +16 -0
- package/dist/src/opencode-catalog.js +135 -0
- package/dist/src/opencode-provider.d.ts +10 -0
- package/dist/src/opencode-provider.js +525 -0
- package/dist/src/paged-transcript.d.ts +58 -0
- package/dist/src/paged-transcript.js +205 -0
- package/dist/src/palette.d.ts +61 -0
- package/dist/src/palette.js +63 -0
- package/dist/src/permissions.d.ts +36 -0
- package/dist/src/permissions.js +93 -0
- package/dist/src/powershell-pool.d.ts +26 -0
- package/dist/src/powershell-pool.js +235 -0
- package/dist/src/profile.d.ts +80 -0
- package/dist/src/profile.js +200 -0
- package/dist/src/provider-connection.d.ts +36 -0
- package/dist/src/provider-connection.js +222 -0
- package/dist/src/provider-engine.d.ts +37 -0
- package/dist/src/provider-engine.js +401 -0
- package/dist/src/provider-import.d.ts +68 -0
- package/dist/src/provider-import.js +355 -0
- package/dist/src/provider-settings.d.ts +8 -0
- package/dist/src/provider-settings.js +451 -0
- package/dist/src/providers.d.ts +219 -0
- package/dist/src/providers.js +1230 -0
- package/dist/src/pull-requests.d.ts +195 -0
- package/dist/src/pull-requests.js +514 -0
- package/dist/src/qa/api/http-runner.d.ts +3 -0
- package/dist/src/qa/api/http-runner.js +47 -0
- package/dist/src/qa/browser/PlaywrightRunner.d.ts +21 -0
- package/dist/src/qa/browser/PlaywrightRunner.js +190 -0
- package/dist/src/qa/command-policy.d.ts +28 -0
- package/dist/src/qa/command-policy.js +122 -0
- package/dist/src/qa/git/ChangeDetector.d.ts +26 -0
- package/dist/src/qa/git/ChangeDetector.js +177 -0
- package/dist/src/qa/git/DiffReviewer.d.ts +28 -0
- package/dist/src/qa/git/DiffReviewer.js +115 -0
- package/dist/src/qa/index.d.ts +11 -0
- package/dist/src/qa/index.js +19 -0
- package/dist/src/qa/orchestrator/ChangeClassifier.d.ts +14 -0
- package/dist/src/qa/orchestrator/ChangeClassifier.js +28 -0
- package/dist/src/qa/orchestrator/MergeGate.d.ts +14 -0
- package/dist/src/qa/orchestrator/MergeGate.js +40 -0
- package/dist/src/qa/orchestrator/QaOrchestrator.d.ts +79 -0
- package/dist/src/qa/orchestrator/QaOrchestrator.js +373 -0
- package/dist/src/qa/profile/ProjectInspector.d.ts +9 -0
- package/dist/src/qa/profile/ProjectInspector.js +295 -0
- package/dist/src/qa/profile/QaConfigLoader.d.ts +43 -0
- package/dist/src/qa/profile/QaConfigLoader.js +261 -0
- package/dist/src/qa/profile/QaProfile.d.ts +17 -0
- package/dist/src/qa/profile/QaProfile.js +15 -0
- package/dist/src/qa/profile/yaml.d.ts +12 -0
- package/dist/src/qa/profile/yaml.js +203 -0
- package/dist/src/qa/qa-authorize.d.ts +25 -0
- package/dist/src/qa/qa-authorize.js +82 -0
- package/dist/src/qa/runners/CommandRunner.d.ts +22 -0
- package/dist/src/qa/runners/CommandRunner.js +96 -0
- package/dist/src/qa/runners/TestRunner.d.ts +21 -0
- package/dist/src/qa/runners/TestRunner.js +66 -0
- package/dist/src/qa/runtime/ProcessManager.d.ts +53 -0
- package/dist/src/qa/runtime/ProcessManager.js +225 -0
- package/dist/src/qa/runtime/PtyManager.d.ts +57 -0
- package/dist/src/qa/runtime/PtyManager.js +338 -0
- package/dist/src/qa/runtime/RuntimeSmoke.d.ts +11 -0
- package/dist/src/qa/runtime/RuntimeSmoke.js +78 -0
- package/dist/src/qa/runtime-detect.d.ts +10 -0
- package/dist/src/qa/runtime-detect.js +72 -0
- package/dist/src/qa/security/DependencyScanner.d.ts +19 -0
- package/dist/src/qa/security/DependencyScanner.js +167 -0
- package/dist/src/qa/security/SecretScanner.d.ts +3 -0
- package/dist/src/qa/security/SecretScanner.js +55 -0
- package/dist/src/qa/tools.d.ts +3 -0
- package/dist/src/qa/tools.js +301 -0
- package/dist/src/qa/types.d.ts +134 -0
- package/dist/src/qa/types.js +3 -0
- package/dist/src/react-runtime.d.ts +53 -0
- package/dist/src/react-runtime.js +1753 -0
- package/dist/src/remote/cert.d.ts +29 -0
- package/dist/src/remote/cert.js +136 -0
- package/dist/src/remote/client.d.ts +189 -0
- package/dist/src/remote/client.js +659 -0
- package/dist/src/remote/command.d.ts +4 -0
- package/dist/src/remote/command.js +211 -0
- package/dist/src/remote/engine-pool.d.ts +230 -0
- package/dist/src/remote/engine-pool.js +1160 -0
- package/dist/src/remote/errors.d.ts +26 -0
- package/dist/src/remote/errors.js +21 -0
- package/dist/src/remote/network.d.ts +48 -0
- package/dist/src/remote/network.js +135 -0
- package/dist/src/remote/pairing.d.ts +98 -0
- package/dist/src/remote/pairing.js +306 -0
- package/dist/src/remote/roots.d.ts +29 -0
- package/dist/src/remote/roots.js +44 -0
- package/dist/src/remote/serve.d.ts +115 -0
- package/dist/src/remote/serve.js +274 -0
- package/dist/src/remote/server.d.ts +35 -0
- package/dist/src/remote/server.js +484 -0
- package/dist/src/remote/types.d.ts +86 -0
- package/dist/src/remote/types.js +11 -0
- package/dist/src/run-control.d.ts +17 -0
- package/dist/src/run-control.js +52 -0
- package/dist/src/run-progress.d.ts +226 -0
- package/dist/src/run-progress.js +724 -0
- package/dist/src/run-records.d.ts +500 -0
- package/dist/src/run-records.js +1678 -0
- package/dist/src/runtime.d.ts +418 -0
- package/dist/src/runtime.js +247 -0
- package/dist/src/sandbox-child.d.ts +1 -0
- package/dist/src/sandbox-child.js +14 -0
- package/dist/src/save-lock.d.ts +9 -0
- package/dist/src/save-lock.js +186 -0
- package/dist/src/session-monitor.d.ts +98 -0
- package/dist/src/session-monitor.js +323 -0
- package/dist/src/session-reaper.d.ts +23 -0
- package/dist/src/session-reaper.js +33 -0
- package/dist/src/session-summary.d.ts +27 -0
- package/dist/src/session-summary.js +66 -0
- package/dist/src/session-title.d.ts +18 -0
- package/dist/src/session-title.js +54 -0
- package/dist/src/sessions.d.ts +211 -0
- package/dist/src/sessions.js +620 -0
- package/dist/src/shell.d.ts +40 -0
- package/dist/src/shell.js +504 -0
- package/dist/src/side-panel.d.ts +144 -0
- package/dist/src/side-panel.js +366 -0
- package/dist/src/skill-commands.d.ts +1 -0
- package/dist/src/skill-commands.js +11 -0
- package/dist/src/skills/bundled/ai-elements/SKILL.md +155 -0
- package/dist/src/skills/bundled/ai-elements/references/agent.md +138 -0
- package/dist/src/skills/bundled/ai-elements/references/artifact.md +91 -0
- package/dist/src/skills/bundled/ai-elements/references/attachments.md +197 -0
- package/dist/src/skills/bundled/ai-elements/references/audio-player.md +141 -0
- package/dist/src/skills/bundled/ai-elements/references/canvas.md +39 -0
- package/dist/src/skills/bundled/ai-elements/references/chain-of-thought.md +88 -0
- package/dist/src/skills/bundled/ai-elements/references/checkpoint.md +171 -0
- package/dist/src/skills/bundled/ai-elements/references/code-block.md +177 -0
- package/dist/src/skills/bundled/ai-elements/references/commit.md +184 -0
- package/dist/src/skills/bundled/ai-elements/references/confirmation.md +268 -0
- package/dist/src/skills/bundled/ai-elements/references/connection.md +39 -0
- package/dist/src/skills/bundled/ai-elements/references/context.md +133 -0
- package/dist/src/skills/bundled/ai-elements/references/controls.md +37 -0
- package/dist/src/skills/bundled/ai-elements/references/conversation.md +224 -0
- package/dist/src/skills/bundled/ai-elements/references/edge.md +57 -0
- package/dist/src/skills/bundled/ai-elements/references/environment-variables.md +109 -0
- package/dist/src/skills/bundled/ai-elements/references/file-tree.md +79 -0
- package/dist/src/skills/bundled/ai-elements/references/image.md +150 -0
- package/dist/src/skills/bundled/ai-elements/references/inline-citation.md +300 -0
- package/dist/src/skills/bundled/ai-elements/references/jsx-preview.md +108 -0
- package/dist/src/skills/bundled/ai-elements/references/message.md +231 -0
- package/dist/src/skills/bundled/ai-elements/references/mic-selector.md +193 -0
- package/dist/src/skills/bundled/ai-elements/references/model-selector.md +119 -0
- package/dist/src/skills/bundled/ai-elements/references/node.md +78 -0
- package/dist/src/skills/bundled/ai-elements/references/open-in-chat.md +74 -0
- package/dist/src/skills/bundled/ai-elements/references/package-info.md +102 -0
- package/dist/src/skills/bundled/ai-elements/references/panel.md +38 -0
- package/dist/src/skills/bundled/ai-elements/references/persona.md +173 -0
- package/dist/src/skills/bundled/ai-elements/references/plan.md +86 -0
- package/dist/src/skills/bundled/ai-elements/references/prompt-input.md +572 -0
- package/dist/src/skills/bundled/ai-elements/references/queue.md +179 -0
- package/dist/src/skills/bundled/ai-elements/references/reasoning.md +226 -0
- package/dist/src/skills/bundled/ai-elements/references/sandbox.md +133 -0
- package/dist/src/skills/bundled/ai-elements/references/schema-display.md +109 -0
- package/dist/src/skills/bundled/ai-elements/references/shimmer.md +55 -0
- package/dist/src/skills/bundled/ai-elements/references/snippet.md +71 -0
- package/dist/src/skills/bundled/ai-elements/references/sources.md +200 -0
- package/dist/src/skills/bundled/ai-elements/references/speech-input.md +167 -0
- package/dist/src/skills/bundled/ai-elements/references/stack-trace.md +225 -0
- package/dist/src/skills/bundled/ai-elements/references/suggestion.md +128 -0
- package/dist/src/skills/bundled/ai-elements/references/task.md +222 -0
- package/dist/src/skills/bundled/ai-elements/references/terminal.md +110 -0
- package/dist/src/skills/bundled/ai-elements/references/test-results.md +164 -0
- package/dist/src/skills/bundled/ai-elements/references/tool.md +282 -0
- package/dist/src/skills/bundled/ai-elements/references/toolbar.md +37 -0
- package/dist/src/skills/bundled/ai-elements/references/transcription.md +127 -0
- package/dist/src/skills/bundled/ai-elements/references/voice-selector.md +248 -0
- package/dist/src/skills/bundled/ai-elements/references/web-preview.md +204 -0
- package/dist/src/skills/bundled/ai-elements/scripts/agent.tsx +67 -0
- package/dist/src/skills/bundled/ai-elements/scripts/artifact.tsx +117 -0
- package/dist/src/skills/bundled/ai-elements/scripts/attachments-inline.tsx +123 -0
- package/dist/src/skills/bundled/ai-elements/scripts/attachments-list.tsx +94 -0
- package/dist/src/skills/bundled/ai-elements/scripts/attachments.tsx +84 -0
- package/dist/src/skills/bundled/ai-elements/scripts/audio-player-remote.tsx +35 -0
- package/dist/src/skills/bundled/ai-elements/scripts/audio-player.tsx +74 -0
- package/dist/src/skills/bundled/ai-elements/scripts/chain-of-thought.tsx +80 -0
- package/dist/src/skills/bundled/ai-elements/scripts/checkpoint.tsx +96 -0
- package/dist/src/skills/bundled/ai-elements/scripts/code-block-dark.tsx +46 -0
- package/dist/src/skills/bundled/ai-elements/scripts/code-block.tsx +120 -0
- package/dist/src/skills/bundled/ai-elements/scripts/commit.tsx +94 -0
- package/dist/src/skills/bundled/ai-elements/scripts/confirmation-accepted.tsx +41 -0
- package/dist/src/skills/bundled/ai-elements/scripts/confirmation-rejected.tsx +41 -0
- package/dist/src/skills/bundled/ai-elements/scripts/confirmation-request.tsx +54 -0
- package/dist/src/skills/bundled/ai-elements/scripts/confirmation.tsx +59 -0
- package/dist/src/skills/bundled/ai-elements/scripts/context.tsx +45 -0
- package/dist/src/skills/bundled/ai-elements/scripts/conversation.tsx +182 -0
- package/dist/src/skills/bundled/ai-elements/scripts/environment-variables.tsx +61 -0
- package/dist/src/skills/bundled/ai-elements/scripts/file-tree-basic.tsx +20 -0
- package/dist/src/skills/bundled/ai-elements/scripts/file-tree-expanded.tsx +23 -0
- package/dist/src/skills/bundled/ai-elements/scripts/file-tree-selection.tsx +26 -0
- package/dist/src/skills/bundled/ai-elements/scripts/file-tree.tsx +44 -0
- package/dist/src/skills/bundled/ai-elements/scripts/image.tsx +20 -0
- package/dist/src/skills/bundled/ai-elements/scripts/inline-citation.tsx +101 -0
- package/dist/src/skills/bundled/ai-elements/scripts/jsx-preview.tsx +105 -0
- package/dist/src/skills/bundled/ai-elements/scripts/message.tsx +330 -0
- package/dist/src/skills/bundled/ai-elements/scripts/mic-selector.tsx +52 -0
- package/dist/src/skills/bundled/ai-elements/scripts/model-selector.tsx +368 -0
- package/dist/src/skills/bundled/ai-elements/scripts/open-in-chat.tsx +33 -0
- package/dist/src/skills/bundled/ai-elements/scripts/package-info.tsx +52 -0
- package/dist/src/skills/bundled/ai-elements/scripts/persona-command.tsx +101 -0
- package/dist/src/skills/bundled/ai-elements/scripts/persona-glint.tsx +101 -0
- package/dist/src/skills/bundled/ai-elements/scripts/persona-halo.tsx +101 -0
- package/dist/src/skills/bundled/ai-elements/scripts/persona-mana.tsx +101 -0
- package/dist/src/skills/bundled/ai-elements/scripts/persona-obsidian.tsx +101 -0
- package/dist/src/skills/bundled/ai-elements/scripts/persona-opal.tsx +101 -0
- package/dist/src/skills/bundled/ai-elements/scripts/plan.tsx +69 -0
- package/dist/src/skills/bundled/ai-elements/scripts/prompt-input-cursor.tsx +462 -0
- package/dist/src/skills/bundled/ai-elements/scripts/prompt-input-tooltip.tsx +46 -0
- package/dist/src/skills/bundled/ai-elements/scripts/prompt-input.tsx +254 -0
- package/dist/src/skills/bundled/ai-elements/scripts/queue-prompt-input.tsx +372 -0
- package/dist/src/skills/bundled/ai-elements/scripts/queue.tsx +281 -0
- package/dist/src/skills/bundled/ai-elements/scripts/reasoning.tsx +73 -0
- package/dist/src/skills/bundled/ai-elements/scripts/sandbox.tsx +171 -0
- package/dist/src/skills/bundled/ai-elements/scripts/schema-display-basic.tsx +13 -0
- package/dist/src/skills/bundled/ai-elements/scripts/schema-display-body.tsx +20 -0
- package/dist/src/skills/bundled/ai-elements/scripts/schema-display-nested.tsx +23 -0
- package/dist/src/skills/bundled/ai-elements/scripts/schema-display-params.tsx +16 -0
- package/dist/src/skills/bundled/ai-elements/scripts/schema-display.tsx +110 -0
- package/dist/src/skills/bundled/ai-elements/scripts/shimmer-duration.tsx +35 -0
- package/dist/src/skills/bundled/ai-elements/scripts/shimmer-elements.tsx +45 -0
- package/dist/src/skills/bundled/ai-elements/scripts/shimmer.tsx +17 -0
- package/dist/src/skills/bundled/ai-elements/scripts/snippet-plain.tsx +19 -0
- package/dist/src/skills/bundled/ai-elements/scripts/snippet.tsx +25 -0
- package/dist/src/skills/bundled/ai-elements/scripts/sources-custom.tsx +40 -0
- package/dist/src/skills/bundled/ai-elements/scripts/sources.tsx +33 -0
- package/dist/src/skills/bundled/ai-elements/scripts/speech-input.tsx +85 -0
- package/dist/src/skills/bundled/ai-elements/scripts/stack-trace-collapsed.tsx +39 -0
- package/dist/src/skills/bundled/ai-elements/scripts/stack-trace-no-internal.tsx +41 -0
- package/dist/src/skills/bundled/ai-elements/scripts/stack-trace.tsx +60 -0
- package/dist/src/skills/bundled/ai-elements/scripts/suggestion-input.tsx +142 -0
- package/dist/src/skills/bundled/ai-elements/scripts/suggestion.tsx +34 -0
- package/dist/src/skills/bundled/ai-elements/scripts/task.tsx +59 -0
- package/dist/src/skills/bundled/ai-elements/scripts/terminal-basic.tsx +7 -0
- package/dist/src/skills/bundled/ai-elements/scripts/terminal-clear.tsx +19 -0
- package/dist/src/skills/bundled/ai-elements/scripts/terminal-streaming.tsx +38 -0
- package/dist/src/skills/bundled/ai-elements/scripts/terminal.tsx +83 -0
- package/dist/src/skills/bundled/ai-elements/scripts/test-results-basic.tsx +27 -0
- package/dist/src/skills/bundled/ai-elements/scripts/test-results-errors.tsx +51 -0
- package/dist/src/skills/bundled/ai-elements/scripts/test-results-suites.tsx +40 -0
- package/dist/src/skills/bundled/ai-elements/scripts/test-results.tsx +84 -0
- package/dist/src/skills/bundled/ai-elements/scripts/tool-input-available.tsx +31 -0
- package/dist/src/skills/bundled/ai-elements/scripts/tool-input-streaming.tsx +30 -0
- package/dist/src/skills/bundled/ai-elements/scripts/tool-output-available.tsx +81 -0
- package/dist/src/skills/bundled/ai-elements/scripts/tool-output-error.tsx +50 -0
- package/dist/src/skills/bundled/ai-elements/scripts/tool.tsx +210 -0
- package/dist/src/skills/bundled/ai-elements/scripts/transcription.tsx +289 -0
- package/dist/src/skills/bundled/ai-elements/scripts/voice-selector.tsx +233 -0
- package/dist/src/skills/bundled/ai-elements/scripts/web-preview.tsx +105 -0
- package/dist/src/skills/bundled/control-browser/SKILL.md +21 -0
- package/dist/src/skills/bundled/dynamic-workflows/SKILL.md +1520 -0
- package/dist/src/skills/bundled/dynamic-workflows/examples.md +801 -0
- package/dist/src/skills/bundled/dynamic-workflows/patterns.md +460 -0
- package/dist/src/skills/bundled/provenance.json +684 -0
- package/dist/src/skills/bundled/web-gui-tester/SKILL.md +159 -0
- package/dist/src/skills/project-skills.d.ts +11 -0
- package/dist/src/skills/project-skills.js +132 -0
- package/dist/src/skills/runtime-skills.d.ts +10 -0
- package/dist/src/skills/runtime-skills.js +237 -0
- package/dist/src/subagent-run.d.ts +278 -0
- package/dist/src/subagent-run.js +930 -0
- package/dist/src/telemetry/aggregate.d.ts +80 -0
- package/dist/src/telemetry/aggregate.js +217 -0
- package/dist/src/telemetry/capture-core.d.ts +190 -0
- package/dist/src/telemetry/capture-core.js +374 -0
- package/dist/src/telemetry/capture.d.ts +5 -0
- package/dist/src/telemetry/capture.js +16 -0
- package/dist/src/telemetry/classify.d.ts +102 -0
- package/dist/src/telemetry/classify.js +252 -0
- package/dist/src/telemetry/decision-capture.d.ts +13 -0
- package/dist/src/telemetry/decision-capture.js +40 -0
- package/dist/src/telemetry/emitter.d.ts +77 -0
- package/dist/src/telemetry/emitter.js +279 -0
- package/dist/src/telemetry/gate.d.ts +48 -0
- package/dist/src/telemetry/gate.js +55 -0
- package/dist/src/telemetry/identity.d.ts +19 -0
- package/dist/src/telemetry/identity.js +109 -0
- package/dist/src/telemetry/outbox.d.ts +91 -0
- package/dist/src/telemetry/outbox.js +356 -0
- package/dist/src/telemetry/schema.d.ts +184 -0
- package/dist/src/telemetry/schema.js +492 -0
- package/dist/src/telemetry/state.d.ts +90 -0
- package/dist/src/telemetry/state.js +195 -0
- package/dist/src/telemetry/surface.d.ts +76 -0
- package/dist/src/telemetry/surface.js +116 -0
- package/dist/src/telemetry/uploader.d.ts +29 -0
- package/dist/src/telemetry/uploader.js +151 -0
- package/dist/src/telemetry/uploads.d.ts +13 -0
- package/dist/src/telemetry/uploads.js +19 -0
- package/dist/src/telemetry/version.d.ts +5 -0
- package/dist/src/telemetry/version.js +25 -0
- package/dist/src/telemetry/workspace.d.ts +14 -0
- package/dist/src/telemetry/workspace.js +93 -0
- package/dist/src/terminal-ui.d.ts +744 -0
- package/dist/src/terminal-ui.js +3012 -0
- package/dist/src/text.d.ts +2 -0
- package/dist/src/text.js +8 -0
- package/dist/src/timers.d.ts +189 -0
- package/dist/src/timers.js +244 -0
- package/dist/src/todos.d.ts +12 -0
- package/dist/src/todos.js +33 -0
- package/dist/src/token-rate.d.ts +119 -0
- package/dist/src/token-rate.js +287 -0
- package/dist/src/tool-activity.d.ts +20 -0
- package/dist/src/tool-activity.js +76 -0
- package/dist/src/tool-call-clock.d.ts +32 -0
- package/dist/src/tool-call-clock.js +157 -0
- package/dist/src/tool-catalog.d.ts +40 -0
- package/dist/src/tool-catalog.js +100 -0
- package/dist/src/tool-dependencies.d.ts +23 -0
- package/dist/src/tool-dependencies.js +36 -0
- package/dist/src/tool-diff-stats.d.ts +24 -0
- package/dist/src/tool-diff-stats.js +122 -0
- package/dist/src/tool-errors.d.ts +12 -0
- package/dist/src/tool-errors.js +13 -0
- package/dist/src/tool-failure-tracker.d.ts +17 -0
- package/dist/src/tool-failure-tracker.js +71 -0
- package/dist/src/tool-names.d.ts +16 -0
- package/dist/src/tool-names.js +75 -0
- package/dist/src/tool-result-filter.d.ts +65 -0
- package/dist/src/tool-result-filter.js +447 -0
- package/dist/src/tool-schema-compatibility.d.ts +2 -0
- package/dist/src/tool-schema-compatibility.js +42 -0
- package/dist/src/tools.d.ts +3 -0
- package/dist/src/tools.js +663 -0
- package/dist/src/trajectory.d.ts +34 -0
- package/dist/src/trajectory.js +426 -0
- package/dist/src/transcript.d.ts +45 -0
- package/dist/src/transcript.js +228 -0
- package/dist/src/types.d.ts +248 -0
- package/dist/src/types.js +1 -0
- package/dist/src/update.d.ts +58 -0
- package/dist/src/update.js +571 -0
- package/dist/src/usage-analytics.d.ts +48 -0
- package/dist/src/usage-analytics.js +663 -0
- package/dist/src/widgets.d.ts +45 -0
- package/dist/src/widgets.js +71 -0
- package/dist/src/workspace-facts.d.ts +35 -0
- package/dist/src/workspace-facts.js +85 -0
- package/dist/src/workspace-git-metadata.d.ts +6 -0
- package/dist/src/workspace-git-metadata.js +114 -0
- package/dist/src/workspace-instructions.d.ts +7 -0
- package/dist/src/workspace-instructions.js +46 -0
- package/dist/vendor/engine/LICENSE.upstream +21 -0
- package/dist/vendor/engine/provenance.json +17923 -0
- package/dist/vendor/engine/runtime/agent/agent-loop.d.ts +23 -0
- package/dist/vendor/engine/runtime/agent/agent-loop.js +601 -0
- package/dist/vendor/engine/runtime/agent/agent.d.ts +130 -0
- package/dist/vendor/engine/runtime/agent/agent.js +430 -0
- package/dist/vendor/engine/runtime/agent/harness/agent-harness.d.ts +715 -0
- package/dist/vendor/engine/runtime/agent/harness/agent-harness.js +5 -0
- package/dist/vendor/engine/runtime/agent/harness/compaction/branch-summarization.d.ts +67 -0
- package/dist/vendor/engine/runtime/agent/harness/compaction/branch-summarization.js +175 -0
- package/dist/vendor/engine/runtime/agent/harness/compaction/compaction.d.ts +125 -0
- package/dist/vendor/engine/runtime/agent/harness/compaction/compaction.js +559 -0
- package/dist/vendor/engine/runtime/agent/harness/compaction/utils.d.ts +24 -0
- package/dist/vendor/engine/runtime/agent/harness/compaction/utils.js +119 -0
- package/dist/vendor/engine/runtime/agent/harness/config.d.ts +8 -0
- package/dist/vendor/engine/runtime/agent/harness/config.js +34 -0
- package/dist/vendor/engine/runtime/agent/harness/context.d.ts +8 -0
- package/dist/vendor/engine/runtime/agent/harness/context.js +12 -0
- package/dist/vendor/engine/runtime/agent/harness/events.d.ts +24 -0
- package/dist/vendor/engine/runtime/agent/harness/events.js +249 -0
- package/dist/vendor/engine/runtime/agent/harness/execution/assistant.d.ts +41 -0
- package/dist/vendor/engine/runtime/agent/harness/execution/assistant.js +81 -0
- package/dist/vendor/engine/runtime/agent/harness/execution/effect-gate.d.ts +21 -0
- package/dist/vendor/engine/runtime/agent/harness/execution/effect-gate.js +48 -0
- package/dist/vendor/engine/runtime/agent/harness/execution/tools.d.ts +66 -0
- package/dist/vendor/engine/runtime/agent/harness/execution/tools.js +118 -0
- package/dist/vendor/engine/runtime/agent/harness/hooks.d.ts +37 -0
- package/dist/vendor/engine/runtime/agent/harness/hooks.js +405 -0
- package/dist/vendor/engine/runtime/agent/harness/messages.d.ts +50 -0
- package/dist/vendor/engine/runtime/agent/harness/messages.js +102 -0
- package/dist/vendor/engine/runtime/agent/harness/prompt-templates.d.ts +48 -0
- package/dist/vendor/engine/runtime/agent/harness/prompt-templates.js +224 -0
- package/dist/vendor/engine/runtime/agent/harness/result.d.ts +132 -0
- package/dist/vendor/engine/runtime/agent/harness/result.js +80 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/boundary.d.ts +27 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/boundary.js +172 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/checkpoint.d.ts +7 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/checkpoint.js +132 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/deferred.d.ts +14 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/deferred.js +178 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/generation.d.ts +7 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/generation.js +204 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/reconcile.d.ts +4 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/reconcile.js +139 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/recovery.d.ts +7 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/recovery.js +84 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/response.d.ts +22 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/response.js +393 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/retry.d.ts +3 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/retry.js +33 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/structural.d.ts +31 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/structural.js +928 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/terminal.d.ts +6 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/terminal.js +48 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/tool-placement.d.ts +13 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/tool-placement.js +218 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/tools.d.ts +5 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive/tools.js +448 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive.d.ts +5 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/drive.js +92 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/harness.d.ts +58 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/harness.js +310 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/lane.d.ts +117 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/lane.js +1574 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/progress.d.ts +14 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/progress.js +65 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/reducer.d.ts +4 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/reducer.js +239 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/restore.d.ts +23 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/restore.js +116 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/transcript.d.ts +20 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/transcript.js +71 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/types.d.ts +104 -0
- package/dist/vendor/engine/runtime/agent/harness/runtime/types.js +60 -0
- package/dist/vendor/engine/runtime/agent/harness/session/commit.d.ts +52 -0
- package/dist/vendor/engine/runtime/agent/harness/session/commit.js +56 -0
- package/dist/vendor/engine/runtime/agent/harness/session/context.d.ts +9 -0
- package/dist/vendor/engine/runtime/agent/harness/session/context.js +48 -0
- package/dist/vendor/engine/runtime/agent/harness/session/fork-policy.d.ts +20 -0
- package/dist/vendor/engine/runtime/agent/harness/session/fork-policy.js +54 -0
- package/dist/vendor/engine/runtime/agent/harness/session/fork.d.ts +15 -0
- package/dist/vendor/engine/runtime/agent/harness/session/fork.js +78 -0
- package/dist/vendor/engine/runtime/agent/harness/session/in-memory-storage-state.d.ts +38 -0
- package/dist/vendor/engine/runtime/agent/harness/session/in-memory-storage-state.js +275 -0
- package/dist/vendor/engine/runtime/agent/harness/session/index.d.ts +10 -0
- package/dist/vendor/engine/runtime/agent/harness/session/index.js +8 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/codec.d.ts +20 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/codec.js +44 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/fork.d.ts +37 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/fork.js +263 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/index.d.ts +3 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/index.js +3 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/io.d.ts +13 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/io.js +85 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/legacy-v3.d.ts +43 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/legacy-v3.js +461 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/repo.d.ts +34 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/repo.js +300 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/storage.d.ts +40 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/storage.js +199 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/types.d.ts +38 -0
- package/dist/vendor/engine/runtime/agent/harness/session/jsonl/types.js +2 -0
- package/dist/vendor/engine/runtime/agent/harness/session/memory.d.ts +47 -0
- package/dist/vendor/engine/runtime/agent/harness/session/memory.js +368 -0
- package/dist/vendor/engine/runtime/agent/harness/session/mutation-line.d.ts +7 -0
- package/dist/vendor/engine/runtime/agent/harness/session/mutation-line.js +20 -0
- package/dist/vendor/engine/runtime/agent/harness/session/session.d.ts +81 -0
- package/dist/vendor/engine/runtime/agent/harness/session/session.js +360 -0
- package/dist/vendor/engine/runtime/agent/harness/session/types.d.ts +511 -0
- package/dist/vendor/engine/runtime/agent/harness/session/types.js +8 -0
- package/dist/vendor/engine/runtime/agent/harness/session/values.d.ts +94 -0
- package/dist/vendor/engine/runtime/agent/harness/session/values.js +80 -0
- package/dist/vendor/engine/runtime/agent/harness/skills.d.ts +45 -0
- package/dist/vendor/engine/runtime/agent/harness/skills.js +325 -0
- package/dist/vendor/engine/runtime/agent/harness/system-prompt.d.ts +2 -0
- package/dist/vendor/engine/runtime/agent/harness/system-prompt.js +29 -0
- package/dist/vendor/engine/runtime/agent/harness/telemetry.d.ts +1241 -0
- package/dist/vendor/engine/runtime/agent/harness/telemetry.js +526 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/bash.d.ts +26 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/bash.js +104 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/edit-diff.d.ts +88 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/edit-diff.js +385 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/edit.d.ts +18 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/edit.js +107 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/file-mutation-queue.d.ts +4 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/file-mutation-queue.js +45 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/image.d.ts +2 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/image.js +105 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/index.d.ts +5 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/index.js +4 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/path-utils.d.ts +4 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/path-utils.js +25 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/read.d.ts +34 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/read.js +107 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/tool-context.d.ts +5 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/tool-context.js +1 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/write.d.ts +10 -0
- package/dist/vendor/engine/runtime/agent/harness/tools/write.js +30 -0
- package/dist/vendor/engine/runtime/agent/harness/types.d.ts +304 -0
- package/dist/vendor/engine/runtime/agent/harness/types.js +74 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/adaptive-publisher.d.ts +23 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/adaptive-publisher.js +78 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/output-capture.d.ts +30 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/output-capture.js +216 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/shell-output.d.ts +28 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/shell-output.js +70 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/truncate.d.ts +70 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/truncate.js +295 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/usage.d.ts +3 -0
- package/dist/vendor/engine/runtime/agent/harness/utils/usage.js +32 -0
- package/dist/vendor/engine/runtime/agent/index.d.ts +27 -0
- package/dist/vendor/engine/runtime/agent/index.js +25 -0
- package/dist/vendor/engine/runtime/agent/proxy.d.ts +71 -0
- package/dist/vendor/engine/runtime/agent/proxy.js +309 -0
- package/dist/vendor/engine/runtime/agent/search/index.d.ts +28 -0
- package/dist/vendor/engine/runtime/agent/search/index.js +1 -0
- package/dist/vendor/engine/runtime/agent/stream-fn.d.ts +9 -0
- package/dist/vendor/engine/runtime/agent/stream-fn.js +16 -0
- package/dist/vendor/engine/runtime/agent/types.d.ts +431 -0
- package/dist/vendor/engine/runtime/agent/types.js +1 -0
- package/dist/vendor/engine/runtime/ai/api/anthropic-messages.d.ts +70 -0
- package/dist/vendor/engine/runtime/ai/api/anthropic-messages.js +1204 -0
- package/dist/vendor/engine/runtime/ai/api/anthropic-messages.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/anthropic-messages.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/azure-openai-responses.d.ts +16 -0
- package/dist/vendor/engine/runtime/ai/api/azure-openai-responses.js +260 -0
- package/dist/vendor/engine/runtime/ai/api/azure-openai-responses.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/azure-openai-responses.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/bedrock-converse-stream.d.ts +37 -0
- package/dist/vendor/engine/runtime/ai/api/bedrock-converse-stream.js +1091 -0
- package/dist/vendor/engine/runtime/ai/api/bedrock-converse-stream.lazy.d.ts +9 -0
- package/dist/vendor/engine/runtime/ai/api/bedrock-converse-stream.lazy.js +21 -0
- package/dist/vendor/engine/runtime/ai/api/constrained-sampling.d.ts +19 -0
- package/dist/vendor/engine/runtime/ai/api/constrained-sampling.js +221 -0
- package/dist/vendor/engine/runtime/ai/api/github-copilot-headers.d.ts +7 -0
- package/dist/vendor/engine/runtime/ai/api/github-copilot-headers.js +28 -0
- package/dist/vendor/engine/runtime/ai/api/google-generative-ai.d.ts +12 -0
- package/dist/vendor/engine/runtime/ai/api/google-generative-ai.js +368 -0
- package/dist/vendor/engine/runtime/ai/api/google-generative-ai.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/google-generative-ai.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/google-shared.d.ts +92 -0
- package/dist/vendor/engine/runtime/ai/api/google-shared.js +450 -0
- package/dist/vendor/engine/runtime/ai/api/google-vertex.d.ts +14 -0
- package/dist/vendor/engine/runtime/ai/api/google-vertex.js +429 -0
- package/dist/vendor/engine/runtime/ai/api/google-vertex.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/google-vertex.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/lazy.d.ts +24 -0
- package/dist/vendor/engine/runtime/ai/api/lazy.js +69 -0
- package/dist/vendor/engine/runtime/ai/api/mistral-conversations.d.ts +24 -0
- package/dist/vendor/engine/runtime/ai/api/mistral-conversations.js +747 -0
- package/dist/vendor/engine/runtime/ai/api/mistral-conversations.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/mistral-conversations.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/openai-codex-responses.d.ts +30 -0
- package/dist/vendor/engine/runtime/ai/api/openai-codex-responses.js +1302 -0
- package/dist/vendor/engine/runtime/ai/api/openai-codex-responses.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/openai-codex-responses.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/openai-completions.d.ts +25 -0
- package/dist/vendor/engine/runtime/ai/api/openai-completions.js +1339 -0
- package/dist/vendor/engine/runtime/ai/api/openai-completions.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/openai-completions.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/openai-prompt-cache.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/openai-prompt-cache.js +9 -0
- package/dist/vendor/engine/runtime/ai/api/openai-responses-shared.d.ts +27 -0
- package/dist/vendor/engine/runtime/ai/api/openai-responses-shared.js +688 -0
- package/dist/vendor/engine/runtime/ai/api/openai-responses.d.ts +13 -0
- package/dist/vendor/engine/runtime/ai/api/openai-responses.js +292 -0
- package/dist/vendor/engine/runtime/ai/api/openai-responses.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/openai-responses.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/openrouter-images.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/openrouter-images.js +131 -0
- package/dist/vendor/engine/runtime/ai/api/openrouter-images.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/openrouter-images.lazy.js +3 -0
- package/dist/vendor/engine/runtime/ai/api/pi-messages.d.ts +98 -0
- package/dist/vendor/engine/runtime/ai/api/pi-messages.js +312 -0
- package/dist/vendor/engine/runtime/ai/api/pi-messages.lazy.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/api/pi-messages.lazy.js +2 -0
- package/dist/vendor/engine/runtime/ai/api/simple-options.d.ts +14 -0
- package/dist/vendor/engine/runtime/ai/api/simple-options.js +65 -0
- package/dist/vendor/engine/runtime/ai/api/transform-messages.d.ts +7 -0
- package/dist/vendor/engine/runtime/ai/api/transform-messages.js +200 -0
- package/dist/vendor/engine/runtime/ai/auth/context.d.ts +6 -0
- package/dist/vendor/engine/runtime/ai/auth/context.js +33 -0
- package/dist/vendor/engine/runtime/ai/auth/credential-store.d.ts +16 -0
- package/dist/vendor/engine/runtime/ai/auth/credential-store.js +50 -0
- package/dist/vendor/engine/runtime/ai/auth/helpers.d.ts +21 -0
- package/dist/vendor/engine/runtime/ai/auth/helpers.js +52 -0
- package/dist/vendor/engine/runtime/ai/auth/oauth/load.d.ts +28 -0
- package/dist/vendor/engine/runtime/ai/auth/oauth/load.js +55 -0
- package/dist/vendor/engine/runtime/ai/auth/resolve.d.ts +26 -0
- package/dist/vendor/engine/runtime/ai/auth/resolve.js +131 -0
- package/dist/vendor/engine/runtime/ai/auth/types.d.ts +230 -0
- package/dist/vendor/engine/runtime/ai/auth/types.js +1 -0
- package/dist/vendor/engine/runtime/ai/compat/extension-oauth-types.d.ts +38 -0
- package/dist/vendor/engine/runtime/ai/compat/extension-oauth-types.js +1 -0
- package/dist/vendor/engine/runtime/ai/compat.d.ts +66 -0
- package/dist/vendor/engine/runtime/ai/compat.js +201 -0
- package/dist/vendor/engine/runtime/ai/env-api-keys.d.ts +20 -0
- package/dist/vendor/engine/runtime/ai/env-api-keys.js +148 -0
- package/dist/vendor/engine/runtime/ai/image-models.d.ts +9 -0
- package/dist/vendor/engine/runtime/ai/image-models.generated.d.ts +814 -0
- package/dist/vendor/engine/runtime/ai/image-models.generated.js +816 -0
- package/dist/vendor/engine/runtime/ai/image-models.js +22 -0
- package/dist/vendor/engine/runtime/ai/images-api-registry.d.ts +13 -0
- package/dist/vendor/engine/runtime/ai/images-api-registry.js +21 -0
- package/dist/vendor/engine/runtime/ai/images-models.d.ts +94 -0
- package/dist/vendor/engine/runtime/ai/images-models.js +142 -0
- package/dist/vendor/engine/runtime/ai/images.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/images.js +13 -0
- package/dist/vendor/engine/runtime/ai/index.d.ts +36 -0
- package/dist/vendor/engine/runtime/ai/index.js +23 -0
- package/dist/vendor/engine/runtime/ai/legacy-api-aliases.d.ts +41 -0
- package/dist/vendor/engine/runtime/ai/legacy-api-aliases.js +48 -0
- package/dist/vendor/engine/runtime/ai/model-catalog.d.ts +16 -0
- package/dist/vendor/engine/runtime/ai/model-catalog.js +3 -0
- package/dist/vendor/engine/runtime/ai/models-store.d.ts +28 -0
- package/dist/vendor/engine/runtime/ai/models-store.js +16 -0
- package/dist/vendor/engine/runtime/ai/models.d.ts +201 -0
- package/dist/vendor/engine/runtime/ai/models.generated.d.ts +84 -0
- package/dist/vendor/engine/runtime/ai/models.generated.js +86 -0
- package/dist/vendor/engine/runtime/ai/models.js +593 -0
- package/dist/vendor/engine/runtime/ai/oauth.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/oauth.js +1 -0
- package/dist/vendor/engine/runtime/ai/providers/all.d.ts +27 -0
- package/dist/vendor/engine/runtime/ai/providers/all.js +132 -0
- package/dist/vendor/engine/runtime/ai/providers/amazon-bedrock.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/amazon-bedrock.js +92 -0
- package/dist/vendor/engine/runtime/ai/providers/amazon-bedrock.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/amazon-bedrock.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/ant-ling.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/ant-ling.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/ant-ling.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/ant-ling.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/anthropic.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/anthropic.js +55 -0
- package/dist/vendor/engine/runtime/ai/providers/anthropic.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/anthropic.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/azure-openai-responses.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/azure-openai-responses.js +13 -0
- package/dist/vendor/engine/runtime/ai/providers/azure-openai-responses.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/azure-openai-responses.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/baseten.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/baseten.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/baseten.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/baseten.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/cerebras.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/cerebras.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/cerebras.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/cerebras.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-ai-gateway.d.ts +4 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-ai-gateway.js +24 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-ai-gateway.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-ai-gateway.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-auth.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-auth.js +85 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-stream.d.ts +7 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-stream.js +20 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-workers-ai.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-workers-ai.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-workers-ai.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/cloudflare-workers-ai.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/data/.manifest.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/amazon-bedrock.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/ant-ling.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/anthropic.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/azure-openai-responses.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/baseten.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/cerebras.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/cloudflare-ai-gateway.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/cloudflare-workers-ai.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/deepseek.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/fireworks.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/github-copilot.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/google-vertex.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/google.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/groq.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/huggingface.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/kimi-coding.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/meta.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/minimax-cn.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/minimax.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/mistral.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/moonshotai-cn.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/moonshotai.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/nvidia.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/openai-codex.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/openai.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/opencode-go.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/opencode.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/openrouter.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/qwen-token-plan-cn.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/qwen-token-plan-individual.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/qwen-token-plan.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/radius.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/together.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/vercel-ai-gateway.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/xai.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/xiaomi-token-plan-ams.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/xiaomi-token-plan-cn.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/xiaomi-token-plan-sgp.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/xiaomi.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/zai-coding-cn.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/data/zai.json +1 -0
- package/dist/vendor/engine/runtime/ai/providers/deepseek.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/deepseek.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/deepseek.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/deepseek.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/faux.d.ts +102 -0
- package/dist/vendor/engine/runtime/ai/providers/faux.js +488 -0
- package/dist/vendor/engine/runtime/ai/providers/fireworks.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/fireworks.js +18 -0
- package/dist/vendor/engine/runtime/ai/providers/fireworks.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/fireworks.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/github-copilot.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/github-copilot.js +34 -0
- package/dist/vendor/engine/runtime/ai/providers/github-copilot.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/github-copilot.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/google-vertex.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/google-vertex.js +93 -0
- package/dist/vendor/engine/runtime/ai/providers/google-vertex.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/google-vertex.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/google.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/google.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/google.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/google.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/groq.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/groq.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/groq.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/groq.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/huggingface.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/huggingface.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/huggingface.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/huggingface.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/images/register-builtins.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/images/register-builtins.js +33 -0
- package/dist/vendor/engine/runtime/ai/providers/kimi-coding.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/kimi-coding.js +23 -0
- package/dist/vendor/engine/runtime/ai/providers/kimi-coding.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/kimi-coding.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/meta.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/meta.js +23 -0
- package/dist/vendor/engine/runtime/ai/providers/meta.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/meta.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax-cn.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax-cn.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax-cn.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax-cn.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/minimax.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/mistral.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/mistral.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/mistral.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/mistral.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai-cn.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai-cn.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai-cn.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai-cn.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/moonshotai.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/nvidia.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/nvidia.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/nvidia.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/nvidia.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/openai-codex.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/openai-codex.js +21 -0
- package/dist/vendor/engine/runtime/ai/providers/openai-codex.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/openai-codex.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/openai.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/openai.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/openai.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/openai.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode-go.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode-go.js +20 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode-go.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode-go.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode-headers.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode-headers.js +21 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode.js +22 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/opencode.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/openrouter-images.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/openrouter-images.js +21 -0
- package/dist/vendor/engine/runtime/ai/providers/openrouter.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/openrouter.js +26 -0
- package/dist/vendor/engine/runtime/ai/providers/openrouter.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/openrouter.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-cn.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-cn.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-cn.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-cn.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-individual.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-individual.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-individual.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan-individual.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/qwen-token-plan.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/radius-config.d.ts +25 -0
- package/dist/vendor/engine/runtime/ai/providers/radius-config.js +62 -0
- package/dist/vendor/engine/runtime/ai/providers/radius.d.ts +8 -0
- package/dist/vendor/engine/runtime/ai/providers/radius.js +77 -0
- package/dist/vendor/engine/runtime/ai/providers/radius.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/radius.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/together.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/together.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/together.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/together.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/vercel-ai-gateway.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/vercel-ai-gateway.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/vercel-ai-gateway.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/vercel-ai-gateway.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/xai.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/xai.js +23 -0
- package/dist/vendor/engine/runtime/ai/providers/xai.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/xai.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-ams.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-ams.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-ams.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-ams.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-cn.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-cn.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-cn.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-cn.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-sgp.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-sgp.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-sgp.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi-token-plan-sgp.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/xiaomi.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/zai-coding-cn.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/zai-coding-cn.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/zai-coding-cn.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/zai-coding-cn.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/providers/zai.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/providers/zai.js +14 -0
- package/dist/vendor/engine/runtime/ai/providers/zai.models.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/providers/zai.models.js +5 -0
- package/dist/vendor/engine/runtime/ai/session-resources.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/session-resources.js +21 -0
- package/dist/vendor/engine/runtime/ai/types.d.ts +835 -0
- package/dist/vendor/engine/runtime/ai/types.js +1 -0
- package/dist/vendor/engine/runtime/ai/utils/abort-signals.d.ts +5 -0
- package/dist/vendor/engine/runtime/ai/utils/abort-signals.js +33 -0
- package/dist/vendor/engine/runtime/ai/utils/abort.d.ts +7 -0
- package/dist/vendor/engine/runtime/ai/utils/abort.js +48 -0
- package/dist/vendor/engine/runtime/ai/utils/assistant-message-frame.d.ts +76 -0
- package/dist/vendor/engine/runtime/ai/utils/assistant-message-frame.js +424 -0
- package/dist/vendor/engine/runtime/ai/utils/diagnostics.d.ts +19 -0
- package/dist/vendor/engine/runtime/ai/utils/diagnostics.js +24 -0
- package/dist/vendor/engine/runtime/ai/utils/error-body.d.ts +24 -0
- package/dist/vendor/engine/runtime/ai/utils/error-body.js +132 -0
- package/dist/vendor/engine/runtime/ai/utils/estimate.d.ts +16 -0
- package/dist/vendor/engine/runtime/ai/utils/estimate.js +94 -0
- package/dist/vendor/engine/runtime/ai/utils/event-stream.d.ts +20 -0
- package/dist/vendor/engine/runtime/ai/utils/event-stream.js +98 -0
- package/dist/vendor/engine/runtime/ai/utils/hash.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/utils/hash.js +13 -0
- package/dist/vendor/engine/runtime/ai/utils/headers.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/utils/headers.js +17 -0
- package/dist/vendor/engine/runtime/ai/utils/json-parse.d.ts +15 -0
- package/dist/vendor/engine/runtime/ai/utils/json-parse.js +112 -0
- package/dist/vendor/engine/runtime/ai/utils/node-http-proxy.d.ts +3 -0
- package/dist/vendor/engine/runtime/ai/utils/node-http-proxy.js +132 -0
- package/dist/vendor/engine/runtime/ai/utils/overflow.d.ts +68 -0
- package/dist/vendor/engine/runtime/ai/utils/overflow.js +177 -0
- package/dist/vendor/engine/runtime/ai/utils/pi-user-agent.d.ts +1 -0
- package/dist/vendor/engine/runtime/ai/utils/pi-user-agent.js +11 -0
- package/dist/vendor/engine/runtime/ai/utils/provider-env.d.ts +6 -0
- package/dist/vendor/engine/runtime/ai/utils/provider-env.js +43 -0
- package/dist/vendor/engine/runtime/ai/utils/provider-retry.d.ts +15 -0
- package/dist/vendor/engine/runtime/ai/utils/provider-retry.js +93 -0
- package/dist/vendor/engine/runtime/ai/utils/retry.d.ts +57 -0
- package/dist/vendor/engine/runtime/ai/utils/retry.js +182 -0
- package/dist/vendor/engine/runtime/ai/utils/sanitize-unicode.d.ts +21 -0
- package/dist/vendor/engine/runtime/ai/utils/sanitize-unicode.js +25 -0
- package/dist/vendor/engine/runtime/ai/utils/text.d.ts +13 -0
- package/dist/vendor/engine/runtime/ai/utils/text.js +35 -0
- package/dist/vendor/engine/runtime/ai/utils/transcript.d.ts +83 -0
- package/dist/vendor/engine/runtime/ai/utils/transcript.js +203 -0
- package/dist/vendor/engine/runtime/ai/utils/typebox-helpers.d.ts +16 -0
- package/dist/vendor/engine/runtime/ai/utils/typebox-helpers.js +20 -0
- package/dist/vendor/engine/runtime/ai/utils/uuid.d.ts +2 -0
- package/dist/vendor/engine/runtime/ai/utils/uuid.js +41 -0
- package/dist/vendor/engine/runtime/ai/utils/validation.d.ts +17 -0
- package/dist/vendor/engine/runtime/ai/utils/validation.js +308 -0
- package/dist/vendor/engine/runtime/chord/api.d.ts +14 -0
- package/dist/vendor/engine/runtime/chord/api.js +71 -0
- package/dist/vendor/engine/runtime/chord/context/index.d.ts +23 -0
- package/dist/vendor/engine/runtime/chord/context/index.js +96 -0
- package/dist/vendor/engine/runtime/chord/delta/index.d.ts +118 -0
- package/dist/vendor/engine/runtime/chord/delta/index.js +1903 -0
- package/dist/vendor/engine/runtime/chord/facets/host.d.ts +11 -0
- package/dist/vendor/engine/runtime/chord/facets/host.js +762 -0
- package/dist/vendor/engine/runtime/chord/facets/loader.d.ts +2 -0
- package/dist/vendor/engine/runtime/chord/facets/loader.js +4 -0
- package/dist/vendor/engine/runtime/chord/index.d.ts +10 -0
- package/dist/vendor/engine/runtime/chord/index.js +9 -0
- package/dist/vendor/engine/runtime/chord/json.d.ts +3 -0
- package/dist/vendor/engine/runtime/chord/json.js +56 -0
- package/dist/vendor/engine/runtime/chord/services/consumer.d.ts +10 -0
- package/dist/vendor/engine/runtime/chord/services/consumer.js +536 -0
- package/dist/vendor/engine/runtime/chord/services/errors.d.ts +7 -0
- package/dist/vendor/engine/runtime/chord/services/errors.js +21 -0
- package/dist/vendor/engine/runtime/chord/services/handle.d.ts +14 -0
- package/dist/vendor/engine/runtime/chord/services/handle.js +100 -0
- package/dist/vendor/engine/runtime/chord/services/instances.d.ts +24 -0
- package/dist/vendor/engine/runtime/chord/services/instances.js +136 -0
- package/dist/vendor/engine/runtime/chord/services/loopback.d.ts +4 -0
- package/dist/vendor/engine/runtime/chord/services/loopback.js +14 -0
- package/dist/vendor/engine/runtime/chord/services/provider.d.ts +36 -0
- package/dist/vendor/engine/runtime/chord/services/provider.js +471 -0
- package/dist/vendor/engine/runtime/chord/services/state-codec.d.ts +14 -0
- package/dist/vendor/engine/runtime/chord/services/state-codec.js +114 -0
- package/dist/vendor/engine/runtime/chord/services/state-internals.d.ts +10 -0
- package/dist/vendor/engine/runtime/chord/services/state-internals.js +9 -0
- package/dist/vendor/engine/runtime/chord/services/state.d.ts +22 -0
- package/dist/vendor/engine/runtime/chord/services/state.js +123 -0
- package/dist/vendor/engine/runtime/chord/services/wire.d.ts +59 -0
- package/dist/vendor/engine/runtime/chord/services/wire.js +172 -0
- package/dist/vendor/engine/runtime/chord/types.d.ts +202 -0
- package/dist/vendor/engine/runtime/chord/types.js +1 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/args.d.ts +60 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/args.js +439 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/auth-check.d.ts +18 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/auth-check.js +49 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/auth-command.d.ts +23 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/auth-command.js +102 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/config-selector.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/config-selector.js +31 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/credential-print.d.ts +12 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/credential-print.js +75 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/file-processor.d.ts +14 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/file-processor.js +70 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/initial-message.d.ts +17 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/initial-message.js +21 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/list-models.d.ts +8 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/list-models.js +97 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/project-trust.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/project-trust.js +47 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/session-picker.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/session-picker.js +35 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/startup-ui.d.ts +19 -0
- package/dist/vendor/engine/runtime/coding-agent/cli/startup-ui.js +184 -0
- package/dist/vendor/engine/runtime/coding-agent/config.d.ts +97 -0
- package/dist/vendor/engine/runtime/coding-agent/config.js +463 -0
- package/dist/vendor/engine/runtime/coding-agent/core/agent-session-runtime.d.ts +118 -0
- package/dist/vendor/engine/runtime/coding-agent/core/agent-session-runtime.js +316 -0
- package/dist/vendor/engine/runtime/coding-agent/core/agent-session-services.d.ts +85 -0
- package/dist/vendor/engine/runtime/coding-agent/core/agent-session-services.js +133 -0
- package/dist/vendor/engine/runtime/coding-agent/core/agent-session.d.ts +771 -0
- package/dist/vendor/engine/runtime/coding-agent/core/agent-session.js +2990 -0
- package/dist/vendor/engine/runtime/coding-agent/core/auth-guidance.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/core/auth-guidance.js +20 -0
- package/dist/vendor/engine/runtime/coding-agent/core/auth-storage.d.ts +71 -0
- package/dist/vendor/engine/runtime/coding-agent/core/auth-storage.js +425 -0
- package/dist/vendor/engine/runtime/coding-agent/core/bash-executor.d.ts +31 -0
- package/dist/vendor/engine/runtime/coding-agent/core/bash-executor.js +110 -0
- package/dist/vendor/engine/runtime/coding-agent/core/bug-report-upload.d.ts +11 -0
- package/dist/vendor/engine/runtime/coding-agent/core/bug-report-upload.js +21 -0
- package/dist/vendor/engine/runtime/coding-agent/core/bug-report.d.ts +175 -0
- package/dist/vendor/engine/runtime/coding-agent/core/bug-report.js +291 -0
- package/dist/vendor/engine/runtime/coding-agent/core/cache-stats.d.ts +48 -0
- package/dist/vendor/engine/runtime/coding-agent/core/cache-stats.js +111 -0
- package/dist/vendor/engine/runtime/coding-agent/core/cache-warmer.d.ts +102 -0
- package/dist/vendor/engine/runtime/coding-agent/core/cache-warmer.js +355 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/branch-summarization.d.ts +97 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/branch-summarization.js +250 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/compaction.d.ts +142 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/compaction.js +666 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/index.d.ts +6 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/index.js +6 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/utils.d.ts +37 -0
- package/dist/vendor/engine/runtime/coding-agent/core/compaction/utils.js +141 -0
- package/dist/vendor/engine/runtime/coding-agent/core/crash-log.d.ts +26 -0
- package/dist/vendor/engine/runtime/coding-agent/core/crash-log.js +138 -0
- package/dist/vendor/engine/runtime/coding-agent/core/defaults.d.ts +3 -0
- package/dist/vendor/engine/runtime/coding-agent/core/defaults.js +10 -0
- package/dist/vendor/engine/runtime/coding-agent/core/diagnostics.d.ts +14 -0
- package/dist/vendor/engine/runtime/coding-agent/core/diagnostics.js +1 -0
- package/dist/vendor/engine/runtime/coding-agent/core/event-bus.d.ts +8 -0
- package/dist/vendor/engine/runtime/coding-agent/core/event-bus.js +24 -0
- package/dist/vendor/engine/runtime/coding-agent/core/exec.d.ts +28 -0
- package/dist/vendor/engine/runtime/coding-agent/core/exec.js +74 -0
- package/dist/vendor/engine/runtime/coding-agent/core/experimental.d.ts +1 -0
- package/dist/vendor/engine/runtime/coding-agent/core/experimental.js +3 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/ansi-to-html.d.ts +21 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/ansi-to-html.js +248 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/index.d.ts +36 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/index.js +225 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/template.css +1066 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/template.html +55 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/template.js +1864 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/tool-renderer.d.ts +33 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/tool-renderer.js +107 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/vendor/engine/runtime/coding-agent/core/export-html/vendor/marked.min.js +78 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/index.d.ts +11 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/index.js +8 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/jiti-loader.d.ts +1 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/jiti-loader.js +3 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/jiti-static-loader.d.ts +1 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/jiti-static-loader.js +3 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/loader.d.ts +22 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/loader.js +633 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/runner.d.ts +180 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/runner.js +1028 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/types.d.ts +1362 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/types.js +47 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/virtual-modules.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/virtual-modules.js +37 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/wrapper.d.ts +19 -0
- package/dist/vendor/engine/runtime/coding-agent/core/extensions/wrapper.js +21 -0
- package/dist/vendor/engine/runtime/coding-agent/core/footer-data-provider.d.ts +63 -0
- package/dist/vendor/engine/runtime/coding-agent/core/footer-data-provider.js +337 -0
- package/dist/vendor/engine/runtime/coding-agent/core/http-dispatcher.d.ts +21 -0
- package/dist/vendor/engine/runtime/coding-agent/core/http-dispatcher.js +97 -0
- package/dist/vendor/engine/runtime/coding-agent/core/keybindings.d.ts +427 -0
- package/dist/vendor/engine/runtime/coding-agent/core/keybindings.js +320 -0
- package/dist/vendor/engine/runtime/coding-agent/core/messages.d.ts +76 -0
- package/dist/vendor/engine/runtime/coding-agent/core/messages.js +123 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-config.d.ts +723 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-config.js +281 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-registry.d.ts +48 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-registry.js +114 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-resolver.d.ts +123 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-resolver.js +589 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-runtime.d.ts +100 -0
- package/dist/vendor/engine/runtime/coding-agent/core/model-runtime.js +603 -0
- package/dist/vendor/engine/runtime/coding-agent/core/models-store.d.ts +21 -0
- package/dist/vendor/engine/runtime/coding-agent/core/models-store.js +114 -0
- package/dist/vendor/engine/runtime/coding-agent/core/output-guard.d.ts +6 -0
- package/dist/vendor/engine/runtime/coding-agent/core/output-guard.js +88 -0
- package/dist/vendor/engine/runtime/coding-agent/core/package-manager.d.ts +212 -0
- package/dist/vendor/engine/runtime/coding-agent/core/package-manager.js +2176 -0
- package/dist/vendor/engine/runtime/coding-agent/core/pi-manifest.d.ts +7 -0
- package/dist/vendor/engine/runtime/coding-agent/core/pi-manifest.js +25 -0
- package/dist/vendor/engine/runtime/coding-agent/core/project-trust.d.ts +14 -0
- package/dist/vendor/engine/runtime/coding-agent/core/project-trust.js +58 -0
- package/dist/vendor/engine/runtime/coding-agent/core/prompt-templates.d.ts +53 -0
- package/dist/vendor/engine/runtime/coding-agent/core/prompt-templates.js +235 -0
- package/dist/vendor/engine/runtime/coding-agent/core/provider-attribution.d.ts +3 -0
- package/dist/vendor/engine/runtime/coding-agent/core/provider-attribution.js +71 -0
- package/dist/vendor/engine/runtime/coding-agent/core/provider-composer.d.ts +59 -0
- package/dist/vendor/engine/runtime/coding-agent/core/provider-composer.js +422 -0
- package/dist/vendor/engine/runtime/coding-agent/core/radius.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/core/radius.js +7 -0
- package/dist/vendor/engine/runtime/coding-agent/core/remote-catalog-provider.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/core/remote-catalog-provider.js +121 -0
- package/dist/vendor/engine/runtime/coding-agent/core/resolve-config-value.d.ts +29 -0
- package/dist/vendor/engine/runtime/coding-agent/core/resolve-config-value.js +246 -0
- package/dist/vendor/engine/runtime/coding-agent/core/resource-loader.d.ts +220 -0
- package/dist/vendor/engine/runtime/coding-agent/core/resource-loader.js +874 -0
- package/dist/vendor/engine/runtime/coding-agent/core/runtime-credentials.d.ts +14 -0
- package/dist/vendor/engine/runtime/coding-agent/core/runtime-credentials.js +38 -0
- package/dist/vendor/engine/runtime/coding-agent/core/sdk.d.ts +107 -0
- package/dist/vendor/engine/runtime/coding-agent/core/sdk.js +296 -0
- package/dist/vendor/engine/runtime/coding-agent/core/session-cwd.d.ts +18 -0
- package/dist/vendor/engine/runtime/coding-agent/core/session-cwd.js +37 -0
- package/dist/vendor/engine/runtime/coding-agent/core/session-export.d.ts +7 -0
- package/dist/vendor/engine/runtime/coding-agent/core/session-export.js +32 -0
- package/dist/vendor/engine/runtime/coding-agent/core/session-manager.d.ts +379 -0
- package/dist/vendor/engine/runtime/coding-agent/core/session-manager.js +1432 -0
- package/dist/vendor/engine/runtime/coding-agent/core/settings-diagnostics.d.ts +8 -0
- package/dist/vendor/engine/runtime/coding-agent/core/settings-diagnostics.js +20 -0
- package/dist/vendor/engine/runtime/coding-agent/core/settings-manager.d.ts +346 -0
- package/dist/vendor/engine/runtime/coding-agent/core/settings-manager.js +1032 -0
- package/dist/vendor/engine/runtime/coding-agent/core/skills.d.ts +59 -0
- package/dist/vendor/engine/runtime/coding-agent/core/skills.js +406 -0
- package/dist/vendor/engine/runtime/coding-agent/core/slash-commands.d.ts +14 -0
- package/dist/vendor/engine/runtime/coding-agent/core/slash-commands.js +27 -0
- package/dist/vendor/engine/runtime/coding-agent/core/source-info.d.ts +17 -0
- package/dist/vendor/engine/runtime/coding-agent/core/source-info.js +18 -0
- package/dist/vendor/engine/runtime/coding-agent/core/system-prompt.d.ts +70 -0
- package/dist/vendor/engine/runtime/coding-agent/core/system-prompt.js +146 -0
- package/dist/vendor/engine/runtime/coding-agent/core/telemetry.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/core/telemetry.js +8 -0
- package/dist/vendor/engine/runtime/coding-agent/core/timings.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/core/timings.js +40 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/bash.d.ts +89 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/bash.js +303 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/edit-diff.d.ts +100 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/edit-diff.js +420 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/edit.d.ts +43 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/edit.js +146 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/file-mutation-queue.d.ts +5 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/file-mutation-queue.js +51 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/find.d.ts +41 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/find.js +250 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/grep.d.ts +40 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/grep.js +251 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/index.d.ts +42 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/index.js +128 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/ls.d.ts +40 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/ls.js +125 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/output-accumulator.d.ts +54 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/output-accumulator.js +189 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/path-utils.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/path-utils.js +98 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/powershell.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/powershell.js +38 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/read.d.ts +41 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/read.js +168 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/render-utils.d.ts +23 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/render-utils.js +64 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/bash.d.ts +11 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/bash.js +137 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/edit.d.ts +22 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/edit.js +166 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/find.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/find.js +63 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/grep.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/grep.js +68 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/index.d.ts +27 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/index.js +46 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/ls.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/ls.js +57 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/read.d.ts +10 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/read.js +128 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/write.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/renderers/write.js +152 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/tool-definition-wrapper.d.ts +13 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/tool-definition-wrapper.js +35 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/truncate.d.ts +69 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/truncate.js +214 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/write.d.ts +29 -0
- package/dist/vendor/engine/runtime/coding-agent/core/tools/write.js +60 -0
- package/dist/vendor/engine/runtime/coding-agent/core/trust-manager.d.ts +35 -0
- package/dist/vendor/engine/runtime/coding-agent/core/trust-manager.js +202 -0
- package/dist/vendor/engine/runtime/coding-agent/core/usage-totals.d.ts +18 -0
- package/dist/vendor/engine/runtime/coding-agent/core/usage-totals.js +55 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/index.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/index.js +2 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/client.d.ts +68 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/client.js +312 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/huggingface.d.ts +22 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/huggingface.js +140 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/index.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/index.js +218 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/provider.d.ts +11 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/provider.js +160 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/ui.d.ts +41 -0
- package/dist/vendor/engine/runtime/coding-agent/extensions/llama/ui.js +415 -0
- package/dist/vendor/engine/runtime/coding-agent/index.d.ts +36 -0
- package/dist/vendor/engine/runtime/coding-agent/index.js +47 -0
- package/dist/vendor/engine/runtime/coding-agent/main.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/main.js +808 -0
- package/dist/vendor/engine/runtime/coding-agent/migrations.d.ts +32 -0
- package/dist/vendor/engine/runtime/coding-agent/migrations.js +281 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/index.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/index.js +7 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/bug-report.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/bug-report.js +209 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/chat-viewport.d.ts +19 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/chat-viewport.js +27 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/armin.d.ts +33 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/armin.js +332 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/assistant-message.d.ts +25 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/assistant-message.js +157 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/bash-execution.d.ts +33 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/bash-execution.js +174 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/bordered-loader.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/bordered-loader.js +53 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/branch-summary-message.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/branch-summary-message.js +50 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/compaction-summary-message.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/compaction-summary-message.js +51 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/config-selector.d.ts +101 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/config-selector.js +760 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/countdown-timer.d.ts +13 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/countdown-timer.js +32 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/custom-editor.d.ts +29 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/custom-editor.js +114 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/custom-entry.d.ts +18 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/custom-entry.js +51 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/custom-message.d.ts +21 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/custom-message.js +86 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/daxnuts.d.ts +22 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/daxnuts.js +139 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/diff.d.ts +11 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/diff.js +132 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/dynamic-border.d.ts +14 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/dynamic-border.js +20 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/earendil-announcement.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/earendil-announcement.js +39 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/extension-editor.d.ts +23 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/extension-editor.js +102 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/extension-input.d.ts +24 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/extension-input.js +66 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/extension-selector.d.ts +26 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/extension-selector.js +86 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/first-time-setup.d.ts +24 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/first-time-setup.js +102 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/footer.d.ts +31 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/footer.js +224 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/index.d.ts +33 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/index.js +34 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/keybinding-hints.d.ts +12 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/keybinding-hints.js +35 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/login-dialog.d.ts +51 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/login-dialog.js +187 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/markdown-transform.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/markdown-transform.js +18 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/mermaid.d.ts +10 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/mermaid.js +74 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/model-selector.d.ts +59 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/model-selector.js +360 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/oauth-selector.d.ts +32 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/oauth-selector.js +162 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/scoped-models-selector.d.ts +45 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/scoped-models-selector.js +325 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/session-selector-search.d.ts +22 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/session-selector-search.js +154 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/session-selector.d.ts +94 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/session-selector.js +892 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/settings-selector.d.ts +93 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/settings-selector.js +719 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/settings-submenu.d.ts +71 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/settings-submenu.js +164 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/show-images-selector.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/show-images-selector.js +38 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/skill-invocation-message.d.ts +16 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/skill-invocation-message.js +53 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/status-indicator.d.ts +29 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/status-indicator.js +66 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/theme-selector.d.ts +10 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/theme-selector.js +49 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/thinking-selector.d.ts +22 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/thinking-selector.js +108 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/tool-execution.d.ts +79 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/tool-execution.js +336 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/tree-selector.d.ts +93 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/tree-selector.js +1246 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/trust-selector.d.ts +22 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/trust-selector.js +90 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/user-message-selector.d.ts +29 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/user-message-selector.js +113 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/user-message.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/user-message.js +48 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/visual-truncate.d.ts +23 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/components/visual-truncate.js +32 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/external-editor.d.ts +11 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/external-editor.js +37 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/interactive-mode.d.ts +467 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/interactive-mode.js +5720 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/model-catalog-refresh.d.ts +6 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/model-catalog-refresh.js +33 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/model-search.d.ts +11 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/model-search.js +14 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/session-share.d.ts +17 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/session-share.js +187 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/dark.json +91 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/light.json +90 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/theme-controller.d.ts +40 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/theme-controller.js +129 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/theme-json.d.ts +83 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/theme-json.js +129 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/theme-schema.json +356 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/theme.d.ts +130 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/theme/theme.js +990 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/tui-renderer.d.ts +20 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/interactive/tui-renderer.js +65 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/json-event.d.ts +33 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/json-event.js +28 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/print-mode.d.ts +27 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/print-mode.js +141 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/jsonl.d.ts +16 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/jsonl.js +48 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/rpc-client.d.ts +253 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/rpc-client.js +494 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/rpc-mode.d.ts +19 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/rpc-mode.js +656 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/rpc-types.d.ts +468 -0
- package/dist/vendor/engine/runtime/coding-agent/modes/rpc/rpc-types.js +7 -0
- package/dist/vendor/engine/runtime/coding-agent/package-manager-cli.d.ts +8 -0
- package/dist/vendor/engine/runtime/coding-agent/package-manager-cli.js +960 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/abort.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/abort.js +47 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/ansi.d.ts +1 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/ansi.js +51 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/changelog.d.ts +21 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/changelog.js +164 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/child-process.d.ts +17 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/child-process.js +105 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/clipboard-command.d.ts +6 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/clipboard-command.js +44 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/clipboard-image.d.ts +10 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/clipboard-image.js +216 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/clipboard.d.ts +3 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/clipboard.js +150 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/exif-orientation.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/exif-orientation.js +156 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/frontmatter.d.ts +7 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/frontmatter.js +26 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/fs-watch.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/fs-watch.js +24 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/git.d.ts +25 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/git.js +194 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/html.d.ts +6 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/html.js +39 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-convert.d.ts +9 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-convert.js +44 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-process.d.ts +17 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-process.js +82 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-resize-core.d.ts +29 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-resize-core.js +123 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-resize-worker.d.ts +1 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-resize-worker.js +30 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-resize.d.ts +15 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/image-resize.js +96 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/json.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/json.js +6 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/management-http.d.ts +24 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/management-http.js +53 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/mime.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/mime.js +109 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/open-browser.d.ts +8 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/open-browser.js +21 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/paths.d.ts +33 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/paths.js +113 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/photon.d.ts +20 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/photon.js +120 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/pi-user-agent.d.ts +1 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/pi-user-agent.js +4 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/shell.d.ts +33 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/shell.js +215 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/sleep.d.ts +4 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/sleep.js +16 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/syntax-highlight.d.ts +12 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/syntax-highlight.js +176 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/text.d.ts +7 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/text.js +8 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/tool-result-images.d.ts +20 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/tool-result-images.js +47 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/tools-manager.d.ts +12 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/tools-manager.js +308 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/version-check.d.ts +18 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/version-check.js +78 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/windows-self-update.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/windows-self-update.js +76 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/wsl.d.ts +2 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/wsl.js +14 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/zip.d.ts +6 -0
- package/dist/vendor/engine/runtime/coding-agent/utils/zip.js +59 -0
- package/dist/vendor/engine/runtime/package.json +9 -0
- package/dist/vendor/engine/runtime/telemetry/index.d.ts +193 -0
- package/dist/vendor/engine/runtime/telemetry/index.js +17 -0
- package/dist/vendor/engine/runtime/telemetry/memory.d.ts +25 -0
- package/dist/vendor/engine/runtime/telemetry/memory.js +153 -0
- package/dist/vendor/engine/runtime/telemetry/noop.d.ts +3 -0
- package/dist/vendor/engine/runtime/telemetry/noop.js +17 -0
- package/dist/vendor/engine/runtime/tui/alt-screen-search.d.ts +45 -0
- package/dist/vendor/engine/runtime/tui/alt-screen-search.js +281 -0
- package/dist/vendor/engine/runtime/tui/autocomplete.d.ts +56 -0
- package/dist/vendor/engine/runtime/tui/autocomplete.js +671 -0
- package/dist/vendor/engine/runtime/tui/components/alt-screen-flash.d.ts +12 -0
- package/dist/vendor/engine/runtime/tui/components/alt-screen-flash.js +36 -0
- package/dist/vendor/engine/runtime/tui/components/box.d.ts +23 -0
- package/dist/vendor/engine/runtime/tui/components/box.js +132 -0
- package/dist/vendor/engine/runtime/tui/components/cancellable-loader.d.ts +21 -0
- package/dist/vendor/engine/runtime/tui/components/cancellable-loader.js +34 -0
- package/dist/vendor/engine/runtime/tui/components/editor.d.ts +259 -0
- package/dist/vendor/engine/runtime/tui/components/editor.js +2041 -0
- package/dist/vendor/engine/runtime/tui/components/h-stack.d.ts +6 -0
- package/dist/vendor/engine/runtime/tui/components/h-stack.js +42 -0
- package/dist/vendor/engine/runtime/tui/components/image.d.ts +27 -0
- package/dist/vendor/engine/runtime/tui/components/image.js +89 -0
- package/dist/vendor/engine/runtime/tui/components/input.d.ts +47 -0
- package/dist/vendor/engine/runtime/tui/components/input.js +416 -0
- package/dist/vendor/engine/runtime/tui/components/loader.d.ts +32 -0
- package/dist/vendor/engine/runtime/tui/components/loader.js +75 -0
- package/dist/vendor/engine/runtime/tui/components/markdown.d.ts +102 -0
- package/dist/vendor/engine/runtime/tui/components/markdown.js +810 -0
- package/dist/vendor/engine/runtime/tui/components/mouse-region.d.ts +11 -0
- package/dist/vendor/engine/runtime/tui/components/mouse-region.js +20 -0
- package/dist/vendor/engine/runtime/tui/components/scroll-view.d.ts +58 -0
- package/dist/vendor/engine/runtime/tui/components/scroll-view.js +194 -0
- package/dist/vendor/engine/runtime/tui/components/select-list.d.ts +52 -0
- package/dist/vendor/engine/runtime/tui/components/select-list.js +205 -0
- package/dist/vendor/engine/runtime/tui/components/settings-list.d.ts +59 -0
- package/dist/vendor/engine/runtime/tui/components/settings-list.js +251 -0
- package/dist/vendor/engine/runtime/tui/components/spacer.d.ts +11 -0
- package/dist/vendor/engine/runtime/tui/components/spacer.js +22 -0
- package/dist/vendor/engine/runtime/tui/components/stack.d.ts +31 -0
- package/dist/vendor/engine/runtime/tui/components/stack.js +110 -0
- package/dist/vendor/engine/runtime/tui/components/text.d.ts +18 -0
- package/dist/vendor/engine/runtime/tui/components/text.js +89 -0
- package/dist/vendor/engine/runtime/tui/components/truncated-text.d.ts +12 -0
- package/dist/vendor/engine/runtime/tui/components/truncated-text.js +50 -0
- package/dist/vendor/engine/runtime/tui/components/v-stack.d.ts +7 -0
- package/dist/vendor/engine/runtime/tui/components/v-stack.js +25 -0
- package/dist/vendor/engine/runtime/tui/editor-component.d.ts +38 -0
- package/dist/vendor/engine/runtime/tui/editor-component.js +1 -0
- package/dist/vendor/engine/runtime/tui/fuzzy.d.ts +15 -0
- package/dist/vendor/engine/runtime/tui/fuzzy.js +110 -0
- package/dist/vendor/engine/runtime/tui/index.d.ts +32 -0
- package/dist/vendor/engine/runtime/tui/index.js +44 -0
- package/dist/vendor/engine/runtime/tui/keybindings.d.ts +272 -0
- package/dist/vendor/engine/runtime/tui/keybindings.js +232 -0
- package/dist/vendor/engine/runtime/tui/keys.d.ts +183 -0
- package/dist/vendor/engine/runtime/tui/keys.js +1173 -0
- package/dist/vendor/engine/runtime/tui/kill-ring.d.ts +27 -0
- package/dist/vendor/engine/runtime/tui/kill-ring.js +43 -0
- package/dist/vendor/engine/runtime/tui/latex.d.ts +9 -0
- package/dist/vendor/engine/runtime/tui/latex.js +1377 -0
- package/dist/vendor/engine/runtime/tui/layout-node.d.ts +39 -0
- package/dist/vendor/engine/runtime/tui/layout-node.js +5 -0
- package/dist/vendor/engine/runtime/tui/layout.d.ts +41 -0
- package/dist/vendor/engine/runtime/tui/layout.js +343 -0
- package/dist/vendor/engine/runtime/tui/native-modifiers.d.ts +3 -0
- package/dist/vendor/engine/runtime/tui/native-modifiers.js +12 -0
- package/dist/vendor/engine/runtime/tui/native-module-path.d.ts +6 -0
- package/dist/vendor/engine/runtime/tui/native-module-path.js +18 -0
- package/dist/vendor/engine/runtime/tui/native-platform.d.ts +17 -0
- package/dist/vendor/engine/runtime/tui/native-platform.js +41 -0
- package/dist/vendor/engine/runtime/tui/stdin-buffer.d.ts +55 -0
- package/dist/vendor/engine/runtime/tui/stdin-buffer.js +365 -0
- package/dist/vendor/engine/runtime/tui/terminal-colors.d.ts +9 -0
- package/dist/vendor/engine/runtime/tui/terminal-colors.js +58 -0
- package/dist/vendor/engine/runtime/tui/terminal-image.d.ts +117 -0
- package/dist/vendor/engine/runtime/tui/terminal-image.js +549 -0
- package/dist/vendor/engine/runtime/tui/terminal.d.ts +122 -0
- package/dist/vendor/engine/runtime/tui/terminal.js +441 -0
- package/dist/vendor/engine/runtime/tui/tui-alt-screen.d.ts +159 -0
- package/dist/vendor/engine/runtime/tui/tui-alt-screen.js +1507 -0
- package/dist/vendor/engine/runtime/tui/tui-main-screen.d.ts +38 -0
- package/dist/vendor/engine/runtime/tui/tui-main-screen.js +593 -0
- package/dist/vendor/engine/runtime/tui/tui.d.ts +385 -0
- package/dist/vendor/engine/runtime/tui/tui.js +1054 -0
- package/dist/vendor/engine/runtime/tui/undo-stack.d.ts +16 -0
- package/dist/vendor/engine/runtime/tui/undo-stack.js +24 -0
- package/dist/vendor/engine/runtime/tui/utils.d.ts +100 -0
- package/dist/vendor/engine/runtime/tui/utils.js +1203 -0
- package/dist/vendor/engine/runtime/tui/word-navigation.d.ts +24 -0
- package/dist/vendor/engine/runtime/tui/word-navigation.js +95 -0
- package/dist/vendor/zcode/LICENSE.upstream +202 -0
- package/dist/vendor/zcode/provenance.json +141 -0
- package/dist/vendor/zcode/source/agent/turn-machine.d.ts +56 -0
- package/dist/vendor/zcode/source/agent/turn-machine.js +214 -0
- package/dist/vendor/zcode/source/agent/turn-state.d.ts +118 -0
- package/dist/vendor/zcode/source/agent/turn-state.js +93 -0
- package/dist/vendor/zcode/source/compact/manual.d.ts +11 -0
- package/dist/vendor/zcode/source/compact/manual.js +38 -0
- package/dist/vendor/zcode/source/compact/microcompact.d.ts +47 -0
- package/dist/vendor/zcode/source/compact/microcompact.js +194 -0
- package/dist/vendor/zcode/source/compact/policy.d.ts +59 -0
- package/dist/vendor/zcode/source/compact/policy.js +89 -0
- package/dist/vendor/zcode/source/compact/selection.d.ts +6 -0
- package/dist/vendor/zcode/source/compact/selection.js +12 -0
- package/dist/vendor/zcode/source/contracts.d.ts +52 -0
- package/dist/vendor/zcode/source/contracts.js +9 -0
- package/dist/vendor/zcode/source/runtime/goal-completion-verification.d.ts +17 -0
- package/dist/vendor/zcode/source/runtime/goal-completion-verification.js +138 -0
- package/dist/vendor/zcode/source/runtime/turn-loop.d.ts +3 -0
- package/dist/vendor/zcode/source/runtime/turn-loop.js +21 -0
- package/dist/vendor/zcode/source/runtime/turn-model-step.d.ts +54 -0
- package/dist/vendor/zcode/source/runtime/turn-model-step.js +97 -0
- package/dist/vendor/zcode/source/runtime/turn-output-token-continuation.d.ts +8 -0
- package/dist/vendor/zcode/source/runtime/turn-output-token-continuation.js +15 -0
- package/dist/vendor/zcode/source/runtime/turn-stop.d.ts +6 -0
- package/dist/vendor/zcode/source/runtime/turn-stop.js +18 -0
- package/dist/vendor/zcode/source/tool/executor/validation.d.ts +6 -0
- package/dist/vendor/zcode/source/tool/executor/validation.js +76 -0
- package/dist/vendor/zcode/source/tool/input-normalization.d.ts +16 -0
- package/dist/vendor/zcode/source/tool/input-normalization.js +62 -0
- package/dist/vendor/zcode/source/tool/input-validation-model-content.d.ts +4 -0
- package/dist/vendor/zcode/source/tool/input-validation-model-content.js +263 -0
- package/dist/vendor/zcode/source/tool/json-schema.d.ts +9 -0
- package/dist/vendor/zcode/source/tool/json-schema.js +230 -0
- package/dist/vendor/zcode/source/tool/scheduler.d.ts +43 -0
- package/dist/vendor/zcode/source/tool/scheduler.js +167 -0
- package/dist/vendor/zcode/source/tool/tool-input-validation-issues.d.ts +76 -0
- package/dist/vendor/zcode/source/tool/tool-input-validation-issues.js +148 -0
- package/dist/vendor/zcode/source/tool/validation-contracts.d.ts +27 -0
- package/dist/vendor/zcode/source/tool/validation-contracts.js +8 -0
- package/docs/README.md +36 -0
- package/docs/agents/README.md +62 -0
- package/docs/agents/install-for-agents.md +55 -0
- package/docs/agents/mcp-server.md +187 -0
- package/docs/agents/subagent-mode.md +146 -0
- package/docs/concepts/README.md +47 -0
- package/docs/concepts/jev-actionable-routing.md +113 -0
- package/docs/concepts/jev-decision-thresholds.md +412 -0
- package/docs/concepts/jev-efficiency.md +216 -0
- package/docs/concepts/jev-eval-2026-11-01.md +78 -0
- package/docs/concepts/limits.md +43 -0
- package/docs/concepts/memory.md +30 -0
- package/docs/concepts/security.md +40 -0
- package/docs/concepts/workspace-instructions.md +28 -0
- package/docs/getting-started/README.md +82 -0
- package/docs/getting-started/accounts.md +67 -0
- package/docs/getting-started/configure-providers.md +103 -0
- package/docs/guides/README.md +12 -0
- package/docs/guides/browser.md +15 -0
- package/docs/guides/desktop-app.md +354 -0
- package/docs/guides/extensions.md +100 -0
- package/docs/guides/graph-builder.md +93 -0
- package/docs/guides/headless.md +45 -0
- package/docs/guides/tui.md +75 -0
- package/docs/guides/update.md +68 -0
- package/docs/guides/windows-code-signing.md +316 -0
- package/docs/llms.txt +45 -0
- package/docs/reference/README.md +7 -0
- package/docs/reference/cli.md +70 -0
- package/docs/reference/config.md +85 -0
- package/docs/reference/slash-commands.md +54 -0
- package/docs/superpowers/plans/2026-11-01-claude-console-sign-in.md +111 -0
- package/docs/superpowers/plans/2026-11-01-jev-node-opt-in.md +910 -0
- package/docs/superpowers/plans/2026-11-02-workflow-pane.md +398 -0
- package/docs/superpowers/specs/2026-10-31-work-line-summary-design.md +50 -0
- package/docs/superpowers/specs/2026-11-01-claude-console-sign-in-design.md +176 -0
- package/docs/superpowers/specs/2026-11-01-jev-node-opt-in-design.md +164 -0
- package/docs/superpowers/specs/2026-11-01-pr-section-design.md +104 -0
- package/docs/superpowers/specs/2026-11-02-workflow-pane-design.md +130 -0
- package/licenses/GEIST-OFL-1.1.txt +92 -0
- package/licenses/ZCODE-APACHE-2.0.txt +202 -0
- package/package.json +118 -6
- package/scripts/jev-efficiency-eval.mjs +187 -0
- package/scripts/jev-efficiency-live.mjs +193 -0
- package/scripts/zcode-engine-replay.mjs +223 -0
- package/tests/agent-centric-mcp-test-plan.md +208 -0
- package/tests/analytics-settings-test-plan.md +165 -0
- package/tests/browser-cli-smoke.mjs +276 -0
- package/tests/browser-test-plan.md +280 -0
- package/tests/chat-side-panel-test-plan.md +309 -0
- package/tests/decision-engine-test-plan.md +163 -0
- package/tests/default-active-jev-test-plan.md +85 -0
- package/tests/graphiti-test-plan.md +359 -0
- package/tests/harness-extensions-test-plan.md +110 -0
- package/tests/jev-all-decisions-test-plan.md +156 -0
- package/tests/jev-efficiency/criteria.json +158 -0
- package/tests/jev-efficiency/workloads.mjs +242 -0
- package/tests/jev-efficiency-test-plan.md +198 -0
- package/tests/mock-graphiti.mjs +106 -0
- package/tests/permissions-sandbox-probe.mjs +74 -0
- package/tests/permissions-test-plan.md +190 -0
- package/tests/product-telemetry-test-plan.md +536 -0
- package/tests/thinking-stream-preview-test-plan.md +136 -0
- package/tests/zcode-react-engine-test-plan.md +396 -0
|
@@ -0,0 +1,1803 @@
|
|
|
1
|
+
/* Browser-only graph editor. No dependencies or remote assets. */
|
|
2
|
+
'use strict';
|
|
3
|
+
const $ = id => document.getElementById(id);
|
|
4
|
+
// SVG attributes cannot use CSS custom properties, so a token's value is read from :root.
|
|
5
|
+
// `getComputedStyle` is feature-detected because this module is also loaded into harnesses that
|
|
6
|
+
// provide a partial DOM.
|
|
7
|
+
const themeColor = (token, fallback) => {
|
|
8
|
+
try {
|
|
9
|
+
if (typeof getComputedStyle === 'function') {
|
|
10
|
+
const value = getComputedStyle(document.documentElement).getPropertyValue(token).trim();
|
|
11
|
+
if (value) return value;
|
|
12
|
+
}
|
|
13
|
+
} catch { /* A partial DOM falls through to the literal below. */ }
|
|
14
|
+
return fallback;
|
|
15
|
+
};
|
|
16
|
+
// The connection colours, read once per paint. An outcome is a status, and status is the only
|
|
17
|
+
// colour the chrome carries; the halo is the canvas ground, so a crossing stays legible.
|
|
18
|
+
const connectionPalette = () => ({
|
|
19
|
+
fail: themeColor('--err', '#d64545'),
|
|
20
|
+
pass: themeColor('--ok', '#2f9e6a'),
|
|
21
|
+
blocked: themeColor('--warn', '#d99a2b'),
|
|
22
|
+
plain: themeColor('--text-3', '#85858f'),
|
|
23
|
+
halo: themeColor('--canvas-bg', '#1b1b1e'),
|
|
24
|
+
pill: themeColor('--bg-input', '#202024'),
|
|
25
|
+
});
|
|
26
|
+
const fragmentToken = new URLSearchParams(location.hash.slice(1)).get('token');
|
|
27
|
+
const token = fragmentToken || sessionStorage.getItem('andorra-graph-token');
|
|
28
|
+
if (fragmentToken) sessionStorage.setItem('andorra-graph-token', fragmentToken);
|
|
29
|
+
history.replaceState(null, '', location.pathname + location.search);
|
|
30
|
+
const state = { graphs: [], providers: [], tools: [], definitions: [], libraryExpanded: {}, selectedEdge: null, selectedIds: [], routePick: null, bulkOutcome: null, disclosures: {}, validationErrors: [], validationTimer: null, graph: null, selected: null, dirty: false, saving: false, undo: [], redo: [], zoom: 1, x: 60, y: 120, pendingProviderNodes: null };
|
|
31
|
+
const copy = value => JSON.parse(JSON.stringify(value));
|
|
32
|
+
const el = (tag, text, className) => { const item = document.createElement(tag); if (text !== undefined) item.textContent = text; if (className) item.className = className; return item; };
|
|
33
|
+
// The studio's questions are the app's own dialogs (controls.js). A page without that layer — the
|
|
34
|
+
// test harness — answers through the platform's, so the code path is the same either way.
|
|
35
|
+
function askConfirm(options) {
|
|
36
|
+
const controls = globalThis.AndorraControls;
|
|
37
|
+
if (typeof controls?.confirm === 'function') return controls.confirm(options);
|
|
38
|
+
return Promise.resolve(confirm([options.title, options.message].filter(Boolean).join('\n\n')));
|
|
39
|
+
}
|
|
40
|
+
const DISCARD_QUESTION = { title: 'Discard unsaved changes?', message: 'Edits to this graph since its last revision are lost. Recoverable drafts stay in draft history.', confirmLabel: 'Discard', tone: 'danger' };
|
|
41
|
+
function status(message, error = false) { $('status').textContent = message; $('status').parentElement.classList.toggle('error', error); }
|
|
42
|
+
// The free tier keeps one custom graph of up to three nodes (Done does not count) and leaves the
|
|
43
|
+
// Orchestrator to Premium. The server enforces the same rules on save; these keep the editor honest
|
|
44
|
+
// about them before the user builds something it cannot save.
|
|
45
|
+
const FREE_CREATE_TIP = 'Free tier includes 1 custom graph. Upgrade to Premium for more graphs.';
|
|
46
|
+
const FREE_ORCHESTRATOR_TIP = 'The Orchestrator is a Premium feature. Free tier graphs can use the other agent nodes.';
|
|
47
|
+
function freeTier() { return state.plan?.paid === false; }
|
|
48
|
+
function freeNodeTip() { return `Free tier graphs can have up to ${state.plan.nodeLimit} nodes, not counting Done. Upgrade to Premium for larger graphs.`; }
|
|
49
|
+
function countedNodes(graph) { return Object.values(graph.nodes).filter(node => node.type !== 'end').length; }
|
|
50
|
+
function canCreateGraph() { return !freeTier() || state.graphs.filter(graph => graph.id !== 'default').length < state.plan.customGraphLimit; }
|
|
51
|
+
/** Whether a free account may save this graph: its kept graph, or a new one while it has none. */
|
|
52
|
+
function freeGraphEditable(graph) { return !freeTier() || (graph.revision ? graph.id === (state.plan.freeGraphId ?? state.graphs.find(item => item.id !== 'default')?.id) : canCreateGraph()); }
|
|
53
|
+
/** Why adding these nodes would leave the free allowance, or undefined. */
|
|
54
|
+
function freeNodeRefusal(added) {
|
|
55
|
+
if (!freeTier() || !state.graph) return undefined;
|
|
56
|
+
if (added.some(node => node?.agentRole === 'orchestrator')) return FREE_ORCHESTRATOR_TIP;
|
|
57
|
+
const counted = added.filter(node => node?.type !== 'end').length;
|
|
58
|
+
return counted && countedNodes(state.graph) + counted > state.plan.nodeLimit ? freeNodeTip() : undefined;
|
|
59
|
+
}
|
|
60
|
+
async function api(path, body, options = {}) {
|
|
61
|
+
const response = await fetch(path, { method: options.method || (body ? 'POST' : 'GET'), headers: { Authorization: `Bearer ${token || ''}`, ...(body ? { 'Content-Type': 'application/json' } : {}) }, ...(body ? { body: JSON.stringify(body) } : {}), ...(options.signal ? { signal: options.signal } : {}) });
|
|
62
|
+
const data = await response.json();
|
|
63
|
+
if (!response.ok) throw new Error(typeof data.error === 'string' ? data.error : JSON.stringify(data.error || data));
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
function checkpoint() { state.undo.push(copy(state.graph)); if (state.undo.length > 80) state.undo.shift(); state.redo = []; }
|
|
67
|
+
function changed() { scheduleValidation(); state.dirty = true; renderCanvas(); renderHeading(); renderValidation(); status('Unsaved changes'); syncImportRequirementsMarker(); queueDraft(); }
|
|
68
|
+
let draftTimer, pendingDraft;
|
|
69
|
+
function flushDraft() {
|
|
70
|
+
clearTimeout(draftTimer);
|
|
71
|
+
const graph = pendingDraft; pendingDraft = null;
|
|
72
|
+
if (graph) return api('/api/drafts', graph).then(refreshDrafts).catch(error => status('Draft not saved: ' + error.message, true));
|
|
73
|
+
}
|
|
74
|
+
function queueDraft() {
|
|
75
|
+
if (!state.graph || !state.dirty) return;
|
|
76
|
+
if (pendingDraft && pendingDraft.id !== state.graph.id) void flushDraft();
|
|
77
|
+
pendingDraft = copy(state.graph);
|
|
78
|
+
if ($('sync-status')) $('sync-status').textContent = 'Saving draft locally…';
|
|
79
|
+
clearTimeout(draftTimer);
|
|
80
|
+
draftTimer = setTimeout(flushDraft, 500);
|
|
81
|
+
}
|
|
82
|
+
async function refreshDrafts() {
|
|
83
|
+
state.drafts = await api('/api/drafts'); renderList();
|
|
84
|
+
}
|
|
85
|
+
// The pending-provider set is session memory; the id array mirrored onto the graph object is
|
|
86
|
+
// what survives an autosave, because queueDraft serializes the graph verbatim. Only the draft
|
|
87
|
+
// round-trip carries the mirror (every saved-artifact reader strips it through
|
|
88
|
+
// dropLegacyTokenFields), so a recovered imported draft can rebuild the requirement set.
|
|
89
|
+
function syncImportRequirementsMarker() {
|
|
90
|
+
if (!state.graph) return;
|
|
91
|
+
if (state.pendingProviderNodes?.size) state.graph.pendingProviderNodes = [...state.pendingProviderNodes];
|
|
92
|
+
else if (Array.isArray(state.graph.pendingProviderNodes)) delete state.graph.pendingProviderNodes;
|
|
93
|
+
}
|
|
94
|
+
// A recovered draft rebuilds its requirement set from the mirror, keeping only ids whose node
|
|
95
|
+
// still exists as an unassigned agent, so requirements can neither vanish nor outlive their
|
|
96
|
+
// nodes, and the mirror on the draft converges to what is actually still owed.
|
|
97
|
+
function restoreImportRequirements(graph) {
|
|
98
|
+
if (!graph || !Array.isArray(graph.pendingProviderNodes)) return null;
|
|
99
|
+
const owed = new Set();
|
|
100
|
+
for (const id of graph.pendingProviderNodes) {
|
|
101
|
+
const node = graph.nodes?.[id];
|
|
102
|
+
if (node?.type === 'agent' && !node.provider) owed.add(id);
|
|
103
|
+
}
|
|
104
|
+
if (owed.size) graph.pendingProviderNodes = [...owed]; else delete graph.pendingProviderNodes;
|
|
105
|
+
return owed.size ? owed : null;
|
|
106
|
+
}
|
|
107
|
+
async function openDraft(snapshot) {
|
|
108
|
+
if (state.dirty && !await askConfirm({ title: 'Open the saved draft?', message: 'Current edits are retained in draft history.', confirmLabel: 'Open draft' })) return;
|
|
109
|
+
try { const graph = await api(`/api/drafts/${snapshot}`); const owed = restoreImportRequirements(graph); state.graph = graph; state.dirty = true; clearSelection(); state.undo = []; state.redo = []; state.pendingProviderNodes = owed; render(); fit(); status(owed ? 'Recovered imported draft. Assign a model profile to every outlined node, then save.' : 'Recovered draft. Save a revision when valid, or duplicate if its base revision changed.'); }
|
|
110
|
+
catch (error) { status(error.message, true); }
|
|
111
|
+
}
|
|
112
|
+
function mutate(action, inspector = false) { if (!state.graph) return; checkpoint(); action(); changed(); if (inspector) renderInspector(); }
|
|
113
|
+
/**
|
|
114
|
+
* Drop settings the runtime no longer defines. `maxTokens` and the subagent token pair were
|
|
115
|
+
* removed with the cumulative token ceiling; the server still accepts them so old graphs keep
|
|
116
|
+
* loading, but hiding their controls alone would not remove them from a saved revision because
|
|
117
|
+
* the editor serializes the whole graph. Removing them here makes the next save authoritative.
|
|
118
|
+
* The import-requirements marker (`pendingProviderNodes`) is stripped here too: it is editor
|
|
119
|
+
* state riding on draft snapshots, not graph content, so it never reaches a saved revision, an
|
|
120
|
+
* export or a reopened saved graph. Only the draft round-trip keeps it (queueDraft and
|
|
121
|
+
* openDraft bypass this), which is what lets a recovery restore the requirements.
|
|
122
|
+
*/
|
|
123
|
+
function dropLegacyTokenFields(graph) {
|
|
124
|
+
if (!graph || typeof graph !== 'object') return graph;
|
|
125
|
+
if (graph.limits && typeof graph.limits === 'object') delete graph.limits.maxTokens;
|
|
126
|
+
delete graph.pendingProviderNodes;
|
|
127
|
+
for (const node of Object.values(graph.nodes || {})) {
|
|
128
|
+
if (!node || typeof node !== 'object') continue;
|
|
129
|
+
if (node.limits && typeof node.limits === 'object') delete node.limits.maxTokens;
|
|
130
|
+
if (node.subagents && typeof node.subagents === 'object') { delete node.subagents.maxTokensPerSubagent; delete node.subagents.maxCombinedTokens; }
|
|
131
|
+
}
|
|
132
|
+
return graph;
|
|
133
|
+
}
|
|
134
|
+
function titleFor(provider) { return typeof provider === 'string' ? provider : provider.label || provider.name || provider.id; }
|
|
135
|
+
function idFor(provider) { return typeof provider === 'string' ? provider : provider.id || provider.name; }
|
|
136
|
+
function applyProviderRegistry(value) {
|
|
137
|
+
if (!value || !Array.isArray(value.providers)) return false;
|
|
138
|
+
const nextDefault = value.defaultProvider;
|
|
139
|
+
const nextProviders = value.providers;
|
|
140
|
+
if (JSON.stringify([state.defaultProvider, state.providers]) === JSON.stringify([nextDefault, nextProviders])) return false;
|
|
141
|
+
state.defaultProvider = nextDefault;
|
|
142
|
+
state.providers = nextProviders;
|
|
143
|
+
state.modelContextRequests = new Map();
|
|
144
|
+
// A changed registry can move the default provider or the endpoint's catalog, so discovered
|
|
145
|
+
// suggestions must not survive it; the next inspector render rediscovers against live config.
|
|
146
|
+
state.providerModelRequests = new Map();
|
|
147
|
+
// The same reasoning applies to the record-on-commit dedupe: a model that was recorded under
|
|
148
|
+
// the previous registry may have been removed from the provider's configured list since, and
|
|
149
|
+
// a stale entry would suppress the re-POST that makes such a selection runnable again.
|
|
150
|
+
// Models that are still configured skip re-recording via the `known` set, not this one.
|
|
151
|
+
state.providerModelRecords = new Set();
|
|
152
|
+
// And to the unmet-fallback explanations: each asserts what a fallback provider does not serve,
|
|
153
|
+
// a claim only the previous registry's catalogs justified. The next commit re-derives one.
|
|
154
|
+
state.providerModelWarnings = new Map();
|
|
155
|
+
// A discovery request started before this change is detached from the cleared caches: when it
|
|
156
|
+
// resolves it advertises the PREVIOUS endpoint's catalog, and applying it would record those
|
|
157
|
+
// model names into the new endpoint's configuration — binding checks the configured list, so an
|
|
158
|
+
// unsupported model would pass binding and fail only at inference. Callbacks capture this
|
|
159
|
+
// generation and discard themselves when it no longer matches.
|
|
160
|
+
state.providerRegistryGeneration = (state.providerRegistryGeneration || 0) + 1;
|
|
161
|
+
if (state.graph) {
|
|
162
|
+
document.activeElement?.blur?.();
|
|
163
|
+
renderInspector();
|
|
164
|
+
renderValidation();
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
function outcomes(node) {
|
|
169
|
+
if (node.type === 'end') return [];
|
|
170
|
+
if (node.type === 'agent' && node.modifiers?.condition) return ['true', 'false'];
|
|
171
|
+
if (node.type === 'agent' && node.modifiers?.loop?.until?.outcome !== undefined) return [node.modifiers.loop.until.outcome];
|
|
172
|
+
if (node.type === 'condition') return ['true', 'false'];
|
|
173
|
+
if (node.type === 'loop') return ['body', 'done'];
|
|
174
|
+
if (node.type === 'approval') return ['approved', 'rejected'];
|
|
175
|
+
return node.completion?.mode === 'outcomes' ? node.completion.outcomes : [node.completion?.outcome ?? 'completed'];
|
|
176
|
+
}
|
|
177
|
+
function edgeOutcome(edge) { return edge.outcome || 'completed'; }
|
|
178
|
+
function selectedNodes() { return (state.selectedIds.length ? state.selectedIds : state.selected ? [state.selected] : []).map(id => state.graph?.nodes[id]).filter(Boolean); }
|
|
179
|
+
function selectionType(node) { return `${node.type}:${node.agentRole || 'regular'}`; }
|
|
180
|
+
function clearSelection() { state.selectedIds = []; state.selected = null; state.selectedEdge = null; state.routePick = null; state.bulkOutcome = null; }
|
|
181
|
+
function showInspector() { $('inspector').classList.remove('hidden'); $('toggle-inspector').setAttribute('aria-expanded','true'); }
|
|
182
|
+
function selectNode(node, event = {}) {
|
|
183
|
+
if (state.routePick) { routeSelectionTo(node.id); return; }
|
|
184
|
+
if (state.suppressClick === node.id) { state.suppressClick = null; return; }
|
|
185
|
+
const current = selectedNodes(); let mixed = false;
|
|
186
|
+
if ((event.ctrlKey || event.metaKey) && current.length) {
|
|
187
|
+
if (selectionType(current[0]) !== selectionType(node)) { state.selectedIds = [node.id]; mixed = true; }
|
|
188
|
+
else state.selectedIds = current.some(item => item.id === node.id) ? current.filter(item => item.id !== node.id).map(item => item.id) : [...current.map(item => item.id), node.id];
|
|
189
|
+
} else state.selectedIds = [node.id];
|
|
190
|
+
state.selected = state.selectedIds.at(-1) || null; state.selectedEdge = null; state.bulkOutcome = null;
|
|
191
|
+
renderCanvas(); renderInspector(); showInspector();
|
|
192
|
+
if (mixed) status('Selection restarted. Use Ctrl/Cmd-click to select nodes of the same type.');
|
|
193
|
+
}
|
|
194
|
+
function routeSelectionTo(targetId) {
|
|
195
|
+
const pick = state.routePick, target = state.graph?.nodes[targetId];
|
|
196
|
+
if (!pick || !target) return;
|
|
197
|
+
if (pick.sources.includes(targetId) || target.agentRole === 'orchestrator') { status('Choose a destination outside the selection. The Orchestrator cannot have incoming connections.', true); return; }
|
|
198
|
+
const sources = pick.sources.map(id => state.graph.nodes[id]);
|
|
199
|
+
if (sources.some(node => !node || !outcomes(node).includes(pick.outcome)) || sources.some(node => selectionType(node) !== selectionType(sources[0]))) { state.routePick=null; renderInspector(); status('The selection changed. Select matching nodes and choose an outcome again.',true); return; }
|
|
200
|
+
mutate(() => {
|
|
201
|
+
const existing = state.graph.edges;
|
|
202
|
+
const replacements = sources.map(node => existing.find(edge => edge.source === node.id && edgeOutcome(edge) === pick.outcome && edge.target === targetId) || {id:`edge-${crypto.randomUUID().slice(0,8)}`,source:node.id,target:targetId,outcome:pick.outcome});
|
|
203
|
+
state.graph.edges = [...existing.filter(edge => !pick.sources.includes(edge.source) || edgeOutcome(edge) !== pick.outcome),...replacements];
|
|
204
|
+
state.routePick = null;
|
|
205
|
+
},true);
|
|
206
|
+
status(`Routed ${sources.length} nodes to ${target.name}. Existing matching handoffs were kept; configure and validate new input mappings below.`);
|
|
207
|
+
}
|
|
208
|
+
function renderBulkInspector(parent, nodes) {
|
|
209
|
+
$('inspector-title').textContent = `${nodes.length} nodes selected`;
|
|
210
|
+
parent.append(el('p',nodes.map(node=>node.name).join(', '),'help'));
|
|
211
|
+
const group = section(parent,'Output Node');
|
|
212
|
+
const shared = outcomes(nodes[0]).filter(outcome => nodes.every(node => outcomes(node).includes(outcome)));
|
|
213
|
+
if (!shared.length) {group.append(el('p','These nodes have no shared outcome. Give them a matching completion outcome before routing together.','help'));return;}
|
|
214
|
+
if (!shared.includes(state.bulkOutcome)) state.bulkOutcome=shared[0];
|
|
215
|
+
const selector=choice(group,'Shared outcome',state.bulkOutcome,shared,()=>{});selector.onchange=()=>{state.bulkOutcome=selector.value;state.routePick=null;renderCanvas();renderInspector();};
|
|
216
|
+
group.append(el('p','This replaces only the chosen outcome routes. Other outcomes stay connected. Existing handoffs to the chosen destination are retained; new destinations start without mappings.','help'));
|
|
217
|
+
const route=el('button',state.routePick?'Click a destination on the canvas':`Route all ${nodes.length} to...`,'primary');
|
|
218
|
+
route.onclick=()=>{state.routePick={sources:nodes.map(node=>node.id),outcome:state.bulkOutcome};renderCanvas();renderInspector();status('Click the destination node. Press Escape to cancel.');};group.append(route);
|
|
219
|
+
if(state.routePick){const cancel=el('button','Cancel destination selection');cancel.onclick=cancelRoutePick;group.append(cancel);}
|
|
220
|
+
const connections=section(group,'Handoff mappings');
|
|
221
|
+
for(const node of nodes) for(const edge of state.graph.edges.filter(edge=>edge.source===node.id&&edgeOutcome(edge)===state.bulkOutcome)) {const edit=el('button',`${node.name} -> ${state.graph.nodes[edge.target]?.name} (${Object.keys(edge.inputMapping||{}).length} mappings)`,'graph-row');edit.onclick=()=>{clearSelection();state.selectedEdge=edge;renderCanvas();renderInspector();};connections.append(edit);}
|
|
222
|
+
}
|
|
223
|
+
function cancelRoutePick() { state.routePick=null;renderCanvas();renderInspector();status('Destination selection cancelled. No connections changed.'); }
|
|
224
|
+
/** One validation problem: the message shown to the reader, and the node it blames. Errors that
|
|
225
|
+
* carry their node id directly survive duplicate display names; graph-level ones name none. */
|
|
226
|
+
function issues() {
|
|
227
|
+
const graph = state.graph; if (!graph) return [];
|
|
228
|
+
const result = [], nodes = Object.values(graph.nodes);
|
|
229
|
+
if (nodes.length < 2 || nodes.length > nodeLimit(graph)) result.push({ message: `Use between 2 and ${nodeLimit(graph)} nodes; remove extra nodes before saving.` });
|
|
230
|
+
if (freeTier()) {
|
|
231
|
+
if (!freeGraphEditable(graph)) result.push({ message: graph.revision ? 'On the free tier only your first custom graph can be changed. Upgrade to Premium to edit this graph.' : FREE_CREATE_TIP });
|
|
232
|
+
if (nodes.some(node => node.agentRole === 'orchestrator')) result.push({ message: FREE_ORCHESTRATOR_TIP });
|
|
233
|
+
if (countedNodes(graph) > state.plan.nodeLimit) result.push({ message: freeNodeTip() });
|
|
234
|
+
}
|
|
235
|
+
if (new TextEncoder().encode(JSON.stringify(graph)).byteLength > 512 * 1024) result.push({ message: 'Graph exceeds 512 KiB; shorten instructions or remove nodes before saving.' });
|
|
236
|
+
if (!graph.name.trim()) result.push({ message: 'Give this graph a name.' });
|
|
237
|
+
if (graph.name.length > 200) result.push({ message: 'Keep the graph name to 200 characters or fewer.' });
|
|
238
|
+
if (graph.metadata?.description?.length > 2000) result.push({ message: 'Keep the description to 2000 characters or fewer.' });
|
|
239
|
+
if (Array.isArray(graph.widgets) && graph.widgets.length > 5) result.push({ message: 'Use at most 5 widgets.' });
|
|
240
|
+
const widgetIds = new Set();
|
|
241
|
+
for (const [index, widget] of (graph.widgets ?? []).entries()) {
|
|
242
|
+
const label = widget.name?.trim() || `Widget ${index + 1}`;
|
|
243
|
+
if (!widget.name?.trim() || widget.name.length > 80) result.push({ message: `${label}: give the widget a name of up to 80 characters.` });
|
|
244
|
+
if (!widget.description?.trim() || widget.description.length > 1000) result.push({ message: `${label}: describe what the widget tracks, in up to 1000 characters.` });
|
|
245
|
+
if (widgetIds.has(widget.id)) result.push({ message: `${label}: duplicate widget id; remove and re-add this widget.` });
|
|
246
|
+
widgetIds.add(widget.id);
|
|
247
|
+
}
|
|
248
|
+
if (!graph.nodes[graph.entry]) result.push({ message: 'Choose an existing entry node.' });
|
|
249
|
+
for (const node of nodes) {
|
|
250
|
+
const blame = message => result.push({ message, nodeId: node.id });
|
|
251
|
+
if (node.jevEnabled !== undefined && (node.type !== 'agent' || typeof node.jevEnabled !== 'boolean')) blame(`${node.name}: Jev decisions must be a boolean on an Agent node.`);
|
|
252
|
+
for (const outcome of outcomes(node)) if (typeof outcome !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9_ -]{0,79}$/.test(outcome) || outcome.endsWith(' ') || outcome.includes(' ') || ['constructor', 'prototype', '__proto__'].includes(outcome)) blame(`${node.name}: Use outcome names of 1-80 characters starting with a letter or number and containing only letters, numbers, single spaces, underscores or hyphens. Avoid reserved names constructor, prototype and __proto__.`);
|
|
253
|
+
if (!node.name.trim()) blame(`${node.id}: Add a name.`);
|
|
254
|
+
if (node.name.length > 200) blame(`${node.id}: Keep the node name to 200 characters or fewer.`);
|
|
255
|
+
if (node.position !== undefined && (!Number.isFinite(node.position?.x) || !Number.isFinite(node.position?.y) || Math.abs(node.position.x) > 100000 || Math.abs(node.position.y) > 100000)) blame(`${node.name}: Set finite X and Y coordinates between -100000 and 100000.`);
|
|
256
|
+
if (node.type === 'agent') {
|
|
257
|
+
// An imported graph must not drift onto the machine default provider unnoticed: nodes
|
|
258
|
+
// that arrived without a usable provider stay pinned to this list until one is chosen.
|
|
259
|
+
if (state.pendingProviderNodes?.has(node.id) && !node.provider) blame(`${node.name}: choose a model profile for this imported node before saving.`);
|
|
260
|
+
// Missing provider profiles remain editable; the inspector labels them unavailable.
|
|
261
|
+
// Run-time preflight, not graph storage, enforces local provider availability.
|
|
262
|
+
for (const key of ['instruction', 'systemPrompt']) if (node[key] !== undefined && (typeof node[key] !== 'string' || node[key].length > 100000)) blame(`${node.name}: Keep ${key} to 100000 characters or fewer.`);
|
|
263
|
+
if (node.limits?.maxIterations !== undefined && (!Number.isSafeInteger(node.limits.maxIterations) || node.limits.maxIterations < 0 || node.limits.maxIterations > 1000)) blame(`${node.name}: Set an integer iteration limit from 1 to 1000, or 0 for unlimited.`);
|
|
264
|
+
if (node.prompt !== undefined && (typeof node.prompt !== 'string' || node.prompt.length > 100000)) blame(`${node.name}: Keep the system prompt to 100000 characters or fewer.`);
|
|
265
|
+
if (node.model !== undefined && (typeof node.model !== 'string' || !node.model.trim() || node.model.length > 500)) blame(`${node.name}: Use a nonempty model ID of 500 characters or fewer, or clear the override.`);
|
|
266
|
+
if (node.maxIterations !== undefined && (!Number.isSafeInteger(node.maxIterations) || node.maxIterations < 0 || node.maxIterations > 1000)) blame(`${node.name}: Set an integer iteration limit from 1 to 1000, or 0 for unlimited.`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
function scheduleValidation() {
|
|
272
|
+
clearTimeout(state.validationTimer); state.validationErrors = []; state.validated = false;
|
|
273
|
+
if (!state.graph) return;
|
|
274
|
+
const snapshot = JSON.stringify(state.graph);
|
|
275
|
+
state.validationTimer = setTimeout(async () => {
|
|
276
|
+
try { await api('/api/validate', { graph: JSON.parse(snapshot) }); if (JSON.stringify(state.graph) === snapshot) { state.validated = true; state.validationErrors = []; renderValidation(); renderCanvas(); } }
|
|
277
|
+
catch (error) { if (JSON.stringify(state.graph) === snapshot) { state.validated = true; state.validationErrors = [error.message]; renderValidation(); renderCanvas(); } }
|
|
278
|
+
}, 350);
|
|
279
|
+
}
|
|
280
|
+
function renderHeading() {
|
|
281
|
+
$('graph-title').textContent = state.graph?.name || 'Graph studio';
|
|
282
|
+
$('revision').textContent = state.graph ? `${state.graph.revision ? `Revision ${state.graph.revision}` : 'New graph'}${state.dirty ? ' - Unsaved' : ''}` : '';
|
|
283
|
+
$('save').disabled = state.saving || !state.graph || !state.dirty || state.graph.id === 'default';
|
|
284
|
+
$('save').title = state.graph?.id === 'default' ? 'Duplicate the preset to save your customization' : '';
|
|
285
|
+
$('undo').disabled = !state.undo.length; $('redo').disabled = !state.redo.length;
|
|
286
|
+
for (const id of ['duplicate', 'export', 'layout', 'fit']) $(id).disabled = !state.graph;
|
|
287
|
+
$('duplicate').disabled = state.saving || !state.graph || !canCreateGraph();
|
|
288
|
+
renderLibrary();
|
|
289
|
+
window.AndorraStudio?.heading?.();
|
|
290
|
+
}
|
|
291
|
+
function renderList() {
|
|
292
|
+
$('new-graph').disabled = state.saving || !canCreateGraph();
|
|
293
|
+
$('new-graph').title = canCreateGraph() ? 'Create graph' : FREE_CREATE_TIP;
|
|
294
|
+
$('duplicate').disabled = state.saving || !state.graph || !canCreateGraph();
|
|
295
|
+
$('duplicate').title = canCreateGraph() ? '' : FREE_CREATE_TIP;
|
|
296
|
+
$('graphs').replaceChildren();
|
|
297
|
+
for (const graph of state.graphs.filter(graph => graph.name.toLowerCase().includes($('search').value.toLowerCase()))) {
|
|
298
|
+
const button = el('button', undefined, `graph-row${state.graph?.id === graph.id ? ' active' : ''}`);
|
|
299
|
+
button.disabled = state.saving;
|
|
300
|
+
button.append(el('span', graph.name), el('small', graph.id === 'default' ? 'Preset' : `r${graph.revision}`));
|
|
301
|
+
button.onclick = () => openGraph(graph.id);
|
|
302
|
+
button.oncontextmenu = event => { event.preventDefault(); showGraphMenu(graph, event.clientX, event.clientY); };
|
|
303
|
+
$('graphs').append(button);
|
|
304
|
+
}
|
|
305
|
+
const draftGraphs = new Set();
|
|
306
|
+
for (const draft of (state.drafts || []).filter(draft => draft.name.toLowerCase().includes($('search').value.toLowerCase()))) {
|
|
307
|
+
if (!state.showDraftHistory && draftGraphs.has(draft.graphId)) continue;
|
|
308
|
+
draftGraphs.add(draft.graphId);
|
|
309
|
+
const button = el('button', undefined, 'graph-row'); button.disabled = state.saving;
|
|
310
|
+
button.append(el('span', draft.name), el('small', 'Draft ' + (draft.updatedAt ? new Date(draft.updatedAt).toLocaleString() : '(date unknown)')));
|
|
311
|
+
button.onclick = () => openDraft(draft.snapshot); $('graphs').append(button);
|
|
312
|
+
}
|
|
313
|
+
if (state.drafts?.length) {
|
|
314
|
+
const history = el('button', state.showDraftHistory ? 'Show latest drafts' : `Show draft history (${state.drafts.length})`);
|
|
315
|
+
history.onclick = () => { state.showDraftHistory = !state.showDraftHistory; renderList(); }; $('graphs').append(history);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Right-click actions for a saved graph row, and the Plus button's New/Import choices. The menu
|
|
319
|
+
// floats at the pointer as a body-level overlay, so a list re-render cannot tear it down
|
|
320
|
+
// mid-choice; a pointerdown outside it or Escape closes it.
|
|
321
|
+
let closeGraphMenuHandlers;
|
|
322
|
+
function closeGraphMenu() { closeGraphMenuHandlers?.(); }
|
|
323
|
+
function showMenuAt(x, y, ariaLabel, items) {
|
|
324
|
+
closeGraphMenu();
|
|
325
|
+
// A harness without a body cannot host the overlay; the click then simply does nothing.
|
|
326
|
+
if (!document.body?.append) return;
|
|
327
|
+
const menu = el('div', undefined, 'menu-list graph-context');
|
|
328
|
+
menu.id = 'graph-context-menu';
|
|
329
|
+
menu.setAttribute('role', 'menu'); menu.setAttribute('aria-label', ariaLabel);
|
|
330
|
+
const buttons = [];
|
|
331
|
+
for (const item of items) {
|
|
332
|
+
const button = el('button', item.label, item.danger ? 'danger' : undefined);
|
|
333
|
+
button.type = 'button'; button.setAttribute('role', 'menuitem');
|
|
334
|
+
if (item.icon) button.setAttribute('data-icon', item.icon);
|
|
335
|
+
button.onclick = () => { closeGraphMenu(); item.run(); };
|
|
336
|
+
menu.append(button); buttons.push(button);
|
|
337
|
+
}
|
|
338
|
+
window.AndorraIcons?.hydrate?.(menu);
|
|
339
|
+
document.body.append(menu);
|
|
340
|
+
// A menu near a window edge must not clip an item out of reach.
|
|
341
|
+
const width = menu.offsetWidth || 210, height = menu.offsetHeight || 40;
|
|
342
|
+
menu.style.left = `${Math.max(0, Math.min(x, (window.innerWidth || x + width + 8) - width - 8))}px`;
|
|
343
|
+
menu.style.top = `${Math.max(0, Math.min(y, (window.innerHeight || y + height + 8) - height - 8))}px`;
|
|
344
|
+
const invoker = document.activeElement;
|
|
345
|
+
const close = (restoreFocus = false) => {
|
|
346
|
+
closeGraphMenuHandlers = undefined;
|
|
347
|
+
window.removeEventListener?.('pointerdown', outside, true);
|
|
348
|
+
menu.remove();
|
|
349
|
+
if (restoreFocus) invoker?.focus?.();
|
|
350
|
+
};
|
|
351
|
+
const outside = event => { if (!menu.contains(event.target)) close(); };
|
|
352
|
+
// The toolbar overflow's menu-button pattern: the opening takes focus, arrows move between
|
|
353
|
+
// items, Escape closes and hands focus back to the row, Tab closes without restoring.
|
|
354
|
+
menu.onkeydown = event => {
|
|
355
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
356
|
+
event.preventDefault();
|
|
357
|
+
const index = buttons.indexOf(document.activeElement);
|
|
358
|
+
buttons[(index + (event.key === 'ArrowDown' ? 1 : -1) + buttons.length) % buttons.length]?.focus();
|
|
359
|
+
}
|
|
360
|
+
else if (event.key === 'Escape') { event.preventDefault(); close(true); }
|
|
361
|
+
else if (event.key === 'Tab') close();
|
|
362
|
+
};
|
|
363
|
+
window.addEventListener?.('pointerdown', outside, true);
|
|
364
|
+
closeGraphMenuHandlers = close;
|
|
365
|
+
buttons[0]?.focus?.();
|
|
366
|
+
}
|
|
367
|
+
function showGraphMenu(graph, x, y) {
|
|
368
|
+
showMenuAt(x, y, `${graph.name} actions`, [
|
|
369
|
+
{ label: 'Duplicate', icon: 'copy', run: () => duplicateGraph(graph) },
|
|
370
|
+
{ label: 'Export JSON', icon: 'download', run: () => { exportGraph(graph).catch(error => status(error.message, true)); } },
|
|
371
|
+
]);
|
|
372
|
+
}
|
|
373
|
+
function showNewGraphMenu(x, y) {
|
|
374
|
+
showMenuAt(x, y, 'Create a graph', [
|
|
375
|
+
{ label: 'New graph', icon: 'plus', run: () => newGraph() },
|
|
376
|
+
{ label: 'Import graph', icon: 'upload', run: () => { if (window.AndorraStudio?.openImport) window.AndorraStudio.openImport(); else status('The import dialog is still loading. Try again in a moment.', true); } },
|
|
377
|
+
]);
|
|
378
|
+
}
|
|
379
|
+
// The saved revision a row names is what a friend receives: the open draft's unsaved edits are
|
|
380
|
+
// not part of it. In the desktop host the graph id alone crosses the frame and the host writes
|
|
381
|
+
// the file itself; a plain browser downloads the fetched revision directly.
|
|
382
|
+
async function exportGraph(graph) {
|
|
383
|
+
if (window.AndorraEmbed?.hostChrome?.() && window.AndorraEmbed.exportGraph) { window.AndorraEmbed.exportGraph(graph.id); return; }
|
|
384
|
+
if (state.saving) { status('Wait for the current save before exporting a graph.'); return; }
|
|
385
|
+
downloadGraph(dropLegacyTokenFields(await api(`/api/graphs/${encodeURIComponent(graph.id)}`)));
|
|
386
|
+
}
|
|
387
|
+
function exportFileName(graph) {
|
|
388
|
+
const slug = String(graph.name || '').trim().replace(/[^\w-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 60);
|
|
389
|
+
return slug || graph.id;
|
|
390
|
+
}
|
|
391
|
+
function downloadGraph(graph) { downloadJson(graph, exportFileName(graph)); }
|
|
392
|
+
function downloadJson(value, stem) {
|
|
393
|
+
const url = URL.createObjectURL(new Blob([JSON.stringify(value, null, 2)], { type: 'application/json' }));
|
|
394
|
+
const link = el('a'); link.href = url; link.download = `${stem}.json`; link.click();
|
|
395
|
+
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
|
396
|
+
}
|
|
397
|
+
async function duplicateGraph(source) {
|
|
398
|
+
if (state.saving) { status('Wait for the current save before duplicating a graph.'); return; }
|
|
399
|
+
state.saving = true; renderHeading(); renderList();
|
|
400
|
+
let created;
|
|
401
|
+
try {
|
|
402
|
+
const saved = dropLegacyTokenFields(await api(`/api/graphs/${encodeURIComponent(source.id)}`));
|
|
403
|
+
// validateGraph caps names at 200 characters, so a near-limit source name must make room
|
|
404
|
+
// for the suffix or the save would be rejected with no way to rename the invisible copy.
|
|
405
|
+
const suffix = ' (Copy)', base = saved.name || 'Untitled graph';
|
|
406
|
+
const name = base.length + suffix.length > 200 ? base.slice(0, 200 - suffix.length).trimEnd() + suffix : base + suffix;
|
|
407
|
+
const duplicate = { ...saved, id: newId(), name, revision: 0 };
|
|
408
|
+
const stored = await api('/api/graphs', duplicate);
|
|
409
|
+
created = { id: stored.id, name: stored.name };
|
|
410
|
+
// The rail lists graphs in the server's id order; slot the copy into that order.
|
|
411
|
+
const summary = { id: stored.id, name: stored.name, revision: stored.revision };
|
|
412
|
+
const index = state.graphs.findIndex(item => item.id !== 'default' && item.id > stored.id);
|
|
413
|
+
if (index < 0) state.graphs.push(summary); else state.graphs.splice(index, 0, summary);
|
|
414
|
+
} catch (error) { status(error.message, true); }
|
|
415
|
+
state.saving = false; renderHeading(); renderList();
|
|
416
|
+
if (!created) return;
|
|
417
|
+
if (state.dirty) { status(`Created "${created.name}". Open it from the list to rename it.`); return; }
|
|
418
|
+
await openGraph(created.id);
|
|
419
|
+
if (state.graph?.id === created.id) status(`Duplicated "${source.name}" - Rename it in Graph settings.`);
|
|
420
|
+
}
|
|
421
|
+
function position(node, index) { return node.position || { x: index * 290, y: 0 }; }
|
|
422
|
+
function transform() { $('scene').style.transform = `translate(${state.x}px,${state.y}px) scale(${state.zoom})`; $('zoom').textContent = `${Math.round(state.zoom * 100)}%`; window.AndorraStudio?.viewport?.(); }
|
|
423
|
+
// The canvas tips show until the reader dismisses them once. The choice is a per-browser
|
|
424
|
+
// convenience, so unavailable storage simply shows the tips again next time.
|
|
425
|
+
const HINT_KEY = 'andorra-graph-canvas-hint-dismissed';
|
|
426
|
+
function canvasHintDismissed() {
|
|
427
|
+
if (state.canvasHintDismissed) return true;
|
|
428
|
+
try { return localStorage.getItem(HINT_KEY) === '1'; } catch { return false; }
|
|
429
|
+
}
|
|
430
|
+
function dismissCanvasHint() {
|
|
431
|
+
if (canvasHintDismissed()) return;
|
|
432
|
+
state.canvasHintDismissed = true;
|
|
433
|
+
try { localStorage.setItem(HINT_KEY, '1'); } catch { /* The tips still hide for this session. */ }
|
|
434
|
+
if (!state.routePick && $('canvas-hint')) $('canvas-hint').hidden = true;
|
|
435
|
+
}
|
|
436
|
+
// The model a card names: its own override, else the model its provider profile runs.
|
|
437
|
+
function nodeModelLabel(node) {
|
|
438
|
+
if (node.model) return node.model;
|
|
439
|
+
const providerId = node.provider || state.defaultProvider;
|
|
440
|
+
const provider = state.providers.find(p => idFor(p) === providerId);
|
|
441
|
+
if (provider && typeof provider !== 'string' && provider.model) return provider.model;
|
|
442
|
+
return node.provider ? titleFor(provider || node.provider) : '';
|
|
443
|
+
}
|
|
444
|
+
function nodeSubtitle(node) {
|
|
445
|
+
if (node.type === 'agent') {
|
|
446
|
+
const model = nodeModelLabel(node);
|
|
447
|
+
return node.agentRole === 'orchestrator' ? `Orchestrator${model ? ' · ' + model : ''}` : model;
|
|
448
|
+
}
|
|
449
|
+
if (node.type === 'end') return 'Graph complete';
|
|
450
|
+
if (node.type === 'action') return node.action?.kind === 'tests' ? 'Run tests' : node.action?.kind === 'git' ? 'Git operation' : 'Run command';
|
|
451
|
+
return { join: 'Wait for branches', loop: 'Bounded repetition', condition: 'Branch on run state', parallel: 'Fan out', approval: 'Human approval' }[node.type] || 'Flow control';
|
|
452
|
+
}
|
|
453
|
+
const nodeIconElement = node => globalThis.AndorraIcons?.icon?.(globalThis.AndorraIcons.nodeIcon(node));
|
|
454
|
+
function renderCanvas() {
|
|
455
|
+
$('nodes').replaceChildren(); $('edges').replaceChildren(); $('canvas').classList.toggle('picking-destination',!!state.routePick);
|
|
456
|
+
const hintText = state.routePick ? 'Click a destination node - Escape cancels' : 'Ctrl/Cmd-click same-type nodes to select together - Drag to pan - Scroll to zoom';
|
|
457
|
+
$('canvas-hint-text').textContent = hintText; $('canvas-hint').hidden = !state.routePick && canvasHintDismissed(); $('canvas-hint-close').hidden = !!state.routePick;
|
|
458
|
+
$('empty').hidden = !!state.graph;
|
|
459
|
+
if (!state.graph) return;
|
|
460
|
+
const nodes = Object.values(state.graph.nodes), positions = new Map(nodes.map((node, index) => [node.id, position(node, index)]));
|
|
461
|
+
const connected = new Set(state.graph.edges.map(edge => JSON.stringify([edge.source, edgeOutcome(edge)])));
|
|
462
|
+
const errorIds = nodeErrorIds();
|
|
463
|
+
nodes.forEach((node, index) => {
|
|
464
|
+
const p = positions.get(node.id), button = el('div', undefined, `node ${node.type}${selectedNodes().some(item=>item.id===node.id) ? ' selected' : ''}${errorIds.has(node.id) ? ' node-error' : ''}${state.routePick && !state.routePick.sources.includes(node.id) && node.agentRole !== 'orchestrator' ? ' route-target' : ''}`);
|
|
465
|
+
button.tabIndex = 0; button.setAttribute('data-node-id',node.id); button.setAttribute('role', 'button'); button.style.left = `${p.x}px`; button.style.top = `${p.y}px`; button.setAttribute('aria-label', `${node.name}, ${node.agentRole === 'orchestrator' ? 'orchestrator' : node.type}${node.id === state.graph.entry ? ', entry' : ''}`);
|
|
466
|
+
// The kind is the card's stripe and icon; the subtitle names what the node runs.
|
|
467
|
+
const title = el('div', undefined, 'node-title'), glyph = nodeIconElement(node);
|
|
468
|
+
if (glyph) title.append(glyph);
|
|
469
|
+
title.append(el('b', node.name || 'Untitled'));
|
|
470
|
+
if (node.id === state.graph.entry) title.append(el('span', 'Start', 'chip node-start'));
|
|
471
|
+
button.append(title);
|
|
472
|
+
const subtitle = nodeSubtitle(node);
|
|
473
|
+
if (subtitle) { const line = el('small', subtitle); line.title = subtitle; button.append(line); }
|
|
474
|
+
for (const outcome of outcomes(node)) { const port = el('button', outcome, 'output-port'); port.setAttribute('aria-label', `Connect ${node.name}: ${outcome}`); port.title = `${outcome} - drag to a node to connect`; if (connected.has(JSON.stringify([node.id, outcome]))) port.setAttribute('data-connected', 'true'); port.onpointerdown = event => event.stopPropagation(); port.onclick = event => { event.stopPropagation(); if(state.routePick || event.ctrlKey || event.metaKey) {selectNode(node,event);return;} clearSelection(); state.selectedIds=[node.id]; state.selected = node.id; state.inspectorTab = 'behavior'; renderCanvas(); renderInspector(); $('inspector').classList.remove('hidden'); $('toggle-inspector').setAttribute('aria-expanded','true'); document.getElementById(`route-${outcome}`)?.scrollIntoView({block: 'nearest'}); }; button.append(port); }
|
|
475
|
+
button.onkeydown = event => { if ((event.key === 'Enter' || event.key === ' ') && event.target === button) {event.preventDefault(); selectNode(node,event);} };
|
|
476
|
+
button.onclick = event => selectNode(node,event);
|
|
477
|
+
button.onpointerdown = event => {
|
|
478
|
+
if (event.button !== 0) return; event.stopPropagation(); if(event.ctrlKey || event.metaKey || state.routePick) return; state.suppressClick=null; const start = { x: event.clientX, y: event.clientY }, origin = position(node, index); let moved = false;
|
|
479
|
+
const move = e => { if (!moved && Math.hypot(e.clientX - start.x, e.clientY - start.y) < 3) return; if (!moved) { checkpoint(); moved = true; } const grid = state.studioSnap ? 20 : 1; node.position = { x: Math.round((origin.x + (e.clientX - start.x) / state.zoom) / grid) * grid, y: Math.round((origin.y + (e.clientY - start.y) / state.zoom) / grid) * grid }; changed(); };
|
|
480
|
+
const up = () => { window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up); if (moved) {state.suppressClick=node.id; setTimeout(()=>{if(state.suppressClick===node.id)state.suppressClick=null;},0); renderInspector();} };
|
|
481
|
+
window.addEventListener('pointermove', move); window.addEventListener('pointerup', up, { once: true });
|
|
482
|
+
};
|
|
483
|
+
$('nodes').append(button);
|
|
484
|
+
}); transform(); renderEdges(); window.AndorraStudio?.canvas?.();
|
|
485
|
+
}
|
|
486
|
+
let routedGeometry = '', routedPaths = new Map();
|
|
487
|
+
function renderEdges() {
|
|
488
|
+
$('edges').replaceChildren();
|
|
489
|
+
if (!state.graph) return;
|
|
490
|
+
const svg = tag => document.createElementNS('http://www.w3.org/2000/svg', tag);
|
|
491
|
+
const defs=svg('defs'); $('edges').append(defs);
|
|
492
|
+
const boxes=new Map();
|
|
493
|
+
Object.values(state.graph.nodes).forEach((node,index)=>{
|
|
494
|
+
const element=Array.from($('nodes').children).find(item=>item.getAttribute('data-node-id')===node.id), p=position(node,index);
|
|
495
|
+
const ports=Array.from(element.querySelectorAll('.output-port'));
|
|
496
|
+
boxes.set(node.id,{...p,width:element.offsetWidth,height:element.offsetHeight,ports:ports.map(port=>({x:p.x+element.offsetWidth,y:p.y+port.offsetTop+port.offsetHeight/2}))});
|
|
497
|
+
});
|
|
498
|
+
const geometry=JSON.stringify([...boxes]);
|
|
499
|
+
if(geometry!==routedGeometry){routedGeometry=geometry;routedPaths.clear();}
|
|
500
|
+
const rectangles=[...boxes.values()], rendered=[], pills=[], palette=connectionPalette();
|
|
501
|
+
const caption=svg('text'); caption.setAttribute('class','edge-caption'); caption.style.pointerEvents='none';
|
|
502
|
+
const emphasize = active => {
|
|
503
|
+
for (const item of rendered) {
|
|
504
|
+
item.path.setAttribute('stroke-width',item.edge===active?'3':'1.7');
|
|
505
|
+
item.path.setAttribute('opacity',active && item.edge!==active?'0.25':'1');
|
|
506
|
+
item.halo.setAttribute('opacity',active && item.edge!==active?'0.25':'1');
|
|
507
|
+
item.pill?.setAttribute('opacity',active && item.edge!==active?'0.25':'1');
|
|
508
|
+
}
|
|
509
|
+
for (const element of Array.from($('nodes').children)) {
|
|
510
|
+
const id=element.getAttribute('data-node-id');
|
|
511
|
+
element.classList.toggle('edge-source',Boolean(active && id===active.source));
|
|
512
|
+
element.classList.toggle('edge-target',Boolean(active && id===active.target));
|
|
513
|
+
}
|
|
514
|
+
const item=rendered.find(item=>item.edge===active);
|
|
515
|
+
caption.textContent=item?`${edgeOutcome(item.edge)} -> ${state.graph.nodes[item.edge.target].name}`:'';
|
|
516
|
+
if(item){caption.setAttribute('x',String(item.from.x));caption.setAttribute('y',String(item.from.y-14));caption.setAttribute('fill',item.color);}
|
|
517
|
+
};
|
|
518
|
+
// Draw a selected connection last so crossings cannot obscure its direction.
|
|
519
|
+
const ordered=state.graph.edges.map((edge,index)=>({edge,index})).sort((a,b)=>Number(a.edge===state.selectedEdge)-Number(b.edge===state.selectedEdge));
|
|
520
|
+
ordered.forEach(({edge,index})=>{
|
|
521
|
+
const from=boxes.get(edge.source),to=boxes.get(edge.target);if(!from||!to)return;
|
|
522
|
+
const source=from.ports[Math.max(0,outcomes(state.graph.nodes[edge.source]).indexOf(edgeOutcome(edge)))];if(!source)return;
|
|
523
|
+
const routeKey=JSON.stringify([source,to.x,to.y+48,index]);
|
|
524
|
+
if(!routedPaths.has(routeKey)){
|
|
525
|
+
const points=AndorraEdgeRouter.routeEdge(source,{x:to.x,y:to.y+48},rectangles,index);
|
|
526
|
+
// Elbows are drawn rounded; a router without the helper keeps its square corners.
|
|
527
|
+
routedPaths.set(routeKey,{d:(AndorraEdgeRouter.roundedPath||AndorraEdgeRouter.path)(points),label:AndorraEdgeRouter.labelPoint?.(points)});
|
|
528
|
+
}
|
|
529
|
+
const route=routedPaths.get(routeKey), d=route.d, path=svg('path'), hit=svg('path'), halo=svg('path');
|
|
530
|
+
const outcome=edgeOutcome(edge), color=outcome==='fail'||outcome==='rejected'?palette.fail:outcome==='pass'||outcome==='approved'?palette.pass:outcome==='blocked'?palette.blocked:palette.plain;
|
|
531
|
+
const marker=svg('marker'), arrow=svg('path');
|
|
532
|
+
for(const [name,value] of Object.entries({id:`edge-arrow-${index}`,viewBox:'0 0 10 10',refX:'9',refY:'5',markerWidth:'7',markerHeight:'7',orient:'auto-start-reverse'}))marker.setAttribute(name,value);
|
|
533
|
+
arrow.setAttribute('d','M 0 0 L 10 5 L 0 10 z');arrow.setAttribute('fill',color);arrow.style.pointerEvents='none';marker.append(arrow);defs.append(marker);
|
|
534
|
+
halo.setAttribute('d',d);halo.setAttribute('stroke',palette.halo);halo.setAttribute('stroke-width','6');halo.setAttribute('fill','none');halo.style.pointerEvents='none';
|
|
535
|
+
path.setAttribute('d',d);path.setAttribute('data-route',JSON.stringify([edge.source,edgeOutcome(edge),edge.target]));path.setAttribute('stroke',color);path.setAttribute('fill','none');path.setAttribute('stroke-linejoin','round');path.setAttribute('marker-end',`url(#edge-arrow-${index})`);path.style.pointerEvents='none';
|
|
536
|
+
hit.setAttribute('d',d);hit.setAttribute('stroke','transparent');hit.setAttribute('stroke-width','14');hit.setAttribute('fill','none');hit.style.pointerEvents='stroke';hit.style.cursor='pointer';hit.setAttribute('tabindex','0');hit.setAttribute('role','button');hit.setAttribute('aria-label',`Configure handoff from ${state.graph.nodes[edge.source].name}, ${edgeOutcome(edge)}, to ${state.graph.nodes[edge.target].name}`);
|
|
537
|
+
hit.onclick=event=>{event.stopPropagation();clearSelection();state.selectedEdge=edge;renderInspector();renderCanvas();showInspector();};
|
|
538
|
+
hit.onkeydown=event=>{if(event.key==='Enter'||event.key===' '){event.preventDefault();hit.onclick(event);}};
|
|
539
|
+
// The connection's hint is the app's tooltip (an SVG title would be the platform's).
|
|
540
|
+
hit.setAttribute('data-tip',`${state.graph.nodes[edge.source].name}: ${outcome} -> ${state.graph.nodes[edge.target].name}`);
|
|
541
|
+
hit.onpointerenter=hit.onfocus=()=>emphasize(edge);
|
|
542
|
+
hit.onpointerleave=hit.onblur=()=>emphasize(state.selectedEdge);
|
|
543
|
+
const entry={edge,path,halo,from,color,pill:null};rendered.push(entry);
|
|
544
|
+
$('edges').append(halo,path,hit);
|
|
545
|
+
// The outcome rides its line as a pill. A node's only, default outcome needs no name.
|
|
546
|
+
const single=outcomes(state.graph.nodes[edge.source]).length===1&&outcome==='completed';
|
|
547
|
+
if(route.label&&!single)pills.push({entry,outcome,color,at:route.label});
|
|
548
|
+
});
|
|
549
|
+
const pillLayer=svg('g');pillLayer.setAttribute('class','edge-pills');pillLayer.setAttribute('aria-hidden','true');
|
|
550
|
+
for(const {entry,outcome,color,at} of pills){const edge=entry.edge;
|
|
551
|
+
const group=svg('g'),rect=svg('rect'),text=svg('text');
|
|
552
|
+
const width=Math.max(28,Math.round(outcome.length*6.6+16)),height=18;
|
|
553
|
+
group.setAttribute('class','edge-pill');group.setAttribute('data-route',JSON.stringify([edge.source,outcome,edge.target]));
|
|
554
|
+
for(const [name,value] of Object.entries({x:String(Math.round(at.x-width/2)),y:String(at.y-height/2),width:String(width),height:String(height),rx:String(height/2),fill:palette.pill,stroke:color,'stroke-width':'1'}))rect.setAttribute(name,value);
|
|
555
|
+
for(const [name,value] of Object.entries({x:String(Math.round(at.x)),y:String(at.y+4),'text-anchor':'middle',fill:color}))text.setAttribute(name,value);
|
|
556
|
+
text.textContent=outcome;group.append(rect,text);pillLayer.append(group);
|
|
557
|
+
entry.pill=group;
|
|
558
|
+
}
|
|
559
|
+
$('edges').append(pillLayer,caption); emphasize(state.selectedEdge);
|
|
560
|
+
}
|
|
561
|
+
function removeNodes(ids) {
|
|
562
|
+
const graph = state.graph;
|
|
563
|
+
const remaining = Object.keys(graph.nodes).filter(id => !ids.has(id));
|
|
564
|
+
if (!remaining.length) { status('Keep at least one node as the graph start. Add a replacement before deleting all nodes.', true); return; }
|
|
565
|
+
const nextEntry = ids.has(graph.entry)
|
|
566
|
+
? graph.edges.find(edge => edge.source === graph.entry && !ids.has(edge.target) && graph.nodes[edge.target])?.target ?? remaining[0]
|
|
567
|
+
: graph.entry;
|
|
568
|
+
mutate(() => {
|
|
569
|
+
for (const id of ids) delete graph.nodes[id];
|
|
570
|
+
graph.edges = graph.edges.filter(edge => !ids.has(edge.source) && !ids.has(edge.target));
|
|
571
|
+
if (graph.metadata?.studioLayoutGroupsV1) { for (const group of graph.metadata.studioLayoutGroupsV1) group.nodeIds = group.nodeIds.filter(id => !ids.has(id)); graph.metadata.studioLayoutGroupsV1 = graph.metadata.studioLayoutGroupsV1.filter(group => group.nodeIds.length); }
|
|
572
|
+
graph.entry = nextEntry;
|
|
573
|
+
// Explicitly preserve an edited graph without intake when it is reopened.
|
|
574
|
+
graph.schemaVersion = 3;
|
|
575
|
+
clearSelection();
|
|
576
|
+
}, true);
|
|
577
|
+
status(`Deleted ${ids.size} node${ids.size === 1 ? '' : 's'} and their connections. Start: ${graph.nodes[nextEntry].name}. Undo restores them.`);
|
|
578
|
+
}
|
|
579
|
+
function deleteSelection() {
|
|
580
|
+
if(!state.graph)return;
|
|
581
|
+
if(state.selectedEdge){const edge=state.selectedEdge;mutate(()=>{state.graph.edges=state.graph.edges.filter(item=>item!==edge);clearSelection();},true);return;}
|
|
582
|
+
const selected = selectedNodes();
|
|
583
|
+
if (selected.length) removeNodes(new Set(selected.map(node => node.id)));
|
|
584
|
+
}
|
|
585
|
+
function field(parent, label, value, onChange, options = {}) {
|
|
586
|
+
const wrapper = el('label', undefined, 'field'); wrapper.append(el('span', label));
|
|
587
|
+
const input = el(options.multiline ? 'textarea' : options.options ? 'select' : 'input');
|
|
588
|
+
if (options.options) for (const option of options.options) { const item = el('option', option.label); item.value = option.value; input.append(item); }
|
|
589
|
+
if (options.type) input.type = options.type;
|
|
590
|
+
if (options.type === 'number') input.step = '1';
|
|
591
|
+
if (options.min !== undefined) input.min = options.min; if (options.max !== undefined) input.max = options.max;
|
|
592
|
+
if (options.maxLength !== undefined) input.maxLength = options.maxLength;
|
|
593
|
+
if (options.placeholder !== undefined) input.placeholder = options.placeholder;
|
|
594
|
+
input.value = value ?? ''; if (options.mono) input.className = 'mono';
|
|
595
|
+
input.onchange = () => mutate(() => onChange(options.type === 'number' ? (options.optional && input.value.trim()==='' ? undefined : Number(input.value)) : input.value), !!options.refresh);
|
|
596
|
+
wrapper.append(input); parent.append(wrapper); return input;
|
|
597
|
+
}
|
|
598
|
+
function section(parent, title) { const item = el('section', undefined, 'section'); item.append(el('h3', title)); parent.append(item); return item; }
|
|
599
|
+
// Normalize one validation error for display. Client issues carry the node id directly, so two
|
|
600
|
+
// agents sharing a display name cannot misattribute an aura or a click-to-focus; a server
|
|
601
|
+
// message names its node by the `node <id>:` label or `${node.name}:` and is matched the old way.
|
|
602
|
+
function errorEntry(error) {
|
|
603
|
+
if (typeof error === 'string') {
|
|
604
|
+
return { message: error, nodeId: Object.values(state.graph?.nodes || {}).find(node => error.includes('node ' + node.id) || error.includes(node.name + ':'))?.id ?? null };
|
|
605
|
+
}
|
|
606
|
+
return { message: error.message, nodeId: error.nodeId ?? null };
|
|
607
|
+
}
|
|
608
|
+
function nodeErrorIds() {
|
|
609
|
+
const ids = new Set();
|
|
610
|
+
for (const error of [...issues(), ...state.validationErrors]) { const id = errorEntry(error).nodeId; if (id) ids.add(id); }
|
|
611
|
+
return ids;
|
|
612
|
+
}
|
|
613
|
+
function renderValidation() {
|
|
614
|
+
const container=$('validation');if(!container)return;container.replaceChildren();const errors=[...issues(),...state.validationErrors].map(errorEntry);
|
|
615
|
+
if(!errors.length)container.append(el('p',state.validated?'Validated - Ready to save':'Checking graph...','valid'));
|
|
616
|
+
else {const list=el('ul',undefined,'validation');errors.forEach(({message,nodeId})=>{ const row=el('li',message); row.tabIndex=0; row.title='Click to focus the affected node'; row.onclick=()=>{if(nodeId){clearSelection();state.selected=nodeId;state.selectedIds=[nodeId];renderCanvas();renderInspector();}};row.onkeydown=e=>{if(e.key==='Enter'||e.key===' ')row.click();};list.append(row);});container.append(list);}
|
|
617
|
+
}
|
|
618
|
+
function disclosure(parent, title, open = false) { const item = el('details', undefined, 'section disclosure'); const key = `${state.selectedEdge?.id || state.selected || 'graph'}:${title}`; item.open = state.disclosures[key] ?? open; item.ontoggle = () => {state.disclosures[key] = item.open;}; item.append(el('summary', title)); const body = el('div'); item.append(body); parent.append(item); return body; }
|
|
619
|
+
function check(parent, label, value, update) { const wrapper = el('label', undefined, 'tool-label'), input = el('input'); input.type = 'checkbox'; input.checked = value; input.onchange = () => mutate(() => update(input.checked), true); wrapper.append(input, el('span', label)); parent.append(wrapper); return input; }
|
|
620
|
+
// A "?" beside a label keeps a long explanation one hover, focus or tap away (ADR 0022). The text
|
|
621
|
+
// stays in the document as the trigger's accessible description. `target` is a field's input, its
|
|
622
|
+
// label, or a heading; anything else receives the explanation as an ordinary paragraph.
|
|
623
|
+
let infoTipSeq = 0;
|
|
624
|
+
const tipHost = item => !!item && (item.className === 'field' || item.className === 'field prompt-field' || item.className === 'tool-label' || item.tagName === 'h3' || item.tagName === 'H3');
|
|
625
|
+
function explain(target, text) {
|
|
626
|
+
const host = tipHost(target) ? target : tipHost(target?.parentElement) ? target.parentElement : undefined;
|
|
627
|
+
if (!host) { target?.append?.(el('p', text, 'help')); return; }
|
|
628
|
+
const tip = el('span', undefined, 'info-tip'), trigger = el('button', undefined, 'icon-button'), body = el('span', text, 'info-tip-text');
|
|
629
|
+
const id = `info-tip-${++infoTipSeq}`;
|
|
630
|
+
body.id = id; body.setAttribute('role', 'tooltip');
|
|
631
|
+
trigger.type = 'button'; trigger.setAttribute('aria-label', 'More information'); trigger.setAttribute('aria-describedby', id);
|
|
632
|
+
const glyph = globalThis.AndorraIcons?.icon?.('help', 14); if (glyph) trigger.append(glyph); else trigger.textContent = '?';
|
|
633
|
+
// The trigger sits inside a label, so its click must not reach the label's control.
|
|
634
|
+
trigger.onclick = event => { event?.preventDefault?.(); event?.stopPropagation?.(); tip.classList.toggle('open'); };
|
|
635
|
+
trigger.onkeydown = event => { if (event.key === 'Escape') { tip.classList.remove('open'); trigger.blur?.(); } };
|
|
636
|
+
trigger.onblur = () => tip.classList.remove('open');
|
|
637
|
+
tip.append(trigger, body); host.append(tip);
|
|
638
|
+
}
|
|
639
|
+
// The inspector's node settings are split into tabs. Every panel is rendered, so a field keeps its
|
|
640
|
+
// place in the document and the validity check before saving can still reach it; only the chosen
|
|
641
|
+
// panel is shown. The choice is kept across selections, so moving between nodes stays on a tab.
|
|
642
|
+
const INSPECTOR_TABS = { general: 'General', model: 'Model', behavior: 'Behavior', advanced: 'Advanced' };
|
|
643
|
+
let inspectorTabControls = [];
|
|
644
|
+
function selectInspectorTab(id, focus = false) {
|
|
645
|
+
if (!inspectorTabControls.some(item => item.id === id)) return;
|
|
646
|
+
state.inspectorTab = id;
|
|
647
|
+
for (const item of inspectorTabControls) {
|
|
648
|
+
const active = item.id === id;
|
|
649
|
+
item.tab.setAttribute('aria-selected', String(active)); item.tab.tabIndex = active ? 0 : -1; item.panel.hidden = !active;
|
|
650
|
+
if (active && focus) item.tab.focus?.();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
// Shows the panel holding a control, used before a control in a hidden panel reports a problem.
|
|
654
|
+
function revealInspectorControl(control) {
|
|
655
|
+
for (const item of inspectorTabControls) if (item.panel.contains?.(control)) { selectInspectorTab(item.id); return; }
|
|
656
|
+
}
|
|
657
|
+
function inspectorTabs(parent, ids) {
|
|
658
|
+
const bar = el('div', undefined, 'inspector-tabs'); bar.setAttribute('role', 'tablist'); bar.setAttribute('aria-label', 'Inspector sections');
|
|
659
|
+
parent.append(bar);
|
|
660
|
+
const active = ids.includes(state.inspectorTab) ? state.inspectorTab : ids[0];
|
|
661
|
+
const panels = {}; inspectorTabControls = [];
|
|
662
|
+
for (const id of ids) {
|
|
663
|
+
const tab = el('button', INSPECTOR_TABS[id]); tab.type = 'button'; tab.id = `inspector-tab-${id}`;
|
|
664
|
+
tab.setAttribute('role', 'tab'); tab.setAttribute('aria-controls', `inspector-panel-${id}`);
|
|
665
|
+
const panel = el('div', undefined, 'inspector-panel'); panel.id = `inspector-panel-${id}`;
|
|
666
|
+
panel.setAttribute('role', 'tabpanel'); panel.setAttribute('aria-labelledby', tab.id); panel.setAttribute('data-tab', id);
|
|
667
|
+
tab.onclick = () => selectInspectorTab(id);
|
|
668
|
+
tab.onkeydown = event => {
|
|
669
|
+
const index = ids.indexOf(id);
|
|
670
|
+
const next = event.key === 'ArrowRight' ? ids[(index + 1) % ids.length] : event.key === 'ArrowLeft' ? ids[(index - 1 + ids.length) % ids.length] : event.key === 'Home' ? ids[0] : event.key === 'End' ? ids.at(-1) : undefined;
|
|
671
|
+
if (next) { event.preventDefault(); selectInspectorTab(next, true); }
|
|
672
|
+
};
|
|
673
|
+
bar.append(tab); panels[id] = panel; inspectorTabControls.push({ id, tab, panel });
|
|
674
|
+
}
|
|
675
|
+
for (const id of ids) parent.append(panels[id]);
|
|
676
|
+
// Selecting is an inspection, not a choice: only a click on a tab changes the remembered tab.
|
|
677
|
+
const remembered = state.inspectorTab;
|
|
678
|
+
selectInspectorTab(active);
|
|
679
|
+
if (remembered !== undefined && !ids.includes(remembered)) state.inspectorTab = remembered;
|
|
680
|
+
return panels;
|
|
681
|
+
}
|
|
682
|
+
// The prompt grows with its text up to a ceiling, and a button opens it full screen.
|
|
683
|
+
function promptField(parent, label, value, onChange, options = {}) {
|
|
684
|
+
const input = field(parent, label, value, onChange, { multiline: true, maxLength: 100000, ...options });
|
|
685
|
+
const wrapper = input.parentElement; wrapper.className = 'field prompt-field';
|
|
686
|
+
const isFullscreen = () => !!wrapper.classList.contains?.('fullscreen');
|
|
687
|
+
const grow = () => { try { if (!isFullscreen() && input.scrollHeight) { input.style.height = 'auto'; input.style.height = `${input.scrollHeight + 2}px`; } } catch { /* A partial DOM has no layout. */ } };
|
|
688
|
+
input.addEventListener?.('input', grow);
|
|
689
|
+
const expand = el('button', undefined, 'icon-button btn-small prompt-expand'); expand.type = 'button';
|
|
690
|
+
let backdrop;
|
|
691
|
+
const setFullscreen = on => {
|
|
692
|
+
wrapper.classList.toggle('fullscreen', on);
|
|
693
|
+
document.body?.classList?.toggle?.('prompt-fullscreen', on);
|
|
694
|
+
expand.setAttribute('aria-label', on ? `Exit full screen ${label}` : `Edit ${label} full screen`);
|
|
695
|
+
expand.title = on ? 'Exit full screen (Escape)' : 'Expand to full screen';
|
|
696
|
+
expand.replaceChildren(); const glyph = globalThis.AndorraIcons?.icon?.(on ? 'collapse' : 'expand', 14); if (glyph) expand.append(glyph);
|
|
697
|
+
if (on) { backdrop = el('div', undefined, 'prompt-backdrop'); backdrop.onclick = () => setFullscreen(false); document.body?.append?.(backdrop); input.style.height = ''; input.focus?.(); }
|
|
698
|
+
else { backdrop?.remove?.(); backdrop = undefined; grow(); }
|
|
699
|
+
};
|
|
700
|
+
expand.onclick = event => { event?.preventDefault?.(); event?.stopPropagation?.(); setFullscreen(!isFullscreen()); };
|
|
701
|
+
input.addEventListener?.('keydown', event => { if (event.key === 'Escape' && isFullscreen()) { event.preventDefault(); setFullscreen(false); } });
|
|
702
|
+
setFullscreen(false); wrapper.append(expand);
|
|
703
|
+
setTimeout(grow, 0);
|
|
704
|
+
return input;
|
|
705
|
+
}
|
|
706
|
+
// A provider the graph names but this machine does not configure is a warning, not a model name.
|
|
707
|
+
function providerWarning(parent, providerId) {
|
|
708
|
+
const chip = el('p', undefined, 'chip chip-warning provider-warning'); chip.setAttribute('role', 'status');
|
|
709
|
+
const glyph = globalThis.AndorraIcons?.icon?.('warning', 14); if (glyph) chip.append(glyph);
|
|
710
|
+
chip.append(el('span', `${providerId} unavailable`));
|
|
711
|
+
// The desktop app can open its provider settings; a browser-launched studio has no such route.
|
|
712
|
+
if (typeof window.AndorraEmbed?.openProviderSettings === 'function' && window.AndorraEmbed.hostChrome?.()) {
|
|
713
|
+
const configure = el('button', 'Configure', 'link-button'); configure.type = 'button';
|
|
714
|
+
configure.title = 'Open provider settings in the desktop app'; configure.onclick = () => window.AndorraEmbed.openProviderSettings();
|
|
715
|
+
chip.append(configure);
|
|
716
|
+
} else chip.title = 'Add this provider in the Andorra Code provider settings, or choose another profile.';
|
|
717
|
+
parent.append(chip);
|
|
718
|
+
}
|
|
719
|
+
function choice(parent, label, value, values, update, refresh = true) { return field(parent, label, value, update, { options: values.map(v => typeof v === 'string' ? {value: v, label: v.replaceAll('-', ' ')} : v), refresh }); }
|
|
720
|
+
function jsonField(parent, label, value, update) {
|
|
721
|
+
const wrapper = el('label', undefined, 'field'); wrapper.append(el('span', label)); const input = el('textarea'); input.className = 'mono'; input.value = value === undefined ? '' : JSON.stringify(value, null, 2); input.onchange = () => { try { const parsed = input.value.trim() ? JSON.parse(input.value) : undefined; input.setCustomValidity(''); mutate(() => update(parsed)); } catch { input.setCustomValidity('Enter valid JSON or clear this field.'); input.reportValidity(); } }; wrapper.append(input); parent.append(wrapper);
|
|
722
|
+
}
|
|
723
|
+
const CAPABILITIES = { filesystem: ['none', 'read', 'read-write'], shell: ['disabled', 'read-only', 'allowed'], git: ['none', 'read', 'write'], github: ['none', 'read', 'pull-request', 'review'], browser: ['disabled', 'playwright'], deployment: ['none', 'allowed'] };
|
|
724
|
+
function capabilities(parent, policy, update, ceiling) {
|
|
725
|
+
for (const [key, values] of Object.entries(CAPABILITIES)) {
|
|
726
|
+
const input = choice(parent, key.charAt(0).toUpperCase() + key.slice(1), policy?.[key] || effectiveCaps()[key], values, value => update({...effectiveCaps(), ...policy, [key]: value}));
|
|
727
|
+
if (ceiling) for (const option of input.options) if ((key === 'github' && ['pull-request','review'].includes(option.value) && option.value !== ceiling[key]) || values.indexOf(option.value) > values.indexOf(ceiling[key] || values[0])) option.disabled = true;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
let modelSuggestionSeq = 0;
|
|
731
|
+
function modelFields(parent, target, update, parentModel, inheritedProvider, fallbackProvider) {
|
|
732
|
+
const providers = state.providers.map(p => ({value: idFor(p), label: `${titleFor(p)}${p.model ? ' - ' + p.model : ''}`}));
|
|
733
|
+
if (target.provider && !providers.some(p => p.value === target.provider)) providers.push({value: target.provider, label: target.provider + ' (unavailable)'});
|
|
734
|
+
choice(parent, 'Model profile / provider', target.provider || '', [{value:'', label:'Use configured default'}, ...providers], value => update({ ...target, provider: value || undefined, model: undefined }));
|
|
735
|
+
if (target.provider && !state.providers.some(p => idFor(p) === target.provider)) providerWarning(parent, target.provider);
|
|
736
|
+
// Surface portability without rewriting the synced revision or local credentials. The alias must
|
|
737
|
+
// satisfy every reference to the original provider graph-wide (bindPortableGraphProviders groups
|
|
738
|
+
// them), so the hint mirrors that grouping instead of promising an alias execution would refuse.
|
|
739
|
+
if (target.provider) {
|
|
740
|
+
const originalId = target.provider;
|
|
741
|
+
const recorded = state.graph?.metadata?.graphProviderProfilesV1?.[originalId];
|
|
742
|
+
const explicit = new Set();
|
|
743
|
+
let groupInheritsRecorded = false;
|
|
744
|
+
const note = (reference, parentProvider) => {
|
|
745
|
+
if (reference.provider !== originalId) return;
|
|
746
|
+
if (reference.model) { explicit.add(reference.model); return; }
|
|
747
|
+
if (parentProvider === originalId) return; // Same-provider child without a model inherits the parent at execution.
|
|
748
|
+
groupInheritsRecorded = true;
|
|
749
|
+
};
|
|
750
|
+
for (const node of Object.values(state.graph?.nodes || {})) {
|
|
751
|
+
if (node.type !== 'agent') continue;
|
|
752
|
+
const policy = node.subagents;
|
|
753
|
+
const activeSubagents = policy?.enabled && node.maxSubagents !== 0 && policy.maxTotal !== 0;
|
|
754
|
+
const inheritedModels = [];
|
|
755
|
+
if (activeSubagents) {
|
|
756
|
+
const children = policy.modelPolicy === 'per-role' ? policy.roles || []
|
|
757
|
+
: policy.modelPolicy === 'specific' ? [policy] : [];
|
|
758
|
+
for (const child of children) if (!child.provider && child.model) inheritedModels.push(child.model);
|
|
759
|
+
}
|
|
760
|
+
note(node);
|
|
761
|
+
if (node.provider === originalId) for (const model of inheritedModels) explicit.add(model);
|
|
762
|
+
if (node.retry?.fallback && node.retry.maxAttempts > 1) {
|
|
763
|
+
note(node.retry.fallback);
|
|
764
|
+
if (node.retry.fallback.provider === originalId) for (const model of inheritedModels) explicit.add(model);
|
|
765
|
+
}
|
|
766
|
+
if (!activeSubagents) continue;
|
|
767
|
+
if (policy.modelPolicy === 'specific') note(policy);
|
|
768
|
+
else if (policy.modelPolicy === 'per-role') for (const role of policy.roles || []) note(role, node.provider);
|
|
769
|
+
}
|
|
770
|
+
const explicitModels = [...explicit];
|
|
771
|
+
// The live-model hint describes the inspected selection, not the whole provider group: another
|
|
772
|
+
// reference being unpinned must not claim this one has no override.
|
|
773
|
+
const followsProvider = target.model === undefined && parentModel === undefined;
|
|
774
|
+
const requiredModels = groupInheritsRecorded && recorded?.model ? [...explicitModels, recorded.model] : explicitModels;
|
|
775
|
+
const offers = (p, models) => models.every(model => [p.model, ...(p.models || [])].includes(model));
|
|
776
|
+
// A same-ID local provider is authoritative; its current model is what an unpinned reference
|
|
777
|
+
// uses, so the recorded model is only an alias requirement. This mirrors
|
|
778
|
+
// bindPortableGraphProviders, which execution calls before every run.
|
|
779
|
+
const exact = state.providers.find(p => idFor(p) === originalId && (!recorded?.type || p.type === recorded.type) && offers(p, explicitModels));
|
|
780
|
+
if (!exact) {
|
|
781
|
+
// A local provider that owns the original ID blocks aliasing even when it cannot satisfy
|
|
782
|
+
// the graph, so the editor must not promise a Codex profile execution will refuse.
|
|
783
|
+
const claimedProvider = state.providers.find(p => idFor(p) === originalId);
|
|
784
|
+
const claimed = claimedProvider !== undefined;
|
|
785
|
+
const typeMismatch = claimed && !!recorded?.type && claimedProvider.type !== recorded.type;
|
|
786
|
+
const matches = !claimed && recorded?.type === 'codex' ? state.providers.filter(p => p.type === 'codex' && offers(p, requiredModels)) : [];
|
|
787
|
+
const refusalHint = typeMismatch
|
|
788
|
+
? `Provider "${originalId}" is configured locally with type "${claimedProvider.type}", but this graph was published with type "${recorded.type}". Execution will refuse this graph; reconnect a provider of the recorded type.`
|
|
789
|
+
: `Provider "${originalId}" is configured locally but does not offer ${requiredModels.join(', ')}. Execution will refuse this graph until that provider is configured with the model; another profile is never used as a substitute.`;
|
|
790
|
+
const hint = matches.length === 1
|
|
791
|
+
? `Will use local Codex OAuth profile "${idFor(matches[0])}" (${requiredModels.join(', ') || 'all referenced models'}). The OAuth connection is verified before execution.`
|
|
792
|
+
: matches.length > 1
|
|
793
|
+
? `Multiple local Codex OAuth profiles (${matches.map(idFor).join(', ')}) each satisfy this graph's requirements for "${originalId}". Execution needs exactly one; configure the original provider ID or keep a single compatible profile.`
|
|
794
|
+
: claimed
|
|
795
|
+
? refusalHint
|
|
796
|
+
: `Provider "${originalId}"${requiredModels.length ? ` / ${requiredModels.join(', ')}` : ''} is not configured on this machine. This graph can be saved, but execution requires a compatible provider.`;
|
|
797
|
+
parent.append(el('p', hint, 'help'));
|
|
798
|
+
} else if (followsProvider && recorded?.model && recorded.model !== exact.model) {
|
|
799
|
+
parent.append(el('p', `This selection follows "${originalId}"'s current model, ${exact.model}.`, 'help'));
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
// A providerless subagent child inherits the parent node's provider at execution
|
|
803
|
+
// (bindPortableGraphProviders adds its model to the parent's requirements), so the suggestions
|
|
804
|
+
// shown here and the recording that makes a discovered pick runnable must resolve against that
|
|
805
|
+
// inherited provider, not the machine default, or the selection lands on the wrong provider.
|
|
806
|
+
const listingProvider = target.provider || inheritedProvider || state.defaultProvider || '';
|
|
807
|
+
const provider = state.providers.find(p => idFor(p) === listingProvider);
|
|
808
|
+
const info = el('p', 'Context window: detecting from model...', 'help model-context'); parent.append(info);
|
|
809
|
+
const key = JSON.stringify([target.provider || '', target.model || '', provider?.model || '']);
|
|
810
|
+
// Capture the registry generation before any discovery request starts: a callback resolving
|
|
811
|
+
// after a registry change describes the previous endpoint and must discard itself.
|
|
812
|
+
const registryGeneration = state.providerRegistryGeneration || 0;
|
|
813
|
+
state.modelContextRequests ||= new Map();
|
|
814
|
+
if (!state.modelContextRequests.has(key)) state.modelContextRequests.set(key, api(`/api/model-context?provider=${encodeURIComponent(target.provider || '')}&model=${encodeURIComponent(target.model || '')}`).catch(() => ({contextWindow:null})));
|
|
815
|
+
state.modelContextRequests.get(key).then(data => {
|
|
816
|
+
if ((state.providerRegistryGeneration || 0) !== registryGeneration) return;
|
|
817
|
+
info.textContent = data.contextWindow ? `Context window: ${data.contextWindow.toLocaleString()} tokens (automatic)` : 'Context window: not reported by this model. Runtime uses its default budget.';
|
|
818
|
+
});
|
|
819
|
+
const override = disclosure(parent, 'Model override');
|
|
820
|
+
const model = field(override, 'Model override (optional)', target.model, value => update({...target, model: value.trim() || undefined}), {maxLength:500,refresh:true}); model.placeholder = provider?.model || 'Configured profile model';
|
|
821
|
+
// The override stays free-text so a graph can name a model this machine has never seen, but the
|
|
822
|
+
// provider's catalog is offered alongside it: the configured models first, then everything the
|
|
823
|
+
// endpoint itself lists, so a provider that serves several models is selectable here rather than
|
|
824
|
+
// only the active one. Discovery is per provider, requested once, and failures simply leave the
|
|
825
|
+
// configured suggestions in place.
|
|
826
|
+
const datalist = el('datalist'); datalist.id = `provider-models-${++modelSuggestionSeq}`; model.setAttribute('list', datalist.id); override.append(datalist);
|
|
827
|
+
const displayed = new Set();
|
|
828
|
+
// Recording candidates are ONLY names discovery listed. Everything shown in the datalist lives in
|
|
829
|
+
// `displayed` (dedupe for <option> elements), but committing a displayed name must not authorize
|
|
830
|
+
// recording it: the configured models are already configured (skipped via `known`), and the node's
|
|
831
|
+
// own free-text override is precisely the speculative name this machine must not endorse into the
|
|
832
|
+
// provider configuration just because the graph happened to contain it.
|
|
833
|
+
const offered = new Set();
|
|
834
|
+
const addModelOption = (name, label) => {
|
|
835
|
+
const value = name?.trim();
|
|
836
|
+
if (!value || displayed.has(value)) return;
|
|
837
|
+
displayed.add(value);
|
|
838
|
+
const option = el('option'); option.value = value; if (label) option.label = label; datalist.append(option);
|
|
839
|
+
};
|
|
840
|
+
const activeName = provider?.model?.trim() || '';
|
|
841
|
+
for (const name of [activeName, ...(provider?.models || [])]) addModelOption(name, name?.trim() === activeName && name ? '(active)' : undefined);
|
|
842
|
+
if (target.model) addModelOption(target.model, target.model.trim() === activeName ? '(active)' : undefined);
|
|
843
|
+
// Keyed by the resolved provider: a node using the configured default must follow that default's
|
|
844
|
+
// identity, not share a blank key that survives a default switch.
|
|
845
|
+
state.providerModelRequests ||= new Map();
|
|
846
|
+
if (!state.providerModelRequests.has(listingProvider)) state.providerModelRequests.set(listingProvider, api(`/api/provider-models?provider=${encodeURIComponent(listingProvider)}`).catch(() => ({ models: [] })));
|
|
847
|
+
state.providerModelRequests.get(listingProvider).then(data => {
|
|
848
|
+
if ((state.providerRegistryGeneration || 0) !== registryGeneration) return;
|
|
849
|
+
for (const name of data.models || []) {
|
|
850
|
+
const value = name?.trim();
|
|
851
|
+
if (value) offered.add(value);
|
|
852
|
+
addModelOption(name, name === activeName ? '(active)' : undefined);
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
// Committing one of the discovered suggestions records it with the provider, the way /model does:
|
|
856
|
+
// execution validates a node's explicit model against the provider's configured models, so an
|
|
857
|
+
// unrecorded discovered pick would save a graph that refuses to run. Eligibility keys on the
|
|
858
|
+
// discovered catalog, not the displayed options, so a stored free-text override the provider never
|
|
859
|
+
// listed stays untouched even when recommitted, keeping speculative model names out of this
|
|
860
|
+
// machine's configuration.
|
|
861
|
+
const known = new Set([activeName, ...(provider?.models || []).map(name => name?.trim() || '')].filter(Boolean));
|
|
862
|
+
const committed = model.onchange;
|
|
863
|
+
// A providerless subagent child executes on the inherited provider OR on the parent node's
|
|
864
|
+
// enabled retry fallback (bindPortableGraphProviders adds every providerless child model to the
|
|
865
|
+
// fallback provider's requirements when retry.maxAttempts > 1), so a discovered pick must be
|
|
866
|
+
// recorded on every provider the child can run on. But recording must not endorse a model the
|
|
867
|
+
// fallback does not actually serve: binding checks each provider's CONFIGURED list, and recording
|
|
868
|
+
// rewrites exactly that list, so a primary-only name POSTed blindly to the fallback would turn
|
|
869
|
+
// the save-time GraphProviderUnavailableError into a failure deferred to a retry executing the
|
|
870
|
+
// child. Verify against the fallback's own catalog before recording there, and explain an unmet
|
|
871
|
+
// requirement instead of configuring an unsupported model.
|
|
872
|
+
const fallbackTarget = !target.provider && fallbackProvider && fallbackProvider !== listingProvider ? fallbackProvider : '';
|
|
873
|
+
let fallbackCheck = null;
|
|
874
|
+
const recordWith = (recordProvider, value) => {
|
|
875
|
+
state.providerModelRecords ||= new Set();
|
|
876
|
+
const key = JSON.stringify([recordProvider, value]);
|
|
877
|
+
if (state.providerModelRecords.has(key)) return;
|
|
878
|
+
state.providerModelRecords.add(key);
|
|
879
|
+
api('/api/provider-models', { provider: recordProvider, model: value }).catch(() => state.providerModelRecords.delete(key));
|
|
880
|
+
};
|
|
881
|
+
// The commit path re-renders the whole inspector (the field's refresh), so a note appended to
|
|
882
|
+
// this closure's `override` would land on detached DOM. Persist the unmet requirement in state:
|
|
883
|
+
// every re-rendered modelFields draws it from the map on its initial pass, and a decision that
|
|
884
|
+
// the fallback does serve the model removes it the same way.
|
|
885
|
+
const warningKey = (value) => JSON.stringify([fallbackTarget, value]);
|
|
886
|
+
const setWarning = (value, text) => {
|
|
887
|
+
state.providerModelWarnings ||= new Map();
|
|
888
|
+
const had = state.providerModelWarnings.has(warningKey(value));
|
|
889
|
+
if (text) { if (!had) { state.providerModelWarnings.set(warningKey(value), text); renderInspector(); } }
|
|
890
|
+
else if (had) { state.providerModelWarnings.delete(warningKey(value)); renderInspector(); }
|
|
891
|
+
};
|
|
892
|
+
const applyCommit = (value) => {
|
|
893
|
+
// Eligibility is per provider, not per commit: the model being configured on the primary
|
|
894
|
+
// (live registry updates can add it there after an earlier commit) must not suppress the
|
|
895
|
+
// fallback leg — the fallback's own catalog decides whether it runs. Same on the fallback
|
|
896
|
+
// side: already-configured names need no POST, verified or not.
|
|
897
|
+
if (!known.has(value)) recordWith(listingProvider, value);
|
|
898
|
+
if (!fallbackCheck) return;
|
|
899
|
+
if (fallbackCheck.configured.has(value) || fallbackCheck.offered.has(value)) {
|
|
900
|
+
fallbackCheck.pending = null;
|
|
901
|
+
if (!fallbackCheck.configured.has(value)) recordWith(fallbackTarget, value);
|
|
902
|
+
setWarning(value, null);
|
|
903
|
+
} else if (fallbackCheck.loaded) {
|
|
904
|
+
fallbackCheck.pending = null;
|
|
905
|
+
setWarning(value, `The retry fallback "${fallbackTarget}" does not serve ${value}. The model was recorded on "${listingProvider}" only; a retry that runs this child on the fallback will be refused until the model is offered there.`);
|
|
906
|
+
} else {
|
|
907
|
+
// The fallback's catalog is still loading: withhold the endorsement until it answers rather
|
|
908
|
+
// than recording an unverified name into that provider's configuration.
|
|
909
|
+
fallbackCheck.pending = value;
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
if (fallbackTarget) {
|
|
913
|
+
state.providerModelRequests ||= new Map();
|
|
914
|
+
if (!state.providerModelRequests.has(fallbackTarget)) state.providerModelRequests.set(fallbackTarget, api(`/api/provider-models?provider=${encodeURIComponent(fallbackTarget)}`).catch(() => ({ models: [] })));
|
|
915
|
+
const configuredFallback = state.providers.find(p => idFor(p) === fallbackTarget);
|
|
916
|
+
fallbackCheck = { offered: new Set(), configured: new Set([configuredFallback?.model?.trim() || '', ...(configuredFallback?.models || []).map(name => name?.trim() || '')].filter(Boolean)), loaded: false, pending: null };
|
|
917
|
+
state.providerModelRequests.get(fallbackTarget).then(data => {
|
|
918
|
+
// A catalog resolving after a registry change came from the previous endpoint: recording its
|
|
919
|
+
// names into the new endpoint's configuration, or running a withheld commit against it,
|
|
920
|
+
// would endorse models the new endpoint may not serve. Discard it; the re-render started by
|
|
921
|
+
// applyProviderRegistry discovers against the live registry.
|
|
922
|
+
if ((state.providerRegistryGeneration || 0) !== registryGeneration) return;
|
|
923
|
+
for (const name of data.models || []) { const value = name?.trim(); if (value) fallbackCheck.offered.add(value); }
|
|
924
|
+
fallbackCheck.loaded = true;
|
|
925
|
+
// A commit made before the catalog arrived is decided now: recorded if served, explained if not.
|
|
926
|
+
if (fallbackCheck.pending !== null) applyCommit(fallbackCheck.pending);
|
|
927
|
+
});
|
|
928
|
+
// Draw a pending explanation recorded against this field's current model value.
|
|
929
|
+
const initialWarning = state.providerModelWarnings?.get(warningKey(target.model?.trim() || ''));
|
|
930
|
+
if (initialWarning) override.append(el('p', initialWarning, 'help'));
|
|
931
|
+
}
|
|
932
|
+
model.onchange = () => {
|
|
933
|
+
committed?.();
|
|
934
|
+
// Recording eligibility keys on whether the model still needs recording, not on whether the
|
|
935
|
+
// commit changed the graph value: a commit whose POST failed transiently must stay retryable
|
|
936
|
+
// by recomitting the same suggestion (the failed attempt already wrote the model into the
|
|
937
|
+
// graph, and a value-unchanged early-return would strand the node against execution's
|
|
938
|
+
// provider/model validation). The per-provider skips live inside applyCommit — `known` for
|
|
939
|
+
// the primary, the fallback's configured set for the child's other home — so a model that
|
|
940
|
+
// became configured on one provider cannot silence reconciliation on the other. Already-
|
|
941
|
+
// recorded ones skip via the dedupe set, which the failed POST removed.
|
|
942
|
+
const value = model.value.trim();
|
|
943
|
+
if (!value || !offered.has(value)) return;
|
|
944
|
+
applyCommit(value);
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
function renderCompletion(parent, node) {
|
|
948
|
+
const graph = state.graph, routing = node.agentRole === 'orchestrator';
|
|
949
|
+
const behavior = choice(parent, routing ? 'Routing behavior' : 'Completion behavior', node.completion?.mode || 'single', [
|
|
950
|
+
{value:'single',label:routing ? 'Continue to connected nodes' : 'Continue when complete'},
|
|
951
|
+
{value:'outcomes',label:'Choose outcome using written criteria'},
|
|
952
|
+
], mode => {
|
|
953
|
+
node.completion = mode === 'single' ? {mode,outcome:'completed'} : {mode,outcomes:routing ? ['frontend','backend','devops'] : ['pass','fail','blocked']};
|
|
954
|
+
graph.edges = graph.edges.filter(edge => edge.source !== node.id || outcomes(node).includes(edgeOutcome(edge)));
|
|
955
|
+
});
|
|
956
|
+
explain(behavior, 'Outcome names are short phrases such as DONE, PASS, FAILED TESTING or BLOCKED. Describe when the agent should choose each one; for a single outcome, describe when the work is considered achieved, for example "This is considered DONE when xyz is finished". The agent evaluates these written criteria using its evidence; they are not automatic checks. Connect outcomes to destinations under Connections.');
|
|
957
|
+
if (node.completion?.mode === 'outcomes') {
|
|
958
|
+
parent.append(el('p', 'Criteria are optional; blank rows use the agent prompt. Removing or renaming an outcome removes its old routes. Undo restores routes and criteria.', 'help'));
|
|
959
|
+
if (node.modifiers?.condition || node.modifiers?.loop?.until.outcome !== undefined) parent.append(el('p', 'Modifiers control the final connections: a Condition routes to true/false; an outcome Loop exposes its exit outcome.', 'help'));
|
|
960
|
+
const completion = node.completion;
|
|
961
|
+
completion.outcomes.forEach((outcome, index) => {
|
|
962
|
+
const row = section(parent, `Outcome ${index + 1}`);
|
|
963
|
+
const name = field(row, `Outcome ${index + 1} name`, outcome, () => {}, {maxLength:80});
|
|
964
|
+
name.onchange = () => {
|
|
965
|
+
const value = name.value.trim();
|
|
966
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9_ -]{0,79}$/.test(value) || value.endsWith(' ') || value.includes(' ') || ['constructor','prototype','__proto__'].includes(value) || completion.outcomes.some((item, i) => i !== index && item === value)) {
|
|
967
|
+
status('Use a unique outcome name of 1 to 80 letters, numbers, single spaces, underscores or hyphens, starting with a letter or number. Reserved names are not allowed.', true);
|
|
968
|
+
name.value = outcome; return;
|
|
969
|
+
}
|
|
970
|
+
if (value === outcome) { name.value = value; return; }
|
|
971
|
+
mutate(() => {
|
|
972
|
+
completion.outcomes[index] = value;
|
|
973
|
+
if (completion.criteria && Object.hasOwn(completion.criteria, outcome)) {
|
|
974
|
+
completion.criteria[value] = completion.criteria[outcome]; delete completion.criteria[outcome];
|
|
975
|
+
}
|
|
976
|
+
graph.edges = graph.edges.filter(edge => edge.source !== node.id || outcomes(node).includes(edgeOutcome(edge)));
|
|
977
|
+
}, true);
|
|
978
|
+
};
|
|
979
|
+
field(row, `Written criteria for ${outcome}`, completion.criteria && Object.hasOwn(completion.criteria, outcome) ? completion.criteria[outcome] : '', value => {
|
|
980
|
+
const criteria = {...completion.criteria};
|
|
981
|
+
if (value.trim()) criteria[outcome] = value; else delete criteria[outcome];
|
|
982
|
+
if (Object.keys(criteria).length) completion.criteria = criteria; else delete completion.criteria;
|
|
983
|
+
}, {multiline:true,maxLength:8000,placeholder:outcome === 'pass' ? 'All requested changes are complete and relevant checks passed.' : outcome === 'fail' ? 'Verification found a defect that remains unresolved.' : 'Describe when the agent should choose this outcome.'});
|
|
984
|
+
const remove = el('button', `Remove ${outcome}`, 'danger');
|
|
985
|
+
remove.disabled = completion.outcomes.length === 1;
|
|
986
|
+
remove.onclick = () => mutate(() => {
|
|
987
|
+
completion.outcomes.splice(index, 1);
|
|
988
|
+
if (completion.criteria) {
|
|
989
|
+
delete completion.criteria[outcome];
|
|
990
|
+
if (!Object.keys(completion.criteria).length) delete completion.criteria;
|
|
991
|
+
}
|
|
992
|
+
graph.edges = graph.edges.filter(edge => edge.source !== node.id || outcomes(node).includes(edgeOutcome(edge)));
|
|
993
|
+
}, true);
|
|
994
|
+
row.append(remove);
|
|
995
|
+
});
|
|
996
|
+
const add = el('button', 'Add outcome');
|
|
997
|
+
add.disabled = completion.outcomes.length >= 20;
|
|
998
|
+
add.title = 'Up to 20 outcomes per agent';
|
|
999
|
+
add.onclick = () => mutate(() => {
|
|
1000
|
+
let name = 'outcome';
|
|
1001
|
+
for (let i = 2; completion.outcomes.includes(name); i++) name = `outcome-${i}`;
|
|
1002
|
+
completion.outcomes.push(name);
|
|
1003
|
+
}, true);
|
|
1004
|
+
parent.append(add);
|
|
1005
|
+
check(parent, 'Require a route for every outcome', completion.requireRoutes ?? true, value => {completion.requireRoutes=value;});
|
|
1006
|
+
} else {
|
|
1007
|
+
field(parent, 'Outcome', node.completion?.outcome || 'completed', value => {
|
|
1008
|
+
const previous = node.completion?.outcome ?? 'completed', outcome = value.trim();
|
|
1009
|
+
node.completion = {mode:'single',outcome,...(node.completion?.criteria ? {criteria:node.completion.criteria} : {})};
|
|
1010
|
+
if (!node.modifiers?.condition && node.modifiers?.loop?.until?.outcome === undefined) for (const edge of graph.edges) if (edge.source === node.id && edgeOutcome(edge) === previous) edge.outcome = outcome;
|
|
1011
|
+
}, {refresh:true});
|
|
1012
|
+
field(parent, `Written criteria for ${node.completion?.outcome || 'completed'}`, node.completion?.criteria ?? '', value => {
|
|
1013
|
+
const outcome = node.completion?.outcome ?? 'completed';
|
|
1014
|
+
node.completion = value.trim() ? {mode:'single',outcome,criteria:value} : {mode:'single',outcome};
|
|
1015
|
+
}, {multiline:true,maxLength:8000,placeholder:'Describe when this outcome is considered achieved, for example: This is considered DONE when xyz is finished.'});
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
function routes(parent, node) {
|
|
1019
|
+
if (!outcomes(node).length) return;
|
|
1020
|
+
const group = disclosure(parent, 'Connections', true);
|
|
1021
|
+
group.append(el('p', 'Select every destination for an outcome. Multiple destinations run independently; add a Join to wait for branches.', 'help'));
|
|
1022
|
+
for (const outcome of outcomes(node)) {
|
|
1023
|
+
const row = section(group, outcome); row.id = `route-${outcome}`;
|
|
1024
|
+
for (const destination of Object.values(state.graph.nodes).filter(n => n.id !== node.id && n.agentRole !== 'orchestrator')) {
|
|
1025
|
+
const edge = state.graph.edges.find(e => e.source === node.id && edgeOutcome(e) === outcome && e.target === destination.id);
|
|
1026
|
+
check(row, destination.name, !!edge, enabled => { if (enabled) state.graph.edges.push({id: `edge-${crypto.randomUUID().slice(0,8)}`, source: node.id, target: destination.id, outcome}); else state.graph.edges = state.graph.edges.filter(e => e !== edge); });
|
|
1027
|
+
if (edge) { const edit = el('button', 'Configure handoff', 'link-button'); edit.onclick = () => { state.selectedEdge = edge; state.selected = null; renderInspector(); renderCanvas(); }; row.append(edit); }
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function renderEdgeInspector(parent, edge) {
|
|
1032
|
+
$('inspector-title').textContent = 'Connection handoff';
|
|
1033
|
+
parent.append(el('h3', `${state.graph.nodes[edge.source]?.name} - ${edgeOutcome(edge)}`), el('p', `To: ${state.graph.nodes[edge.target]?.name}`, 'help'));
|
|
1034
|
+
if (edge.bootstrap) parent.append(el('p', 'Initial handoff: starts this upgraded graph at its original Join. Later loop iterations wait for the other incoming branches. Removing this connection removes that initial-start behavior.', 'help'));
|
|
1035
|
+
const mappings = section(parent, 'Input mapping'); mappings.append(el('p', 'Map validated outputs or run context into the destination named inputs. Constants must be valid JSON.', 'help'));
|
|
1036
|
+
const targetSchema=state.graph.nodes[edge.target]?.inputSchema, sourceSchema=state.graph.nodes[edge.source]?.modifiers?.parallel?.mode === 'copies' ? {properties:{results:{type:'array'}}} : state.graph.nodes[edge.source]?.outputSchema; const targetKeys = Object.keys(targetSchema?.properties || {}), sourceKeys = Object.keys(sourceSchema?.properties || {}); if(targetKeys.length)mappings.append(el('p',`Destination inputs: ${targetKeys.map(key=>key+(targetSchema.required?.includes(key)?' (required)':'')).join(', ')}`,'help'));if(sourceKeys.length)mappings.append(el('p',`Available source outputs: ${sourceKeys.join(', ')}`,'help'));
|
|
1037
|
+
for (const [key, value] of Object.entries(edge.inputMapping || {})) {
|
|
1038
|
+
const row = section(mappings, key);
|
|
1039
|
+
const set = next => { edge.inputMapping[key] = next; };
|
|
1040
|
+
const targetInput = field(row, 'Target input', key, next => { if (next !== key && next && !Object.hasOwn(edge.inputMapping, next)) { edge.inputMapping[next] = edge.inputMapping[key]; delete edge.inputMapping[key]; } }, {refresh:true}); if (targetKeys.length) { const list=el('datalist'); list.id=`targets-${crypto.randomUUID()}`; for (const name of targetKeys) {const option=el('option');option.value=name;list.append(option);} targetInput.setAttribute('list',list.id);row.append(list); }
|
|
1041
|
+
const kind = typeof value !== 'string' ? 'constant' : value.startsWith('$source.output.') ? '$source.output' : value.startsWith('$run.input.') ? '$run.input' : value.startsWith('$run.state.') ? '$run.state' : value;
|
|
1042
|
+
choice(row, 'Source', kind, [{value:'$source.output', label:'Source output field'}, {value:'$run.input', label:'Run input field'}, {value:'$run.state', label:'Run state field'}, {value:'$run.loop.iteration', label:'Loop iteration'}, {value:'$source.artifacts', label:'Source artifacts'}, {value:'constant', label:'Constant'}], next => set(next === 'constant' ? {constant: ''} : ['$source.output','$run.input','$run.state'].includes(next) ? `${next}.${next === '$source.output' ? sourceKeys[0] || 'result' : 'task'}` : next));
|
|
1043
|
+
if (kind === 'constant') jsonField(row, 'Constant value', value.constant, next => set({constant:next}));
|
|
1044
|
+
else if (['$source.output','$run.input','$run.state'].includes(kind)) { const input = field(row, 'Field / path', value.slice(kind.length + 1), next => set(`${kind}.${next}`)); const availableKeys = kind === '$source.output' ? sourceKeys : Object.keys((kind === '$run.input' ? state.graph.inputSchema : state.graph.stateSchema)?.properties || {}); if (availableKeys.length) { const list = el('datalist'); list.id = `mapping-${crypto.randomUUID()}`; availableKeys.forEach(key => { const option = el('option'); option.value = key; list.append(option); }); input.setAttribute('list', list.id); row.append(list); } }
|
|
1045
|
+
const remove = el('button', 'Remove mapping'); remove.onclick = () => mutate(() => { delete edge.inputMapping[key]; }, true); row.append(remove);
|
|
1046
|
+
}
|
|
1047
|
+
const add = el('button', 'Add mapping'); add.onclick = () => mutate(() => { edge.inputMapping ||= {}; let key = targetKeys.find(k => !Object.hasOwn(edge.inputMapping,k)) || 'input'; while (Object.hasOwn(edge.inputMapping,key)) key += '_'; edge.inputMapping[key] = {constant:''}; }, true);
|
|
1048
|
+
const suggest = el('button', 'Suggest matching fields'); suggest.onclick = () => mutate(() => { edge.inputMapping ||= {}; for (const key of targetKeys.filter(k => sourceKeys.includes(k))) if (!Object.hasOwn(edge.inputMapping,key)) edge.inputMapping[key] = `$source.output.${key}`; }, true); mappings.append(add, suggest);
|
|
1049
|
+
const remove = el('button', 'Remove connection', 'danger'); remove.onclick = () => mutate(() => { state.graph.edges = state.graph.edges.filter(e => e !== edge); state.selectedEdge = null; }, true); parent.append(remove);
|
|
1050
|
+
}
|
|
1051
|
+
function effectiveCaps(node = {}) { return node.capabilities || {filesystem:'read-write',shell:'allowed',git:'write',github:'none',browser:'playwright',deployment:'none'}; }
|
|
1052
|
+
// Browser copy of src/tool-names.ts. The server treats these spellings as aliases of the canonical
|
|
1053
|
+
// tools it exposes, so every comparison on tool names here resolves them first: a name that
|
|
1054
|
+
// skips this step cannot match a canonical allowlist, and the editor then silently drops
|
|
1055
|
+
// allowed tools. 'shell' is deliberately absent: it is platform-resolved server-side and kept
|
|
1056
|
+
// as its own family token below rather than pinned to a spelling this page cannot know.
|
|
1057
|
+
const TOOL_ALIASES = {
|
|
1058
|
+
read_file: 'Read', read: 'Read',
|
|
1059
|
+
write_file: 'Write', write: 'Write',
|
|
1060
|
+
edit_file: 'Edit', edit: 'Edit',
|
|
1061
|
+
find: 'Glob', list_files: 'Glob', ls: 'Glob',
|
|
1062
|
+
search_files: 'Grep', grep: 'Grep',
|
|
1063
|
+
bash: 'Bash', powershell: 'PowerShell',
|
|
1064
|
+
};
|
|
1065
|
+
const SHELL_TOOLS = ['Bash', 'PowerShell', 'shell'];
|
|
1066
|
+
// Display spelling round-trips back into role.tools, so it must stay one-to-one.
|
|
1067
|
+
function displayToolName(name) { return TOOL_ALIASES[name] || name; }
|
|
1068
|
+
// Permission comparison spelling: folds the whole shell family onto one token so the server's
|
|
1069
|
+
// platform-dependent resolution of 'shell' cannot change which tools the editor offers.
|
|
1070
|
+
function canonicalToolName(name) { const d = displayToolName(name); return SHELL_TOOLS.includes(d) ? 'shell' : d; }
|
|
1071
|
+
function roleToolOptions(node, role, policy) {
|
|
1072
|
+
const parent = effectiveCaps(node);
|
|
1073
|
+
const child = role.capabilities || {...parent,...((policy.workspace || 'shared-read-only') === 'shared-read-only' ? {filesystem:parent.filesystem === 'none' ? 'none' : 'read',git:parent.git === 'none' ? 'none' : 'read',shell:'disabled'} : {})};
|
|
1074
|
+
const canonical = canonicalToolName;
|
|
1075
|
+
const permits = (caps, name) => name === 'qa.browser_session' ? caps.browser === 'playwright' : ['Read','Glob','Grep','repo_explore','read_skill_resource'].includes(canonical(name)) ? caps.filesystem !== 'none' : ['Write','Edit'].includes(canonical(name)) ? caps.filesystem === 'read-write' : canonical(name) === 'shell' ? caps.shell === 'allowed' && caps.filesystem === 'read-write' && caps.git === 'write' : name === 'git_read' ? caps.git !== 'none' : ['read_artifact','write_artifact'].includes(name);
|
|
1076
|
+
const configured = node.tools?.map(displayToolName);
|
|
1077
|
+
const available = (configured || state.tools.map(t=>displayToolName(typeof t === 'string' ? t : t.name || t.id))).filter((name,index,array)=>array.indexOf(name)===index).filter(name=>permits(parent,name)&&permits(child,name));
|
|
1078
|
+
const defaults = policy.toolInheritance === 'inherit' ? available : available.filter(name=>['Read','Glob','Grep','git_read','qa.browser_session','read_skill_resource'].includes(canonical(name)));
|
|
1079
|
+
return {available, selected:policy.toolInheritance === 'inherit' ? defaults : (role.tools?.map(displayToolName) ?? defaults)};
|
|
1080
|
+
}
|
|
1081
|
+
function renderSubagents(parent, node) {
|
|
1082
|
+
const policy = node.subagents || {enabled:false}; const set = patch => {Object.assign(policy,patch);node.subagents=policy;};
|
|
1083
|
+
explain(check(parent,'Allow subagents',policy.enabled,value=>set({enabled:value})),'Internal delegation returns observations to this Agent. Only this parent chooses its graph outcome. Active children finish or cancel before the parent can complete. Subagents never receive the unsandboxed host shell, including in worktrees. Read-only roles use filesystem tools and supported Git read operations.');
|
|
1084
|
+
if (!policy.enabled) return;
|
|
1085
|
+
for (const [key,label,fallback] of [['maxConcurrent','Max concurrent',3],['maxTotal','Max total per node run',8],['maxDepth','Max nesting depth',1]]) field(parent,label,policy[key]??fallback,value=>set({[key]:value}),{type:'number',min:1,max:key==='maxDepth'?3:key==='maxConcurrent'?16:1000});
|
|
1086
|
+
choice(parent,'Model policy',policy.modelPolicy||'inherit',[{value:'inherit',label:'Inherit parent model'},{value:'specific',label:'Use specific model'},{value:'per-role',label:'Per-role model'}],value=>set({modelPolicy:value}));
|
|
1087
|
+
// Mirrors bindPortableGraphProviders: enabled retry attempts may spawn providerless children on
|
|
1088
|
+
// the fallback provider, so a discovered child pick must be recorded there as well.
|
|
1089
|
+
const childFallbackProvider = node.retry?.fallback && node.retry.maxAttempts > 1 ? node.retry.fallback.provider : '';
|
|
1090
|
+
if(policy.modelPolicy==='specific') modelFields(parent,policy,value=>set({provider:value.provider,model:value.model}),undefined,node.provider,childFallbackProvider);
|
|
1091
|
+
choice(parent,'Workspace policy',policy.workspace||'shared-read-only',[{value:'shared-read-only',label:'Shared workspace, read only'},{value:'shared-write',label:'Shared workspace, write allowed'},{value:'worktree',label:'Separate Git worktree'}],value=>set({workspace:value}));
|
|
1092
|
+
choice(parent,'Tool inheritance',policy.toolInheritance||'restricted',[{value:'restricted',label:'Restricted subset'},{value:'inherit',label:'Inherit parent allowlist'}],value=>set({toolInheritance:value}));
|
|
1093
|
+
choice(parent,'Context',policy.context||'selected',[{value:'selected',label:'Selected context only'},{value:'task-only',label:'Task only'}],value=>set({context:value}));
|
|
1094
|
+
// The runtime no longer invents a child deadline, so this field must not display one: blank
|
|
1095
|
+
// means the child inherits the parent's bounds, and a shown fallback would claim a two-minute
|
|
1096
|
+
// ceiling that is not configured.
|
|
1097
|
+
field(parent,'Wall time per child, ms (blank = inherits the parent)',policy.maxWallTimeMs,value=>{if(value===undefined)delete policy.maxWallTimeMs;else policy.maxWallTimeMs=value;node.subagents=policy;},{type:'number',min:1,optional:true,placeholder:'Inherits the parent'});
|
|
1098
|
+
const roles = disclosure(parent,'Configure roles',true);
|
|
1099
|
+
roles.append(el('p','Roles can only narrow parent capabilities. Concurrent writing roles require separate worktrees.', 'help'));
|
|
1100
|
+
for(const role of policy.roles||[]) {
|
|
1101
|
+
const body=disclosure(roles,role.name||'New role',true);
|
|
1102
|
+
field(body,'Role ID',role.id,value=>{role.id=value;}); field(body,'Name',role.name,value=>{role.name=value;});field(body,'Instruction',role.instruction,value=>{role.instruction=value;},{multiline:true,maxLength:100000});
|
|
1103
|
+
if(policy.modelPolicy==='per-role')modelFields(body,role,value=>{role.provider=value.provider;role.model=value.model;},role.provider===node.provider?node.model:undefined,node.provider,childFallbackProvider);
|
|
1104
|
+
capabilities(disclosure(body,'Role capabilities'),role.capabilities||effectiveCaps(node),value=>{role.capabilities=value;},effectiveCaps(node));
|
|
1105
|
+
const allowedTools=disclosure(body,'Role tools'); const toolOptions=roleToolOptions(node,role,policy);
|
|
1106
|
+
for(const name of new Set([...toolOptions.available,...toolOptions.selected])) {
|
|
1107
|
+
const available=toolOptions.available.includes(name);
|
|
1108
|
+
check(allowedTools,available?name:`${name} (unavailable — remove to repair)`,toolOptions.selected.includes(name),enabled=>{role.tools=enabled?[...new Set([...toolOptions.selected,name])]:toolOptions.selected.filter(t=>t!==name);policy.toolInheritance='restricted';});
|
|
1109
|
+
}
|
|
1110
|
+
const contracts=disclosure(body,'Role contracts');jsonField(contracts,'Input schema',role.inputSchema,value=>{role.inputSchema=value;});jsonField(contracts,'Output schema',role.outputSchema,value=>{role.outputSchema=value;});
|
|
1111
|
+
const remove=el('button','Remove role');remove.onclick=()=>mutate(()=>{set({roles:policy.roles.filter(r=>r!==role)});},true);body.append(remove);
|
|
1112
|
+
}
|
|
1113
|
+
const add=el('button','Add role');add.onclick=()=>mutate(()=>{set({roles:[...(policy.roles||[]),{id:`role-${crypto.randomUUID().slice(0,8)}`,name:'Repository Researcher',instruction:'Research the bounded task and return findings.',capabilities:{...effectiveCaps(node),filesystem:effectiveCaps(node).filesystem==='none'?'none':'read',shell:effectiveCaps(node).shell==='disabled'?'disabled':'read-only',git:effectiveCaps(node).git==='none'?'none':'read'}}]});},true);roles.append(add);
|
|
1114
|
+
}
|
|
1115
|
+
function renderControlInspector(parent,node) {
|
|
1116
|
+
if(node.type==='join')choice(parent,'Wait for branches',node.join?.mode||'all',['all','any'],value=>{node.join={mode:value};});
|
|
1117
|
+
if(node.type==='loop')field(parent,'Maximum loop iterations',node.loop?.maxIterations??3,value=>{node.loop={maxIterations:value};},{type:'number',min:1});
|
|
1118
|
+
if(node.type==='condition') {
|
|
1119
|
+
choice(parent,'Source node',node.condition?.source||'', [{value:'',label:'Choose a predecessor'},...Object.values(state.graph.nodes).filter(n=>n.id!==node.id).map(n=>({value:n.id,label:n.name}))],value=>{node.condition={path:'',equals:true,...node.condition,source:value};});
|
|
1120
|
+
field(parent,'Output field path',node.condition?.path||'',value=>{node.condition={source:'',equals:true,...node.condition,path:value};});
|
|
1121
|
+
jsonField(parent,'Equals',node.condition?.equals??true,value=>{node.condition={source:'',path:'',...node.condition,equals:value};});
|
|
1122
|
+
}
|
|
1123
|
+
if(node.type==='action') {choice(parent,'Action',node.action?.kind||'command',['command','tests','git'],value=>{node.action={command:'',...node.action,kind:value};});field(parent,'Command',node.action?.command||'',value=>{node.action={kind:'command',...node.action,command:value};},{multiline:true,maxLength:100000});}
|
|
1124
|
+
if(node.type==='parallel')parent.append(el('p','All completed connections become ready. A Parallel node is optional for ordinary outcome fan-out.', 'help'));
|
|
1125
|
+
if(node.type==='approval')parent.append(el('p','The CLI asks for approval. Route approved and rejected separately.', 'help'));
|
|
1126
|
+
}
|
|
1127
|
+
function setAgentModifier(node, kind, value) {
|
|
1128
|
+
const before = outcomes(node);
|
|
1129
|
+
node.modifiers = {...node.modifiers};
|
|
1130
|
+
if (value === undefined) delete node.modifiers[kind]; else node.modifiers[kind] = value;
|
|
1131
|
+
if (!Object.keys(node.modifiers).length) delete node.modifiers;
|
|
1132
|
+
const after = outcomes(node);
|
|
1133
|
+
if (kind === 'condition' || kind === 'loop') {
|
|
1134
|
+
state.graph.edges = state.graph.edges.flatMap(edge => {
|
|
1135
|
+
if (edge.source !== node.id || after.includes(edgeOutcome(edge))) return [edge];
|
|
1136
|
+
if (before.length === 1 || (!value && edgeOutcome(edge) === 'true')) return [{...edge, outcome:after[0]}];
|
|
1137
|
+
return [];
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
function scalarField(parent, label, value, update) {
|
|
1142
|
+
const input = field(parent, label, JSON.stringify(value ?? true), () => {});
|
|
1143
|
+
input.onchange = () => {
|
|
1144
|
+
try {
|
|
1145
|
+
const parsed = JSON.parse(input.value);
|
|
1146
|
+
if (!['string','number','boolean'].includes(typeof parsed)) throw new Error();
|
|
1147
|
+
input.setCustomValidity(''); mutate(() => update(parsed));
|
|
1148
|
+
} catch { input.setCustomValidity('Enter a JSON string, number, or boolean, for example true or "approved".'); input.reportValidity(); }
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
function renderModifiers(parent, node) {
|
|
1152
|
+
if (node.agentRole === 'orchestrator') return;
|
|
1153
|
+
const group = disclosure(parent, 'Modifiers', Boolean(node.modifiers && Object.keys(node.modifiers).length));
|
|
1154
|
+
group.append(el('p','Add behavior to this agent without extra control nodes.','help'));
|
|
1155
|
+
check(group, 'Condition modifier', Boolean(node.modifiers?.condition), enabled => setAgentModifier(node,'condition',enabled ? {path:'approved',equals:true} : undefined));
|
|
1156
|
+
if (node.modifiers?.condition) {
|
|
1157
|
+
const config = node.modifiers.condition;
|
|
1158
|
+
field(group,'Output field to check',config.path,value=>{config.path=value.trim();});
|
|
1159
|
+
scalarField(group,'Expected value (JSON)',config.equals,value=>{config.equals=value;});
|
|
1160
|
+
group.append(el('p','After this agent finishes, route matching output to true and nonmatching output to false. Configure both connections below. Changing this modifier removes incompatible routes; Undo restores them.','help'));
|
|
1161
|
+
}
|
|
1162
|
+
check(group, 'Loop modifier', Boolean(node.modifiers?.loop), enabled => setAgentModifier(node,'loop',enabled ? {maxIterations:3,until:{outcome:node.completion?.mode==='outcomes' ? node.completion.outcomes[0] : node.completion?.outcome || 'completed'}} : undefined));
|
|
1163
|
+
if (node.modifiers?.loop) {
|
|
1164
|
+
const config = node.modifiers.loop;
|
|
1165
|
+
field(group,'Maximum attempts',config.maxIterations,value=>{config.maxIterations=value;},{type:'number',min:1,max:100});
|
|
1166
|
+
choice(group,'Exit when',config.until.outcome!==undefined?'outcome':'output',[{value:'outcome',label:'Agent returns an outcome'},{value:'output',label:'Output field matches a value'}],value=>{setAgentModifier(node,'loop',{...config,until:value==='outcome'?{outcome:node.completion?.mode==='outcomes'?node.completion.outcomes[0]:node.completion?.outcome||'completed'}:{path:'finished',equals:true}});});
|
|
1167
|
+
if (config.until.outcome !== undefined) choice(group,'Exit outcome',config.until.outcome,node.completion?.mode==='outcomes'?node.completion.outcomes:[node.completion?.outcome||'completed'],value=>{setAgentModifier(node,'loop',{...config,until:{outcome:value}});});
|
|
1168
|
+
else { field(group,'Exit output field',config.until.path,value=>{config.until.path=value.trim();}); scalarField(group,'Exit value (JSON)',config.until.equals,value=>{config.until.equals=value;}); }
|
|
1169
|
+
group.append(el('p','Repeat this agent until the exit condition matches. If the attempt limit is reached, stop with an exhausted result instead of continuing as if successful.','help'));
|
|
1170
|
+
}
|
|
1171
|
+
choice(group,'Parallel modifier',node.modifiers?.parallel?.mode||'off',[{value:'off',label:'Off'},{value:'branches',label:'Connected downstream agents'},{value:'copies',label:'Copies of this agent'}],mode=>setAgentModifier(node,'parallel',mode==='off'?undefined:{mode,maxConcurrent:2,...(mode==='copies'?{copies:2}:{})}));
|
|
1172
|
+
if (node.modifiers?.parallel) {
|
|
1173
|
+
const config = node.modifiers.parallel;
|
|
1174
|
+
field(group,'Maximum concurrent agents',config.maxConcurrent,value=>{config.maxConcurrent=value;},{type:'number',min:1,max:16});
|
|
1175
|
+
if (config.mode==='copies') { field(group,'Number of copies',config.copies,value=>{config.copies=value;},{type:'number',min:1,max:16}); group.append(el('p','Copies perform independent read-only work. Set read-only permissions under Advanced. Downstream output contains a results array with every copy\'s result.','help')); }
|
|
1176
|
+
else group.append(el('p','Connect this agent directly to the Agent branches to run concurrently. Each branch can then connect to End or Join. Add a Join when later work needs all branch results.','help'));
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
function hasRetryCycle(graph) {
|
|
1180
|
+
const active = new Set(), visited = new Set();
|
|
1181
|
+
const visit = id => {
|
|
1182
|
+
if (active.has(id)) return true;
|
|
1183
|
+
if (visited.has(id)) return false;
|
|
1184
|
+
active.add(id); visited.add(id);
|
|
1185
|
+
for (const edge of graph.edges.filter(edge => edge.source === id)) if (visit(edge.target)) return true;
|
|
1186
|
+
active.delete(id); return false;
|
|
1187
|
+
};
|
|
1188
|
+
return Object.keys(graph.nodes).some(visit);
|
|
1189
|
+
}
|
|
1190
|
+
function retryLimitHelp(parent, graph) {
|
|
1191
|
+
if (!hasRetryCycle(graph) || graph.limits?.maxNodeVisits || graph.limits?.wallTimeMs) return;
|
|
1192
|
+
const box = el('div', undefined, 'cycle-help');
|
|
1193
|
+
box.append(el('strong', 'This graph includes a retry cycle'), el('p', 'A return connection can run the same agents repeatedly, so the run needs a ceiling: set a maximum number of visits per node, or give the run a wall clock. Without one the cycle never ends.'));
|
|
1194
|
+
const fix = el('button', 'Limit each node to 3 visits');
|
|
1195
|
+
fix.onclick = () => mutate(() => { graph.limits = {...graph.limits, maxNodeVisits:3}; }, true);
|
|
1196
|
+
const clock = el('button', 'Give the run 30 minutes');
|
|
1197
|
+
clock.onclick = () => mutate(() => { graph.limits = {...graph.limits, wallTimeMs:30 * 60_000}; }, true);
|
|
1198
|
+
box.append(fix, clock); parent.append(box);
|
|
1199
|
+
}
|
|
1200
|
+
function renderInspector() {
|
|
1201
|
+
// A redraw replaces a full-screen prompt editor, so its backdrop goes with it.
|
|
1202
|
+
document.body?.classList?.remove?.('prompt-fullscreen'); for (const backdrop of document.querySelectorAll?.('.prompt-backdrop') ?? []) backdrop.remove();
|
|
1203
|
+
const parent = $('inspector-body'); parent.replaceChildren(); const graph = state.graph; if (!graph) { parent.append(el('p', 'Create a graph or choose a preset.', 'help')); return; }
|
|
1204
|
+
if (state.selectedEdge && !graph.edges.includes(state.selectedEdge)) state.selectedEdge = null;
|
|
1205
|
+
const node = graph.nodes[state.selected]; $('inspector-title').textContent = node ? 'Node settings' : 'Graph settings';
|
|
1206
|
+
retryLimitHelp(parent, graph);
|
|
1207
|
+
if (state.selectedEdge) renderEdgeInspector(parent, state.selectedEdge);
|
|
1208
|
+
else if (selectedNodes().length > 1) renderBulkInspector(parent,selectedNodes());
|
|
1209
|
+
else if (!node) {
|
|
1210
|
+
const panels = inspectorTabs(parent, ['general', 'behavior', 'advanced']); const general = panels.general;
|
|
1211
|
+
field(general, 'Graph name', graph.name, value => { graph.name = value; renderList(); }, {maxLength:200});
|
|
1212
|
+
general.append(el('p', `${graph.id} - Revision ${graph.revision}`, 'mono'));
|
|
1213
|
+
if (graph.id === 'default') general.append(el('p', 'Duplicate this bundled preset to save your customization.', 'help'));
|
|
1214
|
+
const start = field(general,'Starting node',graph.nodes[graph.entry]?.name || '',()=>{}); start.disabled=true; explain(start,'The Orchestrator is optional. Deleting the starting node promotes its first remaining connected successor, or the first remaining node if none is connected.');
|
|
1215
|
+
field(general, 'Description', graph.metadata?.description, value => {graph.metadata={...graph.metadata,description:value};}, {multiline:true,maxLength:2000});
|
|
1216
|
+
const widgetGroup = disclosure(panels.behavior, 'Widgets', true);
|
|
1217
|
+
widgetGroup.append(el('p','Widgets appear as sections beside the run plan. Each description tells the agents what belongs in the widget; during runs the agents keep its value current.','help'));
|
|
1218
|
+
for (const [index, widget] of (graph.widgets ?? []).entries()) {
|
|
1219
|
+
const label = `Widget ${index + 1} name`;
|
|
1220
|
+
field(widgetGroup, label, widget.name, value => { widget.name = value; }, {maxLength:80,refresh:true});
|
|
1221
|
+
field(widgetGroup, `Widget ${index + 1} description`, widget.description, value => { widget.description = value; }, {multiline:true,maxLength:1000});
|
|
1222
|
+
const remove = el('button','Remove widget','danger');
|
|
1223
|
+
remove.onclick = () => mutate(() => { graph.widgets = (graph.widgets ?? []).filter(item => item !== widget); if (!graph.widgets.length) delete graph.widgets; }, true);
|
|
1224
|
+
widgetGroup.append(remove);
|
|
1225
|
+
}
|
|
1226
|
+
if ((graph.widgets ?? []).length < 5) {
|
|
1227
|
+
const add = el('button','Add widget');
|
|
1228
|
+
add.onclick = () => mutate(() => { graph.widgets = [...(graph.widgets ?? []), { id: `widget-${crypto.randomUUID().slice(0,8)}`, name: '', description: '' }]; }, true);
|
|
1229
|
+
widgetGroup.append(add);
|
|
1230
|
+
widgetGroup.append(el('p','Up to 5 widgets per graph. Names and descriptions are required before saving.','help'));
|
|
1231
|
+
} else widgetGroup.append(el('p','Widget limit reached (5).','help'));
|
|
1232
|
+
const visits = field(panels.behavior, 'Maximum visits per node', graph.limits?.maxNodeVisits ?? 0, value => {graph.limits={...graph.limits}; if(value===undefined || value===0) delete graph.limits.maxNodeVisits; else graph.limits.maxNodeVisits=value;}, {type:'number',optional:true,min:0,max:100,refresh:true});
|
|
1233
|
+
explain(visits,'0 means unlimited, which is the default. A return connection repeats a node, so a graph with one needs a ceiling: a visit limit, or a wall clock. An agent Loop modifier has its own attempt limit.');
|
|
1234
|
+
// Per-graph desktop settings render here; a browser-launched studio has no host bridge and skips them.
|
|
1235
|
+
window.AndorraEmbed?.inspector?.(general);
|
|
1236
|
+
const advanced = panels.advanced; jsonField(advanced, 'Run limits', graph.limits, value => {graph.limits=value;}); jsonField(advanced,'Run input schema',graph.inputSchema,value=>{graph.inputSchema=value;}); jsonField(advanced,'Run state schema',graph.stateSchema,value=>{graph.stateSchema=value;});
|
|
1237
|
+
} else {
|
|
1238
|
+
const panels = inspectorTabs(parent, node.type === 'agent' ? ['general', 'model', 'behavior', 'advanced'] : outcomes(node).length ? ['general', 'behavior', 'advanced'] : ['general', 'advanced']);
|
|
1239
|
+
const general = panels.general; field(general, 'Name', node.name, value => {node.name=value;}, {maxLength:200});
|
|
1240
|
+
if (node.type === 'agent') {
|
|
1241
|
+
if(node.agentRole==='orchestrator'){general.append(el('p','Orchestrator - optional starting Agent for research, clarification and handoff. Remove it to start directly at the next node.','help'));explain(field(general,'Max subagents',node.maxSubagents,value=>{if(value===undefined)delete node.maxSubagents;else node.maxSubagents=value;},{type:'number',optional:true,min:0,max:100}),'Optional ceiling, not a target. Leave blank to use the configured subagent policy default. Zero disables internal subagents; this does not control top-level graph concurrency.');}
|
|
1242
|
+
const prompt = promptField(general, 'Prompt', node.instruction ?? node.prompt ?? '', value => {node.instruction=value; delete node.prompt;});
|
|
1243
|
+
explain(prompt, 'Edit the instructions for this agent. Save the graph to use this prompt in future runs. This replaces this node\'s instructions; project guidance, advanced system instructions and runtime permissions still apply.');
|
|
1244
|
+
explain(check(general, 'Jev decisions', node.jevEnabled === true, value => { if (value) node.jevEnabled = true; else delete node.jevEnabled; }), 'Off unless ticked. When Jev is on, it assists this agent with routing decisions. The coding model still implements the task; sign-in, quota and runtime permissions apply.');
|
|
1245
|
+
const model = panels.model;
|
|
1246
|
+
modelFields(model, node, value => {node.provider=value.provider; node.model=value.model;});
|
|
1247
|
+
const conversation = choice(model, 'Conversation', node.contextPolicy?.conversation ?? 'reuse', [{value:'reuse',label:'Reuse with the same provider and model'}, {value:'isolate',label:'Start an isolated conversation'}], value => {node.contextPolicy={...node.contextPolicy,conversation:value};});
|
|
1248
|
+
explain(conversation, 'Reuse continues from the preceding Agent with this node\'s instructions and permissions. Different providers or models start fresh. Branches receive separate copies of their shared history. Provider caching and token savings depend on the model service.');
|
|
1249
|
+
const skills = choice(model, 'Skill inheritance', node.contextPolicy?.skillInheritance ?? 'inherit', [{value:'inherit',label:'Inherit active workflow skills'}, {value:'none',label:'Do not inherit skills'}], value => {node.contextPolicy={...node.contextPolicy,skillInheritance:value};});
|
|
1250
|
+
explain(skills, 'Inherits skills activated earlier in this graph, even when the conversation is isolated or the model changes. Each Agent loads the skill for its own role. Opting out also isolates predecessor conversation text to avoid leaking loaded skills; it never changes tool or approval permissions.');
|
|
1251
|
+
renderCompletion(section(panels.behavior, node.agentRole === 'orchestrator' ? 'Routing' : 'Outcomes and conditions'), node);
|
|
1252
|
+
renderModifiers(panels.behavior, node);
|
|
1253
|
+
const advanced = panels.advanced;
|
|
1254
|
+
const caps = disclosure(advanced, 'Permissions'); capabilities(caps,node.capabilities,value=>{node.capabilities=value;}); caps.append(el('p', 'Restricted filesystem or Git policies disable the unsandboxed host shell. Read-only Agents use filesystem tools and supported Git read operations. Browser and deployment access require compatible runtime tools; configuration does not supply credentials.', 'help'));
|
|
1255
|
+
const context = disclosure(advanced, 'Context sharing'); check(context,'Include previous task summaries',node.contextPolicy?.history??false,value=>{node.contextPolicy={...node.contextPolicy,history:value};}); choice(context,'Visible predecessor state',node.contextPolicy?.predecessors||'none',['none','direct','all'],value=>{node.contextPolicy={...node.contextPolicy,predecessors:value};}); field(context,'Maximum context characters',node.contextPolicy?.maxChars??32000,value=>{node.contextPolicy={...node.contextPolicy,maxChars:value};},{type:'number',min:1}); jsonField(context, 'Input mapping', node.inputs, value=>{node.inputs=value;});
|
|
1256
|
+
renderSubagents(disclosure(advanced,'Subagents'),node);
|
|
1257
|
+
const limits = disclosure(advanced,'Execution limits');
|
|
1258
|
+
for (const [key,label,defaultValue] of [['maxContextChars','Context characters',120000],['maxCompletionRepairs','Completion repair attempts',2]]) field(limits,label,node.limits?.[key] ?? defaultValue,value=>{node.limits={...node.limits,[key]:value}; delete node.limits.maxTokens;},{type:'number',min:key==='maxCompletionRepairs'?0:1});
|
|
1259
|
+
// Iterations and wall time default to blank, and blank means unlimited. The editor must
|
|
1260
|
+
// not invent a bound the author never chose: a task that legitimately runs for hours
|
|
1261
|
+
// should not be cut short, and a person answering a question is never on the clock.
|
|
1262
|
+
// Clearing the field removes the limit rather than writing a zero, which the runtime
|
|
1263
|
+
// accepts as the same thing but which reads to a human as "no time at all".
|
|
1264
|
+
field(limits,'Iterations (blank = unlimited)',node.limits?.maxIterations ?? node.maxIterations,value=>{node.limits={...node.limits,maxIterations:value}; delete node.limits.maxTokens; if(value===undefined){delete node.limits.maxIterations; delete node.maxIterations;} else node.maxIterations=value;},{type:'number',min:0,max:1000,optional:true,placeholder:'Unlimited'});
|
|
1265
|
+
field(limits,'Wall time, milliseconds (blank = unlimited)',node.limits?.wallTimeMs,value=>{node.limits={...node.limits,wallTimeMs:value}; delete node.limits.maxTokens; if(value===undefined)delete node.limits.wallTimeMs;},{type:'number',min:0,optional:true,placeholder:'Unlimited'});
|
|
1266
|
+
// Tool calls default to blank, and blank means unlimited: an absent limit is only
|
|
1267
|
+
// written when the field is cleared, so a node keeps its ceiling once one is set.
|
|
1268
|
+
field(limits,'Tool calls (blank = unlimited)',node.limits?.maxToolCalls,value=>{node.limits={...node.limits,maxToolCalls:value}; if(value===undefined)delete node.limits.maxToolCalls;},{type:'number',min:0,optional:true,placeholder:'Unlimited'});
|
|
1269
|
+
field(advanced,'System prompt',node.systemPrompt ?? node.prompt,value=>{node.systemPrompt=value; delete node.prompt;},{multiline:true,maxLength:100000}); jsonField(advanced,'Input schema (JSON Schema)',node.inputSchema,value=>{node.inputSchema=value;}); jsonField(advanced,'Output schema (JSON Schema)',node.outputSchema,value=>{node.outputSchema=value;}); field(advanced,'Retry attempts',node.retry?.maxAttempts??1,value=>{node.retry={...node.retry,maxAttempts:value};},{type:'number',min:1}); const fallback=disclosure(advanced,'Fallback model'); modelFields(fallback,node.retry?.fallback||{},value=>{node.retry={maxAttempts:1,...node.retry,fallback:value.provider?{provider:value.provider,model:value.model}:undefined};});
|
|
1270
|
+
field(advanced,'Executor','react-basic',()=>{}).disabled=true;
|
|
1271
|
+
const tools = disclosure(advanced,'Tool allowlist');
|
|
1272
|
+
for (const name of [...new Set([...state.tools.map(t=>typeof t==='string'?t:t.name||t.id),...(node.tools||[])])]) check(tools,name,node.tools===undefined||node.tools.includes(name),enabled=>{const all=state.tools.map(t=>typeof t==='string'?t:t.name||t.id); node.tools=enabled?[...new Set([...(node.tools??all),name])]:(node.tools??all).filter(t=>t!==name);});
|
|
1273
|
+
const saveDefinition = el('button','Save agent variant'); saveDefinition.onclick=()=>saveAgentVariant(node); general.append(saveDefinition);
|
|
1274
|
+
} else { general.append(el('p', 'This control node does not call a model and has no agent prompt.', 'help')); renderControlInspector(general,node); }
|
|
1275
|
+
if (panels.behavior) routes(panels.behavior,node);
|
|
1276
|
+
const layout = disclosure(panels.advanced,'Position'); const p=position(node,Object.keys(graph.nodes).indexOf(node.id)); field(layout,'X',p.x,value=>{node.position={...p,x:value};},{type:'number',min:-100000,max:100000,refresh:true});field(layout,'Y',p.y,value=>{node.position={...p,y:value};},{type:'number',min:-100000,max:100000,refresh:true});
|
|
1277
|
+
const remove=el('button','Remove node','danger');remove.disabled=Object.keys(graph.nodes).length===1;remove.onclick=()=>{void askConfirm({title:`Remove ${node.name}?`,message:'The node and its connections are removed from this graph. Undo brings them back.',confirmLabel:'Remove node',tone:'danger'}).then(confirmed=>{if(confirmed&&state.graph?.nodes?.[node.id])removeNodes(new Set([node.id]));});};panels.advanced.append(remove);
|
|
1278
|
+
}
|
|
1279
|
+
const validation=section(parent,'Validation');validation.id='validation';renderValidation();
|
|
1280
|
+
window.AndorraStudio?.inspector?.(parent, node);
|
|
1281
|
+
}
|
|
1282
|
+
function render() { renderHeading(); renderList(); renderLibrary(); renderCanvas(); renderInspector(); scheduleValidation(); queueDraft(); }
|
|
1283
|
+
async function openGraph(id) {
|
|
1284
|
+
if (state.saving) { status('Wait for the current save before opening another graph.'); return; }
|
|
1285
|
+
if (state.dirty && !await askConfirm(DISCARD_QUESTION)) return;
|
|
1286
|
+
try { state.graph = dropLegacyTokenFields(await api(`/api/graphs/${encodeURIComponent(id)}`)); state.dirty = state.graph.editorMigration === true; delete state.graph.editorMigration; clearSelection(); state.undo = []; state.redo = []; state.pendingProviderNodes = null; render(); fit(); status(state.dirty ? 'Legacy graph upgraded in editor - Save to persist a new revision' : 'Graph loaded'); } catch (error) { status(error.message, true); }
|
|
1287
|
+
}
|
|
1288
|
+
function newId() { return `graph-${crypto.randomUUID()}`; }
|
|
1289
|
+
function newGraph(duplicate = false, discarded = false) {
|
|
1290
|
+
if (state.saving) { status('Wait for the current save before creating another graph.'); return; }
|
|
1291
|
+
if (!canCreateGraph()) { status(FREE_CREATE_TIP, true); return; }
|
|
1292
|
+
// Unsaved edits are asked about first; a clean graph is replaced at once.
|
|
1293
|
+
if (state.dirty && !discarded) { void askConfirm(DISCARD_QUESTION).then(discard => { if (discard) newGraph(duplicate, true); }); return; }
|
|
1294
|
+
if (duplicate) state.graph={...copy(state.graph),id:newId(),name:`${state.graph.name} copy`,revision:0};
|
|
1295
|
+
else if (freeTier()) {
|
|
1296
|
+
// A free graph starts from the Software Engineer alone: the Orchestrator is a Premium node.
|
|
1297
|
+
const engineerPreset=state.definitions.find(definition=>definition.id==='software-engineer')?.node;
|
|
1298
|
+
if(!engineerPreset){status('Starting presets are unavailable. Reload the Graph Builder and try again.',true);return;}
|
|
1299
|
+
state.graph={schemaVersion:3,id:newId(),name:'Untitled graph',revision:0,entry:'engineer',nodes:{engineer:{...copy(engineerPreset),id:'engineer',position:{x:0,y:0}},done:{id:'done',name:'Done',type:'end',position:{x:320,y:0}}},edges:[{id:'engineer-done',source:'engineer',target:'done',outcome:'completed'}]};
|
|
1300
|
+
}
|
|
1301
|
+
else {
|
|
1302
|
+
const orchestratorPreset=state.definitions.find(definition=>definition.node.agentRole==='orchestrator')?.node;
|
|
1303
|
+
const engineerPreset=state.definitions.find(definition=>definition.id==='software-engineer')?.node;
|
|
1304
|
+
if(!orchestratorPreset || !engineerPreset){status('Starting presets are unavailable. Reload the Graph Builder and try again.',true);return;}
|
|
1305
|
+
const orchestrator={...copy(orchestratorPreset),id:'orchestrator',position:{x:0,y:0}};
|
|
1306
|
+
const engineer={...copy(engineerPreset),id:'engineer',position:{x:320,y:0}};
|
|
1307
|
+
const inputMapping={originalTask:'$run.input.task'};
|
|
1308
|
+
for(const key of ['taskInstruction','requirements','acceptanceCriteria','designConsiderations','codebaseFindings']) inputMapping[key]=`$source.output.${key}`;
|
|
1309
|
+
state.graph={schemaVersion:3,id:newId(),name:'Untitled graph',revision:0,entry:'orchestrator',nodes:{orchestrator,engineer,done:{id:'done',name:'Done',type:'end',position:{x:640,y:0}}},edges:[{id:'orchestrator-engineer',source:'orchestrator',target:'engineer',outcome:'completed',inputMapping},{id:'engineer-done',source:'engineer',target:'done',outcome:'completed'}]};
|
|
1310
|
+
}
|
|
1311
|
+
// A duplicate copies the open graph, providerless nodes included, so its unmet provider
|
|
1312
|
+
// requirements travel with it; an unrelated new graph starts without any.
|
|
1313
|
+
state.dirty = true; clearSelection(); state.undo = []; state.redo = [];
|
|
1314
|
+
state.pendingProviderNodes = duplicate ? new Set(state.pendingProviderNodes ?? []) : null;
|
|
1315
|
+
render(); fit(); status('New graph - Customize your agent and save your first revision');
|
|
1316
|
+
}
|
|
1317
|
+
// The settings a new Agent starts from, whether it is dropped on the canvas or added to the list.
|
|
1318
|
+
function blankAgentSettings() {
|
|
1319
|
+
return { executor: 'react-basic', instruction: '', contextPolicy: {history: false, predecessors: 'none'}, completion: { mode: 'single', outcome: 'completed' }, subagents: { enabled: false } };
|
|
1320
|
+
}
|
|
1321
|
+
function nodeLimit(graph, definition) {
|
|
1322
|
+
return graph.schemaVersion === 3 && (definition?.agentRole === 'orchestrator' || Object.values(graph.nodes).some(node => node.agentRole === 'orchestrator')) ? 101 : 100;
|
|
1323
|
+
}
|
|
1324
|
+
function addNode(type, definition, dropPosition) {
|
|
1325
|
+
const refusal = freeNodeRefusal([{ type, agentRole: definition?.agentRole }]);
|
|
1326
|
+
if (refusal) { status(refusal, true); return; }
|
|
1327
|
+
if (definition?.agentRole === 'orchestrator') {
|
|
1328
|
+
// Compare canonically: saved variants may carry either the retired spellings or the
|
|
1329
|
+
// canonical tool names, and the server canonicalizes tool lists on validation.
|
|
1330
|
+
const researchTools = (definition.tools ?? []).map(canonicalToolName);
|
|
1331
|
+
const canResearch = definition.capabilities?.filesystem !== 'none' &&
|
|
1332
|
+
(definition.tools === undefined || ['Read','Glob','Grep','repo_explore'].some(tool => researchTools.includes(tool)));
|
|
1333
|
+
if (!canResearch) {
|
|
1334
|
+
status('Cannot apply this Orchestrator variant: enable filesystem read access and at least one research tool (Read, Glob, Grep, or repo_explore), then save the variant again. Choose another Orchestrator variant to continue.', true);
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
// Saved definitions can predate intake's required research and clarification.
|
|
1338
|
+
// Normalize a copy for both insertion and replacement, preserving unlimited ceilings.
|
|
1339
|
+
definition = copy(definition);
|
|
1340
|
+
// Completion guarantees these declared fields even in older optional schemas.
|
|
1341
|
+
if (definition.outputSchema?.properties) {
|
|
1342
|
+
const runtimeFields = ['originalTask','taskInstruction','requirements','acceptanceCriteria','designConsiderations','codebaseFindings'];
|
|
1343
|
+
definition.outputSchema.required = [...new Set([...(definition.outputSchema.required || []), ...runtimeFields.filter(key => Object.hasOwn(definition.outputSchema.properties, key))])];
|
|
1344
|
+
}
|
|
1345
|
+
if (definition.inputSchema?.required?.includes('originalTask') && !Object.hasOwn(definition.inputs || {}, 'originalTask')) {
|
|
1346
|
+
definition.inputs = {...definition.inputs, originalTask:'$run.input.task'};
|
|
1347
|
+
}
|
|
1348
|
+
if (definition.maxIterations > 0) definition.maxIterations = Math.max(definition.maxIterations, 3);
|
|
1349
|
+
if (definition.limits?.maxIterations > 0) definition.limits.maxIterations = Math.max(definition.limits.maxIterations, 3);
|
|
1350
|
+
if (definition.limits?.maxToolCalls !== undefined) definition.limits.maxToolCalls = Math.max(definition.limits.maxToolCalls, 2);
|
|
1351
|
+
const existing = Object.values(state.graph?.nodes || {}).find(node => node.agentRole === 'orchestrator');
|
|
1352
|
+
if (existing) {
|
|
1353
|
+
mutate(() => {
|
|
1354
|
+
const replacement = {...copy(definition), id:existing.id, position:existing.position, type:'agent', executor:'react-basic'};
|
|
1355
|
+
state.graph.nodes[existing.id] = replacement;
|
|
1356
|
+
state.graph.edges = state.graph.edges.filter(edge => edge.source !== existing.id || outcomes(replacement).includes(edgeOutcome(edge)));
|
|
1357
|
+
clearSelection(); state.selected = existing.id; state.selectedIds = [existing.id];
|
|
1358
|
+
}, true);
|
|
1359
|
+
showInspector();
|
|
1360
|
+
status('Starting Orchestrator definition applied. Matching routes and handoffs were kept; validate mappings before saving. Undo restores the previous definition.');
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
if (!state.graph || Object.keys(state.graph.nodes).length >= nodeLimit(state.graph, definition)) return;
|
|
1365
|
+
mutate(() => {
|
|
1366
|
+
const id = `${type}-${crypto.randomUUID().slice(0, 8)}`;
|
|
1367
|
+
if (!dropPosition) { dropPosition = {x:(120-state.x)/state.zoom,y:(180-state.y)/state.zoom}; for (let attempts=0; attempts<100 && Object.values(state.graph.nodes).some((node,index)=>{const p=position(node,index);return Math.abs(p.x-dropPosition.x)<45 && Math.abs(p.y-dropPosition.y)<45;});attempts++) {dropPosition.x+=48;dropPosition.y+=48;} }
|
|
1368
|
+
state.graph.schemaVersion = 3;
|
|
1369
|
+
// A new Agent starts with no iteration ceiling, matching the runtime default. Seeding it
|
|
1370
|
+
// with 40 would silently reinstate the legacy limit the runtime no longer applies.
|
|
1371
|
+
state.graph.nodes[id] = { ...(definition ? copy(definition) : type === 'agent' ? blankAgentSettings() : {}), id, type, ...(type==='join'?{join:{mode:'all'}}:type==='loop'?{loop:{maxIterations:3}}:type==='condition'?{condition:{source:state.graph.entry,path:'result',equals:true}}:{}), name: definition?.name || (type === 'agent' ? 'New Agent' : type.charAt(0).toUpperCase() + type.slice(1)), position: dropPosition || { x: (120 - state.x) / state.zoom, y: (180 - state.y) / state.zoom } };
|
|
1372
|
+
if (definition?.agentRole === 'orchestrator') {
|
|
1373
|
+
const previousEntry = state.graph.entry;
|
|
1374
|
+
// Keep the direct-start graph's tool budget available after intake uses its
|
|
1375
|
+
// required research and clarification calls. An absent ceiling stays unlimited.
|
|
1376
|
+
if (state.graph.limits?.maxToolCalls !== undefined) state.graph.limits.maxToolCalls = Math.min(1_000_000_000, state.graph.limits.maxToolCalls + 2);
|
|
1377
|
+
const outcome = outcomes(state.graph.nodes[id])[0];
|
|
1378
|
+
const bootstrap = state.graph.nodes[previousEntry]?.type === 'join' && state.graph.edges.some(edge => edge.target === previousEntry);
|
|
1379
|
+
if (previousEntry && outcome) {
|
|
1380
|
+
const targetNode = state.graph.nodes[previousEntry];
|
|
1381
|
+
const handoff = {originalTask:'$run.input.task'};
|
|
1382
|
+
for (const key of ['taskInstruction','requirements','acceptanceCriteria','designConsiderations','codebaseFindings']) handoff[key] = `$source.output.${key}`;
|
|
1383
|
+
const inputMapping = Object.fromEntries(Object.entries(handoff).filter(([key]) => {
|
|
1384
|
+
if (Object.hasOwn(targetNode.inputs || {}, key)) return false;
|
|
1385
|
+
const target = targetNode.inputSchema?.properties?.[key];
|
|
1386
|
+
if (!target) return targetNode.inputSchema?.additionalProperties !== false;
|
|
1387
|
+
const sourceSchema = key === 'originalTask' ? state.graph.inputSchema : state.graph.nodes[id].outputSchema;
|
|
1388
|
+
// Intake owns these output types even when a saved variant omits its schema.
|
|
1389
|
+
const runtimeSource = key === 'originalTask' || key === 'taskInstruction' ? {type:'string'} : {type:'array',items:{type:'string'}};
|
|
1390
|
+
const declaredSource = sourceSchema?.properties?.[key === 'originalTask' ? 'task' : key];
|
|
1391
|
+
const source = declaredSource?.type === 'array' && !declaredSource.items && runtimeSource.type === 'array'
|
|
1392
|
+
? {...declaredSource, items:runtimeSource.items} : declaredSource ?? runtimeSource;
|
|
1393
|
+
return target.type === source.type && (source.type !== 'array' || !target.items || !source.items || target.items.type === source.items.type);
|
|
1394
|
+
}));
|
|
1395
|
+
state.graph.edges.unshift({...(bootstrap ? {bootstrap:true} : {}),id:`edge-${crypto.randomUUID().slice(0,8)}`,source:id,target:previousEntry,outcome,inputMapping});
|
|
1396
|
+
}
|
|
1397
|
+
state.graph.entry = id;
|
|
1398
|
+
}
|
|
1399
|
+
clearSelection(); state.selected = id; state.selectedIds=[id];
|
|
1400
|
+
$('inspector').classList.remove('hidden');
|
|
1401
|
+
}, true);
|
|
1402
|
+
}
|
|
1403
|
+
function libraryDialog(title, fields, submit, submitLabel = 'Save') {
|
|
1404
|
+
const dialog = el('dialog', undefined, 'library-dialog'), form = el('form');
|
|
1405
|
+
form.append(el('h3', title));
|
|
1406
|
+
for (const [label, input] of fields) { const row = el('label', label); row.append(input); form.append(row); }
|
|
1407
|
+
const error = el('p', '', 'help'), actions = el('div', undefined, 'library-dialog-actions');
|
|
1408
|
+
const cancel = el('button', 'Cancel'); cancel.type = 'button'; cancel.onclick = () => dialog.close();
|
|
1409
|
+
const save = el('button', submitLabel); save.type = 'submit'; actions.append(cancel, save); form.append(error, actions);
|
|
1410
|
+
form.onsubmit = async event => { event.preventDefault(); save.disabled = true; try { await submit(); dialog.close(); } catch (failure) { error.textContent = failure.message; } finally { save.disabled = false; } };
|
|
1411
|
+
dialog.onclose = () => dialog.remove(); dialog.append(form); document.body.append(dialog); dialog.showModal(); fields[0]?.[1].focus();
|
|
1412
|
+
}
|
|
1413
|
+
// The browser's `required` accepts whitespace, so a name that only trims to nothing is
|
|
1414
|
+
// refused here instead of being sent as a request that can only fail.
|
|
1415
|
+
function requireAgentName(input) {
|
|
1416
|
+
const value = input.value.trim();
|
|
1417
|
+
if (!value) throw new Error('Enter an Agent name.');
|
|
1418
|
+
return value;
|
|
1419
|
+
}
|
|
1420
|
+
function saveAgentVariant(node) {
|
|
1421
|
+
const name = el('input'); name.value = node.name; name.required = true; name.maxLength = 200;
|
|
1422
|
+
const snapshot = copy(node), id = `definition-${crypto.randomUUID()}`;
|
|
1423
|
+
libraryDialog('Save Agent variant', [['Variant name', name]], async () => {
|
|
1424
|
+
const agentName = requireAgentName(name);
|
|
1425
|
+
await writeDefinition({schemaVersion:2, id, name:agentName, description:'', revision:0, node:{...snapshot,name:agentName}}, 'Agent variant saved');
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
// Truncation counts the field's own unit (UTF-16 code units) but must not cut between the two
|
|
1429
|
+
// halves of an astral character: a split pair still passes the length check while showing as a
|
|
1430
|
+
// replacement character. Walk whole code points and stop before the budget is exceeded.
|
|
1431
|
+
function truncateToUnits(value, limit) {
|
|
1432
|
+
let kept = '';
|
|
1433
|
+
for (const character of value) {
|
|
1434
|
+
if (kept.length + character.length > limit) break;
|
|
1435
|
+
kept += character;
|
|
1436
|
+
}
|
|
1437
|
+
return kept;
|
|
1438
|
+
}
|
|
1439
|
+
// A saved Agent is never edited in place, so copying always writes a new definition.
|
|
1440
|
+
function copyAgent(definition) {
|
|
1441
|
+
// The suffix must not push a long source name past the field's own limit, which would
|
|
1442
|
+
// prefill an invalid default the browser then refuses to submit.
|
|
1443
|
+
const suffix = ' copy', source = definition.name.trim(), id = `definition-${crypto.randomUUID()}`;
|
|
1444
|
+
const name = el('input'); name.value = `${truncateToUnits(source, 200 - suffix.length)}${suffix}`; name.required = true; name.maxLength = 200;
|
|
1445
|
+
libraryDialog(`Clone ${definition.name}`, [['Agent name', name]], async () => {
|
|
1446
|
+
const agentName = requireAgentName(name);
|
|
1447
|
+
await writeDefinition({schemaVersion:2, id, name:agentName, description:definition.description || '', revision:0, node:{...copy(definition.node),name:agentName}}, `Agent ${agentName} created`);
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
// Add agent appends a new Agent to the list from a name, an optional description and its
|
|
1451
|
+
// instructions; the rest of its settings start as a blank canvas Agent's do. Deeper settings are
|
|
1452
|
+
// edited on the canvas and kept with Save Agent variant.
|
|
1453
|
+
function addAgent() {
|
|
1454
|
+
const name = el('input'); name.required = true; name.maxLength = 200;
|
|
1455
|
+
const description = el('input'); description.maxLength = 2000;
|
|
1456
|
+
const instruction = el('textarea'); instruction.maxLength = 100000; instruction.rows = 5;
|
|
1457
|
+
const id = `definition-${crypto.randomUUID()}`;
|
|
1458
|
+
libraryDialog('Add agent', [['Agent name', name], ['Description', description], ['Instructions', instruction]], async () => {
|
|
1459
|
+
const agentName = requireAgentName(name);
|
|
1460
|
+
await writeDefinition({schemaVersion:2, id, name:agentName, description:description.value.trim(), revision:0, node:{id:'agent', type:'agent', name:agentName, ...blankAgentSettings(), instruction:instruction.value.trim()}}, `Agent ${agentName} added`);
|
|
1461
|
+
}, 'Add agent');
|
|
1462
|
+
}
|
|
1463
|
+
// The server's 512 KiB limit applies to the import request, not the file: Share pretty-prints its
|
|
1464
|
+
// file, so a file over that limit can still make a request under it. The request is measured
|
|
1465
|
+
// exactly; files far beyond anything that could fit are refused before they are read.
|
|
1466
|
+
const AGENT_REQUEST_LIMIT = 512 * 1024;
|
|
1467
|
+
const AGENT_FILE_LIMIT = 4 * AGENT_REQUEST_LIMIT;
|
|
1468
|
+
// Import accepts only a file made by Share. The server checks the format marker and version and
|
|
1469
|
+
// validates the Agent like any saved one, so this dialog only reads the file.
|
|
1470
|
+
function importAgent() {
|
|
1471
|
+
const file = el('input'); file.type = 'file'; file.accept = '.json,application/json';
|
|
1472
|
+
const id = `definition-${crypto.randomUUID()}`;
|
|
1473
|
+
libraryDialog('Import agent', [['Agent JSON file shared from Andorra Code', file]], async () => {
|
|
1474
|
+
const chosen = file.files?.[0];
|
|
1475
|
+
if (!chosen) throw new Error('Choose an Agent JSON file.');
|
|
1476
|
+
if (chosen.size > AGENT_FILE_LIMIT) throw new Error('The file is larger than an Agent export can be.');
|
|
1477
|
+
let parsed;
|
|
1478
|
+
try { parsed = JSON.parse(await chosen.text()); }
|
|
1479
|
+
catch { throw new Error('The file is not valid JSON, so it is not an Andorra Code Agent export.'); }
|
|
1480
|
+
if (new TextEncoder().encode(JSON.stringify({ id, file: parsed })).length > AGENT_REQUEST_LIMIT) throw new Error('This Agent is larger than the 512 KiB Andorra Code can import.');
|
|
1481
|
+
await importDefinition(id, parsed);
|
|
1482
|
+
}, 'Import');
|
|
1483
|
+
}
|
|
1484
|
+
// Like writeDefinition, a committed import whose response was lost is confirmed from the store by
|
|
1485
|
+
// the id this dialog minted, so a retry never adds the Agent twice.
|
|
1486
|
+
async function importDefinition(id, file) {
|
|
1487
|
+
let stored;
|
|
1488
|
+
try { stored = await api('/api/definitions/import', { id, file }); }
|
|
1489
|
+
catch (error) {
|
|
1490
|
+
stored = (await readDefinitions().catch(() => undefined))?.find(definition => definition.id === id);
|
|
1491
|
+
if (!stored) throw error;
|
|
1492
|
+
const expected = typeof file?.agent?.name === 'string' ? file.agent.name.trim() : undefined;
|
|
1493
|
+
if (expected !== undefined && stored.name !== expected) throw new Error(`An earlier import from this dialog is already saved as "${stored.name}". Close the dialog and import again.`);
|
|
1494
|
+
}
|
|
1495
|
+
state.libraryExpanded.agents = true;
|
|
1496
|
+
const saved = `Agent ${stored.name} imported`;
|
|
1497
|
+
try { await readDefinitions(); renderLibrary(); status(saved); }
|
|
1498
|
+
catch (error) { status(`${saved}, but the library did not refresh: ${error.message}`, true); }
|
|
1499
|
+
}
|
|
1500
|
+
// Share writes the Agent's export file. In the desktop host only the id crosses the frame and the
|
|
1501
|
+
// host writes the file to Downloads; a plain browser downloads it directly.
|
|
1502
|
+
async function shareAgent(definition) {
|
|
1503
|
+
if (window.AndorraEmbed?.hostChrome?.() && window.AndorraEmbed.exportAgent) { await window.AndorraEmbed.exportAgent(definition.id); return; }
|
|
1504
|
+
downloadJson(await api(`/api/definitions/${encodeURIComponent(definition.id)}/export`), exportFileName(definition));
|
|
1505
|
+
status(`Agent ${definition.name} shared as a JSON file`);
|
|
1506
|
+
}
|
|
1507
|
+
// Built-in Agents have no Delete. Graphs that already use a deleted Agent keep their own copy.
|
|
1508
|
+
async function deleteAgent(definition) {
|
|
1509
|
+
if (definition.preset) return;
|
|
1510
|
+
if (!confirm(`Delete the Agent "${definition.name}"? Graphs that already use it keep their own copy. This cannot be undone.`)) return;
|
|
1511
|
+
try { await api(`/api/definitions/${encodeURIComponent(definition.id)}`, undefined, { method: 'DELETE' }); }
|
|
1512
|
+
catch (error) {
|
|
1513
|
+
// A lost response can still have deleted it, so the refreshed list decides what is reported.
|
|
1514
|
+
const remaining = (await readDefinitions().catch(() => undefined))?.some(item => item.id === definition.id);
|
|
1515
|
+
if (remaining !== false) { if (remaining) renderLibrary(); status(error.message, true); return; }
|
|
1516
|
+
}
|
|
1517
|
+
try { await readDefinitions(); renderLibrary(); status(`Agent ${definition.name} deleted`); }
|
|
1518
|
+
catch (error) { status(`Agent ${definition.name} deleted, but the library did not refresh: ${error.message}`, true); }
|
|
1519
|
+
}
|
|
1520
|
+
// The same menu opens from a right-click (or the keyboard's context-menu key) on the row and from
|
|
1521
|
+
// the row's More actions button.
|
|
1522
|
+
function showAgentMenu(definition, use, x, y) {
|
|
1523
|
+
showMenuAt(x, y, `${definition.name} actions`, [
|
|
1524
|
+
{ label: 'Use', icon: 'plus', run: use },
|
|
1525
|
+
{ label: 'Clone', icon: 'copy', run: () => copyAgent(definition) },
|
|
1526
|
+
{ label: 'Share', icon: 'share', run: () => { shareAgent(definition).catch(error => status(error.message, true)); } },
|
|
1527
|
+
...(definition.preset ? [] : [{ label: 'Delete', icon: 'trash', danger: true, run: () => { void deleteAgent(definition); } }]),
|
|
1528
|
+
]);
|
|
1529
|
+
}
|
|
1530
|
+
async function readDefinitions() {
|
|
1531
|
+
const data = await api('/api/bootstrap'); state.definitions = data.definitions || []; return state.definitions;
|
|
1532
|
+
}
|
|
1533
|
+
// The id is fixed for the dialog's lifetime and a committed write is confirmed from the store
|
|
1534
|
+
// before any failure is reported: a dropped response or a failed refresh must not turn the
|
|
1535
|
+
// author's second Save into a duplicate Agent. A refresh failure after a committed write is
|
|
1536
|
+
// reported instead of rethrown, because the Agent is saved either way.
|
|
1537
|
+
async function writeDefinition(payload, saved) {
|
|
1538
|
+
try { await api('/api/definitions', payload); }
|
|
1539
|
+
catch (error) {
|
|
1540
|
+
// A lost response can still have committed the write, so confirm it from the store. The
|
|
1541
|
+
// confirmation must be the record the author asked for: a form edited after that commit is a
|
|
1542
|
+
// different Agent, and reporting it as created would hide that the stored name differs.
|
|
1543
|
+
const existing = (await readDefinitions().catch(() => undefined))?.find(definition => definition.id === payload.id);
|
|
1544
|
+
if (!existing) throw error;
|
|
1545
|
+
if (existing.name !== payload.name) throw new Error(`This Agent is already saved as "${existing.name}". Reload the library to see it, then copy again for a different name.`);
|
|
1546
|
+
}
|
|
1547
|
+
state.libraryExpanded.agents = true;
|
|
1548
|
+
try { await readDefinitions(); renderLibrary(); status(saved); }
|
|
1549
|
+
catch (error) { status(`${saved}, but the library did not refresh: ${error.message}`, true); }
|
|
1550
|
+
}
|
|
1551
|
+
function renderLibrary() {
|
|
1552
|
+
const container = $('node-library'); container.replaceChildren();
|
|
1553
|
+
const query = $('node-search').value.toLowerCase();
|
|
1554
|
+
const definitionItem = d => ({name:d.name,type:'agent',description:d.preset ? 'Editable Agent preset' : `Saved variant - r${d.revision}`,node:d.node,definition:d});
|
|
1555
|
+
const addItem = (parent, item) => {
|
|
1556
|
+
// A library item drags onto the canvas; a click, Enter or Space adds it, so the library stays
|
|
1557
|
+
// usable without a pointer. The type icon is placed first by the stylesheet's grid.
|
|
1558
|
+
const row = el('div', undefined, 'library-row'), button = el('button', undefined, 'library-item'); button.append(el('b', item.name), el('span', item.description));
|
|
1559
|
+
// Add agent and Import agent manage the list itself: a click opens their dialog, and they are
|
|
1560
|
+
// neither draggable nor given the Agent menu.
|
|
1561
|
+
if (item.action) {
|
|
1562
|
+
const actionGlyph = globalThis.AndorraIcons?.icon?.(item.icon);
|
|
1563
|
+
if (actionGlyph) button.append(actionGlyph);
|
|
1564
|
+
button.type = 'button'; button.title = item.title; button.setAttribute('data-library-action', item.id); button.onclick = item.action;
|
|
1565
|
+
if (item.last) row.className = 'library-row library-actions-end';
|
|
1566
|
+
row.append(button); parent.append(row); return;
|
|
1567
|
+
}
|
|
1568
|
+
const glyph = globalThis.AndorraIcons?.icon?.(globalThis.AndorraIcons.nodeIcon({type:item.type, agentRole:item.node?.agentRole}));
|
|
1569
|
+
if (glyph) button.append(glyph);
|
|
1570
|
+
button.setAttribute('data-node-type', item.type);
|
|
1571
|
+
button.title = `Drag onto the canvas, or press Enter to add ${item.name}`;
|
|
1572
|
+
const cannotAdd = !state.graph || (Object.keys(state.graph.nodes).length >= nodeLimit(state.graph, item.node) && !(item.node?.agentRole === 'orchestrator' && Object.values(state.graph.nodes).some(node => node.agentRole === 'orchestrator')));
|
|
1573
|
+
// A free-tier refusal leaves the item clickable, so a click explains the limit rather than doing nothing.
|
|
1574
|
+
const freeRefusal = freeNodeRefusal([{ type: item.type, agentRole: item.node?.agentRole }]);
|
|
1575
|
+
if (freeRefusal) button.title = freeRefusal;
|
|
1576
|
+
button.disabled = cannotAdd && !item.definition; button.draggable = !button.disabled && !freeRefusal;
|
|
1577
|
+
button.onclick = () => { if (cannotAdd) { status(state.graph ? 'Graph node limit reached.' : 'Open a graph to add this Agent.', true); return; } addNode(item.type, item.node); };
|
|
1578
|
+
button.ondragstart = event => { event.dataTransfer.setData('application/andorra-node', JSON.stringify({name:item.name,type:item.type,node:item.node})); event.dataTransfer.effectAllowed = 'copy'; };
|
|
1579
|
+
row.append(button);
|
|
1580
|
+
// An Agent's actions are secondary, so they open from a right-click on the row (which the
|
|
1581
|
+
// keyboard's context-menu key and Shift+F10 also raise) or from a quiet icon that shows on the
|
|
1582
|
+
// row's hover or focus rather than a pill on every row.
|
|
1583
|
+
if (item.definition) {
|
|
1584
|
+
const openMenu = (x, y) => showAgentMenu(item.definition, () => button.onclick(), x, y);
|
|
1585
|
+
row.oncontextmenu = event => { event.preventDefault(); openMenu(event.clientX, event.clientY); };
|
|
1586
|
+
// Not every host raises a contextmenu event for the keyboard's own menu keys, so they open
|
|
1587
|
+
// the menu directly beneath the focused row; preventing the default avoids a second opening.
|
|
1588
|
+
button.onkeydown = event => {
|
|
1589
|
+
if (event.key !== 'ContextMenu' && !(event.shiftKey && event.key === 'F10')) return;
|
|
1590
|
+
event.preventDefault();
|
|
1591
|
+
const box = button.getBoundingClientRect?.();
|
|
1592
|
+
openMenu(box ? box.left + 24 : 0, box ? box.bottom : 0);
|
|
1593
|
+
};
|
|
1594
|
+
const more = el('button', undefined, 'library-more icon-button'); more.type = 'button';
|
|
1595
|
+
more.title = `Actions for ${item.name}`; more.setAttribute('aria-label', `More actions for ${item.name}`); more.setAttribute('aria-haspopup', 'menu');
|
|
1596
|
+
const moreGlyph = globalThis.AndorraIcons?.icon?.('more', 14); if (moreGlyph) more.append(moreGlyph);
|
|
1597
|
+
more.onclick = event => { const box = more.getBoundingClientRect?.(); openMenu(box ? box.left : event?.clientX ?? 0, box ? box.bottom : event?.clientY ?? 0); };
|
|
1598
|
+
row.append(more);
|
|
1599
|
+
}
|
|
1600
|
+
parent.append(row);
|
|
1601
|
+
};
|
|
1602
|
+
const section = (parent, id, name, entries) => {
|
|
1603
|
+
const matching = entries.filter(item => `${name} ${item.name} ${item.description}`.toLowerCase().includes(query));
|
|
1604
|
+
if (query && !matching.length && !name.toLowerCase().includes(query)) return;
|
|
1605
|
+
const group = el('details', undefined, 'library-group');
|
|
1606
|
+
group.open = !!query || (state.libraryExpanded[id] ?? true); group.append(el('summary', name));
|
|
1607
|
+
group.ontoggle = () => { if (!query) state.libraryExpanded[id] = group.open; };
|
|
1608
|
+
for (const item of matching) addItem(group, item);
|
|
1609
|
+
parent.append(group); return group;
|
|
1610
|
+
};
|
|
1611
|
+
const agents = section(container, 'agents', 'Agents', [
|
|
1612
|
+
{id:'add', name:'Add agent', description:'Create a new Agent in this list', icon:'plus', title:'Create a new Agent and add it to this list', action:addAgent},
|
|
1613
|
+
{id:'import', name:'Import agent', description:'Add an Agent from a shared JSON file', icon:'upload', title:'Import an Agent shared from Andorra Code', action:importAgent, last:true},
|
|
1614
|
+
...state.definitions.filter(d=>d.preset).map(definitionItem),
|
|
1615
|
+
...state.definitions.filter(d=>!d.preset).map(definitionItem),
|
|
1616
|
+
]);
|
|
1617
|
+
if (agents) agents.append(el('p','Select an Agent to configure Condition, Loop, and Parallel modifiers.','help'));
|
|
1618
|
+
section(container,'control','Control',['join'].map(type=>({name:type.charAt(0).toUpperCase()+type.slice(1),type,description:{condition:'Branch on run state',loop:'Bounded repetition',parallel:'Explicit fan-out',join:'Wait for all or any branches'}[type]})));
|
|
1619
|
+
section(container,'actions','Actions',[{name:'Run command',type:'action',node:{name:'Run command',action:{kind:'command',command:''}},description:'Execute a shell command'},{name:'Run tests',type:'action',node:{name:'Run tests',action:{kind:'tests',command:'npm test'}},description:'Execute project tests'},{name:'Git operation',type:'action',node:{name:'Git operation',action:{kind:'git',command:'git status'}},description:'Run a Git operation'}]);
|
|
1620
|
+
section(container,'flow','Flow',[{name:'Human approval',type:'approval',description:'Pause for a decision'},{name:'End',type:'end',description:'Finish this graph path'}]);
|
|
1621
|
+
}
|
|
1622
|
+
function fit() {
|
|
1623
|
+
if (!state.graph) return; const nodes = Object.values(state.graph.nodes); if (!nodes.length) return;
|
|
1624
|
+
const positions = nodes.map(position), minX = Math.min(...positions.map(p => p.x)), minY = Math.min(...positions.map(p => p.y)), maxX = Math.max(...positions.map(p => p.x)) + 210, maxY = Math.max(...positions.map(p => p.y)) + Math.max(...nodes.map(n => 94 + outcomes(n).length * 25));
|
|
1625
|
+
state.zoom = Math.min(1, Math.max(.2, Math.min(($('canvas').clientWidth - 90) / (maxX - minX), ($('canvas').clientHeight - 170) / (maxY - minY))));
|
|
1626
|
+
state.x = ($('canvas').clientWidth - (maxX - minX) * state.zoom) / 2 - minX * state.zoom; state.y = ($('canvas').clientHeight - (maxY - minY) * state.zoom) / 2 - minY * state.zoom; transform();
|
|
1627
|
+
}
|
|
1628
|
+
function zoom(factor, x = $('canvas').clientWidth / 2, y = $('canvas').clientHeight / 2) { const next = Math.max(.2, Math.min(2, state.zoom * factor)); state.x = x - (x - state.x) * next / state.zoom; state.y = y - (y - state.y) * next / state.zoom; state.zoom = next; transform(); }
|
|
1629
|
+
// A keyboard-activated click carries no pointer coordinates, so the menu falls back to the
|
|
1630
|
+
// window corner rather than refusing to open.
|
|
1631
|
+
$('new-graph').onclick = event => showNewGraphMenu(event?.clientX ?? 0, event?.clientY ?? 0); $('duplicate').onclick = () => newGraph(true); $('search').oninput = renderList;
|
|
1632
|
+
$('node-search').oninput = renderLibrary;
|
|
1633
|
+
$('graph-settings').onclick = () => { clearSelection(); renderCanvas(); renderInspector(); };
|
|
1634
|
+
$('toggle-inspector').onclick = () => { const hidden = $('inspector').classList.toggle('hidden'); $('toggle-inspector').setAttribute('aria-expanded', String(!hidden)); };
|
|
1635
|
+
$('undo').onclick = () => { if (!state.undo.length) return; state.redo.push(copy(state.graph)); state.graph = state.undo.pop(); clearSelection(); state.dirty = true; render(); status('Change undone'); };
|
|
1636
|
+
$('redo').onclick = () => { if (!state.redo.length) return; state.undo.push(copy(state.graph)); state.graph = state.redo.pop(); clearSelection(); state.dirty = true; render(); status('Change restored'); };
|
|
1637
|
+
// A refused Save briefly pulses the outlined nodes, so the eye finds the cards it must fix
|
|
1638
|
+
// before the run can be saved. No re-render happens on that early return, so the class lives.
|
|
1639
|
+
function pulseErrorNodes() {
|
|
1640
|
+
for (const element of document.querySelectorAll?.('.node.node-error') ?? []) element.classList.add('node-error-pulse');
|
|
1641
|
+
setTimeout(() => { for (const element of document.querySelectorAll?.('.node.node-error-pulse') ?? []) element.classList.remove('node-error-pulse'); }, 1300);
|
|
1642
|
+
}
|
|
1643
|
+
// After a successful save, a requirement is retired only if its node is gone or now has a
|
|
1644
|
+
// provider: edits made while the save was in flight (a providerless clipboard paste) keep
|
|
1645
|
+
// theirs, since the submitted snapshot never covered them.
|
|
1646
|
+
function retireSatisfiedProviderRequirements() {
|
|
1647
|
+
if (!state.pendingProviderNodes?.size) return;
|
|
1648
|
+
const stillOwed = new Set();
|
|
1649
|
+
for (const id of state.pendingProviderNodes) {
|
|
1650
|
+
const node = state.graph?.nodes[id];
|
|
1651
|
+
if (node?.type === 'agent' && !node.provider) stillOwed.add(id);
|
|
1652
|
+
}
|
|
1653
|
+
state.pendingProviderNodes = stillOwed.size ? stillOwed : null;
|
|
1654
|
+
syncImportRequirementsMarker();
|
|
1655
|
+
}
|
|
1656
|
+
$('save').onclick = async () => {
|
|
1657
|
+
if (state.saving) return;
|
|
1658
|
+
const invalid = document.querySelector('textarea:invalid, input:invalid'); if (invalid) { revealInspectorControl(invalid); invalid.reportValidity(); return; } const errors = issues(); if (errors.length) { status(errors[0].message, true); pulseErrorNodes(); return; }
|
|
1659
|
+
state.saving = true; renderHeading(); renderList();
|
|
1660
|
+
try { const submitted = dropLegacyTokenFields(copy(state.graph)); const graph = await api('/api/graphs', submitted); if (state.graph.id === submitted.id) {
|
|
1661
|
+
// The draft marker is editor state, not graph content, so a difference in it alone is not an edit.
|
|
1662
|
+
const liveView = { ...state.graph }; delete liveView.pendingProviderNodes;
|
|
1663
|
+
const edited = JSON.stringify(liveView) !== JSON.stringify(submitted); if (edited) { state.graph.revision = graph.revision; state.undo = []; state.redo = []; } else { state.graph = graph; state.dirty = false; state.undo = []; state.redo = []; } retireSatisfiedProviderRequirements(); } const index = state.graphs.findIndex(g => g.id === graph.id); const summary = { id: graph.id, name: graph.name, revision: graph.revision }; if (index >= 0) state.graphs[index] = summary; else state.graphs.push(summary); render(); status(`Saved revision ${graph.revision}${state.dirty ? ' - You have newer unsaved changes' : ''}`); } catch (error) { status(error.message, true); } finally { state.saving = false; renderHeading(); renderList(); }
|
|
1664
|
+
};
|
|
1665
|
+
$('canvas-hint-close').onclick = dismissCanvasHint;
|
|
1666
|
+
$('fit').onclick = fit; $('zoom-in').onclick = () => zoom(1.2); $('zoom-out').onclick = () => zoom(1 / 1.2);
|
|
1667
|
+
$('layout').onclick = () => mutate(() => {
|
|
1668
|
+
const levels = new Map([[state.graph.entry, 0]]), queue = [state.graph.entry];
|
|
1669
|
+
while (queue.length) { const id = queue.shift(); for (const edge of state.graph.edges.filter(e => e.source === id)) if (!levels.has(edge.target)) { levels.set(edge.target, levels.get(id) + 1); queue.push(edge.target); } }
|
|
1670
|
+
const rows = new Map(); for (const node of Object.values(state.graph.nodes)) { const level = levels.get(node.id) ?? 0, row = rows.get(level) || 0; node.position = { x: level * 300, y: row * 220 }; rows.set(level, row + 1); } fit();
|
|
1671
|
+
}, true);
|
|
1672
|
+
$('canvas').addEventListener('wheel', event => { if (event.target.closest('button, .node, path')) return; event.preventDefault(); dismissCanvasHint(); const bounds = $('canvas').getBoundingClientRect(); zoom(Math.exp(-event.deltaY * .001), event.clientX - bounds.left, event.clientY - bounds.top); }, { passive: false });
|
|
1673
|
+
$('canvas').ondragover = event => {
|
|
1674
|
+
const types = Array.from(event.dataTransfer?.types || []);
|
|
1675
|
+
if ((state.graph && !state.saving && types.includes('application/andorra-node')) || types.includes('Files')) {event.preventDefault();event.dataTransfer.dropEffect='copy';}
|
|
1676
|
+
};
|
|
1677
|
+
$('canvas').ondrop = event => {
|
|
1678
|
+
const raw=event.dataTransfer?.getData('application/andorra-node');
|
|
1679
|
+
if (raw) {
|
|
1680
|
+
if(!state.graph || state.saving)return;event.preventDefault();
|
|
1681
|
+
try {const item=JSON.parse(raw);if(!item || typeof item.type!=='string')return;const bounds=$('canvas').getBoundingClientRect();addNode(item.type,item.node,{x:Math.round((event.clientX-bounds.left-state.x)/state.zoom),y:Math.round((event.clientY-bounds.top-state.y)/state.zoom)});} catch(error){status('This library item could not be added: '+error.message,true);}
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
// An OS file dropped onto the canvas imports as a new graph (the desktop host hands drops
|
|
1685
|
+
// over through its own frame channel, so this path only serves a browser-opened studio).
|
|
1686
|
+
const file = Array.from(event.dataTransfer?.files || []).find(item => /\.json$/i.test(item.name) || item.type === 'application/json');
|
|
1687
|
+
if (file) { event.preventDefault(); void window.AndorraStudio?.importGraphFile?.(file)?.catch(error => status(error.message, true)); }
|
|
1688
|
+
};
|
|
1689
|
+
$('canvas').onpointerdown = event => { if (event.button !== 0 || event.target.closest('button, .node, path, .canvas-hint')) return; dismissCanvasHint(); const start = { x: event.clientX - state.x, y: event.clientY - state.y }; $('canvas').setPointerCapture(event.pointerId); $('canvas').onpointermove = e => { state.x = e.clientX - start.x; state.y = e.clientY - start.y; transform(); }; $('canvas').onpointerup = () => { $('canvas').onpointermove = null; }; };
|
|
1690
|
+
$('resize').onpointerdown = event => { $('resize').setPointerCapture(event.pointerId); $('resize').onpointermove = e => { document.documentElement.style.setProperty('--panel', `${Math.max(360, Math.min(720, innerWidth - e.clientX))}px`); }; $('resize').onpointerup = () => { $('resize').onpointermove = null; }; };
|
|
1691
|
+
$('resize').onkeydown = event => { if (!['ArrowLeft', 'ArrowRight'].includes(event.key)) return; event.preventDefault(); const width = $('inspector').getBoundingClientRect().width + (event.key === 'ArrowLeft' ? 20 : -20); document.documentElement.style.setProperty('--panel', `${Math.max(360, Math.min(720, width))}px`); };
|
|
1692
|
+
$('export').onclick = () => { if (!state.graph) return; downloadGraph(state.graph); };
|
|
1693
|
+
// A change of appearance repaints the connections, whose colours are read from the tokens.
|
|
1694
|
+
if (typeof document.addEventListener === 'function') {
|
|
1695
|
+
document.addEventListener('andorra:themechange', () => { if (state.graph) renderCanvas(); });
|
|
1696
|
+
}
|
|
1697
|
+
window.addEventListener('beforeunload', event => { document.activeElement?.blur(); if (state.dirty) { event.preventDefault(); event.returnValue = ''; } });
|
|
1698
|
+
window.addEventListener('keydown', event => { if(event.key==='Delete' && !document.querySelector('dialog[open]') && !event.target?.closest('input, textarea, select, [contenteditable]:not([contenteditable=\"false\"])') && !event.isComposing) {event.preventDefault();deleteSelection();return;} if(event.key==='Escape' && state.routePick){event.preventDefault();cancelRoutePick();return;} if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') { event.preventDefault(); document.activeElement?.blur(); if (!$('save').disabled) $('save').click(); } });
|
|
1699
|
+
async function refreshCloudState() {
|
|
1700
|
+
if (!token) return;
|
|
1701
|
+
try {
|
|
1702
|
+
const sync = await api('/api/sync');
|
|
1703
|
+
if ($('sync-status')) $('sync-status').textContent = sync.detail;
|
|
1704
|
+
await refreshDrafts();
|
|
1705
|
+
const data = await api('/api/bootstrap'); state.plan = data.plan; state.graphs = data.graphs; applyProviderRegistry(data); renderList();
|
|
1706
|
+
} catch (error) { if ($('sync-status')) $('sync-status').textContent = 'Cloud sync unavailable: ' + error.message; }
|
|
1707
|
+
setTimeout(refreshCloudState, 10000);
|
|
1708
|
+
}
|
|
1709
|
+
// First sync check after one second; subsequent status/list refreshes remain periodic.
|
|
1710
|
+
if (token) setTimeout(refreshCloudState, 1000);
|
|
1711
|
+
|
|
1712
|
+
/* CLI run activity: this tab mirrors the live run state of the CLI sharing this installation.
|
|
1713
|
+
A spinner favicon turns while the CLI works; an exclamation favicon, a title prefix, and a
|
|
1714
|
+
system notification (a Windows toast) fire when the CLI waits on the user. Every browser
|
|
1715
|
+
entry point is feature-detected because this module also loads into partial-DOM harnesses.
|
|
1716
|
+
The idle favicon is the published Andorra Labs logo; the two busy states are status markers
|
|
1717
|
+
rather than the brand, so they keep their own artwork. */
|
|
1718
|
+
const baseTitle = document.title || 'Graph studio - Andorra Code';
|
|
1719
|
+
const faviconHref = svg => 'data:image/svg+xml,' + encodeURIComponent(svg);
|
|
1720
|
+
const FAVICONS = {
|
|
1721
|
+
idle: '/andorra-logo.png',
|
|
1722
|
+
running: faviconHref('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><circle cx="16" cy="16" r="11" fill="none" stroke="#8d8d96" stroke-width="4" opacity="0.45"/><g><path d="M16 5a11 11 0 0 1 11 11" fill="none" stroke="#5b5b63" stroke-width="4" stroke-linecap="round"/><animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 16 16" to="360 16 16" dur="0.9s" repeatCount="indefinite"/></g></svg>'),
|
|
1723
|
+
'awaiting-input': faviconHref('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="7" fill="#D97706"/><rect x="14" y="7" width="4" height="13" rx="2" fill="#fff"/><circle cx="16" cy="24.5" r="2.4" fill="#fff"/></svg>'),
|
|
1724
|
+
};
|
|
1725
|
+
function setFavicon(activity) {
|
|
1726
|
+
try {
|
|
1727
|
+
let link = document.querySelector('link[rel="icon"]');
|
|
1728
|
+
if (!link) {
|
|
1729
|
+
link = document.createElement('link');
|
|
1730
|
+
link.setAttribute('rel', 'icon');
|
|
1731
|
+
(document.head || document.body).append(link);
|
|
1732
|
+
}
|
|
1733
|
+
const href = FAVICONS[activity] || FAVICONS.idle;
|
|
1734
|
+
link.setAttribute('type', href.startsWith('data:') ? 'image/svg+xml' : 'image/png');
|
|
1735
|
+
link.setAttribute('href', href);
|
|
1736
|
+
} catch { /* A partial DOM cannot host a favicon. */ }
|
|
1737
|
+
}
|
|
1738
|
+
let lastActivityKey;
|
|
1739
|
+
function applyActivity(value) {
|
|
1740
|
+
if (!value) return;
|
|
1741
|
+
// Feature-detected: the run-activity block is exercised in partial-DOM harnesses where the
|
|
1742
|
+
// provider registry lives outside the evaluated slice.
|
|
1743
|
+
if (typeof applyProviderRegistry === 'function') applyProviderRegistry(value);
|
|
1744
|
+
if (!Object.hasOwn(FAVICONS, value.state)) return;
|
|
1745
|
+
setFavicon(value.state);
|
|
1746
|
+
document.title = value.state === 'running' ? `Running · ${baseTitle}` : value.state === 'awaiting-input' ? `Input needed · ${baseTitle}` : baseTitle;
|
|
1747
|
+
const activityKey = JSON.stringify([value.state, value.runId, value.updatedAt, value.kind, value.detail]);
|
|
1748
|
+
// Native-app notifications are requested by the top-level Tauri window. Browsers
|
|
1749
|
+
// deny permission requests from cross-origin iframes, so relay only safe status.
|
|
1750
|
+
window.AndorraEmbed?.activity?.(value);
|
|
1751
|
+
if ((!window.parent || window.parent === window) && value.state === 'awaiting-input' &&
|
|
1752
|
+
lastActivityKey !== activityKey && typeof Notification === 'function' && Notification.permission === 'granted') {
|
|
1753
|
+
try { new Notification('Andorra Code needs your input', { body: value.detail || 'Open the terminal to answer.', tag: 'andorra-activity' }); } catch { /* The favicon and title still changed. */ }
|
|
1754
|
+
}
|
|
1755
|
+
lastActivityKey = activityKey;
|
|
1756
|
+
}
|
|
1757
|
+
// Browsers want a user gesture before showing the permission prompt, so ask on the first click
|
|
1758
|
+
// or keypress; until then the favicon and title carry the state without notifications.
|
|
1759
|
+
function requestActivityNotifications() {
|
|
1760
|
+
try { if (typeof Notification === 'function' && Notification.permission === 'default') void Notification.requestPermission(); } catch { /* Denied or unsupported. */ }
|
|
1761
|
+
window.removeEventListener('pointerdown', requestActivityNotifications);
|
|
1762
|
+
window.removeEventListener('keydown', requestActivityNotifications);
|
|
1763
|
+
}
|
|
1764
|
+
function watchActivity() {
|
|
1765
|
+
let pollFailures = 0;
|
|
1766
|
+
const poll = async () => {
|
|
1767
|
+
try {
|
|
1768
|
+
applyActivity(await api('/api/activity'));
|
|
1769
|
+
pollFailures = 0;
|
|
1770
|
+
} catch {
|
|
1771
|
+
// A dead server must not leave the fallback path claiming a run forever: after the same
|
|
1772
|
+
// 20-second grace the stream path uses (four failed five-second polls), clear to idle
|
|
1773
|
+
// and keep polling quietly in case a server comes back.
|
|
1774
|
+
if (++pollFailures === 4) applyActivity({ state: 'idle' });
|
|
1775
|
+
}
|
|
1776
|
+
setTimeout(poll, 5000);
|
|
1777
|
+
};
|
|
1778
|
+
// Prefer a server-sent event stream: background tabs throttle timers, and a throttled poll
|
|
1779
|
+
// could report an input request minutes late. EventSource cannot send the Authorization
|
|
1780
|
+
// header, so the stream accepts the session token in the query string.
|
|
1781
|
+
if (typeof EventSource !== 'function' || !token) { setTimeout(poll, 1000); return; }
|
|
1782
|
+
let source;
|
|
1783
|
+
try { source = new EventSource(`/api/activity/stream?token=${encodeURIComponent(token)}`); }
|
|
1784
|
+
catch { setTimeout(poll, 1000); return; }
|
|
1785
|
+
// The CLI that hosts this tab's server can exit mid-run, and a dead stream must not leave the
|
|
1786
|
+
// tab claiming a run forever. EventSource retries silently, so only clear the state after the
|
|
1787
|
+
// retries have had a real grace period; polling then takes over if a server ever returns.
|
|
1788
|
+
let staleTimer;
|
|
1789
|
+
source.onmessage = event => {
|
|
1790
|
+
clearTimeout(staleTimer);
|
|
1791
|
+
staleTimer = undefined;
|
|
1792
|
+
try { applyActivity(JSON.parse(event.data)); } catch { /* Ignore a malformed frame. */ }
|
|
1793
|
+
};
|
|
1794
|
+
source.onerror = () => {
|
|
1795
|
+
if (staleTimer !== undefined) return;
|
|
1796
|
+
staleTimer = setTimeout(() => { try { source.close(); } catch { /* Already closed. */ } applyActivity({ state: 'idle' }); poll(); }, 20000);
|
|
1797
|
+
};
|
|
1798
|
+
}
|
|
1799
|
+
setFavicon('idle');
|
|
1800
|
+
if (token) watchActivity();
|
|
1801
|
+
try { if ((!window.parent || window.parent === window) && typeof Notification === 'function' && Notification.permission === 'default') { window.addEventListener('pointerdown', requestActivityNotifications); window.addEventListener('keydown', requestActivityNotifications); } } catch { /* Partial DOM. */ }
|
|
1802
|
+
|
|
1803
|
+
(async () => { renderHeading(); if (!token) { status('Session token missing. Open this app using andorra graph.', true); return; } try { const data = await api('/api/bootstrap'); state.plan = data.plan; state.graphs = data.graphs; applyProviderRegistry(data); state.tools = data.tools || []; state.definitions = data.definitions || []; renderLibrary(); renderList(); const wantsNew = new URLSearchParams(location.search).get('new') === '1'; if (wantsNew && canCreateGraph()) newGraph(); else if (state.graphs.length) { await openGraph((freeTier() && state.plan.freeGraphId) || state.graphs[0].id); if (wantsNew) status(FREE_CREATE_TIP, true); } else { render(); status('Create your first graph'); } window.AndorraEmbed?.ready?.(); if (data.graphMigrationErrors?.length) status('Some saved graphs could not be opened: ' + data.graphMigrationErrors.map(item => item.name + ' (' + item.id + '): ' + item.error).join('; ') + '. Their saved revisions are unchanged.', true); } catch (error) { status(error.message, true); } })();
|