@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,3012 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { emitKeypressEvents } from 'node:readline';
|
|
3
|
+
import { PassThrough } from 'node:stream';
|
|
4
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
5
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
6
|
+
import stringWidth from 'string-width';
|
|
7
|
+
import { DashboardMetrics } from './dashboard.js';
|
|
8
|
+
import { dashboardRows } from './dashboard-view.js';
|
|
9
|
+
import { transcriptColor } from './transcript.js';
|
|
10
|
+
import { ToolCallClock, toolHeaderRows } from './tool-call-clock.js';
|
|
11
|
+
import { formatDuration } from './duration.js';
|
|
12
|
+
import { PagedTranscript } from './paged-transcript.js';
|
|
13
|
+
import { accentSgr, ATTACHMENT_TOKEN, DIM, FAINT, GRAY, STATUS, SUBTLE, WHITE } from './palette.js';
|
|
14
|
+
import { isCustomGraph, panelRowText, panelWidth, PANEL_MIN_COLUMNS, PANEL_MIN_ROWS, sidePanelRows } from './side-panel.js';
|
|
15
|
+
import { TokenRateMeter } from './token-rate.js';
|
|
16
|
+
import { attachmentLabel, droppedPaths, formatBytes, isLargePaste, MAX_ATTACHMENTS } from './attachments.js';
|
|
17
|
+
const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
18
|
+
const graphemes = (text) => [...segmenter.segment(text)].map(part => part.segment);
|
|
19
|
+
/**
|
|
20
|
+
* Attachment tokens live in the composer draft as one code point each from Supplementary
|
|
21
|
+
* Private Use Area-B, which no font or input method emits. `clean` strips that plane from
|
|
22
|
+
* everything typed or pasted, so only `addAttachment` can put a token into the draft.
|
|
23
|
+
*/
|
|
24
|
+
const TOKEN_BASE = 0x100000;
|
|
25
|
+
const isToken = (part) => (part.codePointAt(0) ?? 0) >= TOKEN_BASE;
|
|
26
|
+
/** Graphemes of a draft, keeping each token its own element even when a combining mark follows it. */
|
|
27
|
+
const composerGraphemes = (text) => graphemes(text).flatMap(part => isToken(part) && part.length > 2 ? [part.slice(0, 2), part.slice(2)] : [part]);
|
|
28
|
+
const clean = (text) => stripVTControlCharacters(text).replace(/\r\n?/g, '\n').replace(/[\x00-\x08\x0b-\x1f\x7f-\x9f\u202a-\u202e\u2066-\u2069]/g, '').replace(/[\u{100000}-\u{10FFFF}]/gu, '').replace(/\t/g, ' ');
|
|
29
|
+
const oneLine = (text) => clean(text).replace(/\n/g, ' ');
|
|
30
|
+
const commands = ['/model', '/providers', '/subagent', '/reasoning', '/graph', '/codegraph', '/dashboard', '/browser', '/attach', '/skills', '/plugins', '/mcp', '/usage', '/permissions', '/yolo', '/jev', '/feedback', '/tools', '/session', '/status', '/clear', '/compact', '/help', '/login', '/logout', '/auth status', '/auth logout', '/exit', '/quit'];
|
|
31
|
+
/**
|
|
32
|
+
* The arguments the popup offers once a command and a space are typed. The read-only choice comes
|
|
33
|
+
* first wherever there is one, so a second Enter on a freshly opened list reports rather than
|
|
34
|
+
* changes a setting.
|
|
35
|
+
*/
|
|
36
|
+
const argumentCompletions = {
|
|
37
|
+
'/jev': ['/jev status', '/jev on', '/jev off'],
|
|
38
|
+
'/feedback': ['/feedback status', '/feedback on', '/feedback off'],
|
|
39
|
+
'/yolo': ['/yolo off', '/yolo on'],
|
|
40
|
+
'/reasoning': ['default', 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'].map(level => `/reasoning ${level}`),
|
|
41
|
+
'/codegraph': ['/codegraph status', '/codegraph enable', '/codegraph disable', '/codegraph rebuild', '/codegraph enable --global', '/codegraph disable --global'],
|
|
42
|
+
'/attach': [],
|
|
43
|
+
'/logout': ['/logout codex'],
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Commands that do nothing useful bare. Enter or Tab on one fills in the command and a space and
|
|
47
|
+
* waits for the argument instead of running it; `/logout` is complete on its own.
|
|
48
|
+
*/
|
|
49
|
+
const argumentRequired = new Set(['/jev', '/feedback', '/yolo', '/reasoning', '/codegraph', '/attach']);
|
|
50
|
+
const completionOptions = (query) => {
|
|
51
|
+
const command = /^(\/\S+)\s/.exec(query)?.[1];
|
|
52
|
+
return (command === undefined ? commands : argumentCompletions[command] ?? []).filter(option => option.startsWith(query));
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Whether the composer text is a command name, or a command with arguments, that the popup completes.
|
|
56
|
+
* A command that is complete on its own lists its arguments only once one is being typed: `/logout `
|
|
57
|
+
* must submit the bare sign-out, not have Enter pick `/logout codex` from a list nobody asked for.
|
|
58
|
+
*/
|
|
59
|
+
const completable = (query) => {
|
|
60
|
+
if (/^\/\S*$/.test(query))
|
|
61
|
+
return true;
|
|
62
|
+
const [, command, argument] = /^(\/\S+) (\S*)$/.exec(query) ?? [];
|
|
63
|
+
return command !== undefined && Object.hasOwn(argumentCompletions, command) && (argument !== '' || argumentRequired.has(command));
|
|
64
|
+
};
|
|
65
|
+
/** A fixed-width, two-line terminal wordmark for the default Andorra CLI. */
|
|
66
|
+
const ANDORRA_WORDMARK = [
|
|
67
|
+
'▄▀█ █▄ █ █▀▄ █▀█ █▀█ █▀█ ▄▀█',
|
|
68
|
+
'█▀█ █ ▀█ █▄▀ █▄█ █▀▄ █▀▄ █▀█',
|
|
69
|
+
];
|
|
70
|
+
/** Said under the workflow name while the selected graph cannot bind to this machine's providers. */
|
|
71
|
+
const OVERRIDE_HINT = 'Choose a model to override the nodes with · /model';
|
|
72
|
+
const commandDescriptions = {
|
|
73
|
+
'/browser': 'Open the browser workspace',
|
|
74
|
+
'/attach': 'Attach a file or folder to your next task',
|
|
75
|
+
'/session': 'Browse and resume saved sessions',
|
|
76
|
+
'/login': 'Sign in or create an Andorra account', '/logout': 'Sign out of the Andorra account', '/logout codex': 'Sign out of every Codex account', '/auth logout': 'Sign out of the Andorra account', '/auth status': 'Account and membership status',
|
|
77
|
+
'/model': 'Choose a model', '/providers': 'Choose or edit providers',
|
|
78
|
+
'/subagent': 'Choose the provider and model external hosts run Andorra with',
|
|
79
|
+
'/reasoning': 'Choose thinking effort', '/dashboard': 'Toggle live dashboard / transcript',
|
|
80
|
+
'/skills': 'Manage and install skills', '/plugins': 'Manage and install plugins',
|
|
81
|
+
'/mcp': 'Manage MCP servers',
|
|
82
|
+
'/jev': 'Turn Jev on or off for nodes that enable it', '/jev on': 'Enable Jev', '/jev off': 'Disable Jev', '/jev status': 'Show saved Jev setting',
|
|
83
|
+
'/feedback': 'Show the anonymous-feedback setting; Paid accounts can turn it off', '/feedback on': 'Allow anonymous product feedback', '/feedback off': 'Stop anonymous product feedback (Paid plan)', '/feedback status': 'Show saved feedback setting',
|
|
84
|
+
'/graph': 'Choose a graph', '/codegraph': 'Code intelligence status and actions', '/usage': 'Usage and token totals', '/yolo': 'Turn automatic approvals on or off', '/yolo on': 'Approve everything for this session', '/yolo off': 'Restore Ask for approval',
|
|
85
|
+
'/permissions': 'Choose workspace permissions',
|
|
86
|
+
'/tools': 'Available coding tools', '/status': 'Workspace and settings', '/clear': 'Clear conversation',
|
|
87
|
+
'/compact': 'Compact conversation history',
|
|
88
|
+
'/help': 'Show command help', '/exit': 'Exit Andorra', '/quit': 'Alias for /exit',
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* The session command a submitted line starts with, if any.
|
|
92
|
+
*
|
|
93
|
+
* The first whitespace-delimited token must match a known command's root exactly. A leading-slash
|
|
94
|
+
* test alone would swallow legitimate steering text that merely mentions a path such as
|
|
95
|
+
* `/src/app.ts`, and an unknown `/notacommand` is not a session command either.
|
|
96
|
+
* @param value - the submitted composer text.
|
|
97
|
+
* @returns the command token, or undefined when the text is ordinary input.
|
|
98
|
+
*/
|
|
99
|
+
const submittedCommand = (value) => {
|
|
100
|
+
const [token] = value.trim().split(/\s+/);
|
|
101
|
+
return commands.some(command => command.split(/\s+/)[0] === token) ? token : undefined;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* The hint shown when a session command is typed while a task is working.
|
|
105
|
+
*
|
|
106
|
+
* Commands run between tasks: a started run has its history snapshotted and stays pinned to
|
|
107
|
+
* its graph revision, so executing one mid-run would misreport what the run actually used.
|
|
108
|
+
* The hint names the command and the way out instead of queueing the text as an instruction
|
|
109
|
+
* the model would then follow.
|
|
110
|
+
* @param command - the recognized command token that was submitted.
|
|
111
|
+
*/
|
|
112
|
+
const workingCommandHint = (command) => `${command} doesn't run while a task is working. Press Ctrl+C to stop this task, then run ${command}.`
|
|
113
|
+
+ (command === '/graph' ? ' Switching graphs clears the previous graph progress and starts fresh.' : '');
|
|
114
|
+
/** Commands the run input handler executes live during a run, plus its exits; they must reach it. */
|
|
115
|
+
const liveRunCommands = ['/browser', '/attach', '/yolo', '/permissions', '/jev', '/help', '/status', '/usage', '/tools', '/exit', '/quit'];
|
|
116
|
+
const paint = (text, color = GRAY) => typeof color === 'number'
|
|
117
|
+
? `\x1b[38;5;${color}m${text}\x1b[0m`
|
|
118
|
+
: `\x1b[${color}m${text}\x1b[0m`;
|
|
119
|
+
/**
|
|
120
|
+
* Foreground sequence for the Andorra accent.
|
|
121
|
+
*
|
|
122
|
+
* Resolved per render rather than at module load: truecolor support is read from the
|
|
123
|
+
* environment, which a test or embedder may set after this module is imported, and
|
|
124
|
+
* caching the first answer would pin the fallback for the whole process.
|
|
125
|
+
*/
|
|
126
|
+
const accentPaint = () => accentSgr();
|
|
127
|
+
/** Thousands as `1.2k`, the shape both footer token readouts need to stay on one row. */
|
|
128
|
+
const compactNumber = (value) => Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 1 }).format(value);
|
|
129
|
+
const MAX_INPUT = 65_536;
|
|
130
|
+
/**
|
|
131
|
+
* Bracketed-paste accumulation ceiling. An in-flight paste may exceed the inline limit because
|
|
132
|
+
* a large paste never inlines: it spools to an attachment, whose own cap this matches.
|
|
133
|
+
*/
|
|
134
|
+
const PASTE_ACCUMULATE_LIMIT = 1_048_576;
|
|
135
|
+
const INPUT_BURST_MS = 40;
|
|
136
|
+
/** Rows an echoed prompt may occupy before the tail is replaced by an omission marker. */
|
|
137
|
+
const MAX_PROMPT_ROWS = 200;
|
|
138
|
+
/** Long submitted prompts collapse in chat history until the user expands them with Ctrl+O. */
|
|
139
|
+
const PROMPT_COLLAPSE_AFTER_ROWS = 12;
|
|
140
|
+
const PROMPT_COLLAPSED_BODY_ROWS = 6;
|
|
141
|
+
/**
|
|
142
|
+
* Characters of streamed reasoning retained for the live preview. Only the tail ever
|
|
143
|
+
* renders, so the buffer is a bounded window, not the full reasoning transcript.
|
|
144
|
+
*/
|
|
145
|
+
const THINKING_KEEP = 4_000;
|
|
146
|
+
/** Rows the reasoning preview expands to when opened. */
|
|
147
|
+
const THINKING_ROWS = 6;
|
|
148
|
+
/** Minimum milliseconds between preview repaints; faster streams coalesce into one render. */
|
|
149
|
+
const THINKING_PAINT_MS = 80;
|
|
150
|
+
/**
|
|
151
|
+
* Ownership token for the composer while steering.
|
|
152
|
+
*
|
|
153
|
+
* A deferred Enter is only delivered when the surface that armed it still owns the
|
|
154
|
+
* composer, so this stands in for `pending` when the steering composer is the owner.
|
|
155
|
+
*/
|
|
156
|
+
const STEERING_OWNER = Symbol('steering');
|
|
157
|
+
const commandPopupRows = (width, height, inputRows, matches) => width < 12 || height < 9
|
|
158
|
+
? 0 : Math.min(6, Math.max(1, matches), Math.max(0, height - inputRows - 11));
|
|
159
|
+
function clip(text, width, ellipsis = true) {
|
|
160
|
+
if (width <= 0)
|
|
161
|
+
return '';
|
|
162
|
+
if (stringWidth(text) <= width)
|
|
163
|
+
return text;
|
|
164
|
+
const room = width - (ellipsis ? 1 : 0);
|
|
165
|
+
let result = '', used = 0;
|
|
166
|
+
for (const character of graphemes(text)) {
|
|
167
|
+
const size = stringWidth(character);
|
|
168
|
+
if (used + size > room)
|
|
169
|
+
break;
|
|
170
|
+
result += character;
|
|
171
|
+
used += size;
|
|
172
|
+
}
|
|
173
|
+
return result + (ellipsis ? '…' : '');
|
|
174
|
+
}
|
|
175
|
+
function pad(text, width) { const value = clip(text, width); return value + ' '.repeat(Math.max(0, width - stringWidth(value))); }
|
|
176
|
+
function wrap(text, width) {
|
|
177
|
+
const result = [];
|
|
178
|
+
for (const paragraph of text.split('\n')) {
|
|
179
|
+
let line = '', used = 0;
|
|
180
|
+
const tokens = paragraph.match(/\s+|\S+/gu) ?? [];
|
|
181
|
+
for (const [index, token] of tokens.entries()) {
|
|
182
|
+
const tokenWidth = stringWidth(token);
|
|
183
|
+
const separator = !/\S/u.test(token) && index > 0 && index < tokens.length - 1;
|
|
184
|
+
if (/\S/u.test(token) && tokenWidth <= width && used + tokenWidth > width && line) {
|
|
185
|
+
result.push(line);
|
|
186
|
+
line = '';
|
|
187
|
+
used = 0;
|
|
188
|
+
}
|
|
189
|
+
for (const character of graphemes(token)) {
|
|
190
|
+
const size = stringWidth(character);
|
|
191
|
+
if (separator && used + size > width)
|
|
192
|
+
continue;
|
|
193
|
+
if (used + size > width && line) {
|
|
194
|
+
result.push(line);
|
|
195
|
+
line = '';
|
|
196
|
+
used = 0;
|
|
197
|
+
}
|
|
198
|
+
if (size > width) {
|
|
199
|
+
result.push('…');
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
line += character;
|
|
203
|
+
used += size;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
result.push(line);
|
|
207
|
+
}
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
/** Display-column span [start, end) of the selected graphemes on one wrapped composer row. */
|
|
211
|
+
function selectedColumns(text, positions, [from, to], row) {
|
|
212
|
+
let start = Infinity, end = -Infinity;
|
|
213
|
+
for (let index = from; index < to; index++) {
|
|
214
|
+
const position = positions[index];
|
|
215
|
+
if (position?.row !== row || text[index] === '\n')
|
|
216
|
+
continue;
|
|
217
|
+
start = Math.min(start, position.column);
|
|
218
|
+
end = Math.max(end, position.column + stringWidth(text[index]));
|
|
219
|
+
}
|
|
220
|
+
return start < end ? [start, end] : undefined;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Paint one composer row: attachment token columns in amber, and the selected column span in
|
|
224
|
+
* reverse video over whichever color it covers.
|
|
225
|
+
*/
|
|
226
|
+
function composerRow(text, color, selection, tokens) {
|
|
227
|
+
let painted = '', run = '', style = '';
|
|
228
|
+
let column = 0;
|
|
229
|
+
const flush = () => { if (run)
|
|
230
|
+
painted += paint(style[1] === 'r' ? `\x1b[7m${run}` : run, style[0] === 't' ? ATTACHMENT_TOKEN : color); run = ''; };
|
|
231
|
+
for (const part of graphemes(text)) {
|
|
232
|
+
const token = tokens.some(([start, end]) => column >= start && column < end);
|
|
233
|
+
const selected = !!selection && column >= selection[0] && column < selection[1];
|
|
234
|
+
const next = `${token ? 't' : 'p'}${selected ? 'r' : '-'}`;
|
|
235
|
+
if (next !== style) {
|
|
236
|
+
flush();
|
|
237
|
+
style = next;
|
|
238
|
+
}
|
|
239
|
+
run += part;
|
|
240
|
+
column += stringWidth(part);
|
|
241
|
+
}
|
|
242
|
+
flush();
|
|
243
|
+
return painted;
|
|
244
|
+
}
|
|
245
|
+
/** The display-column spans the draft's tokens occupy on one composer row. */
|
|
246
|
+
function tokenColumns(draft, visible, positions, row) {
|
|
247
|
+
const spans = [];
|
|
248
|
+
draft.forEach((part, index) => { const position = positions[index]; if (isToken(part) && position?.row === row)
|
|
249
|
+
spans.push([position.column, position.column + stringWidth(visible[index])]); });
|
|
250
|
+
return spans;
|
|
251
|
+
}
|
|
252
|
+
/** Whitespace as one editor element; a token label is a single element that contains spaces. */
|
|
253
|
+
const blank = (part) => /^\s+$/u.test(part);
|
|
254
|
+
function editor(text, width) {
|
|
255
|
+
const lines = [''];
|
|
256
|
+
const positions = [];
|
|
257
|
+
const wordWidths = new Map();
|
|
258
|
+
const separators = new Set();
|
|
259
|
+
for (let index = 0; index < text.length;) {
|
|
260
|
+
if (text[index] === '\n') {
|
|
261
|
+
index++;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (blank(text[index])) {
|
|
265
|
+
const start = index;
|
|
266
|
+
while (index < text.length && text[index] !== '\n' && blank(text[index]))
|
|
267
|
+
index++;
|
|
268
|
+
if (start > 0 && !blank(text[start - 1]) && index < text.length && !blank(text[index]))
|
|
269
|
+
for (let offset = start; offset < index; offset++)
|
|
270
|
+
separators.add(offset);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const start = index;
|
|
274
|
+
let size = 0;
|
|
275
|
+
while (index < text.length && !blank(text[index]))
|
|
276
|
+
size += stringWidth(text[index++]);
|
|
277
|
+
wordWidths.set(start, size);
|
|
278
|
+
}
|
|
279
|
+
let column = 0;
|
|
280
|
+
for (let index = 0; index <= text.length; index++) {
|
|
281
|
+
const character = text[index];
|
|
282
|
+
if (separators.has(index) && column + stringWidth(character) > width) {
|
|
283
|
+
positions.push({ row: lines.length - 1, column: Math.min(column, width - 1) });
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const wordWidth = wordWidths.get(index);
|
|
287
|
+
if (wordWidth !== undefined && wordWidth <= width && column > 0 && column + wordWidth > width) {
|
|
288
|
+
lines.push('');
|
|
289
|
+
column = 0;
|
|
290
|
+
}
|
|
291
|
+
if (column === width && character !== '\n') {
|
|
292
|
+
lines.push('');
|
|
293
|
+
column = 0;
|
|
294
|
+
}
|
|
295
|
+
if (character !== undefined && character !== '\n' && column + stringWidth(character) > width) {
|
|
296
|
+
lines.push('');
|
|
297
|
+
column = 0;
|
|
298
|
+
}
|
|
299
|
+
positions.push({ row: lines.length - 1, column: Math.min(column, width - 1) });
|
|
300
|
+
if (character === undefined)
|
|
301
|
+
break;
|
|
302
|
+
if (character === '\n') {
|
|
303
|
+
lines.push('');
|
|
304
|
+
column = 0;
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
lines[lines.length - 1] += character;
|
|
308
|
+
column += stringWidth(character);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return { lines, positions };
|
|
312
|
+
}
|
|
313
|
+
/** Full-screen terminal presentation; provider/runtime behavior remains owned by the CLI. */
|
|
314
|
+
export class TerminalUI extends EventEmitter {
|
|
315
|
+
input;
|
|
316
|
+
output;
|
|
317
|
+
workspace;
|
|
318
|
+
version;
|
|
319
|
+
appName;
|
|
320
|
+
keys = new PassThrough();
|
|
321
|
+
decoder = new StringDecoder('utf8');
|
|
322
|
+
status;
|
|
323
|
+
/**
|
|
324
|
+
* Graph nodes the user currently has running, in the order they started.
|
|
325
|
+
*
|
|
326
|
+
* `provider` and `model` are what each node's own executor reported, not what the graph file
|
|
327
|
+
* configured, so a retry that falls back to another profile moves the footer with it.
|
|
328
|
+
*
|
|
329
|
+
* `resolved` carries the reasoning effort and context window of that same resolution. It stays
|
|
330
|
+
* absent until a run reports them, and an absent `resolved` keeps the session's own numbers on
|
|
331
|
+
* the footer; a present one whose fields are undefined means that node's model has no effort or
|
|
332
|
+
* window of its own, which the footer shows as `provider default` and as no window at all
|
|
333
|
+
* rather than falling back to the session's unrelated values.
|
|
334
|
+
*/
|
|
335
|
+
activeNodes = new Map();
|
|
336
|
+
/**
|
|
337
|
+
* Node ids the current run has finished, in visit order.
|
|
338
|
+
*
|
|
339
|
+
* The side panel's zoom marks the run's trail with it, so it survives the run's end - a
|
|
340
|
+
* reader looking at a finished run can still see where it went - and is cleared only when
|
|
341
|
+
* the next run starts, which is the point the trail stops describing what is on screen.
|
|
342
|
+
*/
|
|
343
|
+
/** Whether the last frame drew without the panel, so its return can be announced once. */
|
|
344
|
+
panelWasHidden = true;
|
|
345
|
+
visitedNodes = new Set();
|
|
346
|
+
/** The node a stopped run ended on, kept as the panel's position until the next run starts. */
|
|
347
|
+
stoppedNode;
|
|
348
|
+
toolClock = new ToolCallClock();
|
|
349
|
+
toolClockTimer;
|
|
350
|
+
updateToolClock() {
|
|
351
|
+
if (this.toolClock.running && !this.closed && !this.toolClockTimer) {
|
|
352
|
+
this.toolClockTimer = setInterval(() => this.scheduleRender(), 100);
|
|
353
|
+
this.toolClockTimer.unref?.();
|
|
354
|
+
}
|
|
355
|
+
else if ((!this.toolClock.running || this.closed) && this.toolClockTimer) {
|
|
356
|
+
clearInterval(this.toolClockTimer);
|
|
357
|
+
this.toolClockTimer = undefined;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
dashboard = false;
|
|
361
|
+
dashboardMetrics = new DashboardMetrics();
|
|
362
|
+
dashboardModel = 0;
|
|
363
|
+
dashboardGraphOffset = 0;
|
|
364
|
+
dashboardNotices = [];
|
|
365
|
+
nodeModels = new Map();
|
|
366
|
+
toggleDashboard() { this.dashboard = !this.dashboard; this.scroll = 0; this.scheduleRender(); }
|
|
367
|
+
/** Start of a run: open the dashboard's run window. */
|
|
368
|
+
startTask() { this.runActive = true; this.updateAlternateScroll(); this.dashboardMetrics.startTask(); this.dashboardNotices = []; this.nodeModels.clear(); this.scheduleRender(); }
|
|
369
|
+
/** End of a run: close the dashboard's run window. */
|
|
370
|
+
finishTask() { this.runActive = false; this.updateAlternateScroll(); this.dashboardMetrics.finishTask(); this.scheduleRender(); }
|
|
371
|
+
resetDashboardSession(usage) { this.dashboardMetrics.resetSession(usage); this.dashboardModel = 0; this.dashboardGraphOffset = 0; this.nodeModels.clear(); this.dashboardNotices = []; this.scheduleRender(); }
|
|
372
|
+
/** Clock backing the per-node speed meters; see {@link TerminalOptions.tokenClock}. */
|
|
373
|
+
tokenClock;
|
|
374
|
+
/**
|
|
375
|
+
* One cumulative speed meter per generating identity, each stamped with the provider, model
|
|
376
|
+
* and reasoning effort its requests were measured under.
|
|
377
|
+
*
|
|
378
|
+
* Parallel nodes interleave model calls (`src/graph-runner.ts` runs branch workers side by
|
|
379
|
+
* side), so a single shared meter would have one node's first request discard the other's
|
|
380
|
+
* in-flight window and both nodes' totals alternate between wipes. Keys extend the nodeId
|
|
381
|
+
* with the parallel `copy` number the modifier stamps on every forwarded event, because two
|
|
382
|
+
* copies of one node can resolve different models and retry independently. Keeping the
|
|
383
|
+
* accumulation per identity means a switch simply displays the new identity's own average,
|
|
384
|
+
* and returning to an earlier one resumes the average it built.
|
|
385
|
+
*/
|
|
386
|
+
speedMeters = new Map();
|
|
387
|
+
/** The executor's `invocationId` → the meter key whose marker opened that request's window. */
|
|
388
|
+
speedInvocations = new Map();
|
|
389
|
+
/** The node whose requests the readout currently follows: the most recent to open a call. */
|
|
390
|
+
activeSpeedNode;
|
|
391
|
+
/** The parallel copy of {@link activeSpeedNode} the readout follows, when one is named. */
|
|
392
|
+
activeSpeedCopy;
|
|
393
|
+
/** The exact meter key the readout displays - a node, a node's copy, or a distillation. */
|
|
394
|
+
activeSpeedKey;
|
|
395
|
+
handleRuntimeEvent(event) {
|
|
396
|
+
if (this.closed)
|
|
397
|
+
return;
|
|
398
|
+
this.dashboardMetrics.handle(event);
|
|
399
|
+
if (event.type === 'agent.session.started' && !event.data.subagentId) {
|
|
400
|
+
const session = event.data;
|
|
401
|
+
const nodeId = session.nodeId, provider = session.provider, model = session.model;
|
|
402
|
+
if (typeof nodeId !== 'string' || (typeof provider !== 'string' && typeof model !== 'string'))
|
|
403
|
+
return;
|
|
404
|
+
const providerLabel = typeof provider === 'string' ? oneLine(provider) : undefined;
|
|
405
|
+
const modelLabel = typeof model === 'string' ? oneLine(model) : undefined;
|
|
406
|
+
const effort = typeof session.reasoningEffort === 'string' ? oneLine(session.reasoningEffort) : undefined;
|
|
407
|
+
if (providerLabel !== undefined && modelLabel !== undefined)
|
|
408
|
+
this.nodeModels.set(nodeId, oneLine(`${providerLabel}/${modelLabel}`));
|
|
409
|
+
// The executor re-announces a node's resolution when a whole-agent retry falls back to
|
|
410
|
+
// the node's other profile: same nodeId, different provider, model or effort. The
|
|
411
|
+
// accumulated average measured the previous resolution, so it is rebuilt from zero
|
|
412
|
+
// under the new one - while a repeat of the same resolution, which every ordinary run
|
|
413
|
+
// emits, keeps it. Parallel copies carry their own `copy` number, so one copy's
|
|
414
|
+
// fallback never resets a sibling copy still running on the primary model.
|
|
415
|
+
this.stampSpeedMeter(this.speedKey(nodeId, typeof session.copy === 'number' ? session.copy : undefined), providerLabel, modelLabel, effort);
|
|
416
|
+
}
|
|
417
|
+
if (event.type.startsWith('dashboard.'))
|
|
418
|
+
this.scheduleRender();
|
|
419
|
+
this.toolClock.accept(event);
|
|
420
|
+
this.updateToolClock();
|
|
421
|
+
if (event.type.startsWith('node.tool.'))
|
|
422
|
+
this.scheduleRender();
|
|
423
|
+
const data = event.data;
|
|
424
|
+
// The executor emits `agent.turn.started` and `agent.iteration.started` back-to-back
|
|
425
|
+
// around one model call (`src/hardened-runtime.ts`), so they are aliases of a single
|
|
426
|
+
// boundary: opening a window for both would queue two per request, and since a completion
|
|
427
|
+
// closes only one, the leftover start would be consumed by a *later* completion and every
|
|
428
|
+
// reading would age against an ever-longer window. `iteration.started` is the marker every
|
|
429
|
+
// other consumer already uses, so it alone opens the window the main call's tokens spread
|
|
430
|
+
// across. Context compaction runs its own model calls between iterations and emits no
|
|
431
|
+
// iteration marker (the next one belongs to the main request): its batch-level start
|
|
432
|
+
// event opens the first window, and because a rejected summary attempt has already spent
|
|
433
|
+
// that window on its usage, every attempt re-emits
|
|
434
|
+
// `agent.context.compaction.attempt.started` so the retry gets a fresh one. All of these
|
|
435
|
+
// events carry the executor's `invocationId`, and the same id names the request on its
|
|
436
|
+
// usage delta, so each window is keyed by it: concurrent requests (branch workers,
|
|
437
|
+
// parallel copies, subagents) completing out of order each spread over their own window
|
|
438
|
+
// instead of the oldest one still open.
|
|
439
|
+
// Goal verification calls the adapter outside every iteration marker with this run's
|
|
440
|
+
// invocationId - the id whose iteration window the main response already closed - so its
|
|
441
|
+
// own boundary re-opens the key and its completion spreads over the verification request
|
|
442
|
+
// instead of the one-second synthetic fallback, whose false spike would then be held.
|
|
443
|
+
if (event.type === 'agent.iteration.started' || event.type === 'agent.context.compaction.started' || event.type === 'agent.context.compaction.attempt.started' || event.type === 'agent.completion.verification.started') {
|
|
444
|
+
// The speed readout averages one generating identity at a time. Every marker above
|
|
445
|
+
// carries the `nodeId` the emit wrapper stamped on it - and, inside a parallel copy,
|
|
446
|
+
// the `copy` number the modifier added - so the readout follows the copy generating
|
|
447
|
+
// now, and because the accumulation lives per identity a switch neither wipes the
|
|
448
|
+
// previous one's totals nor its still-open request window.
|
|
449
|
+
const nodeId = typeof data.nodeId === 'string' ? data.nodeId : 'engineer';
|
|
450
|
+
const invocationId = typeof data.invocationId === 'string' ? data.invocationId : undefined;
|
|
451
|
+
const copy = typeof data.copy === 'number' ? data.copy : undefined;
|
|
452
|
+
const key = this.speedKey(nodeId, copy);
|
|
453
|
+
const entry = this.ensureSpeedMeter(key);
|
|
454
|
+
this.activeSpeedNode = nodeId;
|
|
455
|
+
this.activeSpeedCopy = copy;
|
|
456
|
+
this.activeSpeedKey = key;
|
|
457
|
+
if (invocationId !== undefined) {
|
|
458
|
+
this.speedInvocations.set(invocationId, key);
|
|
459
|
+
while (this.speedInvocations.size > 64) {
|
|
460
|
+
const oldest = this.speedInvocations.keys().next();
|
|
461
|
+
if (oldest.done)
|
|
462
|
+
break;
|
|
463
|
+
this.speedInvocations.delete(oldest.value);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
entry.meter.beginRequest(invocationId);
|
|
467
|
+
// The focus moved: the node row and the speed readout now describe another copy or node, so
|
|
468
|
+
// the frame is repainted even though no token reading has arrived yet.
|
|
469
|
+
this.scheduleRender();
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
// Memory distillation calls the adapter directly, outside every executor marker, so the
|
|
473
|
+
// dashboard adapter's start event is the only boundary it emits. Its metadata names the
|
|
474
|
+
// operation and carries the invocation id the distiller stamps on its usage deltas, plus
|
|
475
|
+
// the provider and model that actually perform it - finalization runs on the graph's own
|
|
476
|
+
// resolution, not inside any node's iteration, so without a nodeId of its own it is keyed
|
|
477
|
+
// by that resolution instead of whichever node generated last. Main model calls also pass
|
|
478
|
+
// through the dashboard adapter but are already covered by their iteration marker, so
|
|
479
|
+
// only the distillation operation opens a window here.
|
|
480
|
+
if (event.type === 'dashboard.model.started' && data.operation === 'memory.distillation') {
|
|
481
|
+
const invocationId = typeof data.invocationId === 'string' ? data.invocationId : undefined;
|
|
482
|
+
const provider = typeof data.provider === 'string' ? oneLine(data.provider) : undefined;
|
|
483
|
+
const model = typeof data.model === 'string' ? oneLine(data.model) : undefined;
|
|
484
|
+
const key = typeof data.nodeId === 'string' ? this.speedKey(data.nodeId, undefined)
|
|
485
|
+
: provider !== undefined || model !== undefined ? `distillation ${provider ?? '?'}/${model ?? '?'}`
|
|
486
|
+
: this.speedKey(this.activeSpeedNode ?? 'engineer', this.activeSpeedCopy);
|
|
487
|
+
if (invocationId !== undefined)
|
|
488
|
+
this.speedInvocations.set(invocationId, key);
|
|
489
|
+
const entry = this.ensureSpeedMeter(key);
|
|
490
|
+
if (provider !== undefined)
|
|
491
|
+
entry.provider = provider;
|
|
492
|
+
if (model !== undefined)
|
|
493
|
+
entry.model = model;
|
|
494
|
+
entry.meter.beginRequest(invocationId);
|
|
495
|
+
// Distillation is work the user can watch decode: the readout follows the meter that
|
|
496
|
+
// performed it, whether or not an iteration marker already named one.
|
|
497
|
+
this.activeSpeedKey = key;
|
|
498
|
+
if (typeof data.nodeId === 'string') {
|
|
499
|
+
this.activeSpeedNode = data.nodeId;
|
|
500
|
+
this.activeSpeedCopy = undefined;
|
|
501
|
+
}
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
// Run boundaries no longer reset the speed readout: each node's cumulative average stays
|
|
505
|
+
// up across runs, and the readout simply follows whichever node generates next.
|
|
506
|
+
if (['graph.started', 'graph.completed', 'graph.stopped'].includes(event.type)) {
|
|
507
|
+
this.activeNodes.clear();
|
|
508
|
+
// The trail belongs to the run that walked it, and so does the position it stopped at:
|
|
509
|
+
// a new run starts over from its own entry.
|
|
510
|
+
if (event.type === 'graph.started') {
|
|
511
|
+
this.visitedNodes.clear();
|
|
512
|
+
this.stoppedNode = undefined;
|
|
513
|
+
}
|
|
514
|
+
// A run that was cancelled, exhausted or failed names the node it stopped on. That node
|
|
515
|
+
// never completes, so without keeping it the zoom would show the last completed
|
|
516
|
+
// predecessor as the position and the node the run actually died on as untouched.
|
|
517
|
+
if (event.type === 'graph.stopped')
|
|
518
|
+
this.stoppedNode = typeof data.nodeId === 'string' ? data.nodeId : undefined;
|
|
519
|
+
this.scheduleRender();
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
if (typeof data.nodeId !== 'string')
|
|
523
|
+
return;
|
|
524
|
+
if (event.type === 'graph.node.completed') {
|
|
525
|
+
this.activeNodes.delete(data.nodeId);
|
|
526
|
+
// A node reached twice (a bounded cycle) is moved to the end of the trail rather than left
|
|
527
|
+
// where it was first inserted: the set's order is the visit order the panel's focus reads,
|
|
528
|
+
// so a repeated visit has to be the last one recorded even though the id stays unique.
|
|
529
|
+
this.visitedNodes.delete(data.nodeId);
|
|
530
|
+
this.visitedNodes.add(data.nodeId);
|
|
531
|
+
this.scheduleRender();
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
// The executor reports the provider and model a node is actually running on, including the
|
|
535
|
+
// profile a retry falls back to, so the footer follows a mid-node switch. A delegated child
|
|
536
|
+
// repeats its parent's nodeId, and an ordinary prompt run reports the synthetic 'engineer'
|
|
537
|
+
// id with no graph node behind it, so only a node the graph already reported as started is
|
|
538
|
+
// updated: nothing else may put a node name on the footer.
|
|
539
|
+
if (event.type === 'agent.session.started') {
|
|
540
|
+
const progress = this.activeNodes.get(data.nodeId);
|
|
541
|
+
if (!progress || typeof data.subagentId === 'string')
|
|
542
|
+
return;
|
|
543
|
+
const provider = typeof data.provider === 'string' ? oneLine(data.provider) : undefined;
|
|
544
|
+
const model = typeof data.model === 'string' ? oneLine(data.model) : undefined;
|
|
545
|
+
if (!provider && !model)
|
|
546
|
+
return;
|
|
547
|
+
// The CLI adds the effort and window of that same resolution (`withNodeModelResolution` in
|
|
548
|
+
// cli.ts). `contextWindow` being present at all - even as undefined - marks the node's own
|
|
549
|
+
// resolution as authoritative, so its unknown window cannot inherit the session's.
|
|
550
|
+
const resolved = Object.hasOwn(data, 'contextWindow')
|
|
551
|
+
? { reasoningEffort: typeof data.reasoningEffort === 'string' ? oneLine(data.reasoningEffort) : undefined,
|
|
552
|
+
contextWindow: typeof data.contextWindow === 'number' && Number.isFinite(data.contextWindow) && data.contextWindow > 0 ? data.contextWindow : undefined }
|
|
553
|
+
: progress.resolved;
|
|
554
|
+
// Parallel copies of one node can resolve different profiles - one falls back while another
|
|
555
|
+
// stays on the primary model - so the resolution is kept per copy as well as for the node:
|
|
556
|
+
// the last announcement must not become the whole node's model.
|
|
557
|
+
const copiesResolved = new Map(progress.copiesResolved ?? []);
|
|
558
|
+
const copyIndex = typeof data.copy === 'number' ? data.copy : 0;
|
|
559
|
+
// The copy keeps the *complete* resolution it announced - effort and window alongside the
|
|
560
|
+
// provider and model - because the footer names one model, and a copy's thinking settings
|
|
561
|
+
// belong to that same resolution: inheriting the node's would describe this copy with a
|
|
562
|
+
// sibling's effort, which the rate comparison then reads as a mismatch and suppresses.
|
|
563
|
+
const ownResolution = Object.hasOwn(data, 'contextWindow')
|
|
564
|
+
? resolved
|
|
565
|
+
: typeof data.reasoningEffort === 'string' ? { reasoningEffort: oneLine(data.reasoningEffort), contextWindow: undefined } : undefined;
|
|
566
|
+
copiesResolved.set(copyIndex, {
|
|
567
|
+
...copiesResolved.get(copyIndex),
|
|
568
|
+
...(provider ? { provider } : {}), ...(model ? { model } : {}),
|
|
569
|
+
...(ownResolution ? { resolved: ownResolution } : {}),
|
|
570
|
+
});
|
|
571
|
+
this.activeNodes.set(data.nodeId, { ...progress, provider: provider ?? progress.provider, model: model ?? progress.model, resolved, copiesResolved });
|
|
572
|
+
this.scheduleRender();
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (!['graph.node.started', 'agent.modifier.iteration.started', 'agent.modifier.copy.started', 'agent.modifier.copy.completed'].includes(event.type))
|
|
576
|
+
return;
|
|
577
|
+
const progress = this.activeNodes.get(data.nodeId) ?? { name: oneLine(String(data.nodeName ?? this.status.graph?.nodes[data.nodeId]?.name ?? data.nodeId)), copies: new Set() };
|
|
578
|
+
if (event.type === 'agent.modifier.iteration.started' && typeof data.iteration === 'number' && typeof data.maxIterations === 'number' && data.maxIterations > 1)
|
|
579
|
+
progress.loop = `loop ${data.iteration}/${data.maxIterations}`;
|
|
580
|
+
if (typeof data.copy === 'number' && typeof data.copies === 'number' && data.copies > 1) {
|
|
581
|
+
progress.totalCopies = data.copies;
|
|
582
|
+
if (event.type === 'agent.modifier.copy.started')
|
|
583
|
+
progress.copies.add(data.copy);
|
|
584
|
+
else
|
|
585
|
+
progress.copies.delete(data.copy);
|
|
586
|
+
}
|
|
587
|
+
this.activeNodes.set(data.nodeId, progress);
|
|
588
|
+
this.scheduleRender();
|
|
589
|
+
}
|
|
590
|
+
nodeProgress() {
|
|
591
|
+
const nodes = [...this.activeNodes.values()];
|
|
592
|
+
return nodes.slice(0, 2).map(node => [node.name, node.loop, node.copies.size ? `copy ${[...node.copies].sort((a, b) => a - b).join(',')}/${node.totalCopies}` : ''].filter(Boolean).join(' - ')).join(' + ') + (nodes.length > 2 ? ` +${nodes.length - 2} more` : '');
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* The columns the chat column actually draws in, panel and gutter excluded.
|
|
596
|
+
*
|
|
597
|
+
* Everything that measures chat content outside the render pass - input navigation, the
|
|
598
|
+
* echoed-prompt frame, the docked selection card, the command popup's own visibility gate -
|
|
599
|
+
* has to measure against this rather than the terminal width, or a draft that the composer
|
|
600
|
+
* wrapped onto two rows is treated as one by the arrow keys, and a stored card is built
|
|
601
|
+
* wider than the transcript that must re-wrap it.
|
|
602
|
+
*/
|
|
603
|
+
chatColumns() {
|
|
604
|
+
const columns = Math.max(1, this.output.columns || 80), height = Math.max(1, this.output.rows || 24);
|
|
605
|
+
const panel = this.panelColumns(columns, height);
|
|
606
|
+
return Math.max(1, columns - panel - (panel ? 1 : 0));
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Columns the transcript itself would have with the panel drawn.
|
|
610
|
+
*
|
|
611
|
+
* A prompt echo is stored in the transcript and re-wrapped there, so its frame has to be built for
|
|
612
|
+
* that column rather than for whatever surface is on screen when the text is submitted: a task sent
|
|
613
|
+
* from the Ctrl+B dashboard (or from a modal) would otherwise freeze a full-width box whose rows the
|
|
614
|
+
* transcript splits as soon as the panel returns. This is `chatColumns()` with the two full-screen
|
|
615
|
+
* surfaces ignored.
|
|
616
|
+
*/
|
|
617
|
+
transcriptColumns() {
|
|
618
|
+
const columns = Math.max(1, this.output.columns || 80), height = Math.max(1, this.output.rows || 24);
|
|
619
|
+
const panel = columns < PANEL_MIN_COLUMNS || height < PANEL_MIN_ROWS ? 0 : panelWidth(columns);
|
|
620
|
+
return Math.max(1, columns - panel - (panel ? 1 : 0));
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Columns the side panel occupies this frame, or 0 when it is not drawn.
|
|
624
|
+
*
|
|
625
|
+
* The panel is a second column of the same frame, so its width has to be known before the
|
|
626
|
+
* chat column renders: below {@link PANEL_MIN_COLUMNS} the chat column would be squeezed
|
|
627
|
+
* past the point where its own wrapping and the command popup still read well, and the two
|
|
628
|
+
* full-screen surfaces - the dashboard (which already reports the same state) and a modal
|
|
629
|
+
* screen (which is a focused flow) - keep the frame to themselves.
|
|
630
|
+
*/
|
|
631
|
+
/**
|
|
632
|
+
* Whether the side panel is on screen for the current terminal and surface.
|
|
633
|
+
*
|
|
634
|
+
* Exposed because the panel is the only consumer of the CLI's Git summary: a caller that would
|
|
635
|
+
* spawn processes to fill it can ask first, and skip the work while nothing can display it.
|
|
636
|
+
*/
|
|
637
|
+
panelVisible() {
|
|
638
|
+
return this.panelColumns(Math.max(1, this.output.columns || 80), Math.max(1, this.output.rows || 24)) > 0;
|
|
639
|
+
}
|
|
640
|
+
panelColumns(width, height) {
|
|
641
|
+
if (this.dashboard || this.modal || width < PANEL_MIN_COLUMNS || height < PANEL_MIN_ROWS)
|
|
642
|
+
return 0;
|
|
643
|
+
return panelWidth(width);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* The side panel's rows for this frame.
|
|
647
|
+
*
|
|
648
|
+
* Assembled per render rather than cached: the rows carry a clock (how long a background
|
|
649
|
+
* terminal has been running) and follow the node set the run is publishing, and the packing
|
|
650
|
+
* only ever walks a handful of sections.
|
|
651
|
+
* @param columns - total columns the panel occupies, divider and gutter included.
|
|
652
|
+
* @param height - rows the panel may use, the whole frame height.
|
|
653
|
+
*/
|
|
654
|
+
panelRows(columns, height) {
|
|
655
|
+
if (!columns)
|
|
656
|
+
return [];
|
|
657
|
+
const entries = [...this.activeNodes.entries()];
|
|
658
|
+
// The node the reader is watching - the one the speed readout follows - leads the section,
|
|
659
|
+
// and the rest follow so a parallel run still names every node that is working.
|
|
660
|
+
const focus = this.activeSpeedNode !== undefined && this.activeNodes.has(this.activeSpeedNode) ? this.activeSpeedNode : entries[0]?.[0];
|
|
661
|
+
const nodes = entries
|
|
662
|
+
.sort(([left], [right]) => (left === focus ? -1 : right === focus ? 1 : 0))
|
|
663
|
+
.map(([id, node]) => {
|
|
664
|
+
const detail = [node.loop, node.copies.size ? `copy ${[...node.copies].sort((a, b) => a - b).join(',')}/${node.totalCopies}` : ''].filter(Boolean).join(' · ');
|
|
665
|
+
// The row describes the copy the reader is watching: when the speed readout follows a
|
|
666
|
+
// parallel copy, that copy's own resolution is the one to name - another copy's fallback
|
|
667
|
+
// must not be reported as this one's model.
|
|
668
|
+
const perCopy = id === focus && this.activeSpeedCopy !== undefined ? node.copiesResolved?.get(this.activeSpeedCopy) : undefined;
|
|
669
|
+
const provider = perCopy?.provider ?? node.provider;
|
|
670
|
+
const model = perCopy?.model ?? node.model;
|
|
671
|
+
const label = provider !== undefined || model !== undefined ? `${provider ?? this.status.provider} / ${model ?? this.status.model}` : '';
|
|
672
|
+
return { id, name: node.name, ...(detail ? { detail } : {}), ...(label ? { model: label } : {}) };
|
|
673
|
+
});
|
|
674
|
+
return sidePanelRows({
|
|
675
|
+
branch: this.status.branch,
|
|
676
|
+
changes: this.status.changes,
|
|
677
|
+
nodes,
|
|
678
|
+
graph: this.status.graph,
|
|
679
|
+
customGraph: isCustomGraph(this.status.graphSelection, this.status.graph),
|
|
680
|
+
visited: [...this.visitedNodes],
|
|
681
|
+
...(this.stoppedNode ? { stoppedNode: this.stoppedNode } : {}),
|
|
682
|
+
todos: this.todos,
|
|
683
|
+
terminals: this.status.terminals ?? [],
|
|
684
|
+
now: this.tokenClock ? this.tokenClock() : Date.now(),
|
|
685
|
+
}, Math.max(8, columns - 2), height);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Compose the chat column's rows with the panel's into the frame's rows.
|
|
689
|
+
*
|
|
690
|
+
* Each row is padded to the chat width so the divider column stays unbroken, then carries
|
|
691
|
+
* the panel cell for that row. A painted row is measured with `stringWidth`, which ignores
|
|
692
|
+
* escape sequences, so padding cannot be confused by the color the chat row already holds.
|
|
693
|
+
*/
|
|
694
|
+
composePanel(lines, rows, columns, chatWidth) {
|
|
695
|
+
if (!columns)
|
|
696
|
+
return lines;
|
|
697
|
+
const divider = paint('│', FAINT);
|
|
698
|
+
return Array.from({ length: Math.max(lines.length, rows.length) }, (_, index) => {
|
|
699
|
+
const left = lines[index] ?? '';
|
|
700
|
+
const size = stringWidth(left);
|
|
701
|
+
const padded = size >= chatWidth ? left : left + ' '.repeat(chatWidth - size);
|
|
702
|
+
const cell = rows[index];
|
|
703
|
+
const text = cell ? cell.segments.map(segment => paint(segment.text, segment.color ?? GRAY)).join('') : '';
|
|
704
|
+
return padded + (text ? ` ${divider} ${text}` : ` ${divider}`);
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* The model currently answering, as its footer label plus the thinking effort and context window
|
|
709
|
+
* that belong to it.
|
|
710
|
+
*
|
|
711
|
+
* While a graph node is active this names the node the user is watching - the one whose
|
|
712
|
+
* requests the speed readout follows, or the first-started one when no speed identity is
|
|
713
|
+
* named - followed by the provider and model that node actually resolved and by the effort
|
|
714
|
+
* and window of that same resolution, so the whole line describes one model. With no active
|
|
715
|
+
* node it is the session's own selection, and no node is named for an idle prompt or for a
|
|
716
|
+
* plain run that never started a graph node.
|
|
717
|
+
*/
|
|
718
|
+
activeModel() {
|
|
719
|
+
const node = this.displayNode();
|
|
720
|
+
if (!node)
|
|
721
|
+
return { label: oneLine(`${this.status.provider} / ${this.status.model}`), reasoningEffort: this.status.reasoningEffort, contextWindow: this.status.contextWindow };
|
|
722
|
+
const more = this.activeNodes.size > 1 ? ` +${this.activeNodes.size - 1} more` : '';
|
|
723
|
+
// The row names the copy the readout follows, so it names that copy's resolution too: two
|
|
724
|
+
// copies of one node can run different profiles, and the last announcement is not the model
|
|
725
|
+
// generating now.
|
|
726
|
+
const perCopy = this.activeSpeedCopy !== undefined ? node.copiesResolved?.get(this.activeSpeedCopy) : undefined;
|
|
727
|
+
const provider = perCopy?.provider ?? node.provider ?? this.status.provider;
|
|
728
|
+
const model = perCopy?.model ?? node.model ?? this.status.model;
|
|
729
|
+
// The whole line describes one resolution: when the followed copy announced its own, that one
|
|
730
|
+
// answers for the effort and the window too, not the node's last announcement from a sibling.
|
|
731
|
+
const resolved = perCopy?.resolved ?? node.resolved;
|
|
732
|
+
return {
|
|
733
|
+
label: oneLine(`${node.name}${more} · ${provider} / ${model}`),
|
|
734
|
+
reasoningEffort: resolved ? resolved.reasoningEffort : this.status.reasoningEffort,
|
|
735
|
+
contextWindow: resolved ? resolved.contextWindow : this.status.contextWindow,
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
started = false;
|
|
739
|
+
closed = false;
|
|
740
|
+
wasRaw = false;
|
|
741
|
+
wasPaused = false;
|
|
742
|
+
scheduled = false;
|
|
743
|
+
pending;
|
|
744
|
+
value = [];
|
|
745
|
+
cursor = 0;
|
|
746
|
+
transcript = new PagedTranscript();
|
|
747
|
+
expandedTranscript = false;
|
|
748
|
+
todos = [];
|
|
749
|
+
expandedTodos = false;
|
|
750
|
+
todoOffset = 0;
|
|
751
|
+
todoPageSize = 0;
|
|
752
|
+
scroll = 0;
|
|
753
|
+
/** Whether a run is streaming: with no prompt pending, the wheel may scroll the transcript. */
|
|
754
|
+
runActive = false;
|
|
755
|
+
/**
|
|
756
|
+
* Whether alternate scroll mode (?1007) is currently armed.
|
|
757
|
+
*
|
|
758
|
+
* The app never takes mouse reporting, so the terminal keeps drag-to-select and its
|
|
759
|
+
* clipboard in every state. In the alternate screen a terminal instead turns the wheel
|
|
760
|
+
* into Up/Down sequences when alternate scroll is on — byte-identical to the arrow keys,
|
|
761
|
+
* and on by default in Windows Terminal, VTE and iTerm2 — so the app arms that mode only
|
|
762
|
+
* where Up/Down cannot recall history: while a screen is open, or while a run streams with
|
|
763
|
+
* no question pending. At the resting prompt it is switched off and the wheel is inert.
|
|
764
|
+
*/
|
|
765
|
+
alternateScroll = false;
|
|
766
|
+
/**
|
|
767
|
+
* Live reasoning preview state. `thinkingActive` marks a stream in progress; the text
|
|
768
|
+
* is the bounded tail the preview renders from.
|
|
769
|
+
*/
|
|
770
|
+
thinking = '';
|
|
771
|
+
thinkingActive = false;
|
|
772
|
+
/** The preview opens expanded on every stream; Ctrl+Y collapses the current one. */
|
|
773
|
+
thinkingExpanded = true;
|
|
774
|
+
expandedPromptIds = new Set();
|
|
775
|
+
/** Prompts the reader explicitly collapsed; an explicit toggle wins over Ctrl+O (see promptExpanded). */
|
|
776
|
+
collapsedPromptIds = new Set();
|
|
777
|
+
/** Every prompt box the transcript currently holds, so Ctrl+O can invert each one on screen. */
|
|
778
|
+
promptBoxIds = new Set();
|
|
779
|
+
expandedPromptVisible = false;
|
|
780
|
+
nextPromptId = 1;
|
|
781
|
+
thinkingPaintedAt = 0;
|
|
782
|
+
thinkingFlush;
|
|
783
|
+
/**
|
|
784
|
+
* The rows currently on screen, so a repaint can rewrite only what changed.
|
|
785
|
+
*
|
|
786
|
+
* See {@link writeFrame}: a terminal drops an in-progress drag selection when the app
|
|
787
|
+
* rewrites the cells under it, and a run repaints eight times a second for its animation.
|
|
788
|
+
*/
|
|
789
|
+
drawn = [];
|
|
790
|
+
/** Terminal size `drawn` was produced at; a resize invalidates the comparison. */
|
|
791
|
+
drawnSize = '';
|
|
792
|
+
/** The caret sequence last emitted, so an unmoved caret costs no extra write. */
|
|
793
|
+
drawnCursor = '';
|
|
794
|
+
history = [];
|
|
795
|
+
historyIndex = 0;
|
|
796
|
+
draft = '';
|
|
797
|
+
completion;
|
|
798
|
+
dismissedCompletion;
|
|
799
|
+
incoming = '';
|
|
800
|
+
pasting = false;
|
|
801
|
+
paste = '';
|
|
802
|
+
pasteQuestion;
|
|
803
|
+
plainTimer;
|
|
804
|
+
pendingBreak = '';
|
|
805
|
+
plainPaste = false;
|
|
806
|
+
plainTrailingCR = false;
|
|
807
|
+
plainQuestion;
|
|
808
|
+
modal;
|
|
809
|
+
modalInput = false;
|
|
810
|
+
/**
|
|
811
|
+
* The last selection screen that was answered.
|
|
812
|
+
*
|
|
813
|
+
* Setup closes a selection screen and then asks for a value, which used to leave the home
|
|
814
|
+
* card where the list had been: the reader lost both the list and the entry it led to the
|
|
815
|
+
* moment they started typing. The card is kept here so a typed field can be answered with
|
|
816
|
+
* the list still on screen (see selectionCard).
|
|
817
|
+
*/
|
|
818
|
+
lastSelection;
|
|
819
|
+
escapeTimer;
|
|
820
|
+
workingTimer;
|
|
821
|
+
/** The panel's one-second age clock; see render(). */
|
|
822
|
+
panelTimer;
|
|
823
|
+
workingSince;
|
|
824
|
+
workingElapsed = 0;
|
|
825
|
+
/**
|
|
826
|
+
* Whether the composer accepts input while a run is active.
|
|
827
|
+
*
|
|
828
|
+
* Enabled for the duration of an interactive run so the user can steer it. Text
|
|
829
|
+
* submitted in this mode is queued rather than resolved as a question answer.
|
|
830
|
+
*/
|
|
831
|
+
steering = false;
|
|
832
|
+
runInputHandler;
|
|
833
|
+
localCommandHandler;
|
|
834
|
+
commandInput = false;
|
|
835
|
+
/** Handle active commands and resumed direction synchronously; true consumes the input. */
|
|
836
|
+
setRunInputHandler(handler) { this.runInputHandler = handler; }
|
|
837
|
+
/** Observe slash commands consumed by the view without submitting them to the run. */
|
|
838
|
+
setLocalCommandHandler(handler) { this.localCommandHandler = handler; }
|
|
839
|
+
/** Settle the current approval after an explicit session permission change. */
|
|
840
|
+
resolveQuestion(value) {
|
|
841
|
+
const pending = this.pending;
|
|
842
|
+
if (!pending)
|
|
843
|
+
return;
|
|
844
|
+
this.finishQuestion();
|
|
845
|
+
pending.resolve(value);
|
|
846
|
+
this.scheduleRender();
|
|
847
|
+
}
|
|
848
|
+
/** Submit from the browser only while the terminal is accepting a conversation prompt. */
|
|
849
|
+
acceptConversationPrompt(value) {
|
|
850
|
+
if (!this.pending?.conversationPrompt || this.modal)
|
|
851
|
+
return false;
|
|
852
|
+
this.resolveQuestion(value);
|
|
853
|
+
return true;
|
|
854
|
+
}
|
|
855
|
+
/** Current runtime question for connected GUI surfaces. Conversation prompts stay in the composer. */
|
|
856
|
+
browserPendingIdentity;
|
|
857
|
+
browserQuestionNumber = 0;
|
|
858
|
+
browserQuestion() {
|
|
859
|
+
const pending = this.pending;
|
|
860
|
+
if (!pending || pending.conversationPrompt)
|
|
861
|
+
return undefined;
|
|
862
|
+
if (pending !== this.browserPendingIdentity) {
|
|
863
|
+
this.browserPendingIdentity = pending;
|
|
864
|
+
this.browserQuestionNumber++;
|
|
865
|
+
}
|
|
866
|
+
const question = pending.dashboardQuestion || pending.choiceTitle || pending.title || pending.label;
|
|
867
|
+
return { id: `terminal-${this.browserQuestionNumber}`, kind: pending.kind, question, approvalDetailsRequired: pending.kind === 'approval', approvalDetails: pending.approvalDetails, choices: pending.choices?.map(item => ({ id: item.id, label: item.label })) };
|
|
868
|
+
}
|
|
869
|
+
steered = [];
|
|
870
|
+
/**
|
|
871
|
+
* Attachments queued in the composer draft — large pastes spooled to text, dropped file
|
|
872
|
+
* paths, clipboard images. Each sits in the draft as an inline token (its `marker` code
|
|
873
|
+
* point), drawn as an amber label and edited as one character. They ride the next submitted
|
|
874
|
+
* task (or the next queued steer) and are drained by the CLI, mirroring how `steered` is
|
|
875
|
+
* drained at turn boundaries.
|
|
876
|
+
*/
|
|
877
|
+
attachments = [];
|
|
878
|
+
attachmentSeq = 0;
|
|
879
|
+
/**
|
|
880
|
+
* Generation of the composer's attachment surface. Advanced by every draft clear and steer
|
|
881
|
+
* submission: an asynchronous clipboard probe that started before one of those lands nowhere,
|
|
882
|
+
* because the composer it was reading for is gone (steering keeps the same owner all run).
|
|
883
|
+
*/
|
|
884
|
+
clipboardProbe = 0;
|
|
885
|
+
clipboardImageProbe;
|
|
886
|
+
clipboardTextWriter;
|
|
887
|
+
/**
|
|
888
|
+
* Where the composer's Shift+Arrow selection started; it runs from here to the cursor.
|
|
889
|
+
* `selectionValue` is the draft it was made in: replacing the draft (a submission, history
|
|
890
|
+
* recall, a completion) swaps the array, which drops the selection without bookkeeping.
|
|
891
|
+
*/
|
|
892
|
+
selectionAnchor;
|
|
893
|
+
selectionValue;
|
|
894
|
+
/**
|
|
895
|
+
* A half-typed steer parked while a question temporarily takes the composer.
|
|
896
|
+
*
|
|
897
|
+
* Questions and steering share `value`; without this a partially typed steer would be
|
|
898
|
+
* wiped the moment the runtime asks for an approval or clarification.
|
|
899
|
+
*/
|
|
900
|
+
steerDraft;
|
|
901
|
+
steerCursor = 0;
|
|
902
|
+
constructor(options) {
|
|
903
|
+
super();
|
|
904
|
+
this.input = options.input ?? process.stdin;
|
|
905
|
+
this.output = options.output ?? process.stdout;
|
|
906
|
+
this.workspace = oneLine(options.workspace);
|
|
907
|
+
this.version = oneLine(options.version);
|
|
908
|
+
this.appName = oneLine(options.appName ?? 'ANDORRA CODE');
|
|
909
|
+
this.status = { ...options };
|
|
910
|
+
this.tokenClock = options.tokenClock;
|
|
911
|
+
this.clipboardImageProbe = options.clipboardImageProbe;
|
|
912
|
+
this.clipboardTextWriter = options.clipboardTextWriter;
|
|
913
|
+
emitKeypressEvents(this.keys);
|
|
914
|
+
this.keys.on('keypress', this.onKey);
|
|
915
|
+
}
|
|
916
|
+
start() {
|
|
917
|
+
if (this.closed)
|
|
918
|
+
throw new Error('Terminal is closed');
|
|
919
|
+
if (this.started)
|
|
920
|
+
return;
|
|
921
|
+
this.wasRaw = this.input.isRaw;
|
|
922
|
+
this.wasPaused = this.input.readableFlowing !== true;
|
|
923
|
+
this.input.setRawMode?.(true);
|
|
924
|
+
this.input.ref?.();
|
|
925
|
+
this.started = true;
|
|
926
|
+
this.input.on('data', this.onData);
|
|
927
|
+
this.input.on('end', this.onEnd);
|
|
928
|
+
this.output.on('resize', this.onResize);
|
|
929
|
+
this.input.resume();
|
|
930
|
+
// The app never takes mouse reporting (?1000h/?1006h): the terminal keeps its own
|
|
931
|
+
// drag-to-select and clipboard in every state, at rest and while a run streams alike, with
|
|
932
|
+
// no modifier bypass to learn. What the wheel does is governed by alternate scroll mode
|
|
933
|
+
// (?1007) instead. In the alternate screen a terminal with that mode on turns the wheel
|
|
934
|
+
// into Up/Down sequences byte-identical to the arrow keys, and Windows Terminal, VTE and
|
|
935
|
+
// iTerm2 have it on by default — which is how an uncaptured wheel once recalled the
|
|
936
|
+
// previous prompt. The mode is therefore switched off explicitly here, and
|
|
937
|
+
// `updateAlternateScroll` arms it only where Up/Down cannot reach history: while a
|
|
938
|
+
// screen is open (its keys scroll or move the highlight) or while a run streams with no
|
|
939
|
+
// question pending (Up/Down scroll the transcript, see onKey). At the resting prompt the
|
|
940
|
+
// wheel is inert and Up/Down stay purely keyboard: input history, or cursor movement in a
|
|
941
|
+
// draft. The collapsed long-prompt boxes open with Ctrl+O and the live reasoning preview
|
|
942
|
+
// toggles with Ctrl+Y; neither needs a click. writeFrame only rewrites rows that changed,
|
|
943
|
+
// so the working animation does not repaint cells under a drag selection either. Entering
|
|
944
|
+
// the alternate screen blanks it, so nothing drawn before is still there to diff.
|
|
945
|
+
this.drawn = [];
|
|
946
|
+
this.drawnSize = '';
|
|
947
|
+
this.drawnCursor = '';
|
|
948
|
+
this.output.write('\x1b[?1049h\x1b[?2004h\x1b[?25l\x1b[?1007l');
|
|
949
|
+
this.alternateScroll = false;
|
|
950
|
+
this.updateAlternateScroll();
|
|
951
|
+
this.render();
|
|
952
|
+
}
|
|
953
|
+
question(prompt = '', options = {}) {
|
|
954
|
+
if (this.closed)
|
|
955
|
+
return Promise.reject(new Error('Terminal is closed'));
|
|
956
|
+
if (this.pending)
|
|
957
|
+
return Promise.reject(new Error('A terminal question is already active'));
|
|
958
|
+
if (this.modal)
|
|
959
|
+
return Promise.reject(new Error('A terminal screen is already active'));
|
|
960
|
+
if (options.signal?.aborted)
|
|
961
|
+
return Promise.reject(new DOMException('Question aborted', 'AbortError'));
|
|
962
|
+
if (!this.started)
|
|
963
|
+
this.start();
|
|
964
|
+
// A question (approval or clarification) can interrupt a run while a steer is half typed.
|
|
965
|
+
// Park it, so taking the composer for the question does not silently discard the draft.
|
|
966
|
+
if (this.steering && this.value.length) {
|
|
967
|
+
this.steerDraft = this.value.join('');
|
|
968
|
+
this.steerCursor = this.cursor;
|
|
969
|
+
}
|
|
970
|
+
this.value = [];
|
|
971
|
+
this.cursor = 0;
|
|
972
|
+
this.historyIndex = this.history.length;
|
|
973
|
+
this.completion = undefined;
|
|
974
|
+
this.dismissedCompletion = undefined;
|
|
975
|
+
const label = clean(prompt).trim();
|
|
976
|
+
const regular = options.kind !== 'approval';
|
|
977
|
+
if (!regular)
|
|
978
|
+
this.print(label);
|
|
979
|
+
return new Promise((resolve, reject) => {
|
|
980
|
+
const pending = { kind: options.kind ?? 'question', resolve, reject, signal: options.signal, label: oneLine(label), title: options.title ? oneLine(options.title).trim() : undefined, regular, cancelOnEscape: options.cancelOnEscape, conversationPrompt: options.conversationPrompt === true, secret: options.secret, history: regular && options.history !== false && !options.secret };
|
|
981
|
+
pending.abort = () => { if (this.pending !== pending)
|
|
982
|
+
return; this.finishQuestion(); reject(new DOMException('Question aborted', 'AbortError')); this.scheduleRender(); };
|
|
983
|
+
this.pending = pending;
|
|
984
|
+
this.updateAlternateScroll();
|
|
985
|
+
this.updateWorkingClock();
|
|
986
|
+
pending.signal?.addEventListener('abort', pending.abort, { once: true });
|
|
987
|
+
this.scheduleRender();
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
async chooseQuestion(prompt, items, options = {}) {
|
|
991
|
+
if (!items.length || items.some(item => !item.id))
|
|
992
|
+
throw new Error('Question choices require nonempty IDs');
|
|
993
|
+
if (this.pending || this.modal)
|
|
994
|
+
throw new Error('A terminal question or screen is already active');
|
|
995
|
+
const displayedPrompt = prompt === 'Choose an answer' ? this.dashboardNotices.at(-1) ?? prompt : prompt;
|
|
996
|
+
if (options.printPrompt !== false)
|
|
997
|
+
this.print(prompt);
|
|
998
|
+
const answer = this.question('↑↓ Choose · Enter confirm · Esc cancel', { ...options, history: false });
|
|
999
|
+
const pending = this.pending;
|
|
1000
|
+
// Keep tool identity alongside its arguments so the browser snapshot sanitizer
|
|
1001
|
+
// can apply tool-specific privacy rules before any details leave the CLI.
|
|
1002
|
+
if (pending && options.kind === 'approval')
|
|
1003
|
+
pending.approvalDetails = options.approvalDetails;
|
|
1004
|
+
if (pending) {
|
|
1005
|
+
pending.choices = items.map(item => ({ ...item }));
|
|
1006
|
+
pending.choiceIndex = 0;
|
|
1007
|
+
pending.choiceTitle = oneLine(prompt).trim();
|
|
1008
|
+
pending.dashboardQuestion = clean(displayedPrompt).trim();
|
|
1009
|
+
}
|
|
1010
|
+
this.scheduleRender();
|
|
1011
|
+
return (await answer) || undefined;
|
|
1012
|
+
}
|
|
1013
|
+
select(title, items, options = {}) {
|
|
1014
|
+
let selected = Math.max(0, items.findIndex(item => item.id === options.selectedId));
|
|
1015
|
+
while (items[selected]?.separator)
|
|
1016
|
+
selected++;
|
|
1017
|
+
return this.openModal({ kind: 'select', title, items: [...items], lines: [], selected, selectedId: options.selectedId, ...options });
|
|
1018
|
+
}
|
|
1019
|
+
/** Move the select highlight, carrying the movement past separator rows: separators are visual line breaks, never choices. */
|
|
1020
|
+
moveSelection(modal, movement, homeEnd) {
|
|
1021
|
+
const selectable = (index) => index >= 0 && index < modal.items.length && !modal.items[index].separator;
|
|
1022
|
+
let target = homeEnd === 'home' ? 0 : homeEnd === 'end' ? modal.items.length - 1 : Math.max(0, Math.min(modal.items.length - 1, modal.selected + movement));
|
|
1023
|
+
if (selectable(target)) {
|
|
1024
|
+
modal.selected = target;
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const direction = Math.sign(movement) || (homeEnd === 'end' ? -1 : 1);
|
|
1028
|
+
for (let probe = target; probe >= 0 && probe < modal.items.length; probe += direction)
|
|
1029
|
+
if (selectable(probe)) {
|
|
1030
|
+
modal.selected = probe;
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
for (let probe = target; probe >= 0 && probe < modal.items.length; probe -= direction)
|
|
1034
|
+
if (selectable(probe)) {
|
|
1035
|
+
modal.selected = probe;
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
async showScreen(title, lines, options = {}) { await this.openModal({ kind: 'text', title, items: [], lines: [...lines], selected: 0, ...options }); }
|
|
1040
|
+
loadScreen(title, load, options = {}) {
|
|
1041
|
+
const controller = new AbortController();
|
|
1042
|
+
const promise = this.openModal({ kind: 'loading', title, items: [], lines: [], selected: 0, controller, ...options });
|
|
1043
|
+
const modal = this.modal;
|
|
1044
|
+
if (modal?.controller === controller)
|
|
1045
|
+
Promise.resolve().then(() => { controller.signal.throwIfAborted(); return load(controller.signal); }).then(value => { if (this.modal === modal)
|
|
1046
|
+
this.finishModal(value); }, error => { if (this.modal === modal)
|
|
1047
|
+
this.finishModal(undefined, error instanceof Error ? error : new Error(String(error))); });
|
|
1048
|
+
return promise;
|
|
1049
|
+
}
|
|
1050
|
+
openModal(options) {
|
|
1051
|
+
if (this.closed)
|
|
1052
|
+
return Promise.reject(new Error('Terminal is closed'));
|
|
1053
|
+
if (this.modal)
|
|
1054
|
+
return Promise.reject(new Error('A terminal screen is already active'));
|
|
1055
|
+
if (options.signal?.aborted)
|
|
1056
|
+
return Promise.reject(new DOMException('Screen aborted', 'AbortError'));
|
|
1057
|
+
if (!this.started)
|
|
1058
|
+
this.start();
|
|
1059
|
+
this.clearPlainInput();
|
|
1060
|
+
this.pasteQuestion = undefined;
|
|
1061
|
+
return new Promise((resolve, reject) => {
|
|
1062
|
+
const modal = { ...options, title: oneLine(options.title), description: options.description ? clean(options.description) : undefined, offset: 0, resolve, reject };
|
|
1063
|
+
modal.abort = () => { if (this.modal === modal)
|
|
1064
|
+
this.finishModal(undefined, new DOMException('Screen aborted', 'AbortError')); };
|
|
1065
|
+
this.modal = modal;
|
|
1066
|
+
this.updateAlternateScroll();
|
|
1067
|
+
this.updateWorkingClock();
|
|
1068
|
+
modal.signal?.addEventListener('abort', modal.abort, { once: true });
|
|
1069
|
+
this.scheduleRender();
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
finishModal(value, error) {
|
|
1073
|
+
const modal = this.modal;
|
|
1074
|
+
if (!modal)
|
|
1075
|
+
return;
|
|
1076
|
+
this.modal = undefined;
|
|
1077
|
+
this.updateAlternateScroll();
|
|
1078
|
+
// Only a selection that was actually made is worth docking: a cancelled list leads to no
|
|
1079
|
+
// field, and the caller returns to the conversation instead.
|
|
1080
|
+
if (modal.kind === 'select' && !error && typeof value === 'string')
|
|
1081
|
+
this.lastSelection = { title: modal.title, description: modal.description, items: modal.items.map(item => ({ ...item })), selected: modal.selected };
|
|
1082
|
+
this.updateWorkingClock();
|
|
1083
|
+
if (modal.abort)
|
|
1084
|
+
modal.signal?.removeEventListener('abort', modal.abort);
|
|
1085
|
+
modal.controller?.abort();
|
|
1086
|
+
this.clearPlainInput();
|
|
1087
|
+
this.pasteQuestion = undefined;
|
|
1088
|
+
if (error)
|
|
1089
|
+
modal.reject(error);
|
|
1090
|
+
else
|
|
1091
|
+
modal.resolve(value);
|
|
1092
|
+
this.scheduleRender();
|
|
1093
|
+
}
|
|
1094
|
+
print(text, detail, toolCall, conversation = false, notice = true, alignRight = false) {
|
|
1095
|
+
if (notice) {
|
|
1096
|
+
this.dashboardNotices.push(clean(String(text)).slice(0, 100_000));
|
|
1097
|
+
this.dashboardNotices = this.dashboardNotices.slice(-12);
|
|
1098
|
+
}
|
|
1099
|
+
const lines = clean(String(text)).split('\n');
|
|
1100
|
+
if (this.modal?.kind === 'loading')
|
|
1101
|
+
this.modal.lines = [...this.modal.lines, ...lines].slice(-100);
|
|
1102
|
+
const entry = { text: lines.join('\n'), ...(detail ? { detail: clean(detail) } : {}),
|
|
1103
|
+
...(toolCall ? { toolCall, timing: this.toolClock.get(toolCall.key) } : {}), ...(conversation ? { conversation: true } : {}), ...(alignRight ? { alignRight: true } : {}) };
|
|
1104
|
+
if (this.scroll)
|
|
1105
|
+
this.scroll += this.transcriptRows(entry, this.chatColumns()).length;
|
|
1106
|
+
this.transcript.append(entry);
|
|
1107
|
+
this.scheduleRender();
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Echo submitted text as its own bordered box.
|
|
1111
|
+
*
|
|
1112
|
+
* The box mirrors the live input field's frame and color so the text reads as the
|
|
1113
|
+
* same surface the user typed into, rather than a `You >` transcript prefix. The
|
|
1114
|
+
* frame itself identifies the text as user input, so a submitted prompt is left
|
|
1115
|
+
* untitled; only a surface that is genuinely something other than a task prompt —
|
|
1116
|
+
* a clarification answer — passes a title. The frame is sized to the terminal at
|
|
1117
|
+
* echo time; a later resize re-wraps the body but keeps the original box, which is
|
|
1118
|
+
* an accepted trade for not rewriting history on resize. The finished box is drawn right-aligned against the transcript's right margin (see wrapTranscript), so a submission reads as the user's speech bubble and re-aligns when the window is resized.
|
|
1119
|
+
* @param text - the submitted text to echo.
|
|
1120
|
+
* @param title - optional top-border label; omitted draws a plain frame.
|
|
1121
|
+
*/
|
|
1122
|
+
printPrompt(text, title = '') {
|
|
1123
|
+
// The width the transcript will show this box at, not the width of the surface submitting it.
|
|
1124
|
+
const width = Math.max(12, this.transcriptColumns()) - 4;
|
|
1125
|
+
// Reserve the four frame characters ('│ ', ' │') plus the two-space transcript indent,
|
|
1126
|
+
// so a body row can never exceed the width the render pass wraps at.
|
|
1127
|
+
const bodyWidth = Math.max(1, width - 4);
|
|
1128
|
+
const titleBudget = Math.max(0, width - 4);
|
|
1129
|
+
const label = oneLine(title).trim();
|
|
1130
|
+
const frameTitle = label ? clip(` ${label} `, titleBudget) : '';
|
|
1131
|
+
const rows = clean(String(text)).slice(0, 100_000).split('\n').flatMap(line => wrap(line, bodyWidth));
|
|
1132
|
+
// Expansion preserves the existing bounded-history contract: the model still receives the
|
|
1133
|
+
// full submitted input, while the transcript stores at most MAX_PROMPT_ROWS rendered rows.
|
|
1134
|
+
const omitted = rows.length - MAX_PROMPT_ROWS;
|
|
1135
|
+
const marker = omitted > 0 ? wrap(`… ${omitted + 1} more rows omitted`, bodyWidth) : [];
|
|
1136
|
+
const fullBody = omitted > 0 ? [...rows.slice(0, MAX_PROMPT_ROWS - marker.length), ...marker] : rows;
|
|
1137
|
+
const frame = (body) => {
|
|
1138
|
+
const widest = body.reduce((max, line) => Math.max(max, stringWidth(line)), 0);
|
|
1139
|
+
const inner = Math.max(widest, stringWidth(frameTitle) - 2);
|
|
1140
|
+
const rule = Math.max(0, inner + 2 - stringWidth(frameTitle));
|
|
1141
|
+
const top = '╭' + frameTitle + '─'.repeat(rule) + '╮';
|
|
1142
|
+
const bottom = '╰' + '─'.repeat(inner + 2) + '╯';
|
|
1143
|
+
return [top, ...body.map(line => '│ ' + pad(line, inner) + ' │'), bottom].join('\n');
|
|
1144
|
+
};
|
|
1145
|
+
if (rows.length <= PROMPT_COLLAPSE_AFTER_ROWS) {
|
|
1146
|
+
// Positional call, so name the last flag: the echo is the user's speech bubble (alignRight).
|
|
1147
|
+
this.print(frame(fullBody), undefined, undefined, true, true, true);
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
// Reserve the entire wrapped disclosure before choosing preview rows. On a narrow terminal
|
|
1151
|
+
// the marker itself may need more than six rows; in that case the marker wins and the preview
|
|
1152
|
+
// shrinks to zero rather than hiding the actionable "Ctrl+O to expand" text.
|
|
1153
|
+
let previewRows = Math.max(0, PROMPT_COLLAPSED_BODY_ROWS - 1);
|
|
1154
|
+
let disclosure = [];
|
|
1155
|
+
for (let pass = 0; pass < 3; pass++) {
|
|
1156
|
+
const hidden = Math.max(1, rows.length - previewRows);
|
|
1157
|
+
const suffix = omitted > 0 ? ` · ${omitted + 1} more rows omitted from expanded view` : '';
|
|
1158
|
+
disclosure = wrap(`… ${hidden} more rows · Ctrl+O to expand${suffix}`, bodyWidth);
|
|
1159
|
+
previewRows = Math.max(0, PROMPT_COLLAPSED_BODY_ROWS - disclosure.length);
|
|
1160
|
+
}
|
|
1161
|
+
const collapsedBody = [...rows.slice(0, previewRows), ...disclosure];
|
|
1162
|
+
const promptDisclosure = {
|
|
1163
|
+
id: this.nextPromptId++,
|
|
1164
|
+
collapsedText: frame(collapsedBody),
|
|
1165
|
+
expandedText: frame([...fullBody, 'Ctrl+O to collapse']),
|
|
1166
|
+
};
|
|
1167
|
+
this.promptBoxIds.add(promptDisclosure.id);
|
|
1168
|
+
const entry = { text: promptDisclosure.collapsedText, detail: promptDisclosure.expandedText, conversation: true, promptDisclosure, alignRight: true };
|
|
1169
|
+
if (this.scroll)
|
|
1170
|
+
this.scroll += this.transcriptRows(entry, this.chatColumns()).length;
|
|
1171
|
+
this.transcript.append(entry);
|
|
1172
|
+
this.scheduleRender();
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Stream one reasoning delta into the live preview line.
|
|
1176
|
+
*
|
|
1177
|
+
* The preview always shows the tail of what has arrived, so each call only has to grow
|
|
1178
|
+
* the bounded buffer; rendering stays on the working clock's repaint cadence, with a
|
|
1179
|
+
* small throttle so a token firehose cannot trigger a full-frame render per network
|
|
1180
|
+
* chunk.
|
|
1181
|
+
* @param delta - the reasoning fragment that just arrived; empty fragments are ignored.
|
|
1182
|
+
*/
|
|
1183
|
+
appendThinking(delta) {
|
|
1184
|
+
if (this.closed || !delta)
|
|
1185
|
+
return;
|
|
1186
|
+
this.thinking = (this.thinking + clean(delta)).slice(-THINKING_KEEP);
|
|
1187
|
+
if (!this.thinkingActive)
|
|
1188
|
+
this.thinkingActive = true;
|
|
1189
|
+
if (Date.now() - this.thinkingPaintedAt >= THINKING_PAINT_MS) {
|
|
1190
|
+
this.thinkingPaintedAt = Date.now();
|
|
1191
|
+
this.scheduleRender();
|
|
1192
|
+
}
|
|
1193
|
+
else {
|
|
1194
|
+
this.thinkingFlush ??= setTimeout(() => { this.thinkingFlush = undefined; this.thinkingPaintedAt = Date.now(); this.scheduleRender(); }, THINKING_PAINT_MS);
|
|
1195
|
+
this.thinkingFlush.unref?.();
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Wipe the on-screen conversation so the display reads as a freshly started session.
|
|
1200
|
+
*
|
|
1201
|
+
* Only the transcript entries, the scroll position and the live reasoning preview are dropped:
|
|
1202
|
+
* the welcome card is rebuilt as the scrollback prefix on the next render, so the frame returns
|
|
1203
|
+
* to its startup shape without re-emitting a banner or a terminal clear escape. The composer's
|
|
1204
|
+
* prompt-recall history is deliberately kept — it is input history, not chat output.
|
|
1205
|
+
*/
|
|
1206
|
+
clearConversation() {
|
|
1207
|
+
if (this.closed)
|
|
1208
|
+
return;
|
|
1209
|
+
this.transcript.clear();
|
|
1210
|
+
this.expandedTranscript = false;
|
|
1211
|
+
this.expandedPromptIds.clear();
|
|
1212
|
+
this.collapsedPromptIds.clear();
|
|
1213
|
+
this.promptBoxIds.clear();
|
|
1214
|
+
this.expandedPromptVisible = false;
|
|
1215
|
+
// A cleared conversation abandons its pending attachments with it: they were queued for a
|
|
1216
|
+
// task in this conversation, and silently attaching them to the next one would submit files
|
|
1217
|
+
// the user never re-chose.
|
|
1218
|
+
this.attachments = [];
|
|
1219
|
+
// The scroll offset is clamped against the transcript, so a stale offset would draw an empty
|
|
1220
|
+
// or misplaced window over the cleared list instead of the live tail.
|
|
1221
|
+
this.scroll = 0;
|
|
1222
|
+
this.clearThinking();
|
|
1223
|
+
this.scheduleRender();
|
|
1224
|
+
}
|
|
1225
|
+
/** Retract the preview: the stream ended, was retried, or the whole run finished. */
|
|
1226
|
+
clearThinking() {
|
|
1227
|
+
if (this.thinkingFlush) {
|
|
1228
|
+
clearTimeout(this.thinkingFlush);
|
|
1229
|
+
this.thinkingFlush = undefined;
|
|
1230
|
+
}
|
|
1231
|
+
if (!this.thinkingActive && !this.thinking)
|
|
1232
|
+
return;
|
|
1233
|
+
this.thinking = '';
|
|
1234
|
+
this.thinkingActive = false;
|
|
1235
|
+
this.thinkingExpanded = true;
|
|
1236
|
+
this.scheduleRender();
|
|
1237
|
+
}
|
|
1238
|
+
setStatus(partial) {
|
|
1239
|
+
// The CLI reloads and re-validates the selected graph before every run, handing setStatus
|
|
1240
|
+
// a fresh object for an unchanged selection. Display bookkeeping treats any new graph
|
|
1241
|
+
// object as a change (its node identities repopulate from the run's own events anyway),
|
|
1242
|
+
// while the speed readout identifies the graph by id and revision: a reload of the same
|
|
1243
|
+
// graph keeps its average, a genuinely different or re-edited graph starts over.
|
|
1244
|
+
const graphIdentity = (graph) => graph === undefined ? undefined : `${graph.id}@${graph.revision}`;
|
|
1245
|
+
const modelChanged = (partial.provider !== undefined && partial.provider !== this.status.provider)
|
|
1246
|
+
|| (partial.model !== undefined && partial.model !== this.status.model)
|
|
1247
|
+
|| (partial.reasoningEffort !== undefined && partial.reasoningEffort !== this.status.reasoningEffort)
|
|
1248
|
+
|| (partial.providerModels !== undefined && JSON.stringify(partial.providerModels) !== JSON.stringify(this.status.providerModels));
|
|
1249
|
+
const graphObjectChanged = partial.graph !== undefined && partial.graph !== this.status.graph;
|
|
1250
|
+
const graphChanged = partial.graph !== undefined && graphIdentity(partial.graph) !== graphIdentity(this.status.graph);
|
|
1251
|
+
if (modelChanged || graphObjectChanged) {
|
|
1252
|
+
this.nodeModels.clear();
|
|
1253
|
+
this.dashboardGraphOffset = 0;
|
|
1254
|
+
}
|
|
1255
|
+
if (modelChanged || graphChanged) {
|
|
1256
|
+
// The nodes now decode under a different model or inference configuration, so every
|
|
1257
|
+
// accumulated average describes something the footer no longer shows.
|
|
1258
|
+
this.speedMeters.clear();
|
|
1259
|
+
this.speedInvocations.clear();
|
|
1260
|
+
this.activeSpeedNode = undefined;
|
|
1261
|
+
this.activeSpeedCopy = undefined;
|
|
1262
|
+
this.activeSpeedKey = undefined;
|
|
1263
|
+
}
|
|
1264
|
+
// A trail of node ids means nothing in another graph: the panel's zoom would focus an id
|
|
1265
|
+
// that does not exist there and count visits against the new graph's total, so a changed
|
|
1266
|
+
// selection starts it over - including the position a stopped run ended on, which is a node
|
|
1267
|
+
// id from that same graph. Reloading the same graph (same id and revision) keeps both.
|
|
1268
|
+
if (graphChanged) {
|
|
1269
|
+
this.visitedNodes.clear();
|
|
1270
|
+
this.stoppedNode = undefined;
|
|
1271
|
+
}
|
|
1272
|
+
this.status = { ...this.status, ...partial };
|
|
1273
|
+
// A run ending returns the footer to idle but does not retire the speed readout: each
|
|
1274
|
+
// node's cumulative average keeps describing the node that just ran, and it is the
|
|
1275
|
+
// baseline the next run of that node continues from.
|
|
1276
|
+
if (partial.activity === 'Ready') {
|
|
1277
|
+
this.activeNodes.clear();
|
|
1278
|
+
this.toolClock.stop();
|
|
1279
|
+
this.updateToolClock();
|
|
1280
|
+
this.clearThinking();
|
|
1281
|
+
}
|
|
1282
|
+
this.updateWorkingClock();
|
|
1283
|
+
this.scheduleRender();
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Feed the footer's token-speed readout with one finished model request.
|
|
1287
|
+
*
|
|
1288
|
+
* Providers report a request's tokens only when it completes. A streamed request carries its
|
|
1289
|
+
* measured decode window, which is the time the tokens are credited with; otherwise the
|
|
1290
|
+
* number is measured over the window opened by the call's `agent.iteration.started` event
|
|
1291
|
+
* rather than credited to the instant it arrived, which would leave the readout no duration
|
|
1292
|
+
* to divide by. The completion also replaces the live estimate {@link noteStreamedOutput}
|
|
1293
|
+
* kept for the same request. `invocationId` - the id the executor stamps on both the start
|
|
1294
|
+
* event and the usage delta - selects that window and, through the marker that opened it,
|
|
1295
|
+
* the node whose average the measurement belongs to, so a completion from a concurrent request cannot
|
|
1296
|
+
* borrow another request's window or another node's average. The measurement folds into
|
|
1297
|
+
* that node's cumulative average, which only a changed selection or a changed model
|
|
1298
|
+
* resolution for the node resets. Deltas that carry no tokens (the adapter's per-attempt
|
|
1299
|
+
* request counting, retries included) are not completions and are passed through to the
|
|
1300
|
+
* meter, which ignores them for window pairing. A final delta without tokens - a provider
|
|
1301
|
+
* that omits usage - still closes its request's window but leaves the average untouched:
|
|
1302
|
+
* it describes the requests that did report.
|
|
1303
|
+
* @param tokens - output tokens the provider reported for that single request.
|
|
1304
|
+
* @param invocationId - request identity from the executor, when one is known.
|
|
1305
|
+
* @param final - true when the delta closes its request, per the runtime's origin flag.
|
|
1306
|
+
* @param decodeMs - the adapter's measured decode window for the request, when it has one.
|
|
1307
|
+
*/
|
|
1308
|
+
noteGeneratedTokens(tokens, invocationId, final, decodeMs) {
|
|
1309
|
+
const key = this.speedRoute(invocationId);
|
|
1310
|
+
// Attempt bookkeeping (zero tokens, not final) keeps its routing entry, so the completion
|
|
1311
|
+
// that follows the retries still finds its meter; a completion consumes the entry.
|
|
1312
|
+
if (invocationId !== undefined && (tokens > 0 || final))
|
|
1313
|
+
this.speedInvocations.delete(invocationId);
|
|
1314
|
+
this.ensureSpeedMeter(key).meter.report(tokens, invocationId, final, decodeMs);
|
|
1315
|
+
this.scheduleRender();
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Feed the footer's token-speed readout with a fragment a request is still streaming.
|
|
1319
|
+
*
|
|
1320
|
+
* A thinking model can stream for minutes before its usage arrives, and a readout that moved
|
|
1321
|
+
* only on completions sat on the previous number the whole time. The fragment is estimated
|
|
1322
|
+
* into the same meter the completion will report to, and repaints only when the number on
|
|
1323
|
+
* screen changes - a stream from a node the footer does not follow costs nothing.
|
|
1324
|
+
* @param text - the streamed reasoning or answer fragment.
|
|
1325
|
+
* @param invocationId - request identity from the executor, when one is known.
|
|
1326
|
+
*/
|
|
1327
|
+
noteStreamedOutput(text, invocationId) {
|
|
1328
|
+
const before = this.displayRate();
|
|
1329
|
+
this.ensureSpeedMeter(this.speedRoute(invocationId)).meter.stream(text, invocationId);
|
|
1330
|
+
if (this.displayRate() !== before)
|
|
1331
|
+
this.scheduleRender();
|
|
1332
|
+
}
|
|
1333
|
+
/** Drop a request's live estimate: the attempt failed, is about to be retried, or was aborted. */
|
|
1334
|
+
noteStreamEnded(invocationId) {
|
|
1335
|
+
const before = this.displayRate();
|
|
1336
|
+
this.speedMeters.get(this.speedRoute(invocationId))?.meter.endStream(invocationId);
|
|
1337
|
+
if (this.displayRate() !== before)
|
|
1338
|
+
this.scheduleRender();
|
|
1339
|
+
}
|
|
1340
|
+
/** The meter a request's measurements belong to: the one its start marker named, else the followed one. */
|
|
1341
|
+
speedRoute(invocationId) {
|
|
1342
|
+
const routed = invocationId !== undefined ? this.speedInvocations.get(invocationId) : undefined;
|
|
1343
|
+
return routed ?? this.activeSpeedKey ?? 'engineer';
|
|
1344
|
+
}
|
|
1345
|
+
/** The meter key for a node's requests: parallel copies each keep their own meter. */
|
|
1346
|
+
speedKey(nodeId, copy) {
|
|
1347
|
+
return copy === undefined ? nodeId : `${nodeId}#copy${copy}`;
|
|
1348
|
+
}
|
|
1349
|
+
/** The meter's speed entry, created on first sight so no measurement is ever dropped. */
|
|
1350
|
+
ensureSpeedMeter(key) {
|
|
1351
|
+
let entry = this.speedMeters.get(key);
|
|
1352
|
+
if (!entry) {
|
|
1353
|
+
entry = { meter: new TokenRateMeter(this.tokenClock) };
|
|
1354
|
+
this.speedMeters.set(key, entry);
|
|
1355
|
+
}
|
|
1356
|
+
return entry;
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Stamp a meter with the resolution its generating identity announced.
|
|
1360
|
+
*
|
|
1361
|
+
* A resolution different from the one the meter already measured under rebuilds the meter:
|
|
1362
|
+
* its average described the previous model or reasoning effort, which is exactly the
|
|
1363
|
+
* whole-agent-fallback case. Learning the identity for a meter that had none (the session
|
|
1364
|
+
* event merely arrives before the meter was stamped) never discards measurements.
|
|
1365
|
+
*/
|
|
1366
|
+
stampSpeedMeter(key, provider, model, reasoningEffort) {
|
|
1367
|
+
const entry = this.ensureSpeedMeter(key);
|
|
1368
|
+
const changed = (provider !== undefined && entry.provider !== undefined && provider !== entry.provider)
|
|
1369
|
+
|| (model !== undefined && entry.model !== undefined && model !== entry.model)
|
|
1370
|
+
|| (reasoningEffort !== undefined && entry.reasoningEffort !== undefined && reasoningEffort !== entry.reasoningEffort);
|
|
1371
|
+
if (changed)
|
|
1372
|
+
this.speedMeters.set(key, { meter: new TokenRateMeter(this.tokenClock), provider: provider ?? entry.provider, model: model ?? entry.model, reasoningEffort: reasoningEffort ?? entry.reasoningEffort });
|
|
1373
|
+
else {
|
|
1374
|
+
if (provider !== undefined)
|
|
1375
|
+
entry.provider = provider;
|
|
1376
|
+
if (model !== undefined)
|
|
1377
|
+
entry.model = model;
|
|
1378
|
+
if (reasoningEffort !== undefined)
|
|
1379
|
+
entry.reasoningEffort = reasoningEffort;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
/**
|
|
1383
|
+
* The footer's token speed: the cumulative average of the generating identity the readout
|
|
1384
|
+
* currently follows, unchanged between completions.
|
|
1385
|
+
*
|
|
1386
|
+
* Exposed for callers and tests that need the exact number the readout is based on. The
|
|
1387
|
+
* footer draws {@link displayRate}, which adds the model-identity check.
|
|
1388
|
+
*/
|
|
1389
|
+
tokenSpeed() { return this.activeSpeedKey === undefined ? 0 : this.speedMeters.get(this.activeSpeedKey)?.meter.rate() ?? 0; }
|
|
1390
|
+
/**
|
|
1391
|
+
* The node whose resolution the model row and the speed readout describe.
|
|
1392
|
+
*
|
|
1393
|
+
* This is the identity the readout follows - the most recent node or parallel copy to open
|
|
1394
|
+
* a model call - so the row names the same node whose average is drawn, not whichever node
|
|
1395
|
+
* happened to start first. Without a followed identity it falls back to the first active
|
|
1396
|
+
* node, and with no active node at all the session's own selection answers.
|
|
1397
|
+
*/
|
|
1398
|
+
displayNode() {
|
|
1399
|
+
return (this.activeSpeedNode !== undefined ? this.activeNodes.get(this.activeSpeedNode) : undefined)
|
|
1400
|
+
?? [...this.activeNodes.values()][0];
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* The speed the footer shows: the followed identity's cumulative average, but only while
|
|
1404
|
+
* the model row names the resolution the average was measured under.
|
|
1405
|
+
*
|
|
1406
|
+
* After a run ends the row reverts to the session's own selection, so an average measured
|
|
1407
|
+
* on a node with a provider, model or effort override would otherwise sit beside a
|
|
1408
|
+
* different resolution's name; the segment disappears instead of misdescribing it.
|
|
1409
|
+
*/
|
|
1410
|
+
displayRate() {
|
|
1411
|
+
const entry = this.activeSpeedKey === undefined ? undefined : this.speedMeters.get(this.activeSpeedKey);
|
|
1412
|
+
if (!entry)
|
|
1413
|
+
return 0;
|
|
1414
|
+
const node = this.displayNode();
|
|
1415
|
+
const perCopy = this.activeSpeedCopy !== undefined ? node?.copiesResolved?.get(this.activeSpeedCopy) : undefined;
|
|
1416
|
+
const provider = perCopy?.provider ?? node?.provider ?? this.status.provider;
|
|
1417
|
+
const model = perCopy?.model ?? node?.model ?? this.status.model;
|
|
1418
|
+
// The followed copy's own effort comes first: comparing the meter's reading against a
|
|
1419
|
+
// sibling's effort suppressed a rate that was measured on this copy's own resolution.
|
|
1420
|
+
const effort = perCopy?.resolved?.reasoningEffort ?? node?.resolved?.reasoningEffort ?? this.status.reasoningEffort;
|
|
1421
|
+
if ((entry.provider !== undefined && entry.provider !== provider)
|
|
1422
|
+
|| (entry.model !== undefined && entry.model !== model)
|
|
1423
|
+
|| (entry.reasoningEffort !== undefined && entry.reasoningEffort !== effort))
|
|
1424
|
+
return 0;
|
|
1425
|
+
return entry.meter.rate();
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Let the composer accept steering input for the duration of a run.
|
|
1429
|
+
*
|
|
1430
|
+
* Called with `true` when an interactive run starts and `false` when it ends, so the
|
|
1431
|
+
* normal question flow owns the composer outside a run.
|
|
1432
|
+
* @param enabled - whether submitted text should be queued as a steer.
|
|
1433
|
+
* @returns when disabling, any queued steers that can no longer be injected. The
|
|
1434
|
+
* executor's last poll happens before finalization, so a steer submitted in that
|
|
1435
|
+
* window is visibly accepted but has nowhere to go; returning it lets the caller say
|
|
1436
|
+
* so instead of dropping it silently.
|
|
1437
|
+
*/
|
|
1438
|
+
setSteering(enabled) {
|
|
1439
|
+
if (this.steering === enabled)
|
|
1440
|
+
return [];
|
|
1441
|
+
this.steering = enabled;
|
|
1442
|
+
// A parked draft belongs to the run that parked it.
|
|
1443
|
+
if (!enabled) {
|
|
1444
|
+
this.steerDraft = undefined;
|
|
1445
|
+
this.steerCursor = 0;
|
|
1446
|
+
}
|
|
1447
|
+
this.scheduleRender();
|
|
1448
|
+
if (enabled)
|
|
1449
|
+
return [];
|
|
1450
|
+
// A steer that reached the executor's finalization window has nowhere to go: its text is
|
|
1451
|
+
// returned for the caller to report, and its chips return to the queue so they can ride the
|
|
1452
|
+
// next task. The queue itself survives too — a paste is draft material like typed text.
|
|
1453
|
+
const undelivered = this.takeSteeringTurns();
|
|
1454
|
+
for (const turn of undelivered)
|
|
1455
|
+
for (const pending of turn.attachments)
|
|
1456
|
+
this.addAttachment(pending);
|
|
1457
|
+
return undelivered.map(turn => turn.text);
|
|
1458
|
+
}
|
|
1459
|
+
/** The surface that currently owns the composer, if any. */
|
|
1460
|
+
composerOwner() {
|
|
1461
|
+
return this.pending ?? (this.steering ? STEERING_OWNER : undefined);
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Whether a captured composer owner is still the owner.
|
|
1465
|
+
*
|
|
1466
|
+
* Deferred input (a paste, or an Enter held back by the input-burst window) is only
|
|
1467
|
+
* delivered when the surface that armed it still owns the composer. Steering is an
|
|
1468
|
+
* owner too, so a pasted steer must not be discarded just because no question is
|
|
1469
|
+
* pending.
|
|
1470
|
+
* @param token - the owner captured when the input arrived.
|
|
1471
|
+
* @returns whether that owner may still accept the deferred input.
|
|
1472
|
+
*/
|
|
1473
|
+
ownsComposer(token) {
|
|
1474
|
+
// Object identity against a module-private sentinel, compared by reference and never by
|
|
1475
|
+
// value. A static analyser flags `===` near the word "token" as a secret comparison; there
|
|
1476
|
+
// is no secret here -- `STEERING_OWNER` is this module's own marker object and `token` is
|
|
1477
|
+
// never a string, so no constant-time byte comparison applies or would mean anything.
|
|
1478
|
+
if (token === STEERING_OWNER)
|
|
1479
|
+
return this.steering && !this.pending;
|
|
1480
|
+
return token !== undefined && token === this.pending;
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Take every queued steer message, without blocking.
|
|
1484
|
+
*
|
|
1485
|
+
* The hardened executor polls this at turn boundaries; returning immediately with an
|
|
1486
|
+
* empty array is what lets a run continue when the user has typed nothing.
|
|
1487
|
+
* @returns the queued messages, oldest first.
|
|
1488
|
+
*/
|
|
1489
|
+
takeSteering() {
|
|
1490
|
+
return this.takeSteeringTurns().map(turn => turn.text);
|
|
1491
|
+
}
|
|
1492
|
+
/** The queued steers with their attachments, oldest first; each turn is one injected user message. */
|
|
1493
|
+
takeSteeringTurns() {
|
|
1494
|
+
const queued = this.steered;
|
|
1495
|
+
this.steered = [];
|
|
1496
|
+
return queued;
|
|
1497
|
+
}
|
|
1498
|
+
setTodos(todos) { this.todos = todos.map(todo => ({ ...todo, text: oneLine(todo.text) })); this.todoOffset = Math.min(this.todoOffset, Math.max(0, todos.length - 1)); if (!todos.length)
|
|
1499
|
+
this.expandedTodos = false; this.scheduleRender(); }
|
|
1500
|
+
todoLines(maxRows) {
|
|
1501
|
+
if (!this.todos.length || maxRows < 1)
|
|
1502
|
+
return [];
|
|
1503
|
+
const done = this.todos.filter(todo => todo.status === 'completed').length;
|
|
1504
|
+
// While scrolled back the todo block stays pinned but collapses to one line, so it
|
|
1505
|
+
// never competes with the transcript the user is reading. Scrolling to the live tail
|
|
1506
|
+
// restores the full list without changing the expand/collapse state.
|
|
1507
|
+
if (this.scroll > 0 && !this.expandedTodos) {
|
|
1508
|
+
const active = this.todos.find(todo => todo.status === 'in_progress');
|
|
1509
|
+
const label = `${done}/${this.todos.length} done${active ? ` · ${active.text}` : ''}`;
|
|
1510
|
+
return [`Todo ${label} · ctrl+t to expand`];
|
|
1511
|
+
}
|
|
1512
|
+
// The expanded form needs a header, at least one item and a summary; the collapsed form
|
|
1513
|
+
// above needs only one row, so this guard sits after it rather than hiding both.
|
|
1514
|
+
if (maxRows < 3)
|
|
1515
|
+
return [];
|
|
1516
|
+
const count = Math.min(this.todos.length, this.expandedTodos ? maxRows - 2 : Math.min(5, maxRows - 2));
|
|
1517
|
+
this.todoPageSize = count;
|
|
1518
|
+
this.todoOffset = this.expandedTodos ? Math.min(this.todoOffset, this.todos.length - count) : 0;
|
|
1519
|
+
const visible = this.todos.slice(this.todoOffset, this.todoOffset + count);
|
|
1520
|
+
const hidden = this.todos.length - count;
|
|
1521
|
+
const summary = this.expandedTodos && hidden ? `${this.todoOffset + 1}-${this.todoOffset + count}/${this.todos.length} · Page Up/Down · ` : hidden ? `… +${hidden} more ` : '';
|
|
1522
|
+
return ['Todo', ...visible.map(todo => ` ${todo.status === 'completed' ? '✓' : todo.status === 'in_progress' ? '●' : '○'} ${todo.text}`), `${summary}(${done} done) · ctrl+t to ${this.expandedTodos ? 'collapse' : 'expand'}`];
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Rows for the live reasoning preview, standing in for the plain working line.
|
|
1526
|
+
*
|
|
1527
|
+
* Collapsed it keeps the latest reasoning on one row and pins elapsed time plus the
|
|
1528
|
+
* expand control on the row directly beneath it, so a growing reasoning tail cannot push
|
|
1529
|
+
* the control off to the right. Expanded, the default for every new stream, it opens a
|
|
1530
|
+
* fixed {@link THINKING_ROWS}-row window on the tail, padded at the top with the marker on
|
|
1531
|
+
* the first reasoning row, with the same control row beneath it. `maxRows`
|
|
1532
|
+
* is the room the terminal offers once the transcript keeps at least its last row; a
|
|
1533
|
+
* one-row budget still shows the reasoning row.
|
|
1534
|
+
*/
|
|
1535
|
+
thinkingLines(width, seconds, maxRows) {
|
|
1536
|
+
if (!this.thinkingActive || maxRows < 1)
|
|
1537
|
+
return [];
|
|
1538
|
+
const inner = Math.max(1, width - 4);
|
|
1539
|
+
const stamp = seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
1540
|
+
const trace = clip(`◌ ${this.thinkingTail() || 'Thinking…'}`, inner);
|
|
1541
|
+
const controls = clip(`◌ ${stamp} · ctrl+y`, inner);
|
|
1542
|
+
const collapsed = maxRows === 1 ? [trace] : [trace, controls];
|
|
1543
|
+
if (!this.thinkingExpanded || maxRows === 1)
|
|
1544
|
+
return collapsed;
|
|
1545
|
+
const traceCount = Math.min(THINKING_ROWS, Math.max(1, maxRows - 1));
|
|
1546
|
+
const wrapped = wrap(this.thinking.trimEnd(), inner - 2).slice(-traceCount);
|
|
1547
|
+
const rows = [...Array.from({ length: traceCount - wrapped.length }, () => ''), ...wrapped];
|
|
1548
|
+
const first = traceCount - wrapped.length;
|
|
1549
|
+
return [...rows.map((row, index) => clip(`${index === first ? '◌ ' : ' '}${row}`, inner)), clip(`◌ ${stamp} · ctrl+y`, inner)];
|
|
1550
|
+
}
|
|
1551
|
+
/** The last nonempty line of the retained reasoning, flattened for one row. */
|
|
1552
|
+
thinkingTail() {
|
|
1553
|
+
const rows = this.thinking.split('\n');
|
|
1554
|
+
for (let index = rows.length - 1; index >= 0; index--)
|
|
1555
|
+
if (rows[index].trim())
|
|
1556
|
+
return oneLine(rows[index]);
|
|
1557
|
+
return '';
|
|
1558
|
+
}
|
|
1559
|
+
updateWorkingClock() {
|
|
1560
|
+
if (!this.status.activity || this.status.activity === 'Ready') {
|
|
1561
|
+
this.workingSince = undefined;
|
|
1562
|
+
this.workingElapsed = 0;
|
|
1563
|
+
}
|
|
1564
|
+
else if (this.status.activity === 'Paused' || this.pending || this.modal || this.closed) {
|
|
1565
|
+
if (this.workingSince !== undefined)
|
|
1566
|
+
this.workingElapsed += Date.now() - this.workingSince;
|
|
1567
|
+
this.workingSince = undefined;
|
|
1568
|
+
}
|
|
1569
|
+
else
|
|
1570
|
+
this.workingSince ??= Date.now();
|
|
1571
|
+
}
|
|
1572
|
+
/**
|
|
1573
|
+
* Recompute whether the wheel may act: alternate scroll mode is armed while a screen is
|
|
1574
|
+
* open, or while a run streams with no question pending, and off everywhere else.
|
|
1575
|
+
*
|
|
1576
|
+
* Only transitions write anything. Entering the alternate screen resets the flag first
|
|
1577
|
+
* (`start`), because that screen begins with the mode explicitly switched off.
|
|
1578
|
+
*/
|
|
1579
|
+
updateAlternateScroll() {
|
|
1580
|
+
const armed = Boolean(this.modal) || (this.runActive && !this.pending);
|
|
1581
|
+
if (armed === this.alternateScroll)
|
|
1582
|
+
return;
|
|
1583
|
+
this.alternateScroll = armed;
|
|
1584
|
+
if (!this.started || this.closed)
|
|
1585
|
+
return;
|
|
1586
|
+
this.output.write(armed ? '\x1b[?1007h' : '\x1b[?1007l');
|
|
1587
|
+
}
|
|
1588
|
+
close() {
|
|
1589
|
+
this.transcript.close();
|
|
1590
|
+
this.toolClock.stop();
|
|
1591
|
+
if (this.thinkingFlush) {
|
|
1592
|
+
clearTimeout(this.thinkingFlush);
|
|
1593
|
+
this.thinkingFlush = undefined;
|
|
1594
|
+
}
|
|
1595
|
+
if (this.toolClockTimer)
|
|
1596
|
+
clearInterval(this.toolClockTimer);
|
|
1597
|
+
this.toolClockTimer = undefined;
|
|
1598
|
+
if (this.panelTimer)
|
|
1599
|
+
clearInterval(this.panelTimer);
|
|
1600
|
+
this.panelTimer = undefined;
|
|
1601
|
+
if (this.closed)
|
|
1602
|
+
return;
|
|
1603
|
+
this.closed = true;
|
|
1604
|
+
if (this.workingTimer)
|
|
1605
|
+
clearInterval(this.workingTimer);
|
|
1606
|
+
this.workingTimer = undefined;
|
|
1607
|
+
if (this.escapeTimer)
|
|
1608
|
+
clearTimeout(this.escapeTimer);
|
|
1609
|
+
this.finishModal(undefined, new DOMException('Terminal closed', 'AbortError'));
|
|
1610
|
+
const pending = this.pending;
|
|
1611
|
+
this.finishQuestion();
|
|
1612
|
+
pending?.reject(new DOMException('Terminal closed', 'AbortError'));
|
|
1613
|
+
this.input.off('data', this.onData);
|
|
1614
|
+
this.input.off('end', this.onEnd);
|
|
1615
|
+
this.output.off('resize', this.onResize);
|
|
1616
|
+
this.keys.off('keypress', this.onKey);
|
|
1617
|
+
this.keys.destroy();
|
|
1618
|
+
if (this.started) {
|
|
1619
|
+
try {
|
|
1620
|
+
this.input.setRawMode?.(this.wasRaw);
|
|
1621
|
+
}
|
|
1622
|
+
finally {
|
|
1623
|
+
if (this.wasPaused) {
|
|
1624
|
+
this.input.pause();
|
|
1625
|
+
this.input.unref?.();
|
|
1626
|
+
}
|
|
1627
|
+
this.output.write('\x1b[?1007h\x1b[?2004l\x1b[?25h\x1b[0m\x1b[?1049l');
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
this.emit('close');
|
|
1631
|
+
}
|
|
1632
|
+
finishQuestion() {
|
|
1633
|
+
this.commandInput = false;
|
|
1634
|
+
this.clearPlainInput();
|
|
1635
|
+
if (this.pending?.abort)
|
|
1636
|
+
this.pending.signal?.removeEventListener('abort', this.pending.abort);
|
|
1637
|
+
this.pending = undefined;
|
|
1638
|
+
this.updateAlternateScroll();
|
|
1639
|
+
this.updateWorkingClock();
|
|
1640
|
+
this.value = [];
|
|
1641
|
+
this.cursor = 0;
|
|
1642
|
+
this.paste = '';
|
|
1643
|
+
this.pasteQuestion = undefined;
|
|
1644
|
+
this.completion = undefined;
|
|
1645
|
+
this.dismissedCompletion = undefined;
|
|
1646
|
+
// Put back a steer the question interrupted, so the user resumes where they left off.
|
|
1647
|
+
if (this.steering && this.steerDraft !== undefined) {
|
|
1648
|
+
this.value = this.restoredDraft(this.steerDraft);
|
|
1649
|
+
this.cursor = Math.min(this.steerCursor, this.value.length);
|
|
1650
|
+
this.steerDraft = undefined;
|
|
1651
|
+
this.steerCursor = 0;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
onEnd = () => this.close();
|
|
1655
|
+
onResize = () => this.scheduleRender();
|
|
1656
|
+
onData = (chunk) => {
|
|
1657
|
+
if (this.escapeTimer)
|
|
1658
|
+
clearTimeout(this.escapeTimer);
|
|
1659
|
+
this.escapeTimer = undefined;
|
|
1660
|
+
this.modalInput = !!this.modal;
|
|
1661
|
+
this.incoming += this.decoder.write(typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : chunk);
|
|
1662
|
+
this.consumeIncoming();
|
|
1663
|
+
};
|
|
1664
|
+
/** Drain the decoded stream: paste markers and ordinary keys. */
|
|
1665
|
+
consumeIncoming() {
|
|
1666
|
+
const start = '\x1b[200~', end = '\x1b[201~';
|
|
1667
|
+
while (this.incoming) {
|
|
1668
|
+
const marker = this.pasting ? end : start;
|
|
1669
|
+
const found = this.incoming.indexOf(marker);
|
|
1670
|
+
if (found >= 0) {
|
|
1671
|
+
const before = this.incoming.slice(0, found);
|
|
1672
|
+
this.incoming = this.incoming.slice(found + marker.length);
|
|
1673
|
+
if (this.pasting) {
|
|
1674
|
+
this.paste += before;
|
|
1675
|
+
if (this.ownsComposer(this.pasteQuestion))
|
|
1676
|
+
this.landPaste(this.paste);
|
|
1677
|
+
this.paste = '';
|
|
1678
|
+
this.pasting = false;
|
|
1679
|
+
this.pasteQuestion = undefined;
|
|
1680
|
+
}
|
|
1681
|
+
else {
|
|
1682
|
+
this.normalData(before);
|
|
1683
|
+
if (this.pendingBreak && this.ownsComposer(this.plainQuestion))
|
|
1684
|
+
this.insert(clean(this.pendingBreak));
|
|
1685
|
+
this.clearPlainInput();
|
|
1686
|
+
this.pasting = true;
|
|
1687
|
+
this.pasteQuestion = this.composerOwner();
|
|
1688
|
+
}
|
|
1689
|
+
continue;
|
|
1690
|
+
}
|
|
1691
|
+
let suffix = 0;
|
|
1692
|
+
for (let length = 1; length < marker.length; length++)
|
|
1693
|
+
if (this.incoming.endsWith(marker.slice(0, length)))
|
|
1694
|
+
suffix = length;
|
|
1695
|
+
const ready = this.incoming.slice(0, this.incoming.length - suffix);
|
|
1696
|
+
this.incoming = this.incoming.slice(this.incoming.length - suffix);
|
|
1697
|
+
if (this.pasting)
|
|
1698
|
+
this.paste = (this.paste + ready).slice(0, PASTE_ACCUMULATE_LIMIT);
|
|
1699
|
+
else
|
|
1700
|
+
this.normalData(ready);
|
|
1701
|
+
if (this.incoming === '\x1b') {
|
|
1702
|
+
const modal = this.modal, question = this.pending;
|
|
1703
|
+
this.escapeTimer = setTimeout(() => { this.escapeTimer = undefined; this.incoming = ''; if (!this.closed && this.modal === modal && this.pending === question)
|
|
1704
|
+
this.onKey(undefined, { name: 'escape', sequence: '\x1b' }); }, INPUT_BURST_MS);
|
|
1705
|
+
}
|
|
1706
|
+
break;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
/**
|
|
1710
|
+
* The effective disclosure state of one prompt box.
|
|
1711
|
+
*
|
|
1712
|
+
* An explicit per-prompt toggle wins over the Ctrl+O default, and Ctrl+O clears those
|
|
1713
|
+
* toggles when it is pressed (see onKey), so the keyboard always remains a way out of
|
|
1714
|
+
* either state.
|
|
1715
|
+
*/
|
|
1716
|
+
promptExpanded(id) {
|
|
1717
|
+
if (this.expandedPromptIds.has(id))
|
|
1718
|
+
return true;
|
|
1719
|
+
if (this.collapsedPromptIds.has(id))
|
|
1720
|
+
return false;
|
|
1721
|
+
return this.expandedTranscript;
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* Scroll the transcript (or the active screen). Positive `direction` scrolls up (toward
|
|
1725
|
+
* older output), which is what an Up key means — typed, or sent by the wheel under
|
|
1726
|
+
* alternate scroll mode.
|
|
1727
|
+
*/
|
|
1728
|
+
scrollBy(direction) {
|
|
1729
|
+
if (this.modal) {
|
|
1730
|
+
if (this.modal.kind === 'text')
|
|
1731
|
+
this.modal.offset = Math.max(0, this.modal.offset - direction * 3);
|
|
1732
|
+
else if (this.modal.kind === 'select')
|
|
1733
|
+
this.moveSelection(this.modal, -direction);
|
|
1734
|
+
}
|
|
1735
|
+
else if (this.dashboard)
|
|
1736
|
+
return;
|
|
1737
|
+
else
|
|
1738
|
+
this.scroll = Math.max(0, this.scroll + direction * 3);
|
|
1739
|
+
this.scheduleRender();
|
|
1740
|
+
}
|
|
1741
|
+
normalData(text) {
|
|
1742
|
+
if (!text || this.closed)
|
|
1743
|
+
return;
|
|
1744
|
+
const control = text.search(/[\x03\x04]/);
|
|
1745
|
+
if (control >= 0) {
|
|
1746
|
+
this.normalData(text.slice(0, control));
|
|
1747
|
+
this.clearPlainInput();
|
|
1748
|
+
this.keys.write(text[control]);
|
|
1749
|
+
this.normalData(text.slice(control + 1));
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
if (this.modal) {
|
|
1753
|
+
if (/[\r\n]/.test(text) && !/^(?:\r\n|[\r\n])$/.test(text))
|
|
1754
|
+
return;
|
|
1755
|
+
this.keys.write(text === '\r\n' ? '\r' : text);
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
if (this.modalInput)
|
|
1759
|
+
return;
|
|
1760
|
+
if (!this.pending && !this.steering) {
|
|
1761
|
+
this.keys.write(text);
|
|
1762
|
+
return;
|
|
1763
|
+
}
|
|
1764
|
+
if (text.startsWith('\x1b')) {
|
|
1765
|
+
if (this.pendingBreak)
|
|
1766
|
+
this.insert(clean(this.pendingBreak));
|
|
1767
|
+
this.clearPlainInput();
|
|
1768
|
+
this.keys.write(text);
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
if (this.plainPaste) {
|
|
1772
|
+
this.insertPlain(text);
|
|
1773
|
+
this.armPlainInput();
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
if (this.pendingBreak) {
|
|
1777
|
+
if (this.pendingBreak === '\r' && text === '\n') {
|
|
1778
|
+
this.pendingBreak = '\r\n';
|
|
1779
|
+
this.armPlainInput();
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
this.insertPlain(this.pendingBreak + text);
|
|
1783
|
+
this.pendingBreak = '';
|
|
1784
|
+
this.plainPaste = true;
|
|
1785
|
+
this.armPlainInput();
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
// Steering shares the plain-input path so a pasted steer is handled like pasted text,
|
|
1789
|
+
// but the deferred Enter must fire even with no pending question, so the ownership
|
|
1790
|
+
// token carries whichever surface currently owns the composer.
|
|
1791
|
+
const owner = this.composerOwner();
|
|
1792
|
+
if (/^[\r\n]$|^\r\n$/.test(text)) {
|
|
1793
|
+
this.pendingBreak = text;
|
|
1794
|
+
this.plainQuestion = owner;
|
|
1795
|
+
this.armPlainInput();
|
|
1796
|
+
}
|
|
1797
|
+
else if (/[\r\n]/.test(text)) {
|
|
1798
|
+
this.plainQuestion = owner;
|
|
1799
|
+
this.plainPaste = true;
|
|
1800
|
+
this.insertPlain(text);
|
|
1801
|
+
this.armPlainInput();
|
|
1802
|
+
}
|
|
1803
|
+
else
|
|
1804
|
+
this.keys.write(text);
|
|
1805
|
+
}
|
|
1806
|
+
insertPlain(text) { if (this.plainTrailingCR && text.startsWith('\n'))
|
|
1807
|
+
text = text.slice(1); if (!text) {
|
|
1808
|
+
this.plainTrailingCR = false;
|
|
1809
|
+
return;
|
|
1810
|
+
} this.plainTrailingCR = text.endsWith('\r'); this.insert(clean(text)); }
|
|
1811
|
+
clearPlainInput() { if (this.plainTimer)
|
|
1812
|
+
clearTimeout(this.plainTimer); this.plainTimer = undefined; this.pendingBreak = ''; this.plainPaste = false; this.plainTrailingCR = false; this.plainQuestion = undefined; }
|
|
1813
|
+
armPlainInput() { if (this.plainTimer)
|
|
1814
|
+
clearTimeout(this.plainTimer); const question = this.plainQuestion; this.plainTimer = setTimeout(() => { const enter = this.pendingBreak; this.clearPlainInput(); if (enter && this.ownsComposer(question) && !this.closed)
|
|
1815
|
+
this.keys.write('\r'); }, INPUT_BURST_MS); }
|
|
1816
|
+
insert(text) { if ((this.pending?.choices && !this.commandInput && !(this.runInputHandler && text.startsWith('/'))) || (!this.pending && !this.steering) || this.modal || !text)
|
|
1817
|
+
return; if (this.pending?.choices && text.startsWith('/'))
|
|
1818
|
+
this.commandInput = true; const selected = this.selectionRange(); if (selected)
|
|
1819
|
+
this.deleteSelection(selected); const before = this.value.slice(0, this.cursor).join(''), after = this.value.slice(this.cursor).join(''); const insertion = clean(text).slice(0, Math.max(0, MAX_INPUT - before.length - after.length)); this.value = composerGraphemes(before + insertion + after); this.cursor = composerGraphemes(before + insertion).length; this.completion = undefined; this.dismissedCompletion = undefined; this.scroll = 0; this.scheduleRender(); }
|
|
1820
|
+
/** Whether the surface that owns the composer accepts task input — the only place attachments mean anything. */
|
|
1821
|
+
conversationComposer() {
|
|
1822
|
+
// Steering owns the conversation only while no question holds the composer: an approval or
|
|
1823
|
+
// clarification owns it the moment it appears, and a queued attachment would then ride a
|
|
1824
|
+
// later model turn while the visible question receives an empty Enter. This mirrors the
|
|
1825
|
+
// `steering && !pending` owner rule in ownsComposer's STEERING_OWNER branch.
|
|
1826
|
+
return (this.steering && !this.pending) || this.pending?.conversationPrompt === true;
|
|
1827
|
+
}
|
|
1828
|
+
/**
|
|
1829
|
+
* Land a completed bracketed paste. Terminal drag-and-drop arrives as one or more existing
|
|
1830
|
+
* filesystem paths, which become file references; a paste past the inline threshold becomes a
|
|
1831
|
+
* spooled text attachment instead of flooding the composer; everything else inlines as before.
|
|
1832
|
+
*/
|
|
1833
|
+
landPaste(text) {
|
|
1834
|
+
const cleaned = clean(text);
|
|
1835
|
+
if (this.conversationComposer()) {
|
|
1836
|
+
const paths = droppedPaths(cleaned);
|
|
1837
|
+
if (paths) {
|
|
1838
|
+
for (const path of paths)
|
|
1839
|
+
this.addAttachment({ kind: 'file', path });
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
if (isLargePaste(cleaned)) {
|
|
1843
|
+
this.addAttachment({ kind: 'text', content: cleaned });
|
|
1844
|
+
return;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
this.insert(cleaned);
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Queue one attachment as an inline token at the composer cursor; false means the per-turn cap
|
|
1851
|
+
* refused it. Outside the conversation composer the token waits, and `adoptTokens` appends it
|
|
1852
|
+
* to the draft once that composer is armed again.
|
|
1853
|
+
*/
|
|
1854
|
+
addAttachment(pending) {
|
|
1855
|
+
if (this.attachments.length >= MAX_ATTACHMENTS) {
|
|
1856
|
+
this.print(`Attachment limit reached (${MAX_ATTACHMENTS}). Submit, or press Ctrl+X to remove the last one.`);
|
|
1857
|
+
return false;
|
|
1858
|
+
}
|
|
1859
|
+
const seq = ++this.attachmentSeq;
|
|
1860
|
+
if (pending.kind === 'text' && !pending.name)
|
|
1861
|
+
pending = { ...pending, name: `pasted-${seq}.txt` };
|
|
1862
|
+
if (pending.kind === 'image' && !pending.name)
|
|
1863
|
+
pending = { ...pending, name: `clipboard-${seq}.png` };
|
|
1864
|
+
// One code point per attachment for the session: a marker parked in a history or steer draft
|
|
1865
|
+
// after its attachment was dropped must never come back as a reference to a newer one.
|
|
1866
|
+
const marker = String.fromCodePoint(TOKEN_BASE + seq % 0xFFFFE);
|
|
1867
|
+
this.attachments.push({ marker, seq, pending });
|
|
1868
|
+
// The token replaces a selection, as a small paste does; a space follows it unless one
|
|
1869
|
+
// already does, so typing on reads as a new word.
|
|
1870
|
+
if (this.conversationComposer()) {
|
|
1871
|
+
const selected = this.selectionRange();
|
|
1872
|
+
if (selected)
|
|
1873
|
+
this.deleteSelection(selected);
|
|
1874
|
+
const spaced = blank(this.value[this.cursor] ?? '');
|
|
1875
|
+
this.value.splice(this.cursor, 0, ...(spaced ? [marker] : [marker, ' ']));
|
|
1876
|
+
this.cursor += spaced ? 1 : 2;
|
|
1877
|
+
this.selectionAnchor = undefined;
|
|
1878
|
+
}
|
|
1879
|
+
this.scroll = 0;
|
|
1880
|
+
this.scheduleRender();
|
|
1881
|
+
return true;
|
|
1882
|
+
}
|
|
1883
|
+
/** Take every queued attachment in draft order, without blocking — the CLI drains this when a task is submitted. */
|
|
1884
|
+
takeAttachments() { const queued = this.attachments.map(entry => entry.pending); this.attachments = []; this.scheduleRender(); return queued; }
|
|
1885
|
+
/** The amber label a token draws as in the composer. */
|
|
1886
|
+
tokenLabel({ seq, pending }) {
|
|
1887
|
+
if (pending.kind === 'text') {
|
|
1888
|
+
const lines = pending.content.split('\n').length;
|
|
1889
|
+
return `[Pasted text #${seq} · ${lines} line${lines === 1 ? '' : 's'}]`;
|
|
1890
|
+
}
|
|
1891
|
+
if (pending.kind === 'image')
|
|
1892
|
+
return `[Image #${seq} · ${formatBytes(Math.floor(pending.dataBase64.length * 3 / 4))}]`;
|
|
1893
|
+
const label = attachmentLabel(pending);
|
|
1894
|
+
const folder = /[\\/]$/.test(label);
|
|
1895
|
+
return `[${folder ? 'Folder' : 'File'} #${seq} · ${label.replace(/[\\/]+$/, '').split(/[\\/]/).pop() || label}${folder ? '/' : ''}]`;
|
|
1896
|
+
}
|
|
1897
|
+
/** The draft as display elements: each token replaced by its label, clipped to the composer. */
|
|
1898
|
+
visibleDraft(width) {
|
|
1899
|
+
if (this.pending?.secret)
|
|
1900
|
+
return this.value.map(() => '*');
|
|
1901
|
+
const labels = new Map(this.attachments.map(entry => [entry.marker, clip(this.tokenLabel(entry), Math.max(1, width))]));
|
|
1902
|
+
return this.value.map(part => labels.get(part) ?? (isToken(part) ? '' : part));
|
|
1903
|
+
}
|
|
1904
|
+
/**
|
|
1905
|
+
* The draft as submitted text. Tokens become `[name]` references the model can match against
|
|
1906
|
+
* the attachment block, and the queue is put in the order the tokens appear. A draft that is
|
|
1907
|
+
* only tokens submits empty, so the CLI keeps its attachment-only task text, and a slash
|
|
1908
|
+
* command submits without them, so the command runs and the attachments stay queued.
|
|
1909
|
+
*/
|
|
1910
|
+
submittedDraft() {
|
|
1911
|
+
const order = new Map(this.value.map((part, index) => [part, index]));
|
|
1912
|
+
this.attachments.sort((left, right) => (order.get(left.marker) ?? Infinity) - (order.get(right.marker) ?? Infinity));
|
|
1913
|
+
const typed = this.value.filter(part => !isToken(part)).join('');
|
|
1914
|
+
if (!typed.trim())
|
|
1915
|
+
return '';
|
|
1916
|
+
if (typed.trimStart().startsWith('/'))
|
|
1917
|
+
return typed.trimStart();
|
|
1918
|
+
const names = new Map(this.attachments.map(({ marker, pending }) => [marker, `[${pending.kind === 'file' ? pending.path : pending.name}]`]));
|
|
1919
|
+
return this.value.map(part => isToken(part) ? names.get(part) ?? '' : part).join('');
|
|
1920
|
+
}
|
|
1921
|
+
/** A parked draft brought back into the composer, keeping only tokens whose attachment is still queued. */
|
|
1922
|
+
restoredDraft(text) {
|
|
1923
|
+
const live = new Set(this.attachments.map(entry => entry.marker));
|
|
1924
|
+
return composerGraphemes(text).filter(part => !isToken(part) || live.has(part));
|
|
1925
|
+
}
|
|
1926
|
+
/** Remove draft elements, dropping the attachment behind every token they held. */
|
|
1927
|
+
removeDraft(start, count) {
|
|
1928
|
+
const removed = new Set(this.value.splice(start, count).filter(isToken));
|
|
1929
|
+
if (removed.size)
|
|
1930
|
+
this.attachments = this.attachments.filter(entry => !removed.has(entry.marker));
|
|
1931
|
+
}
|
|
1932
|
+
/**
|
|
1933
|
+
* Put every queued token that is missing from the armed conversation draft back at its end. A
|
|
1934
|
+
* submitted prompt clears the composer before the CLI drains the queue, and `/attach` queues a
|
|
1935
|
+
* file between prompts, so a token can be queued while no draft holds it.
|
|
1936
|
+
*/
|
|
1937
|
+
adoptTokens() {
|
|
1938
|
+
if (!this.conversationComposer() || this.historyIndex !== this.history.length)
|
|
1939
|
+
return;
|
|
1940
|
+
const present = new Set(this.value);
|
|
1941
|
+
const atEnd = this.cursor === this.value.length;
|
|
1942
|
+
for (const { marker } of this.attachments)
|
|
1943
|
+
if (!present.has(marker))
|
|
1944
|
+
this.value.push(...(this.value.length && !blank(this.value.at(-1)) ? [' ', marker, ' '] : [marker, ' ']));
|
|
1945
|
+
if (atEnd)
|
|
1946
|
+
this.cursor = this.value.length;
|
|
1947
|
+
}
|
|
1948
|
+
/** Whether attachments are queued, without draining them (the CLI decides whether a submission carries them). */
|
|
1949
|
+
hasQueuedAttachments() { return this.attachments.length > 0; }
|
|
1950
|
+
/** Read the system clipboard for an image and attach it (Ctrl+V; terminals cannot paste images as text). */
|
|
1951
|
+
pasteClipboardImage() {
|
|
1952
|
+
if (!this.conversationComposer())
|
|
1953
|
+
return;
|
|
1954
|
+
if (!this.clipboardImageProbe) {
|
|
1955
|
+
this.print('Clipboard image paste is unavailable here.');
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
// The probe is asynchronous (a shell-out on Windows): bind the result to the composer that
|
|
1959
|
+
// initiated it — and to its generation, so a steer submitted while the probe ran cannot be
|
|
1960
|
+
// overtaken by an image the user pasted for a draft that no longer exists.
|
|
1961
|
+
const owner = this.composerOwner();
|
|
1962
|
+
const generation = this.clipboardProbe;
|
|
1963
|
+
void this.clipboardImageProbe().then(buffer => {
|
|
1964
|
+
if (this.closed)
|
|
1965
|
+
return;
|
|
1966
|
+
if (this.clipboardProbe !== generation || !this.ownsComposer(owner)) {
|
|
1967
|
+
this.print('The clipboard image arrived after the composer changed; press Ctrl+V again to attach it.');
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
if (!buffer?.length) {
|
|
1971
|
+
this.print('No image on the clipboard.');
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1974
|
+
this.addAttachment({ kind: 'image', mimeType: 'image/png', dataBase64: buffer.toString('base64') });
|
|
1975
|
+
}).catch(() => this.print('Could not read an image from the clipboard.'));
|
|
1976
|
+
}
|
|
1977
|
+
clearDraft() { this.clipboardProbe += 1; this.value = []; this.cursor = 0; this.historyIndex = this.history.length; this.draft = ''; this.commandInput = false; this.completion = undefined; this.dismissedCompletion = undefined; this.attachments = []; this.scroll = 0; this.scheduleRender(); }
|
|
1978
|
+
onKey = (text, key) => {
|
|
1979
|
+
if (key.ctrl && key.name === 'b' && !this.modal) {
|
|
1980
|
+
this.toggleDashboard();
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
if (key.ctrl && key.name === 'g' && this.dashboard && !this.modal) {
|
|
1984
|
+
this.dashboardGraphOffset++;
|
|
1985
|
+
this.scheduleRender();
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
if (key.ctrl && key.name === 'n' && this.dashboard && !this.modal) {
|
|
1989
|
+
this.dashboardModel++;
|
|
1990
|
+
this.scheduleRender();
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1993
|
+
// Expanding from the collapsed summary must not throw the reader back to the live tail:
|
|
1994
|
+
// the summary advertises ctrl+t precisely while scrolled back, so the position is kept.
|
|
1995
|
+
if (key.ctrl && key.name === 't' && !this.modal) {
|
|
1996
|
+
this.expandedTodos = !this.expandedTodos;
|
|
1997
|
+
this.todoOffset = 0;
|
|
1998
|
+
this.scheduleRender();
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
if (key.ctrl && key.name === 'o' && !this.modal && this.dashboard) {
|
|
2002
|
+
// Leaving the dashboard always lands on the expanded transcript, and no prompt box is on
|
|
2003
|
+
// screen to invert: inverting stored boxes the reader cannot see would silently change
|
|
2004
|
+
// rows behind their back, so every box simply follows the expanded flag.
|
|
2005
|
+
this.dashboard = false;
|
|
2006
|
+
this.expandedTranscript = true;
|
|
2007
|
+
this.expandedPromptIds.clear();
|
|
2008
|
+
this.collapsedPromptIds.clear();
|
|
2009
|
+
this.scroll = 0;
|
|
2010
|
+
this.scheduleRender();
|
|
2011
|
+
return;
|
|
2012
|
+
}
|
|
2013
|
+
if (key.ctrl && key.name === 'o' && !this.modal) {
|
|
2014
|
+
// Ctrl+O inverts exactly what is on screen: the details flag flips, and every prompt box
|
|
2015
|
+
// flips relative to the state the reader could see, so one press performs the action each
|
|
2016
|
+
// row advertises ("Ctrl+O to expand" / "Ctrl+O to collapse"). A box
|
|
2017
|
+
// whose state contradicts the flipped flag keeps an explicit override, because no single
|
|
2018
|
+
// global value can express per-box inversion; boxes created later follow the flag.
|
|
2019
|
+
const expandedBefore = new Set([...this.promptBoxIds].filter(id => this.expandedPromptIds.has(id)
|
|
2020
|
+
|| (this.expandedTranscript && !this.collapsedPromptIds.has(id))));
|
|
2021
|
+
this.expandedTranscript = this.dashboard || !this.expandedTranscript;
|
|
2022
|
+
this.dashboard = false;
|
|
2023
|
+
this.expandedPromptIds.clear();
|
|
2024
|
+
this.collapsedPromptIds.clear();
|
|
2025
|
+
for (const id of this.promptBoxIds) {
|
|
2026
|
+
const target = !expandedBefore.has(id);
|
|
2027
|
+
if (target === this.expandedTranscript)
|
|
2028
|
+
continue;
|
|
2029
|
+
(target ? this.expandedPromptIds : this.collapsedPromptIds).add(id);
|
|
2030
|
+
}
|
|
2031
|
+
this.scroll = 0;
|
|
2032
|
+
this.scheduleRender();
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
// The reasoning preview collapses and reopens from the keyboard; no click reaches the app.
|
|
2036
|
+
if (key.ctrl && key.name === 'y' && !this.modal) {
|
|
2037
|
+
if (this.thinkingActive) {
|
|
2038
|
+
this.thinkingExpanded = !this.thinkingExpanded;
|
|
2039
|
+
this.scheduleRender();
|
|
2040
|
+
}
|
|
2041
|
+
return;
|
|
2042
|
+
}
|
|
2043
|
+
// Composer attachments: Ctrl+X removes the last queued chip, Ctrl+V reads the system
|
|
2044
|
+
// clipboard for an image (a terminal's own paste cannot deliver one). Both are no-ops
|
|
2045
|
+
// without queued attachments / a clipboard probe, so they never shadow other intents.
|
|
2046
|
+
// Over a composer selection Ctrl+C copies and Ctrl+X cuts, ahead of their other meanings
|
|
2047
|
+
// (clearing the draft, interrupting, removing a chip). A secret prompt never copies.
|
|
2048
|
+
if (key.ctrl && (key.name === 'c' || key.name === 'x') && !this.modal && !this.pending?.secret && this.selectionRange()) {
|
|
2049
|
+
this.copySelection(key.name === 'x');
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
if (key.ctrl && key.name === 'x' && !this.modal) {
|
|
2053
|
+
const last = this.attachments.at(-1);
|
|
2054
|
+
if (last) {
|
|
2055
|
+
const at = this.value.indexOf(last.marker);
|
|
2056
|
+
if (at < 0)
|
|
2057
|
+
this.attachments.pop();
|
|
2058
|
+
else {
|
|
2059
|
+
this.removeDraft(at, 1);
|
|
2060
|
+
if (at < this.cursor)
|
|
2061
|
+
this.cursor--;
|
|
2062
|
+
this.selectionAnchor = undefined;
|
|
2063
|
+
}
|
|
2064
|
+
this.scheduleRender();
|
|
2065
|
+
}
|
|
2066
|
+
return;
|
|
2067
|
+
}
|
|
2068
|
+
if (key.ctrl && key.name === 'v' && !this.modal) {
|
|
2069
|
+
this.pasteClipboardImage();
|
|
2070
|
+
return;
|
|
2071
|
+
}
|
|
2072
|
+
// Ctrl+C clears a non-empty draft before it interrupts anything: the draft is the
|
|
2073
|
+
// user's unfinished work, and one stray press should not pause a run or exit the
|
|
2074
|
+
// session and take the draft with it. An empty composer escalates as before. Only a
|
|
2075
|
+
// modal screen truly hides the composer — the dashboard keeps it drawn and editable,
|
|
2076
|
+
// so a draft there clears like any other. Ctrl+C inside a paste payload is unreachable
|
|
2077
|
+
// here: while a bracketed paste is in flight the bytes accumulate in the paste buffer
|
|
2078
|
+
// and are stripped by clean() when the paste lands.
|
|
2079
|
+
if (key.ctrl && key.name === 'c') {
|
|
2080
|
+
if (!this.modal && (this.value.length || this.hasQueuedAttachments())) {
|
|
2081
|
+
this.clearDraft();
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
this.emit('SIGINT');
|
|
2085
|
+
return;
|
|
2086
|
+
}
|
|
2087
|
+
if (key.ctrl && key.name === 'd') {
|
|
2088
|
+
if (this.modal || !this.value.length)
|
|
2089
|
+
this.close();
|
|
2090
|
+
else {
|
|
2091
|
+
this.removeDraft(this.cursor, 1);
|
|
2092
|
+
this.scheduleRender();
|
|
2093
|
+
}
|
|
2094
|
+
return;
|
|
2095
|
+
}
|
|
2096
|
+
if (this.modal) {
|
|
2097
|
+
this.modalKey(key);
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
if (this.modalInput)
|
|
2101
|
+
return;
|
|
2102
|
+
if (key.name === 'escape' && this.commandMatches(true)) {
|
|
2103
|
+
this.dismissedCompletion = this.value.join('');
|
|
2104
|
+
this.completion = undefined;
|
|
2105
|
+
this.scheduleRender();
|
|
2106
|
+
return;
|
|
2107
|
+
}
|
|
2108
|
+
if (key.name === 'escape' && this.pending?.cancelOnEscape) {
|
|
2109
|
+
const question = this.pending;
|
|
2110
|
+
this.finishQuestion();
|
|
2111
|
+
question.reject(new DOMException('Question canceled', 'AbortError'));
|
|
2112
|
+
this.scheduleRender();
|
|
2113
|
+
return;
|
|
2114
|
+
}
|
|
2115
|
+
// Enter runs what the popup is highlighting: the popup promises that the selected row is
|
|
2116
|
+
// the command that runs, and a prefix such as `/prov` is not itself a command, so sending
|
|
2117
|
+
// it verbatim only ever produced an unknown-command notice. A plain Enter (Alt+Enter keeps
|
|
2118
|
+
// inserting a newline) substitutes the visible selection for the draft and then falls
|
|
2119
|
+
// through to the ordinary submit path below, so a single press is enough and the
|
|
2120
|
+
// substituted text is submitted, echoed and recorded exactly as if it had been typed.
|
|
2121
|
+
if ((key.name === 'return' || key.name === 'enter') && !key.meta && !key.shift) {
|
|
2122
|
+
const selected = this.selectedCompletion();
|
|
2123
|
+
if (selected) {
|
|
2124
|
+
this.value = graphemes(selected);
|
|
2125
|
+
this.cursor = this.value.length;
|
|
2126
|
+
this.completion = undefined;
|
|
2127
|
+
this.dismissedCompletion = undefined;
|
|
2128
|
+
}
|
|
2129
|
+
const waiting = this.argumentPending();
|
|
2130
|
+
if (waiting) {
|
|
2131
|
+
this.awaitArgument(waiting);
|
|
2132
|
+
this.scheduleRender();
|
|
2133
|
+
return;
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
if ((key.name === 'return' || key.name === 'enter') && !this.modal && !key.meta && !key.shift && (this.pending?.conversationPrompt || this.steering) && (!this.pending?.choices || this.commandInput) && this.value.filter(part => !isToken(part)).join('').trim() === '/dashboard') {
|
|
2137
|
+
const started = Date.now();
|
|
2138
|
+
const mode = this.steering || this.runInputHandler ? 'in-run' : 'interactive';
|
|
2139
|
+
this.commandInput = false;
|
|
2140
|
+
this.value = [];
|
|
2141
|
+
this.cursor = 0;
|
|
2142
|
+
this.completion = undefined;
|
|
2143
|
+
this.toggleDashboard();
|
|
2144
|
+
this.localCommandHandler?.('/dashboard', mode, Math.max(0, Date.now() - started));
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
if (key.name === 'pageup' || key.name === 'pagedown') {
|
|
2148
|
+
if (this.dashboard) {
|
|
2149
|
+
this.todoOffset = Math.max(0, Math.min(Math.max(0, this.todos.length - 1), this.todoOffset + (key.name === 'pageup' ? -1 : 1)));
|
|
2150
|
+
this.scheduleRender();
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
if (this.expandedTodos && this.todoPageSize > 0 && this.todos.length > this.todoPageSize) {
|
|
2154
|
+
this.todoOffset = Math.max(0, Math.min(this.todos.length - 1, this.todoOffset + (key.name === 'pageup' ? -1 : 1) * this.todoPageSize));
|
|
2155
|
+
this.scheduleRender();
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
this.scroll = Math.max(0, this.scroll + (key.name === 'pageup' ? 1 : -1) * Math.max(1, (this.output.rows || 24) - 10));
|
|
2159
|
+
this.scheduleRender();
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
2162
|
+
// While no prompt is pending — a run streaming output — there is no history to
|
|
2163
|
+
// navigate, so Up/Down scroll the transcript, alongside Page Up/Down. This is also the
|
|
2164
|
+
// state in which alternate scroll mode is armed (`updateAlternateScroll`), so the wheel
|
|
2165
|
+
// arrives here as Up/Down and scrolls too. Steering keeps the composer editable, so a
|
|
2166
|
+
// draft rebinds the arrows to cursor movement inside it.
|
|
2167
|
+
if ((key.name === 'up' || key.name === 'down') && !this.pending && (!this.steering || !this.value.length)) {
|
|
2168
|
+
this.scrollBy(key.name === 'up' ? 1 : -1);
|
|
2169
|
+
return;
|
|
2170
|
+
}
|
|
2171
|
+
// Steering owns the composer for the duration of a run: submitted text is queued for
|
|
2172
|
+
// the executor instead of resolving a question, and a real question (approval,
|
|
2173
|
+
// clarification) still takes precedence because it sets `pending`.
|
|
2174
|
+
if (this.steering && !this.pending && !this.modal) {
|
|
2175
|
+
if ((key.name === 'return' || key.name === 'enter') && (key.meta || key.shift)) {
|
|
2176
|
+
this.insert('\n');
|
|
2177
|
+
return;
|
|
2178
|
+
}
|
|
2179
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
2180
|
+
const value = this.submittedDraft().trim();
|
|
2181
|
+
// An attachment-only steer submits too: the tokens are the message, and the CLI names
|
|
2182
|
+
// them with the same stand-in text an attachment-only task gets. Enter with neither
|
|
2183
|
+
// text nor tokens stays a no-op.
|
|
2184
|
+
if (value || this.hasQueuedAttachments()) {
|
|
2185
|
+
const drainAttachments = () => {
|
|
2186
|
+
const queuedAttachments = this.takeAttachments();
|
|
2187
|
+
if (queuedAttachments.length)
|
|
2188
|
+
this.print(`⌷ attached: ${queuedAttachments.map(attachmentLabel).join(' · ')}`);
|
|
2189
|
+
return queuedAttachments;
|
|
2190
|
+
};
|
|
2191
|
+
if (value) {
|
|
2192
|
+
if (this.history.at(-1) !== value) {
|
|
2193
|
+
this.history.push(value);
|
|
2194
|
+
this.history = this.history.slice(-100);
|
|
2195
|
+
}
|
|
2196
|
+
// Steering is the composer for the live run, so a slash command typed here would
|
|
2197
|
+
// otherwise be delivered to the model as an instruction. Session commands that cannot
|
|
2198
|
+
// run mid-run say so immediately rather than queueing text the run would treat as a
|
|
2199
|
+
// prompt; the live subset, exits, and paused runs fall through to the run input
|
|
2200
|
+
// handler, which owns them.
|
|
2201
|
+
const command = submittedCommand(value);
|
|
2202
|
+
const hinted = command && !liveRunCommands.includes(command) && this.status.activity !== 'Paused' ? command : undefined;
|
|
2203
|
+
if (hinted)
|
|
2204
|
+
this.print(workingCommandHint(hinted));
|
|
2205
|
+
else {
|
|
2206
|
+
this.printPrompt(value);
|
|
2207
|
+
// Attachments leave the queue only when the text actually becomes a steer. A live
|
|
2208
|
+
// command (`/status`, `/attach`, …) is consumed by the run input handler, and a
|
|
2209
|
+
// paused run turns the text into a resume direction: both keep the queue for the
|
|
2210
|
+
// next submission, so running a command never discards queued files.
|
|
2211
|
+
if (!this.runInputHandler?.(value))
|
|
2212
|
+
this.steered.push({ text: value, attachments: drainAttachments() });
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
else {
|
|
2216
|
+
this.steered.push({ text: '', attachments: drainAttachments() });
|
|
2217
|
+
}
|
|
2218
|
+
// The submission ends this draft: a clipboard probe still running belongs to it.
|
|
2219
|
+
this.clipboardProbe += 1;
|
|
2220
|
+
this.value = [];
|
|
2221
|
+
this.cursor = 0;
|
|
2222
|
+
this.historyIndex = this.history.length;
|
|
2223
|
+
this.completion = undefined;
|
|
2224
|
+
this.dismissedCompletion = undefined;
|
|
2225
|
+
this.scroll = 0;
|
|
2226
|
+
}
|
|
2227
|
+
this.scheduleRender();
|
|
2228
|
+
return;
|
|
2229
|
+
}
|
|
2230
|
+
if (this.selectionKey(key, text))
|
|
2231
|
+
return;
|
|
2232
|
+
if (key.name === 'left')
|
|
2233
|
+
this.cursor = Math.max(0, this.cursor - 1);
|
|
2234
|
+
else if (key.name === 'right')
|
|
2235
|
+
this.cursor = Math.min(this.value.length, this.cursor + 1);
|
|
2236
|
+
else if (key.name === 'home' || (key.ctrl && key.name === 'a')) {
|
|
2237
|
+
while (this.cursor > 0 && this.value[this.cursor - 1] !== '\n')
|
|
2238
|
+
this.cursor--;
|
|
2239
|
+
}
|
|
2240
|
+
else if (key.name === 'end' || (key.ctrl && key.name === 'e')) {
|
|
2241
|
+
while (this.cursor < this.value.length && this.value[this.cursor] !== '\n')
|
|
2242
|
+
this.cursor++;
|
|
2243
|
+
}
|
|
2244
|
+
else if (key.name === 'backspace') {
|
|
2245
|
+
if (this.cursor)
|
|
2246
|
+
this.removeDraft(--this.cursor, 1);
|
|
2247
|
+
}
|
|
2248
|
+
else if (key.name === 'delete')
|
|
2249
|
+
this.removeDraft(this.cursor, 1);
|
|
2250
|
+
else if (key.name === 'up' || key.name === 'down')
|
|
2251
|
+
this.navigate(key.name === 'up' ? -1 : 1);
|
|
2252
|
+
else if (key.name === 'tab')
|
|
2253
|
+
this.complete();
|
|
2254
|
+
else if (!key.ctrl && !key.meta && text)
|
|
2255
|
+
this.insert(text);
|
|
2256
|
+
this.scheduleRender();
|
|
2257
|
+
return;
|
|
2258
|
+
}
|
|
2259
|
+
if (!this.pending)
|
|
2260
|
+
return;
|
|
2261
|
+
if (!this.pending.secret && this.runInputHandler && (this.commandInput || this.value[0] === '/')) {
|
|
2262
|
+
if (key.name === 'escape') {
|
|
2263
|
+
this.commandInput = false;
|
|
2264
|
+
this.value = [];
|
|
2265
|
+
this.cursor = 0;
|
|
2266
|
+
this.scheduleRender();
|
|
2267
|
+
return;
|
|
2268
|
+
}
|
|
2269
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
2270
|
+
const command = this.submittedDraft().trim();
|
|
2271
|
+
this.value = [];
|
|
2272
|
+
this.cursor = 0;
|
|
2273
|
+
this.commandInput = false;
|
|
2274
|
+
// Clarification cancellation belongs to the question, not the live-run command
|
|
2275
|
+
// router. Never settle an approval or resume a paused run with this command.
|
|
2276
|
+
if (command.toLowerCase() === '/cancel') {
|
|
2277
|
+
if (this.pending.choices?.some(choice => choice.id === 'cancel')) {
|
|
2278
|
+
this.resolveQuestion('cancel');
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
if (!this.pending.choices && this.pending.cancelOnEscape) {
|
|
2282
|
+
this.resolveQuestion(command);
|
|
2283
|
+
return;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
this.runInputHandler(command);
|
|
2287
|
+
this.scheduleRender();
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
if (this.pending.choices && !this.commandInput && text === '/' && this.runInputHandler) {
|
|
2292
|
+
this.commandInput = true;
|
|
2293
|
+
this.insert('/');
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
if (this.pending.choices && !this.commandInput) {
|
|
2297
|
+
const pending = this.pending;
|
|
2298
|
+
if (key.name === 'escape') {
|
|
2299
|
+
this.finishQuestion();
|
|
2300
|
+
pending.resolve('');
|
|
2301
|
+
}
|
|
2302
|
+
else if (key.name === 'return' || key.name === 'enter') {
|
|
2303
|
+
const id = pending.choices[pending.choiceIndex ?? 0].id;
|
|
2304
|
+
this.finishQuestion();
|
|
2305
|
+
pending.resolve(id);
|
|
2306
|
+
}
|
|
2307
|
+
else if (key.name === 'up' || key.name === 'down')
|
|
2308
|
+
pending.choiceIndex = Math.max(0, Math.min(pending.choices.length - 1, (pending.choiceIndex ?? 0) + (key.name === 'up' ? -1 : 1)));
|
|
2309
|
+
this.scheduleRender();
|
|
2310
|
+
return;
|
|
2311
|
+
}
|
|
2312
|
+
if ((key.name === 'return' || key.name === 'enter') && (key.meta || key.shift)) {
|
|
2313
|
+
this.insert('\n');
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
2317
|
+
const pending = this.pending;
|
|
2318
|
+
const value = this.submittedDraft();
|
|
2319
|
+
if (value.trim() && pending.history && this.history.at(-1) !== value) {
|
|
2320
|
+
this.history.push(value);
|
|
2321
|
+
this.history = this.history.slice(-100);
|
|
2322
|
+
}
|
|
2323
|
+
this.finishQuestion();
|
|
2324
|
+
pending.resolve(value);
|
|
2325
|
+
this.scheduleRender();
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
if (this.selectionKey(key, text))
|
|
2329
|
+
return;
|
|
2330
|
+
if (key.name === 'left')
|
|
2331
|
+
this.cursor = Math.max(0, this.cursor - 1);
|
|
2332
|
+
else if (key.name === 'right')
|
|
2333
|
+
this.cursor = Math.min(this.value.length, this.cursor + 1);
|
|
2334
|
+
else if (key.name === 'home' || (key.ctrl && key.name === 'a')) {
|
|
2335
|
+
while (this.cursor > 0 && this.value[this.cursor - 1] !== '\n')
|
|
2336
|
+
this.cursor--;
|
|
2337
|
+
}
|
|
2338
|
+
else if (key.name === 'end' || (key.ctrl && key.name === 'e')) {
|
|
2339
|
+
while (this.cursor < this.value.length && this.value[this.cursor] !== '\n')
|
|
2340
|
+
this.cursor++;
|
|
2341
|
+
}
|
|
2342
|
+
else if (key.name === 'backspace') {
|
|
2343
|
+
if (this.cursor)
|
|
2344
|
+
this.removeDraft(--this.cursor, 1);
|
|
2345
|
+
}
|
|
2346
|
+
else if (key.name === 'delete')
|
|
2347
|
+
this.removeDraft(this.cursor, 1);
|
|
2348
|
+
else if (key.name === 'up' || key.name === 'down')
|
|
2349
|
+
this.navigate(key.name === 'up' ? -1 : 1);
|
|
2350
|
+
else if (key.name === 'tab')
|
|
2351
|
+
this.complete();
|
|
2352
|
+
else if (!key.ctrl && !key.meta && text)
|
|
2353
|
+
this.insert(text);
|
|
2354
|
+
this.scheduleRender();
|
|
2355
|
+
};
|
|
2356
|
+
modalKey(key) {
|
|
2357
|
+
const modal = this.modal;
|
|
2358
|
+
if (modal.kind === 'select' && modal.editPrefix && (key.name === 'right' || (key.name === 'e' && !key.ctrl && !key.meta))) {
|
|
2359
|
+
const item = modal.items[modal.selected];
|
|
2360
|
+
if (item && !item.separator)
|
|
2361
|
+
this.finishModal(item.id.startsWith(':') ? item.id : modal.editPrefix + item.id);
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
if (key.name === 'escape') {
|
|
2365
|
+
this.finishModal();
|
|
2366
|
+
return;
|
|
2367
|
+
}
|
|
2368
|
+
if (key.name === 'return' || key.name === 'enter' || (modal.kind === 'select' && key.name === 'space')) {
|
|
2369
|
+
if (modal.kind === 'select') {
|
|
2370
|
+
const choice = modal.items[modal.selected];
|
|
2371
|
+
if (choice && !choice.separator)
|
|
2372
|
+
this.finishModal(choice.id);
|
|
2373
|
+
}
|
|
2374
|
+
else if (modal.kind === 'text')
|
|
2375
|
+
this.finishModal();
|
|
2376
|
+
return;
|
|
2377
|
+
}
|
|
2378
|
+
if (modal.kind === 'loading')
|
|
2379
|
+
return;
|
|
2380
|
+
const page = Math.max(1, (this.output.rows || 24) - 10);
|
|
2381
|
+
const movement = key.name === 'up' ? -1 : key.name === 'down' ? 1 : key.name === 'pageup' ? -page : key.name === 'pagedown' ? page : 0;
|
|
2382
|
+
if (modal.kind === 'select')
|
|
2383
|
+
this.moveSelection(modal, movement, key.name === 'home' ? 'home' : key.name === 'end' ? 'end' : undefined);
|
|
2384
|
+
else
|
|
2385
|
+
modal.offset = key.name === 'home' ? 0 : key.name === 'end' ? Number.MAX_SAFE_INTEGER : Math.max(0, modal.offset + movement);
|
|
2386
|
+
this.scheduleRender();
|
|
2387
|
+
}
|
|
2388
|
+
navigate(direction) {
|
|
2389
|
+
const completion = this.commandMatches(true);
|
|
2390
|
+
if (completion) {
|
|
2391
|
+
if (completion.options.length)
|
|
2392
|
+
completion.index = (completion.index + direction + completion.options.length) % completion.options.length;
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
if (this.moveRow(direction))
|
|
2396
|
+
return;
|
|
2397
|
+
const historyAt = this.pending?.history ? Math.max(0, Math.min(this.history.length, this.historyIndex + direction)) : this.historyIndex;
|
|
2398
|
+
// The wheel never reaches this method: alternate scroll mode is off whenever a question
|
|
2399
|
+
// is pending (`updateAlternateScroll`), so the terminal sends nothing for it. Up/Down are
|
|
2400
|
+
// therefore purely the keyboard — cursor movement above, history recall here — and never
|
|
2401
|
+
// scroll, so there is no exhaustion heuristic reconciling the two gestures.
|
|
2402
|
+
if (this.pending?.history) {
|
|
2403
|
+
if (this.historyIndex === this.history.length)
|
|
2404
|
+
this.draft = this.value.join('');
|
|
2405
|
+
this.historyIndex = historyAt;
|
|
2406
|
+
this.value = this.restoredDraft(this.history[this.historyIndex] ?? this.draft);
|
|
2407
|
+
this.cursor = this.value.length;
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
/** Move the caret one wrapped row up or down inside the draft; false on the first/last row. */
|
|
2411
|
+
moveRow(direction) {
|
|
2412
|
+
// Lay out the draft as it is drawn: a token is one element but spans its whole label.
|
|
2413
|
+
const columns = Math.max(1, this.chatColumns() - 4);
|
|
2414
|
+
const layout = editor(this.visibleDraft(columns), columns);
|
|
2415
|
+
const current = layout.positions[this.cursor];
|
|
2416
|
+
const row = current.row + direction;
|
|
2417
|
+
if (row < 0 || row >= layout.lines.length)
|
|
2418
|
+
return false;
|
|
2419
|
+
const candidates = layout.positions.map((position, index) => ({ ...position, index })).filter(position => position.row === row);
|
|
2420
|
+
candidates.sort((a, b) => Math.abs(a.column - current.column) - Math.abs(b.column - current.column));
|
|
2421
|
+
this.cursor = candidates[0]?.index ?? this.cursor;
|
|
2422
|
+
return true;
|
|
2423
|
+
}
|
|
2424
|
+
/** The composer's selected grapheme range, or undefined when nothing is selected. */
|
|
2425
|
+
selectionRange() {
|
|
2426
|
+
const anchor = this.selectionAnchor;
|
|
2427
|
+
if (anchor === undefined || this.selectionValue !== this.value || anchor === this.cursor || anchor > this.value.length)
|
|
2428
|
+
return undefined;
|
|
2429
|
+
return anchor < this.cursor ? [anchor, this.cursor] : [this.cursor, anchor];
|
|
2430
|
+
}
|
|
2431
|
+
deleteSelection([start, end]) {
|
|
2432
|
+
this.removeDraft(start, end - start);
|
|
2433
|
+
this.cursor = start;
|
|
2434
|
+
this.selectionAnchor = undefined;
|
|
2435
|
+
this.completion = undefined;
|
|
2436
|
+
this.dismissedCompletion = undefined;
|
|
2437
|
+
}
|
|
2438
|
+
/**
|
|
2439
|
+
* Selection keys for the prompt and steering editors. Shift with an arrow, Home or End
|
|
2440
|
+
* extends the selection from where it started (Shift+Up/Down past the first or last row runs
|
|
2441
|
+
* to that end of the draft, never into history). Over a selection a plain Left/Right
|
|
2442
|
+
* collapses it to that edge and Backspace/Delete remove it; typed or pasted text replaces it
|
|
2443
|
+
* in `insert`. Any other key drops it. True when the key was consumed.
|
|
2444
|
+
*/
|
|
2445
|
+
selectionKey(key, text) {
|
|
2446
|
+
if (key.shift && !key.ctrl && !key.meta && ['left', 'right', 'home', 'end', 'up', 'down'].includes(key.name ?? '')) {
|
|
2447
|
+
if (this.selectionAnchor === undefined || this.selectionValue !== this.value) {
|
|
2448
|
+
this.selectionAnchor = this.cursor;
|
|
2449
|
+
this.selectionValue = this.value;
|
|
2450
|
+
}
|
|
2451
|
+
if (key.name === 'left')
|
|
2452
|
+
this.cursor = Math.max(0, this.cursor - 1);
|
|
2453
|
+
else if (key.name === 'right')
|
|
2454
|
+
this.cursor = Math.min(this.value.length, this.cursor + 1);
|
|
2455
|
+
else if (key.name === 'home') {
|
|
2456
|
+
while (this.cursor > 0 && this.value[this.cursor - 1] !== '\n')
|
|
2457
|
+
this.cursor--;
|
|
2458
|
+
}
|
|
2459
|
+
else if (key.name === 'end') {
|
|
2460
|
+
while (this.cursor < this.value.length && this.value[this.cursor] !== '\n')
|
|
2461
|
+
this.cursor++;
|
|
2462
|
+
}
|
|
2463
|
+
else if (!this.moveRow(key.name === 'up' ? -1 : 1))
|
|
2464
|
+
this.cursor = key.name === 'up' ? 0 : this.value.length;
|
|
2465
|
+
this.scheduleRender();
|
|
2466
|
+
return true;
|
|
2467
|
+
}
|
|
2468
|
+
const range = this.selectionRange();
|
|
2469
|
+
if (!range) {
|
|
2470
|
+
this.selectionAnchor = undefined;
|
|
2471
|
+
return false;
|
|
2472
|
+
}
|
|
2473
|
+
if (key.name === 'left' || key.name === 'right') {
|
|
2474
|
+
this.cursor = key.name === 'left' ? range[0] : range[1];
|
|
2475
|
+
this.selectionAnchor = undefined;
|
|
2476
|
+
this.scheduleRender();
|
|
2477
|
+
return true;
|
|
2478
|
+
}
|
|
2479
|
+
if (key.name === 'backspace' || key.name === 'delete') {
|
|
2480
|
+
this.deleteSelection(range);
|
|
2481
|
+
this.scheduleRender();
|
|
2482
|
+
return true;
|
|
2483
|
+
}
|
|
2484
|
+
const typed = !!text && !key.ctrl && !key.meta && !['return', 'enter', 'tab', 'escape'].includes(key.name ?? '');
|
|
2485
|
+
if (!typed)
|
|
2486
|
+
this.selectionAnchor = undefined;
|
|
2487
|
+
return false;
|
|
2488
|
+
}
|
|
2489
|
+
/**
|
|
2490
|
+
* Copy the composer selection to the clipboard; a cut also removes it from the draft.
|
|
2491
|
+
*
|
|
2492
|
+
* The system writer is preferred; without one, or when it fails, an OSC 52 sequence asks
|
|
2493
|
+
* the terminal to set the clipboard instead.
|
|
2494
|
+
*/
|
|
2495
|
+
copySelection(cut) {
|
|
2496
|
+
const range = this.selectionRange();
|
|
2497
|
+
if (!range)
|
|
2498
|
+
return;
|
|
2499
|
+
// A token copies as what it stands for: the pasted text itself, a file's path, an image's name.
|
|
2500
|
+
const tokens = new Map(this.attachments.map(({ marker, pending }) => [marker, pending.kind === 'text' ? pending.content : pending.kind === 'file' ? pending.path : `[${pending.name}]`]));
|
|
2501
|
+
const text = this.value.slice(range[0], range[1]).map(part => tokens.get(part) ?? part).join('');
|
|
2502
|
+
const osc52 = () => { if (this.started && !this.closed)
|
|
2503
|
+
this.output.write(`\x1b]52;c;${Buffer.from(text, 'utf8').toString('base64')}\x07`); };
|
|
2504
|
+
if (this.clipboardTextWriter)
|
|
2505
|
+
void this.clipboardTextWriter(text).catch(osc52);
|
|
2506
|
+
else
|
|
2507
|
+
osc52();
|
|
2508
|
+
if (cut)
|
|
2509
|
+
this.deleteSelection(range);
|
|
2510
|
+
this.scheduleRender();
|
|
2511
|
+
}
|
|
2512
|
+
complete() { this.dismissedCompletion = undefined; const completion = this.commandMatches(true); const selected = completion?.options[completion.index]; if (!selected)
|
|
2513
|
+
return; if (argumentRequired.has(selected)) {
|
|
2514
|
+
this.awaitArgument(selected);
|
|
2515
|
+
return;
|
|
2516
|
+
} this.value = graphemes(selected); this.cursor = this.value.length; const options = completionOptions(selected); this.completion = { query: selected, options, index: options.indexOf(selected) }; }
|
|
2517
|
+
/** Put `command ` in the composer and open its argument list, without submitting anything. */
|
|
2518
|
+
awaitArgument(command) { this.value = graphemes(`${command} `); this.cursor = this.value.length; this.completion = undefined; this.dismissedCompletion = undefined; }
|
|
2519
|
+
/**
|
|
2520
|
+
* The command Enter must not run yet: the draft is only the name of a command that needs an
|
|
2521
|
+
* argument, so it is completed to `command ` and the argument list opens. Applies wherever the
|
|
2522
|
+
* popup does — the conversation prompt and the live-run composer — and never to a question,
|
|
2523
|
+
* a secret, or a modal.
|
|
2524
|
+
*/
|
|
2525
|
+
argumentPending() {
|
|
2526
|
+
if (this.pending?.secret || (!this.pending?.conversationPrompt && !this.runInputHandler) || this.modal)
|
|
2527
|
+
return undefined;
|
|
2528
|
+
const draft = this.value.join('').trim();
|
|
2529
|
+
return argumentRequired.has(draft) ? draft : undefined;
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* The popup entry Enter should run, or undefined when there is nothing runnable.
|
|
2533
|
+
*
|
|
2534
|
+
* Re-derived from the composer text on every call rather than read from the cached
|
|
2535
|
+
* completion: that cache is shared with the renderer, and a resize or an edit outside the
|
|
2536
|
+
* popup's own key handling can leave it stale, which would let Enter run a row that is no
|
|
2537
|
+
* longer highlighted or no longer drawn. `commandMatches(true)` applies the same visibility
|
|
2538
|
+
* gate the renderer uses, so a candidate that is off-screen on a short terminal reports
|
|
2539
|
+
* nothing, and an entry identical to the draft is not a completion at all.
|
|
2540
|
+
*/
|
|
2541
|
+
selectedCompletion() {
|
|
2542
|
+
const completion = this.commandMatches(true);
|
|
2543
|
+
const selected = completion?.options[completion.index];
|
|
2544
|
+
return selected && selected !== this.value.join('') ? selected : undefined;
|
|
2545
|
+
}
|
|
2546
|
+
commandMatches(visibleOnly = false) {
|
|
2547
|
+
const query = this.value.join('');
|
|
2548
|
+
if (this.pending?.secret || (!this.pending?.conversationPrompt && !this.runInputHandler) || this.modal || query === this.dismissedCompletion || !completable(query))
|
|
2549
|
+
return undefined;
|
|
2550
|
+
if (this.completion?.query !== query)
|
|
2551
|
+
this.completion = { query, options: completionOptions(query), index: 0 };
|
|
2552
|
+
if (visibleOnly) {
|
|
2553
|
+
const width = this.chatColumns(), height = Math.max(1, this.output.rows || 24);
|
|
2554
|
+
const inputRows = Math.min(editor(this.visibleDraft(width - 4), Math.max(1, width - 4)).lines.length, Math.min(6, Math.max(1, height - 9)));
|
|
2555
|
+
if (!commandPopupRows(width, height, inputRows, this.completion.options.length))
|
|
2556
|
+
return undefined;
|
|
2557
|
+
}
|
|
2558
|
+
return this.completion;
|
|
2559
|
+
}
|
|
2560
|
+
scheduleRender() { if (!this.started || this.closed || this.scheduled)
|
|
2561
|
+
return; this.scheduled = true; queueMicrotask(() => { this.scheduled = false; if (!this.closed)
|
|
2562
|
+
this.render(); }); }
|
|
2563
|
+
/**
|
|
2564
|
+
* Paint a frame, rewriting only the rows whose content actually changed.
|
|
2565
|
+
*
|
|
2566
|
+
* The app never takes the mouse (`start`), so the terminal keeps drag-to-select and the
|
|
2567
|
+
* clipboard in every state. What defeated those selections was output churn: a run repaints eight times a second for the working animation alone, and an
|
|
2568
|
+
* emulator abandons the cells under a drag as soon as the app rewrites them. Diffing
|
|
2569
|
+
* against what is already drawn means an unchanged screen writes nothing at all, and every
|
|
2570
|
+
* *contiguous run* of changed rows gets its own write: when two separated rows change (the
|
|
2571
|
+
* animated working row and the footer counters after a request completes, say) the
|
|
2572
|
+
* unchanged rows between them are left alone, so a selection over the transcript, the
|
|
2573
|
+
* composer or the model line survives a footer update. The composed picture is identical
|
|
2574
|
+
* either way - the row diff is a delivery detail, never a change in what is drawn.
|
|
2575
|
+
* @param lines - the frame's rows, top to bottom, exactly as they should read.
|
|
2576
|
+
* @param cursor - optional caret sequence; re-emitted after any painted row, because painting
|
|
2577
|
+
* hides the caret and only this sequence brings it back. A frame that paints nothing and
|
|
2578
|
+
* leaves the caret where it was still writes zero bytes, so the caret can ride along with
|
|
2579
|
+
* the frame without breaking the settled-frame contract.
|
|
2580
|
+
*/
|
|
2581
|
+
writeFrame(lines, cursor = '') {
|
|
2582
|
+
const size = `${this.output.columns || 80}x${this.output.rows || 24}`;
|
|
2583
|
+
const previous = this.drawnSize === size ? this.drawn : undefined;
|
|
2584
|
+
const rows = Math.max(lines.length, previous?.length ?? 0);
|
|
2585
|
+
const unchanged = (index) => (previous?.[index] ?? '') === (lines[index] ?? '');
|
|
2586
|
+
let painted = false;
|
|
2587
|
+
if (!previous) {
|
|
2588
|
+
// The first frame has nothing trustworthy to compare against, so it draws every row and
|
|
2589
|
+
// clears the rest of the screen, byte for byte what an undiffed frame writes.
|
|
2590
|
+
this.output.write('\x1b[?25l\x1b[H' + lines.map(line => '\x1b[2K' + line).join('\r\n') + '\x1b[J');
|
|
2591
|
+
painted = true;
|
|
2592
|
+
}
|
|
2593
|
+
else {
|
|
2594
|
+
// One write per contiguous run of changed rows, never one write spanning the unchanged
|
|
2595
|
+
// rows that separate two runs: rewriting those cells is what breaks a drag selection.
|
|
2596
|
+
const spans = [];
|
|
2597
|
+
for (let index = 0; index < rows; index++) {
|
|
2598
|
+
if (unchanged(index))
|
|
2599
|
+
continue;
|
|
2600
|
+
let end = index;
|
|
2601
|
+
while (end + 1 < rows && !unchanged(end + 1))
|
|
2602
|
+
end++;
|
|
2603
|
+
spans.push(`\x1b[${index + 1};1H${lines.slice(index, end + 1).map(line => '\x1b[2K' + line).join('\r\n')}`);
|
|
2604
|
+
index = end;
|
|
2605
|
+
}
|
|
2606
|
+
if (spans.length) {
|
|
2607
|
+
// A frame shorter than the one on screen is the only way content can linger underneath,
|
|
2608
|
+
// so that is the one case that still needs an erase-below.
|
|
2609
|
+
const tail = lines.length < previous.length ? `\x1b[${lines.length + 1};1H\x1b[J` : '';
|
|
2610
|
+
this.output.write('\x1b[?25l' + spans.join('') + tail);
|
|
2611
|
+
painted = true;
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
this.drawn = [...lines];
|
|
2615
|
+
this.drawnSize = size;
|
|
2616
|
+
if (cursor) {
|
|
2617
|
+
if (painted || cursor !== this.drawnCursor)
|
|
2618
|
+
this.output.write(cursor);
|
|
2619
|
+
this.drawnCursor = cursor;
|
|
2620
|
+
}
|
|
2621
|
+
else
|
|
2622
|
+
this.drawnCursor = '';
|
|
2623
|
+
}
|
|
2624
|
+
/** A quiet startup identity, never a full-width alert-colored diagnostics panel. */
|
|
2625
|
+
welcome(width, viewportHeight) {
|
|
2626
|
+
const status = this.status;
|
|
2627
|
+
const available = Math.max(1, width - 4); // the transcript adds two columns of inset
|
|
2628
|
+
const graph = status.graph;
|
|
2629
|
+
const selected = status.graphSelection ?? (graph?.id === 'software-engineer' ? 'default' : graph?.id);
|
|
2630
|
+
const graphName = selected === 'default' ? 'Default · Software Engineer' : oneLine(graph?.name ?? 'Not selected');
|
|
2631
|
+
const nodes = graph ? Object.keys(graph.nodes).length : 0;
|
|
2632
|
+
const nodeCount = graph && selected !== 'default' ? ` · ${nodes} ${nodes === 1 ? 'node' : 'nodes'}` : '';
|
|
2633
|
+
const activity = oneLine(status.activity || 'Ready');
|
|
2634
|
+
// Compact terminals and setup screens use a legible single-line label.
|
|
2635
|
+
const showArt = this.appName === 'ANDORRA CODE'
|
|
2636
|
+
&& viewportHeight >= 10
|
|
2637
|
+
&& ANDORRA_WORDMARK.every(row => stringWidth(row) <= available);
|
|
2638
|
+
const brand = showArt
|
|
2639
|
+
? [...ANDORRA_WORDMARK, `CODE · v${this.version}`]
|
|
2640
|
+
: [`${this.appName} · v${this.version}`];
|
|
2641
|
+
// A short terminal must not scroll the fallback label out of its own welcome.
|
|
2642
|
+
if (viewportHeight < 9)
|
|
2643
|
+
return [
|
|
2644
|
+
clip(brand.at(-1), available),
|
|
2645
|
+
...(viewportHeight >= 2 ? [clip(`● ${activity}`, available)] : []),
|
|
2646
|
+
...(viewportHeight >= 3 ? [clip(`Workflow · ${graphName}`, available)] : []),
|
|
2647
|
+
...(status.graphNeedsOverride && viewportHeight >= 4 ? [paint(clip(OVERRIDE_HINT, available), STATUS.warn)] : []),
|
|
2648
|
+
];
|
|
2649
|
+
return [
|
|
2650
|
+
'', ...brand, '',
|
|
2651
|
+
clip(`● ${activity}`, available),
|
|
2652
|
+
clip(`Workflow · ${graphName}${nodeCount}`, available),
|
|
2653
|
+
...(status.graphNeedsOverride ? [paint(clip(OVERRIDE_HINT, available), STATUS.warn)] : []),
|
|
2654
|
+
'',
|
|
2655
|
+
...(viewportHeight >= 10 ? ['Describe a task to get started.'] : []),
|
|
2656
|
+
'',
|
|
2657
|
+
];
|
|
2658
|
+
}
|
|
2659
|
+
/**
|
|
2660
|
+
* The selection screen to dock above the composer while a typed field is being answered.
|
|
2661
|
+
*
|
|
2662
|
+
* A plain question that follows a selection screen is a field belonging to that screen, so
|
|
2663
|
+
* the card is drawn where the home card would otherwise be. Run-time questions (approvals,
|
|
2664
|
+
* clarifications) keep their own surface, and the card is windowed around the highlighted
|
|
2665
|
+
* entry so a long list cannot eat the composer's rows on a short terminal.
|
|
2666
|
+
* @param rows - the transcript rows the render pass left for this card.
|
|
2667
|
+
* @returns the card's lines, or undefined when the home card belongs there instead.
|
|
2668
|
+
*/
|
|
2669
|
+
selectionCard(rows) {
|
|
2670
|
+
const selection = this.lastSelection;
|
|
2671
|
+
if (!selection || !this.pending || this.pending.choices || this.pending.conversationPrompt)
|
|
2672
|
+
return undefined;
|
|
2673
|
+
// A run's own questions (approval, clarification) are not fields of a selection screen,
|
|
2674
|
+
// so the docked card stays with the idle configuration flow it belongs to.
|
|
2675
|
+
if (this.status.activity && this.status.activity !== 'Ready')
|
|
2676
|
+
return undefined;
|
|
2677
|
+
const width = Math.max(8, this.chatColumns() - 4);
|
|
2678
|
+
const description = selection.description ? wrap(clean(selection.description), Math.max(1, width - 4)).slice(0, 2) : [];
|
|
2679
|
+
const count = Math.max(1, Math.min(selection.items.length, rows - description.length - 4));
|
|
2680
|
+
const first = Math.max(0, Math.min(selection.selected - count + 1, selection.items.length - count));
|
|
2681
|
+
const items = selection.items.slice(first, first + count).map((item, index) => `${first + index === selection.selected ? '›' : ' '} ${oneLine(item.label)}`);
|
|
2682
|
+
if (count < selection.items.length)
|
|
2683
|
+
items.push(`… ${selection.items.length - count} more`);
|
|
2684
|
+
const title = clip(` ${oneLine(selection.title)} `, Math.max(0, width - 2));
|
|
2685
|
+
const head = '╭' + title + '─'.repeat(Math.max(0, width - 2 - stringWidth(title))) + '╮';
|
|
2686
|
+
const body = [...description, ...items].map(line => '│ ' + pad(line, width - 4) + ' │');
|
|
2687
|
+
return ['', head, ...body, '╰' + '─'.repeat(width - 2) + '╯', ''];
|
|
2688
|
+
}
|
|
2689
|
+
renderModal(width, height) {
|
|
2690
|
+
const modal = this.modal;
|
|
2691
|
+
if (width < 16 || height < 8) {
|
|
2692
|
+
const content = modal.kind === 'select' ? modal.items[modal.selected]?.label || 'No choices' : modal.kind === 'loading' ? 'Loading…' : modal.lines[modal.offset] || '';
|
|
2693
|
+
const compact = height === 1 ? [oneLine(content)] : height === 2 ? [modal.title, oneLine(content)] : [this.appName, modal.title, oneLine(content), 'Esc: back'];
|
|
2694
|
+
const rows = compact.slice(0, height).map(line => clip(line, width));
|
|
2695
|
+
this.writeFrame(rows);
|
|
2696
|
+
return;
|
|
2697
|
+
}
|
|
2698
|
+
const cardWidth = width - 4, innerWidth = width - 8, bodyHeight = height - 7;
|
|
2699
|
+
const descriptionLines = modal.description ? wrap(modal.description, innerWidth).slice(0, Math.max(0, Math.min(3, bodyHeight - 2))) : [];
|
|
2700
|
+
const description = descriptionLines.length ? [...descriptionLines, ''] : [];
|
|
2701
|
+
const viewport = Math.max(1, bodyHeight - description.length);
|
|
2702
|
+
const content = [];
|
|
2703
|
+
let selectedStart = 0, selectedEnd = 0;
|
|
2704
|
+
if (modal.kind === 'select') {
|
|
2705
|
+
for (const [index, item] of modal.items.entries()) {
|
|
2706
|
+
if (item.separator) {
|
|
2707
|
+
content.push({ text: '' });
|
|
2708
|
+
continue;
|
|
2709
|
+
}
|
|
2710
|
+
const selected = index === modal.selected;
|
|
2711
|
+
if (selected)
|
|
2712
|
+
selectedStart = content.length;
|
|
2713
|
+
content.push({ text: `${selected ? '›' : ' '} ${oneLine(item.label)}${item.id === modal.selectedId ? ' ✓' : ''}`, selected, bold: item.bold });
|
|
2714
|
+
if (item.description)
|
|
2715
|
+
for (const line of wrap(clean(item.description), Math.max(1, innerWidth - 2)))
|
|
2716
|
+
content.push({ text: ` ${line}`, selected, dim: true });
|
|
2717
|
+
if (selected)
|
|
2718
|
+
selectedEnd = content.length;
|
|
2719
|
+
}
|
|
2720
|
+
if (!content.length)
|
|
2721
|
+
content.push({ text: 'No choices available. Press Escape to return.', dim: true });
|
|
2722
|
+
if (selectedStart < modal.offset)
|
|
2723
|
+
modal.offset = selectedStart;
|
|
2724
|
+
if (selectedEnd > modal.offset + viewport)
|
|
2725
|
+
modal.offset = Math.min(selectedStart, selectedEnd - viewport);
|
|
2726
|
+
}
|
|
2727
|
+
else if (modal.kind === 'loading') {
|
|
2728
|
+
content.push({ text: '◌ Loading…', selected: true }, { text: '' });
|
|
2729
|
+
for (const line of modal.lines)
|
|
2730
|
+
for (const wrapped of wrap(clean(line), innerWidth))
|
|
2731
|
+
content.push({ text: wrapped });
|
|
2732
|
+
modal.offset = Math.max(0, content.length - viewport);
|
|
2733
|
+
}
|
|
2734
|
+
else {
|
|
2735
|
+
for (const line of modal.lines)
|
|
2736
|
+
for (const wrapped of wrap(clean(line), innerWidth))
|
|
2737
|
+
content.push({ text: wrapped });
|
|
2738
|
+
if (!content.length)
|
|
2739
|
+
content.push({ text: 'No information available.', dim: true });
|
|
2740
|
+
}
|
|
2741
|
+
modal.offset = Math.max(0, Math.min(modal.offset, Math.max(0, content.length - viewport)));
|
|
2742
|
+
const visible = content.slice(modal.offset, modal.offset + viewport);
|
|
2743
|
+
const title = clip(` ${modal.title} `, cardWidth - 2);
|
|
2744
|
+
const rows = [paint(clip(`◈ ${this.appName}`, width), GRAY), '', paint(` ╭${title}${'─'.repeat(Math.max(0, cardWidth - 2 - stringWidth(title)))}╮`, GRAY)];
|
|
2745
|
+
for (const line of description)
|
|
2746
|
+
rows.push(paint(' │ ', GRAY) + paint(pad(line, innerWidth), GRAY) + paint(' │', GRAY));
|
|
2747
|
+
for (let index = 0; index < viewport; index++) {
|
|
2748
|
+
const row = visible[index];
|
|
2749
|
+
const value = pad(row?.text ?? '', innerWidth);
|
|
2750
|
+
const emphasized = row?.bold ? `\x1b[1m${value}\x1b[22m` : value;
|
|
2751
|
+
const styled = row?.selected ? `\x1b[48;5;236m${paint(emphasized, row.dim ? SUBTLE : WHITE)}\x1b[0m` : paint(emphasized, row?.dim ? GRAY : DIM);
|
|
2752
|
+
rows.push(paint(' │ ', GRAY) + styled + paint(' │', GRAY));
|
|
2753
|
+
}
|
|
2754
|
+
rows.push(paint(' ╰' + '─'.repeat(cardWidth - 2) + '╯', GRAY));
|
|
2755
|
+
const help = modal.footer ?? (modal.kind === 'select' ? '↑↓ Move · Enter/Space Select · Esc Back' : modal.kind === 'loading' ? 'Esc Cancel' : '↑↓ Scroll · Page Up/Down · Esc Back');
|
|
2756
|
+
const position = modal.kind === 'select' ? `${modal.items.filter(item => !item.separator).length ? modal.items.slice(0, modal.selected + 1).filter(item => !item.separator).length : 0}/${modal.items.filter(item => !item.separator).length}` : `${Math.min(content.length, modal.offset + viewport)}/${content.length}`;
|
|
2757
|
+
const helpWidth = Math.max(0, width - position.length - 2);
|
|
2758
|
+
rows.push(paint(pad(help, helpWidth) + ' ' + position));
|
|
2759
|
+
rows.push(paint(clip(`Graph: ${(this.status.graphSelection ?? (this.status.graph?.id === 'software-engineer' ? 'default' : this.status.graph?.id)) === 'default' ? 'Default' : this.status.graph?.name ?? 'Not selected'}`, width - 1), GRAY));
|
|
2760
|
+
const yolo = this.status.permissions ? `Permissions: ${this.status.permissions}` : this.status.yolo ? 'Permissions: automatic approvals' : 'Permissions: ask before writes/shell';
|
|
2761
|
+
const footerWidth = width - 1;
|
|
2762
|
+
const labelWidth = Math.min(footerWidth, yolo.length + 2);
|
|
2763
|
+
rows.push(paint(pad(yolo, labelWidth), this.status.yolo ? STATUS.warn : STATUS.ok) + paint(clip(this.activeModel().label, footerWidth - labelWidth)));
|
|
2764
|
+
this.writeFrame(rows);
|
|
2765
|
+
}
|
|
2766
|
+
/**
|
|
2767
|
+
* Wrap transcript text into drawn rows.
|
|
2768
|
+
* @param alignRight - pad each stored row that fits the transcript allowance onto its right margin,
|
|
2769
|
+
* which is what makes a user submission read as a speech bubble. The decision is made on the
|
|
2770
|
+
* stored row rather than on the fragments: wrapping a row that does not fit leaves short tails
|
|
2771
|
+
* (the last cells of a split border) that would otherwise be pushed into the margin, smearing
|
|
2772
|
+
* the frame across the screen, so no fragment of an over-wide row is padded.
|
|
2773
|
+
*/
|
|
2774
|
+
wrapTranscript(text, width, alignRight = false) {
|
|
2775
|
+
return text.split('\n').flatMap(line => {
|
|
2776
|
+
const diff = /^\s*[+-]\s+\d+\s*\|/.test(line), box = /^[╭╰│]/.test(line);
|
|
2777
|
+
const isBrand = ANDORRA_WORDMARK.includes(line) || line === this.appName || line.startsWith(`${this.appName} · v`);
|
|
2778
|
+
const color = isBrand ? WHITE : box ? GRAY : !diff && line.includes(this.appName) ? accentPaint() : transcriptColor(line);
|
|
2779
|
+
const allowance = Math.max(1, width - 4);
|
|
2780
|
+
const aligned = alignRight && stringWidth(line) <= allowance;
|
|
2781
|
+
return wrap(line, allowance).map(text => ({ text: aligned && text ? ' '.repeat(allowance - stringWidth(text)) + text : text, color }));
|
|
2782
|
+
});
|
|
2783
|
+
}
|
|
2784
|
+
transcriptRows(entry, width) {
|
|
2785
|
+
const disclosure = entry.promptDisclosure;
|
|
2786
|
+
// Ctrl+O expands the whole transcript, collapsed prompt boxes included: the app never
|
|
2787
|
+
// takes the mouse, so the keyboard is the way to the stored rows. An explicit per-prompt
|
|
2788
|
+
// toggle wins.
|
|
2789
|
+
const promptExpanded = disclosure ? this.promptExpanded(disclosure.id) : false;
|
|
2790
|
+
const text = disclosure
|
|
2791
|
+
? promptExpanded && entry.detail ? entry.detail : entry.text
|
|
2792
|
+
: this.expandedTranscript && entry.detail ? entry.detail : entry.text + (entry.detail ? ' (Ctrl+O to expand)' : '');
|
|
2793
|
+
if (!entry.toolCall) {
|
|
2794
|
+
const rows = this.wrapTranscript(text + '\n', width, entry.alignRight === true);
|
|
2795
|
+
if (!disclosure)
|
|
2796
|
+
return rows;
|
|
2797
|
+
return rows.map(row => {
|
|
2798
|
+
if (!row.text)
|
|
2799
|
+
return row;
|
|
2800
|
+
const isDisclosure = row.text.toLowerCase().includes(promptExpanded ? 'ctrl+o to collapse' : 'ctrl+o to expand');
|
|
2801
|
+
return {
|
|
2802
|
+
...row,
|
|
2803
|
+
...(isDisclosure ? { color: WHITE } : {}),
|
|
2804
|
+
promptId: disclosure.id,
|
|
2805
|
+
promptExpanded,
|
|
2806
|
+
};
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
const rows = text.split('\n');
|
|
2810
|
+
const elapsed = entry.timing ? formatDuration(this.toolClock.elapsed(entry.timing)) : undefined;
|
|
2811
|
+
const right = [entry.toolCall.timestamp, elapsed].filter(Boolean).join(' · ');
|
|
2812
|
+
return [...toolHeaderRows(rows[0], right, Math.max(1, width - 4)), ...rows.slice(1), ''].flatMap(row => this.wrapTranscript(row, width));
|
|
2813
|
+
}
|
|
2814
|
+
render() {
|
|
2815
|
+
if (!this.started || this.closed)
|
|
2816
|
+
return;
|
|
2817
|
+
this.todoPageSize = 0;
|
|
2818
|
+
const working = Boolean(this.status.activity && this.status.activity !== 'Ready' && this.status.activity !== 'Paused' && !this.pending && !this.modal);
|
|
2819
|
+
this.updateWorkingClock();
|
|
2820
|
+
const columns = Math.max(1, this.output.columns || 80), height = Math.max(1, this.output.rows || 24);
|
|
2821
|
+
// The token speed needs no refresh of its own: its reading is captured when a request
|
|
2822
|
+
// finishes and held static between calls, so the frame already on screen stays correct
|
|
2823
|
+
// across a paused run or an approval prompt, and `noteGeneratedTokens` schedules the one
|
|
2824
|
+
// render that reveals a new reading. Only the animations need the ticker.
|
|
2825
|
+
const ticking = working || (this.dashboard && this.dashboardMetrics.snapshot().running);
|
|
2826
|
+
if (ticking && !this.workingTimer) {
|
|
2827
|
+
this.workingTimer = setInterval(() => this.scheduleRender(), 120);
|
|
2828
|
+
this.workingTimer.unref?.();
|
|
2829
|
+
}
|
|
2830
|
+
else if (!ticking && this.workingTimer) {
|
|
2831
|
+
clearInterval(this.workingTimer);
|
|
2832
|
+
this.workingTimer = undefined;
|
|
2833
|
+
}
|
|
2834
|
+
// A running background terminal ages on screen, but its age changes once a second: the panel
|
|
2835
|
+
// gets its own one-second clock rather than riding the animation timer's eight frames a second
|
|
2836
|
+
// for a string that is not changing. Only a visible panel arms it, and only while a displayed
|
|
2837
|
+
// session runs.
|
|
2838
|
+
const ages = this.panelColumns(columns, height) > 0 && (this.status.terminals?.some(session => session.running) ?? false);
|
|
2839
|
+
if (ages && !this.panelTimer) {
|
|
2840
|
+
this.panelTimer = setInterval(() => this.scheduleRender(), 1_000);
|
|
2841
|
+
this.panelTimer.unref?.();
|
|
2842
|
+
}
|
|
2843
|
+
else if (!ages && this.panelTimer) {
|
|
2844
|
+
clearInterval(this.panelTimer);
|
|
2845
|
+
this.panelTimer = undefined;
|
|
2846
|
+
}
|
|
2847
|
+
if (this.modal) {
|
|
2848
|
+
// A modal screen takes the frame, so the panel is hidden for as long as it is open - and a
|
|
2849
|
+
// render that returns here never reaches the visibility bookkeeping below. Recording it here
|
|
2850
|
+
// is what lets the render after the modal closes announce the panel's return, so its data is
|
|
2851
|
+
// read again instead of showing what was true before the screen opened.
|
|
2852
|
+
this.panelWasHidden = true;
|
|
2853
|
+
this.expandedPromptVisible = false;
|
|
2854
|
+
this.renderModal(columns, height);
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2857
|
+
// The panel is composed alongside the chat column rather than reflowing it: everything
|
|
2858
|
+
// below keeps its own arithmetic at the reduced chat width, and the frame carries both
|
|
2859
|
+
// columns once the rows are built (composePanel). One more column is the gutter that
|
|
2860
|
+
// keeps the chat column's own frame - the composer's border, the header's right edge -
|
|
2861
|
+
// from touching the divider.
|
|
2862
|
+
const panelColumns = this.panelColumns(columns, height);
|
|
2863
|
+
// A resize or a closed screen can bring the panel back: tell the embedder so a summary it
|
|
2864
|
+
// skipped while nothing could show it is read now instead of at the next run boundary.
|
|
2865
|
+
if (panelColumns > 0 && this.panelWasHidden) {
|
|
2866
|
+
this.panelWasHidden = false;
|
|
2867
|
+
this.emit('panel');
|
|
2868
|
+
}
|
|
2869
|
+
else if (panelColumns === 0)
|
|
2870
|
+
this.panelWasHidden = true;
|
|
2871
|
+
const width = columns - panelColumns - (panelColumns ? 1 : 0);
|
|
2872
|
+
this.adoptTokens();
|
|
2873
|
+
const visibleValue = this.visibleDraft(width - 4);
|
|
2874
|
+
const layout = editor(visibleValue, Math.max(1, width - 4));
|
|
2875
|
+
const cursor = layout.positions[this.cursor];
|
|
2876
|
+
const selection = this.selectionRange();
|
|
2877
|
+
const choices = this.commandInput ? undefined : this.pending?.choices;
|
|
2878
|
+
const choiceIndex = this.pending?.choiceIndex ?? 0;
|
|
2879
|
+
if (height < 9 || width < 12) {
|
|
2880
|
+
this.expandedPromptVisible = false;
|
|
2881
|
+
const label = choices ? oneLine(`› ${choiceIndex + 1}. ${choices[choiceIndex].label}`) : this.pending ? visibleValue.join('').replace(/\n/g, ' ') || 'Ask Andorra…' : this.steering ? visibleValue.join('').replace(/\n/g, ' ') || 'Steer this run…' : oneLine(this.nodeProgress() || this.status.activity || this.appName);
|
|
2882
|
+
const lines = height > 1 ? [clip(this.appName, width), clip(label, width, false)] : [clip(label, width, false)];
|
|
2883
|
+
const caret = (this.pending || this.steering) && !choices ? `\x1b[${lines.length};${Math.min(width, 1 + stringWidth(visibleValue.slice(0, this.cursor).join('').replace(/\n/g, ' ')))}H\x1b[?25h` : '';
|
|
2884
|
+
this.writeFrame(lines, caret);
|
|
2885
|
+
return;
|
|
2886
|
+
}
|
|
2887
|
+
const inputRows = Math.min(choices?.length ?? layout.lines.length, Math.min(6, Math.max(1, height - 9)));
|
|
2888
|
+
const firstInput = Math.max(0, Math.min((choices ? choiceIndex : cursor.row) - inputRows + 1, (choices?.length ?? layout.lines.length) - inputRows));
|
|
2889
|
+
const completion = this.commandMatches();
|
|
2890
|
+
const popupRows = completion ? commandPopupRows(width, height, inputRows, completion.options.length) : 0;
|
|
2891
|
+
const popupHeight = popupRows ? popupRows + 2 : 0; // The composer's own todo block stands down while the panel is drawn: the panel's Plan and
|
|
2892
|
+
// Progress sections carry the same list, and one plan should not be reported twice on the
|
|
2893
|
+
// same screen. The panel is the copy that survives a wide terminal.
|
|
2894
|
+
const todoLines = this.dashboard || panelColumns ? [] : this.todoLines(Math.max(0, height - inputRows - 10 - popupHeight));
|
|
2895
|
+
const elapsed = this.workingElapsed + (this.workingSince === undefined ? 0 : Date.now() - this.workingSince);
|
|
2896
|
+
const seconds = Math.floor(elapsed / 1000);
|
|
2897
|
+
const thinkingLines = this.dashboard ? [] : this.thinkingLines(width, seconds, this.thinkingActive ? Math.max(1, Math.min(THINKING_ROWS + 1, height - inputRows - 8 - popupHeight - todoLines.length)) : 0);
|
|
2898
|
+
const transcriptHeight = height - inputRows - 8 - popupHeight - todoLines.length - Math.max(0, thinkingLines.length - 1);
|
|
2899
|
+
const prefix = [...(this.selectionCard(transcriptHeight) ?? this.welcome(width, transcriptHeight)), ...(this.transcript.diagnostics.omitted ? ['Some transcript entries are unavailable because session storage failed.'] : [])].flatMap(text => this.wrapTranscript(text, width));
|
|
2900
|
+
const page = this.transcript.window({ prefix, height: transcriptHeight, scroll: this.scroll,
|
|
2901
|
+
key: `${width}:${this.expandedTranscript}`, render: entry => this.transcriptRows(entry, width),
|
|
2902
|
+
revision: entry => entry.timing ? formatDuration(this.toolClock.elapsed(entry.timing)) ?? ''
|
|
2903
|
+
// The effective state, not just the explicit set: a box expanded by Ctrl+O and then
|
|
2904
|
+
// collapsed by hand must invalidate the cached row count, or the window would slice
|
|
2905
|
+
// against the taller expanded rendering and drop the box entirely.
|
|
2906
|
+
: entry.promptDisclosure ? (this.promptExpanded(entry.promptDisclosure.id) ? 'expanded' : 'collapsed') : '' });
|
|
2907
|
+
this.scroll = page.scroll;
|
|
2908
|
+
const visible = this.dashboard ? dashboardRows({ metrics: this.dashboardMetrics.snapshot(), selectedModel: this.dashboardModel, provider: this.status.provider, model: this.status.model, graph: this.status.graph, providerModels: this.status.providerModels, activeNodes: [...this.activeNodes.keys()], nodeModels: this.nodeModels, todos: this.todos, todoOffset: this.todoOffset, onTodoOffset: offset => { this.todoOffset = offset; }, graphOffset: this.dashboardGraphOffset, notices: this.dashboardNotices, question: this.pending && !this.pending.conversationPrompt ? this.pending.dashboardQuestion ?? this.pending.choiceTitle ?? this.pending.title ?? this.pending.label : undefined }, Math.max(2, width - 4), transcriptHeight).map(line => ({ text: panelRowText(line), color: DIM, segments: line.segments })) : page.rows;
|
|
2909
|
+
while (visible.length < transcriptHeight)
|
|
2910
|
+
visible.push({ text: '', color: DIM });
|
|
2911
|
+
if (!this.dashboard && this.scroll && visible.length)
|
|
2912
|
+
visible[0] = { text: `? Scrollback ? ${this.scroll} lines below ? Page Down to return`, color: DIM };
|
|
2913
|
+
this.expandedPromptVisible = visible.some(row => row.promptExpanded);
|
|
2914
|
+
const status = this.status;
|
|
2915
|
+
const top = this.dashboard ? `\u25c8 ${this.appName} \u00b7 Dashboard \u00b7 Ctrl+B transcript` : `\u25c8 ${this.appName}`;
|
|
2916
|
+
const version = clip(`v${this.version}`, Math.floor(width / 3));
|
|
2917
|
+
const header = paint(pad(top, width - stringWidth(version)), DIM) + paint(version, FAINT);
|
|
2918
|
+
const label = choices ? this.pending?.choiceTitle || 'Choose an answer' : this.pending?.title ? this.pending.title : this.pending && !this.pending.regular ? 'Your approval' : this.pending?.conversationPrompt && this.value[0] === '/' ? 'Commands · Enter runs · Tab completes' : this.steering && status.activity && status.activity !== 'Ready' ? status.activity === 'Paused' ? 'Paused - Send direction to resume' : 'Steer this run · Enter to send' : '';
|
|
2919
|
+
const borderLabel = label ? clip(` ${label} `, Math.max(0, width - 4)) : '';
|
|
2920
|
+
const timestamp = seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
2921
|
+
const progress = this.nodeProgress();
|
|
2922
|
+
const workingLabel = clip(`Working · ${progress ? `${progress} - ` : ''}${timestamp}`, width - 2);
|
|
2923
|
+
const wave = Math.floor(elapsed / 120) % 11;
|
|
2924
|
+
const workingLine = working ? ' ' + [...workingLabel].map((character, index) => paint(character, index < 7 && Math.abs(index - wave) <= 1 ? 255 : GRAY)).join('') : '';
|
|
2925
|
+
const lines = [header, paint(clip(` ${status.account ? `Account: ${oneLine(status.account.label)} | ` : ''}${oneLine(this.workspace)}`, width), FAINT), ...visible.map(line => line.segments ? ' ' + line.segments.map(segment => paint(segment.text, segment.color ?? GRAY)).join('') : paint(' ' + clip(line.text, width - 2), line.color)), ...(thinkingLines.length ? thinkingLines.map(line => paint(' ' + pad(line, width - 4), GRAY)) : [workingLine]), ...todoLines.map(line => paint(' ' + clip(line, width - 2), GRAY))];
|
|
2926
|
+
if (completion && popupRows) {
|
|
2927
|
+
const cardWidth = width - 4;
|
|
2928
|
+
const popupTitle = clip(' Commands · ↑↓ move · Enter runs · Tab completes ', cardWidth - 2);
|
|
2929
|
+
lines.push(paint(' ╭' + popupTitle + '─'.repeat(Math.max(0, cardWidth - 2 - stringWidth(popupTitle))) + '╮', GRAY));
|
|
2930
|
+
const first = Math.max(0, Math.min(completion.index - popupRows + 1, completion.options.length - popupRows));
|
|
2931
|
+
for (let index = 0; index < popupRows; index++) {
|
|
2932
|
+
const item = completion.options[first + index];
|
|
2933
|
+
const selected = !!item && first + index === completion.index;
|
|
2934
|
+
const label = item ? `${selected ? '›' : ' '} ${item} ${commandDescriptions[item]}` : 'No matching commands';
|
|
2935
|
+
const value = pad(label, cardWidth - 4);
|
|
2936
|
+
lines.push(paint(' │ ', GRAY) + (selected ? `\x1b[48;5;236m${paint(value, DIM)}\x1b[0m` : paint(value)) + paint(' │', GRAY));
|
|
2937
|
+
}
|
|
2938
|
+
lines.push(paint(' ╰' + '─'.repeat(cardWidth - 2) + '╯', GRAY));
|
|
2939
|
+
}
|
|
2940
|
+
lines.push(paint('╭' + borderLabel + '─'.repeat(Math.max(0, width - 2 - stringWidth(borderLabel))) + '╮', GRAY));
|
|
2941
|
+
for (let index = 0; index < inputRows; index++) {
|
|
2942
|
+
if (choices) {
|
|
2943
|
+
const item = choices[firstInput + index], selected = firstInput + index === choiceIndex;
|
|
2944
|
+
const text = oneLine(`${selected ? '›' : ' '} ${firstInput + index + 1}. ${item.label}${item.description ? ` — ${item.description}` : ''}`);
|
|
2945
|
+
lines.push(paint('│ ', GRAY) + paint(pad(text, width - 4), selected ? WHITE : DIM) + paint(' │', GRAY));
|
|
2946
|
+
continue;
|
|
2947
|
+
}
|
|
2948
|
+
const value = layout.lines[firstInput + index];
|
|
2949
|
+
const placeholder = !this.value.length && this.pending ? this.pending.regular ? this.pending.label || 'Describe a task… / for commands' : 'Type y to approve, or n to decline' : !this.value.length ? status.activity && status.activity !== 'Ready' ? this.steering ? status.activity === 'Paused' ? 'Paused - Send direction to resume, Ctrl+C again to exit' : 'Steer this run with a message… (Ctrl+C to pause)' : 'Ctrl+C to stop' : 'Ready for your next task' : '';
|
|
2950
|
+
const span = value && selection ? selectedColumns(visibleValue, layout.positions, selection, firstInput + index) : undefined;
|
|
2951
|
+
const tokens = value ? tokenColumns(this.value, visibleValue, layout.positions, firstInput + index) : [];
|
|
2952
|
+
lines.push(paint('│ ', GRAY) + (span || tokens.length ? composerRow(pad(value, width - 4), DIM, span, tokens) : paint(pad(value || placeholder, width - 4), value ? DIM : FAINT)) + paint(' │', GRAY));
|
|
2953
|
+
}
|
|
2954
|
+
const choiceHint = choices ? clip(' ↑↓ Choose · Enter confirm · Esc cancel ', width - 4) : this.attachments.length && this.conversationComposer() ? clip(` ${this.attachments.length} attached · Ctrl+X removes last · Ctrl+V pastes image `, width - 4) : '';
|
|
2955
|
+
lines.push(paint('╰' + choiceHint + '─'.repeat(Math.max(0, width - 2 - stringWidth(choiceHint))) + '╯', GRAY));
|
|
2956
|
+
const active = this.activeModel();
|
|
2957
|
+
const model = oneLine(`${active.label} · Thinking: ${active.reasoningEffort ?? 'provider default'}`);
|
|
2958
|
+
const branch = oneLine(status.branch || 'no branch');
|
|
2959
|
+
const branchWidth = Math.min(Math.floor(width / 3), stringWidth(branch) + 3);
|
|
2960
|
+
const jev = oneLine(status.account?.jevQuota ?? 'Jev unavailable').replace(/^Jev(?= )/, status.jevEnabled === false ? 'Jev [Disabled] ·' : status.jevEnabled === true ? 'Jev [Enabled] ·' : 'Jev');
|
|
2961
|
+
const jevWidth = Math.min(stringWidth(jev), width - 1);
|
|
2962
|
+
lines.push(paint(pad(model, Math.max(0, width - jevWidth - 2)) + (width - jevWidth > 1 ? ' ' : '') + clip(jev, jevWidth), GRAY));
|
|
2963
|
+
const graph = oneLine(`Graph: ${(status.graphSelection ?? (status.graph?.id === 'software-engineer' ? 'default' : status.graph?.id)) === 'default' ? 'Default' : status.graph?.name ?? 'Not selected'}${status.codeIntel ? ` · CodeGraph: ${status.codeIntel}` : ''}`);
|
|
2964
|
+
lines.push(paint(pad(graph, width - branchWidth) + clip(`⎇ ${branch}`, branchWidth), GRAY));
|
|
2965
|
+
const count = (value) => Number.isFinite(value) && value >= 0 ? value : 0;
|
|
2966
|
+
const compactTokens = Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 1 });
|
|
2967
|
+
const activeWindow = active.contextWindow;
|
|
2968
|
+
const context = activeWindow && Number.isFinite(activeWindow) && activeWindow > 0 ? ` · context: ${Math.floor((count(status.contextUsed) / activeWindow) * 100)}% (${compactTokens.format(count(status.contextUsed))}/${compactTokens.format(activeWindow)})` : '';
|
|
2969
|
+
const rate = this.displayRate();
|
|
2970
|
+
// The reading is the cumulative average decoding speed of the node currently shown:
|
|
2971
|
+
// totals only grow, so it holds unchanged between calls, across a pause, and after the
|
|
2972
|
+
// run ends - and it is drawn only while the model row names the model the average was
|
|
2973
|
+
// measured under. A session that has not finished one measured request reads 0 and the
|
|
2974
|
+
// row stays byte for byte the footer it was before this segment existed. The usage row
|
|
2975
|
+
// has one fixed allowance, and a permanent zero would spend it on a number that carries
|
|
2976
|
+
// no information - and it is what pushes the context percentage out of the row on an
|
|
2977
|
+
// 80-column terminal.
|
|
2978
|
+
const measured = rate > 0 ? ` · ${compactTokens.format(rate)} tok/s` : '';
|
|
2979
|
+
const counts = `${count(status.requests)} req · ${count(status.inputTokens)} in · ${count(status.outputTokens)} out`;
|
|
2980
|
+
const usage = `${counts}${measured}${context}`;
|
|
2981
|
+
const approval = status.permissions ? `Permissions: ${status.permissions}` : status.yolo ? 'Permissions: automatic approvals' : 'Permissions: ask before writes/shell';
|
|
2982
|
+
const footerWidth = width - 1;
|
|
2983
|
+
// Under width pressure the optional tail is dropped first - the context segment, as
|
|
2984
|
+
// documented. But the cumulative counts are unbounded and can spend the whole allowance
|
|
2985
|
+
// before the speed segment even starts, clipping it mid-word (`1K to`). While a speed is
|
|
2986
|
+
// being shown, the counts switch to the compact whole-number form the context segment
|
|
2987
|
+
// already uses so the complete `N tok/s` segment keeps its room; without a speed the
|
|
2988
|
+
// row behaves exactly as it did before this segment existed.
|
|
2989
|
+
const wholeTokens = Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 0 });
|
|
2990
|
+
const compactCounts = `${wholeTokens.format(count(status.requests))} req · ${wholeTokens.format(count(status.inputTokens))} in · ${wholeTokens.format(count(status.outputTokens))} out`;
|
|
2991
|
+
const usageCap = Math.floor(footerWidth * 0.6);
|
|
2992
|
+
let usageText = usage;
|
|
2993
|
+
let usageWidth;
|
|
2994
|
+
if (stringWidth(approval) + 1 + stringWidth(usage) <= footerWidth)
|
|
2995
|
+
usageWidth = stringWidth(usage);
|
|
2996
|
+
else if (measured) {
|
|
2997
|
+
usageText = [`${counts}${measured}`, `${compactCounts}${measured}`].find(candidate => stringWidth(candidate) <= usageCap) ?? compactCounts;
|
|
2998
|
+
usageWidth = Math.min(stringWidth(usageText), usageCap);
|
|
2999
|
+
}
|
|
3000
|
+
else
|
|
3001
|
+
usageWidth = Math.min(stringWidth(usage), usageCap);
|
|
3002
|
+
lines.push(paint(clip(pad(approval, footerWidth - usageWidth), footerWidth - usageWidth), status.yolo ? STATUS.warn : STATUS.ok) + paint(clip(usageText, usageWidth), WHITE));
|
|
3003
|
+
// The caret travels through the same diff as the rows: writing it straight to the output
|
|
3004
|
+
// would put an absolute cursor move and a show-cursor sequence on the wire every 120 ms
|
|
3005
|
+
// for the whole of an interactive run (cli.ts keeps steering on), and terminals that clear
|
|
3006
|
+
// or move a selection on cursor traffic would lose a drag over an otherwise untouched
|
|
3007
|
+
// frame. As a frame input it is suppressed whenever nothing was painted and the caret has
|
|
3008
|
+
// not moved, and re-emitted whenever a row repaint hid it.
|
|
3009
|
+
const caret = (this.pending || this.steering) && !choices ? `\x1b[${transcriptHeight + todoLines.length + popupHeight + Math.max(0, thinkingLines.length - 1) + 5 + cursor.row - firstInput};${3 + cursor.column}H\x1b[?25h` : '';
|
|
3010
|
+
this.writeFrame(this.composePanel(lines, this.panelRows(panelColumns, height), panelColumns, width), caret);
|
|
3011
|
+
}
|
|
3012
|
+
}
|