@bastani/atomic 0.7.17-1 → 0.8.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4183 -0
- package/README.md +655 -0
- package/dist/builtin/intercom/CHANGELOG.md +195 -0
- package/dist/builtin/intercom/LICENSE +21 -0
- package/dist/builtin/intercom/README.md +484 -0
- package/dist/builtin/intercom/broker/broker.ts +346 -0
- package/dist/builtin/intercom/broker/client.ts +535 -0
- package/dist/builtin/intercom/broker/framing.ts +57 -0
- package/dist/builtin/intercom/broker/paths.ts +21 -0
- package/dist/builtin/intercom/broker/spawn.ts +308 -0
- package/dist/builtin/intercom/config.ts +109 -0
- package/dist/builtin/intercom/index.ts +1780 -0
- package/dist/builtin/intercom/package.json +59 -0
- package/dist/builtin/intercom/reply-tracker.ts +102 -0
- package/dist/builtin/intercom/skills/intercom/SKILL.md +513 -0
- package/dist/builtin/intercom/types.ts +46 -0
- package/dist/builtin/intercom/ui/compose.ts +139 -0
- package/dist/builtin/intercom/ui/inline-message.ts +76 -0
- package/dist/builtin/intercom/ui/session-list.ts +162 -0
- package/dist/builtin/mcp/CHANGELOG.md +346 -0
- package/dist/builtin/mcp/LICENSE +21 -0
- package/dist/builtin/mcp/OAUTH.md +324 -0
- package/dist/builtin/mcp/README.md +373 -0
- package/dist/builtin/mcp/agent-dir.ts +21 -0
- package/dist/builtin/mcp/app-bridge.bundle.js +67 -0
- package/dist/builtin/mcp/cli.js +186 -0
- package/dist/builtin/mcp/commands.ts +420 -0
- package/dist/builtin/mcp/config.ts +667 -0
- package/dist/builtin/mcp/consent-manager.ts +64 -0
- package/dist/builtin/mcp/direct-tools.ts +427 -0
- package/dist/builtin/mcp/errors.ts +219 -0
- package/dist/builtin/mcp/glimpse-ui.ts +80 -0
- package/dist/builtin/mcp/host-html-template.ts +427 -0
- package/dist/builtin/mcp/index.ts +334 -0
- package/dist/builtin/mcp/init.ts +336 -0
- package/dist/builtin/mcp/lifecycle.ts +93 -0
- package/dist/builtin/mcp/logger.ts +169 -0
- package/dist/builtin/mcp/mcp-auth-flow.ts +362 -0
- package/dist/builtin/mcp/mcp-auth.ts +297 -0
- package/dist/builtin/mcp/mcp-callback-server.ts +284 -0
- package/dist/builtin/mcp/mcp-oauth-provider.ts +302 -0
- package/dist/builtin/mcp/mcp-panel.ts +826 -0
- package/dist/builtin/mcp/mcp-setup-panel.ts +577 -0
- package/dist/builtin/mcp/metadata-cache.ts +201 -0
- package/dist/builtin/mcp/npx-resolver.ts +424 -0
- package/dist/builtin/mcp/oauth-handler.ts +60 -0
- package/dist/builtin/mcp/onboarding-state.ts +68 -0
- package/dist/builtin/mcp/package.json +61 -0
- package/dist/builtin/mcp/proxy-modes.ts +803 -0
- package/dist/builtin/mcp/resource-tools.ts +17 -0
- package/dist/builtin/mcp/sampling-handler.ts +268 -0
- package/dist/builtin/mcp/server-manager.ts +375 -0
- package/dist/builtin/mcp/state.ts +41 -0
- package/dist/builtin/mcp/tool-metadata.ts +152 -0
- package/dist/builtin/mcp/tool-registrar.ts +46 -0
- package/dist/builtin/mcp/tool-result-renderer.ts +65 -0
- package/dist/builtin/mcp/types.ts +441 -0
- package/dist/builtin/mcp/ui-resource-handler.ts +145 -0
- package/dist/builtin/mcp/ui-server.ts +623 -0
- package/dist/builtin/mcp/ui-session.ts +384 -0
- package/dist/builtin/mcp/ui-stream-types.ts +89 -0
- package/dist/builtin/mcp/utils.ts +129 -0
- package/dist/builtin/subagents/CHANGELOG.md +1019 -0
- package/dist/builtin/subagents/README.md +991 -0
- package/dist/builtin/subagents/agents/code-simplifier.md +84 -0
- package/dist/builtin/subagents/agents/codebase-analyzer.md +158 -0
- package/dist/builtin/subagents/agents/codebase-locator.md +113 -0
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +317 -0
- package/dist/builtin/subagents/agents/codebase-pattern-finder.md +236 -0
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +181 -0
- package/dist/builtin/subagents/agents/codebase-research-locator.md +146 -0
- package/dist/builtin/subagents/agents/debugger.md +92 -0
- package/dist/builtin/subagents/package.json +67 -0
- package/dist/builtin/subagents/prompts/gather-context-and-clarify.md +20 -0
- package/dist/builtin/subagents/prompts/parallel-cleanup.md +60 -0
- package/dist/builtin/subagents/prompts/parallel-context-build.md +55 -0
- package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +77 -0
- package/dist/builtin/subagents/prompts/parallel-research.md +58 -0
- package/dist/builtin/subagents/prompts/parallel-review.md +52 -0
- package/dist/builtin/subagents/prompts/review-loop.md +48 -0
- package/dist/builtin/subagents/skills/subagent/SKILL.md +734 -0
- package/dist/builtin/subagents/src/agents/agent-management.ts +644 -0
- package/dist/builtin/subagents/src/agents/agent-scope.ts +6 -0
- package/dist/builtin/subagents/src/agents/agent-selection.ts +23 -0
- package/dist/builtin/subagents/src/agents/agent-serializer.ts +84 -0
- package/dist/builtin/subagents/src/agents/agents.ts +809 -0
- package/dist/builtin/subagents/src/agents/chain-serializer.ts +137 -0
- package/dist/builtin/subagents/src/agents/frontmatter.ts +29 -0
- package/dist/builtin/subagents/src/agents/identity.ts +30 -0
- package/dist/builtin/subagents/src/agents/skills.ts +630 -0
- package/dist/builtin/subagents/src/extension/control-notices.ts +92 -0
- package/dist/builtin/subagents/src/extension/doctor.ts +199 -0
- package/dist/builtin/subagents/src/extension/index.ts +586 -0
- package/dist/builtin/subagents/src/extension/schemas.ts +168 -0
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +378 -0
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +269 -0
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +612 -0
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +267 -0
- package/dist/builtin/subagents/src/runs/background/async-resume.ts +332 -0
- package/dist/builtin/subagents/src/runs/background/async-status.ts +295 -0
- package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +63 -0
- package/dist/builtin/subagents/src/runs/background/notify.ts +108 -0
- package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +45 -0
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +250 -0
- package/dist/builtin/subagents/src/runs/background/run-status.ts +193 -0
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +291 -0
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +1760 -0
- package/dist/builtin/subagents/src/runs/background/top-level-async.ts +13 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +1333 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +932 -0
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +902 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +2231 -0
- package/dist/builtin/subagents/src/runs/shared/completion-guard.ts +125 -0
- package/dist/builtin/subagents/src/runs/shared/long-running-guard.ts +175 -0
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +103 -0
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +108 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +163 -0
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +115 -0
- package/dist/builtin/subagents/src/runs/shared/run-history.ts +56 -0
- package/dist/builtin/subagents/src/runs/shared/single-output.ts +154 -0
- package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +226 -0
- package/dist/builtin/subagents/src/runs/shared/subagent-prompt-runtime.ts +152 -0
- package/dist/builtin/subagents/src/runs/shared/worktree.ts +577 -0
- package/dist/builtin/subagents/src/shared/artifacts.ts +99 -0
- package/dist/builtin/subagents/src/shared/atomic-json.ts +16 -0
- package/dist/builtin/subagents/src/shared/file-coalescer.ts +40 -0
- package/dist/builtin/subagents/src/shared/fork-context.ts +76 -0
- package/dist/builtin/subagents/src/shared/formatters.ts +133 -0
- package/dist/builtin/subagents/src/shared/jsonl-writer.ts +81 -0
- package/dist/builtin/subagents/src/shared/model-info.ts +78 -0
- package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +85 -0
- package/dist/builtin/subagents/src/shared/session-identity.ts +10 -0
- package/dist/builtin/subagents/src/shared/session-tokens.ts +44 -0
- package/dist/builtin/subagents/src/shared/settings.ts +397 -0
- package/dist/builtin/subagents/src/shared/status-format.ts +49 -0
- package/dist/builtin/subagents/src/shared/types.ts +732 -0
- package/dist/builtin/subagents/src/shared/utils.ts +440 -0
- package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +397 -0
- package/dist/builtin/subagents/src/slash/slash-bridge.ts +174 -0
- package/dist/builtin/subagents/src/slash/slash-commands.ts +528 -0
- package/dist/builtin/subagents/src/slash/slash-live-state.ts +292 -0
- package/dist/builtin/subagents/src/tui/render-helpers.ts +80 -0
- package/dist/builtin/subagents/src/tui/render.ts +1257 -0
- package/dist/builtin/web-access/CHANGELOG.md +387 -0
- package/dist/builtin/web-access/LICENSE +21 -0
- package/dist/builtin/web-access/README.md +346 -0
- package/dist/builtin/web-access/activity.ts +101 -0
- package/dist/builtin/web-access/chrome-cookies.ts +322 -0
- package/dist/builtin/web-access/code-search.ts +107 -0
- package/dist/builtin/web-access/curator-page.ts +3359 -0
- package/dist/builtin/web-access/curator-server.ts +605 -0
- package/dist/builtin/web-access/exa.ts +521 -0
- package/dist/builtin/web-access/extract.ts +701 -0
- package/dist/builtin/web-access/gemini-api.ts +113 -0
- package/dist/builtin/web-access/gemini-search.ts +362 -0
- package/dist/builtin/web-access/gemini-url-context.ts +126 -0
- package/dist/builtin/web-access/gemini-web-config.ts +54 -0
- package/dist/builtin/web-access/gemini-web.ts +396 -0
- package/dist/builtin/web-access/github-api.ts +196 -0
- package/dist/builtin/web-access/github-extract.ts +635 -0
- package/dist/builtin/web-access/index.ts +2347 -0
- package/dist/builtin/web-access/package.json +54 -0
- package/dist/builtin/web-access/pdf-extract.ts +192 -0
- package/dist/builtin/web-access/perplexity.ts +196 -0
- package/dist/builtin/web-access/rsc-extract.ts +338 -0
- package/dist/builtin/web-access/storage.ts +72 -0
- package/dist/builtin/web-access/summary-review.ts +276 -0
- package/dist/builtin/web-access/utils.ts +44 -0
- package/dist/builtin/web-access/video-extract.ts +379 -0
- package/dist/builtin/web-access/youtube-extract.ts +311 -0
- package/dist/builtin/workflows/CHANGELOG.md +20 -0
- package/dist/builtin/workflows/README.md +323 -0
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +567 -0
- package/dist/builtin/workflows/builtin/index.ts +10 -0
- package/dist/builtin/workflows/builtin/open-claude-design.ts +985 -0
- package/dist/builtin/workflows/builtin/ralph.ts +613 -0
- package/dist/builtin/workflows/package.json +89 -0
- package/dist/builtin/workflows/skills/create-spec/SKILL.md +247 -0
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +173 -0
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +190 -0
- package/dist/builtin/workflows/skills/impeccable/reference/animate.md +175 -0
- package/dist/builtin/workflows/skills/impeccable/reference/audit.md +133 -0
- package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +113 -0
- package/dist/builtin/workflows/skills/impeccable/reference/brand.md +118 -0
- package/dist/builtin/workflows/skills/impeccable/reference/clarify.md +174 -0
- package/dist/builtin/workflows/skills/impeccable/reference/codex.md +105 -0
- package/dist/builtin/workflows/skills/impeccable/reference/cognitive-load.md +106 -0
- package/dist/builtin/workflows/skills/impeccable/reference/color-and-contrast.md +105 -0
- package/dist/builtin/workflows/skills/impeccable/reference/colorize.md +154 -0
- package/dist/builtin/workflows/skills/impeccable/reference/craft.md +123 -0
- package/dist/builtin/workflows/skills/impeccable/reference/critique.md +261 -0
- package/dist/builtin/workflows/skills/impeccable/reference/delight.md +302 -0
- package/dist/builtin/workflows/skills/impeccable/reference/distill.md +111 -0
- package/dist/builtin/workflows/skills/impeccable/reference/document.md +427 -0
- package/dist/builtin/workflows/skills/impeccable/reference/extract.md +69 -0
- package/dist/builtin/workflows/skills/impeccable/reference/harden.md +347 -0
- package/dist/builtin/workflows/skills/impeccable/reference/heuristics-scoring.md +234 -0
- package/dist/builtin/workflows/skills/impeccable/reference/interaction-design.md +195 -0
- package/dist/builtin/workflows/skills/impeccable/reference/layout.md +141 -0
- package/dist/builtin/workflows/skills/impeccable/reference/live.md +622 -0
- package/dist/builtin/workflows/skills/impeccable/reference/motion-design.md +109 -0
- package/dist/builtin/workflows/skills/impeccable/reference/onboard.md +234 -0
- package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +258 -0
- package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +130 -0
- package/dist/builtin/workflows/skills/impeccable/reference/personas.md +179 -0
- package/dist/builtin/workflows/skills/impeccable/reference/polish.md +242 -0
- package/dist/builtin/workflows/skills/impeccable/reference/product.md +62 -0
- package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +99 -0
- package/dist/builtin/workflows/skills/impeccable/reference/responsive-design.md +114 -0
- package/dist/builtin/workflows/skills/impeccable/reference/shape.md +165 -0
- package/dist/builtin/workflows/skills/impeccable/reference/spatial-design.md +100 -0
- package/dist/builtin/workflows/skills/impeccable/reference/teach.md +156 -0
- package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +124 -0
- package/dist/builtin/workflows/skills/impeccable/reference/typography.md +159 -0
- package/dist/builtin/workflows/skills/impeccable/reference/ux-writing.md +107 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +94 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +226 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/design-parser.mjs +820 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detect-csp.mjs +198 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/impeccable-paths.mjs +110 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/is-generated.mjs +69 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +646 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser-session.js +123 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +4865 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-complete.mjs +75 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-completion.mjs +18 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +446 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +200 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-resume.mjs +48 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +847 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-session-store.mjs +254 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +47 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +632 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +247 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/load-context.mjs +141 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +214 -0
- package/dist/builtin/workflows/skills/playwright-cli/SKILL.md +392 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/element-attributes.md +23 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/request-mocking.md +87 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/running-code.md +241 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/session-management.md +225 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/spec-driven-testing.md +305 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/storage-state.md +275 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/test-generation.md +134 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/tracing.md +139 -0
- package/dist/builtin/workflows/skills/playwright-cli/references/video-recording.md +143 -0
- package/dist/builtin/workflows/skills/prompt-engineer/SKILL.md +263 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/advanced_patterns.md +271 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/core_prompting.md +137 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/quality_improvement.md +193 -0
- package/dist/builtin/workflows/skills/research-codebase/SKILL.md +226 -0
- package/dist/builtin/workflows/skills/tdd/SKILL.md +109 -0
- package/dist/builtin/workflows/skills/tdd/deep-modules.md +33 -0
- package/dist/builtin/workflows/skills/tdd/interface-design.md +31 -0
- package/dist/builtin/workflows/skills/tdd/mocking.md +59 -0
- package/dist/builtin/workflows/skills/tdd/refactoring.md +10 -0
- package/dist/builtin/workflows/skills/tdd/tests.md +61 -0
- package/dist/builtin/workflows/skills/workflow/SKILL.md +255 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/advanced-evaluation.md +404 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/bdi-mental-states.md +313 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-compression.md +274 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-degradation.md +208 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-fundamentals.md +203 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-optimization.md +197 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/evaluation.md +253 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/filesystem-context.md +289 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/hosted-agents.md +262 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/memory-systems.md +221 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/multi-agent-patterns.md +259 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/project-development.md +293 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering/tool-design.md +273 -0
- package/dist/builtin/workflows/skills/workflow/references/context-engineering.md +23 -0
- package/dist/builtin/workflows/skills/workflow/references/design-checklist.md +79 -0
- package/dist/builtin/workflows/skills/workflow/references/running-workflows.md +107 -0
- package/dist/builtin/workflows/skills/workflow/references/sdk-authoring.md +140 -0
- package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +168 -0
- package/dist/builtin/workflows/src/extension/companions.ts +210 -0
- package/dist/builtin/workflows/src/extension/config-loader.ts +493 -0
- package/dist/builtin/workflows/src/extension/discovery.ts +501 -0
- package/dist/builtin/workflows/src/extension/dispatcher.ts +173 -0
- package/dist/builtin/workflows/src/extension/index.ts +2143 -0
- package/dist/builtin/workflows/src/extension/mcp.ts +110 -0
- package/dist/builtin/workflows/src/extension/render-call.ts +39 -0
- package/dist/builtin/workflows/src/extension/render-result.ts +214 -0
- package/dist/builtin/workflows/src/extension/renderers.ts +87 -0
- package/dist/builtin/workflows/src/extension/runtime.ts +360 -0
- package/dist/builtin/workflows/src/extension/status-writer.ts +167 -0
- package/dist/builtin/workflows/src/extension/wiring.ts +555 -0
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +102 -0
- package/dist/builtin/workflows/src/index.ts +25 -0
- package/dist/builtin/workflows/src/intercom/intercom-bridge.ts +93 -0
- package/dist/builtin/workflows/src/intercom/intercom-routing.ts +125 -0
- package/dist/builtin/workflows/src/intercom/result-intercom.ts +240 -0
- package/dist/builtin/workflows/src/runs/background/cancellation-registry.ts +113 -0
- package/dist/builtin/workflows/src/runs/background/job-tracker.ts +81 -0
- package/dist/builtin/workflows/src/runs/background/runner.ts +152 -0
- package/dist/builtin/workflows/src/runs/background/status.ts +354 -0
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +1522 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +233 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +712 -0
- package/dist/builtin/workflows/src/runs/shared/concurrency.ts +76 -0
- package/dist/builtin/workflows/src/runs/shared/graph-inference.ts +69 -0
- package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +293 -0
- package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +83 -0
- package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +170 -0
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +577 -0
- package/dist/builtin/workflows/src/shared/persistence-compaction-policy.ts +72 -0
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +257 -0
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +145 -0
- package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +196 -0
- package/dist/builtin/workflows/src/shared/store-types.ts +160 -0
- package/dist/builtin/workflows/src/shared/store.ts +579 -0
- package/dist/builtin/workflows/src/shared/types.ts +566 -0
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +224 -0
- package/dist/builtin/workflows/src/tui/chat-surface.ts +511 -0
- package/dist/builtin/workflows/src/tui/color-utils.ts +64 -0
- package/dist/builtin/workflows/src/tui/connectors.ts +88 -0
- package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +307 -0
- package/dist/builtin/workflows/src/tui/edge.ts +24 -0
- package/dist/builtin/workflows/src/tui/graph-canvas.ts +108 -0
- package/dist/builtin/workflows/src/tui/graph-theme.ts +283 -0
- package/dist/builtin/workflows/src/tui/graph-view.ts +1217 -0
- package/dist/builtin/workflows/src/tui/header.ts +172 -0
- package/dist/builtin/workflows/src/tui/inline-form-card.ts +421 -0
- package/dist/builtin/workflows/src/tui/inline-form-editor.ts +638 -0
- package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +326 -0
- package/dist/builtin/workflows/src/tui/inline-form-store.ts +78 -0
- package/dist/builtin/workflows/src/tui/inputs-overlay.ts +163 -0
- package/dist/builtin/workflows/src/tui/inputs-picker.ts +888 -0
- package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +154 -0
- package/dist/builtin/workflows/src/tui/layout.ts +153 -0
- package/dist/builtin/workflows/src/tui/node-card.ts +274 -0
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +277 -0
- package/dist/builtin/workflows/src/tui/prompt-card.ts +501 -0
- package/dist/builtin/workflows/src/tui/renderers.ts +15 -0
- package/dist/builtin/workflows/src/tui/run-detail.ts +339 -0
- package/dist/builtin/workflows/src/tui/session-confirm.ts +202 -0
- package/dist/builtin/workflows/src/tui/session-list.ts +32 -0
- package/dist/builtin/workflows/src/tui/session-overlays.ts +239 -0
- package/dist/builtin/workflows/src/tui/session-picker.ts +399 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +1873 -0
- package/dist/builtin/workflows/src/tui/status-helpers.ts +73 -0
- package/dist/builtin/workflows/src/tui/status-list.ts +361 -0
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +206 -0
- package/dist/builtin/workflows/src/tui/switcher.ts +121 -0
- package/dist/builtin/workflows/src/tui/text-helpers.ts +31 -0
- package/dist/builtin/workflows/src/tui/toast.ts +106 -0
- package/dist/builtin/workflows/src/tui/widget.ts +348 -0
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +285 -0
- package/dist/builtin/workflows/src/tui/workflow-list.ts +224 -0
- package/dist/builtin/workflows/src/workflows/define-workflow.ts +150 -0
- package/dist/builtin/workflows/src/workflows/identity.ts +39 -0
- package/dist/builtin/workflows/src/workflows/registry.ts +113 -0
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +9 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/bun/restore-sandbox-env.d.ts +13 -0
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
- package/dist/bun/restore-sandbox-env.js +32 -0
- package/dist/bun/restore-sandbox-env.js.map +1 -0
- package/dist/cli/args.d.ts +53 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +341 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/config-selector.d.ts +14 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/file-processor.d.ts +15 -0
- package/dist/cli/file-processor.d.ts.map +1 -0
- package/dist/cli/file-processor.js +83 -0
- package/dist/cli/file-processor.js.map +1 -0
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli/list-models.d.ts +9 -0
- package/dist/cli/list-models.d.ts.map +1 -0
- package/dist/cli/list-models.js +98 -0
- package/dist/cli/list-models.js.map +1 -0
- package/dist/cli/session-picker.d.ts +9 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +35 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +20 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +102 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +411 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts +117 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +292 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +86 -0
- package/dist/core/agent-session-services.d.ts.map +1 -0
- package/dist/core/agent-session-services.js +117 -0
- package/dist/core/agent-session-services.js.map +1 -0
- package/dist/core/agent-session.d.ts +595 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +2518 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-guidance.d.ts +5 -0
- package/dist/core/auth-guidance.d.ts.map +1 -0
- package/dist/core/auth-guidance.js +21 -0
- package/dist/core/auth-guidance.js.map +1 -0
- package/dist/core/auth-storage.d.ts +141 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +437 -0
- package/dist/core/auth-storage.js.map +1 -0
- package/dist/core/bash-executor.d.ts +32 -0
- package/dist/core/bash-executor.d.ts.map +1 -0
- package/dist/core/bash-executor.js +111 -0
- package/dist/core/bash-executor.js.map +1 -0
- package/dist/core/builtin-packages.d.ts +14 -0
- package/dist/core/builtin-packages.d.ts.map +1 -0
- package/dist/core/builtin-packages.js +113 -0
- package/dist/core/builtin-packages.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +88 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
- package/dist/core/compaction/branch-summarization.js +243 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +121 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -0
- package/dist/core/compaction/compaction.js +615 -0
- package/dist/core/compaction/compaction.js.map +1 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.d.ts.map +1 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/index.js.map +1 -0
- package/dist/core/compaction/utils.d.ts +38 -0
- package/dist/core/compaction/utils.d.ts.map +1 -0
- package/dist/core/compaction/utils.js +153 -0
- package/dist/core/compaction/utils.js.map +1 -0
- package/dist/core/defaults.d.ts +3 -0
- package/dist/core/defaults.d.ts.map +1 -0
- package/dist/core/defaults.js +2 -0
- package/dist/core/defaults.js.map +1 -0
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/event-bus.d.ts +9 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/exec.d.ts +29 -0
- package/dist/core/exec.d.ts.map +1 -0
- package/dist/core/exec.js +75 -0
- package/dist/core/exec.js.map +1 -0
- package/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
- package/dist/core/export-html/ansi-to-html.js +249 -0
- package/dist/core/export-html/ansi-to-html.js.map +1 -0
- package/dist/core/export-html/index.d.ts +37 -0
- package/dist/core/export-html/index.d.ts.map +1 -0
- package/dist/core/export-html/index.js +224 -0
- package/dist/core/export-html/index.js.map +1 -0
- package/dist/core/export-html/template.css +1066 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1834 -0
- package/dist/core/export-html/tool-renderer.d.ts +34 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/dist/core/export-html/tool-renderer.js +108 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.d.ts +12 -0
- package/dist/core/extensions/index.d.ts.map +1 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/index.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +24 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +501 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +159 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +817 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +1173 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/extensions/types.js +45 -0
- package/dist/core/extensions/types.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts +20 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -0
- package/dist/core/extensions/wrapper.js +22 -0
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/footer-data-provider.d.ts +52 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -0
- package/dist/core/footer-data-provider.js +309 -0
- package/dist/core/footer-data-provider.js.map +1 -0
- package/dist/core/index.d.ts +12 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/keybindings.d.ts +353 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +294 -0
- package/dist/core/keybindings.js.map +1 -0
- package/dist/core/messages.d.ts +77 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +123 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/model-registry.d.ts +150 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +726 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +110 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +493 -0
- package/dist/core/model-resolver.js.map +1 -0
- package/dist/core/output-guard.d.ts +6 -0
- package/dist/core/output-guard.d.ts.map +1 -0
- package/dist/core/output-guard.js +59 -0
- package/dist/core/output-guard.js.map +1 -0
- package/dist/core/package-manager.d.ts +198 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +1970 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +52 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/prompt-templates.js +250 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/provider-display-names.d.ts +2 -0
- package/dist/core/provider-display-names.d.ts.map +1 -0
- package/dist/core/provider-display-names.js +33 -0
- package/dist/core/provider-display-names.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +23 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -0
- package/dist/core/resolve-config-value.js +126 -0
- package/dist/core/resolve-config-value.js.map +1 -0
- package/dist/core/resource-loader.d.ts +196 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +698 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +107 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +291 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/session-cwd.d.ts +19 -0
- package/dist/core/session-cwd.d.ts.map +1 -0
- package/dist/core/session-cwd.js +37 -0
- package/dist/core/session-cwd.js.map +1 -0
- package/dist/core/session-manager.d.ts +333 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +1118 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/settings-manager.d.ts +261 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +773 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +60 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +404 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/slash-commands.d.ts +14 -0
- package/dist/core/slash-commands.d.ts.map +1 -0
- package/dist/core/slash-commands.js +25 -0
- package/dist/core/slash-commands.js.map +1 -0
- package/dist/core/source-info.d.ts +18 -0
- package/dist/core/source-info.d.ts.map +1 -0
- package/dist/core/source-info.js +19 -0
- package/dist/core/source-info.js.map +1 -0
- package/dist/core/system-prompt.d.ts +28 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +120 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/telemetry.d.ts +3 -0
- package/dist/core/telemetry.d.ts.map +1 -0
- package/dist/core/telemetry.js +10 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/timings.d.ts +8 -0
- package/dist/core/timings.d.ts.map +1 -0
- package/dist/core/timings.js +32 -0
- package/dist/core/timings.js.map +1 -0
- package/dist/core/tools/ask-user-question/ask-user-question.d.ts +10 -0
- package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/ask-user-question.js +82 -0
- package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -0
- package/dist/core/tools/ask-user-question/config.d.ts +11 -0
- package/dist/core/tools/ask-user-question/config.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/config.js +34 -0
- package/dist/core/tools/ask-user-question/config.js.map +1 -0
- package/dist/core/tools/ask-user-question/index.d.ts +19 -0
- package/dist/core/tools/ask-user-question/index.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/index.js +19 -0
- package/dist/core/tools/ask-user-question/index.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts +36 -0
- package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/build-questionnaire.js +213 -0
- package/dist/core/tools/ask-user-question/state/build-questionnaire.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/key-router.d.ts +53 -0
- package/dist/core/tools/ask-user-question/state/key-router.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/key-router.js +240 -0
- package/dist/core/tools/ask-user-question/state/key-router.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +61 -0
- package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/questionnaire-session.js +147 -0
- package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/row-intent.d.ts +91 -0
- package/dist/core/tools/ask-user-question/state/row-intent.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/row-intent.js +91 -0
- package/dist/core/tools/ask-user-question/state/row-intent.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts +21 -0
- package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/contract.js +2 -0
- package/dist/core/tools/ask-user-question/state/selectors/contract.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/derivations.d.ts +44 -0
- package/dist/core/tools/ask-user-question/state/selectors/derivations.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/derivations.js +76 -0
- package/dist/core/tools/ask-user-question/state/selectors/derivations.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/focus.d.ts +15 -0
- package/dist/core/tools/ask-user-question/state/selectors/focus.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/focus.js +18 -0
- package/dist/core/tools/ask-user-question/state/selectors/focus.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts +16 -0
- package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/projections.js +71 -0
- package/dist/core/tools/ask-user-question/state/selectors/projections.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/state-reducer.d.ts +44 -0
- package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/state-reducer.js +239 -0
- package/dist/core/tools/ask-user-question/state/state-reducer.js.map +1 -0
- package/dist/core/tools/ask-user-question/state/state.d.ts +42 -0
- package/dist/core/tools/ask-user-question/state/state.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/state/state.js +2 -0
- package/dist/core/tools/ask-user-question/state/state.js.map +1 -0
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts +30 -0
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/tool/format-answer.js +39 -0
- package/dist/core/tools/ask-user-question/tool/format-answer.js.map +1 -0
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts +29 -0
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/tool/response-envelope.js +46 -0
- package/dist/core/tools/ask-user-question/tool/response-envelope.js.map +1 -0
- package/dist/core/tools/ask-user-question/tool/types.d.ts +113 -0
- package/dist/core/tools/ask-user-question/tool/types.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/tool/types.js +81 -0
- package/dist/core/tools/ask-user-question/tool/types.js.map +1 -0
- package/dist/core/tools/ask-user-question/tool/validate-questionnaire.d.ts +21 -0
- package/dist/core/tools/ask-user-question/tool/validate-questionnaire.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/tool/validate-questionnaire.js +49 -0
- package/dist/core/tools/ask-user-question/tool/validate-questionnaire.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/body-residual-spacer.d.ts +18 -0
- package/dist/core/tools/ask-user-question/view/body-residual-spacer.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/body-residual-spacer.js +21 -0
- package/dist/core/tools/ask-user-question/view/body-residual-spacer.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/component-binding.d.ts +23 -0
- package/dist/core/tools/ask-user-question/view/component-binding.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/component-binding.js +16 -0
- package/dist/core/tools/ask-user-question/view/component-binding.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts +40 -0
- package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/chat-row-view.js +31 -0
- package/dist/core/tools/ask-user-question/view/components/chat-row-view.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts +35 -0
- package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/multi-select-view.js +91 -0
- package/dist/core/tools/ask-user-question/view/components/multi-select-view.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts +43 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.js +37 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts +36 -0
- package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js +66 -0
- package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts +46 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js +69 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.d.ts +39 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.js +76 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-box-renderer.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.d.ts +116 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.js +173 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.d.ts +66 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.js +124 -0
- package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts +37 -0
- package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/submit-picker.js +44 -0
- package/dist/core/tools/ask-user-question/view/components/submit-picker.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts +32 -0
- package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/tab-bar.js +33 -0
- package/dist/core/tools/ask-user-question/view/components/tab-bar.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts +122 -0
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +161 -0
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts +66 -0
- package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/dialog-builder.js +85 -0
- package/dist/core/tools/ask-user-question/view/dialog-builder.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/props-adapter.d.ts +58 -0
- package/dist/core/tools/ask-user-question/view/props-adapter.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/props-adapter.js +67 -0
- package/dist/core/tools/ask-user-question/view/props-adapter.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/stateful-view.d.ts +24 -0
- package/dist/core/tools/ask-user-question/view/stateful-view.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/stateful-view.js +2 -0
- package/dist/core/tools/ask-user-question/view/stateful-view.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/tab-components.d.ts +15 -0
- package/dist/core/tools/ask-user-question/view/tab-components.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/tab-components.js +2 -0
- package/dist/core/tools/ask-user-question/view/tab-components.js.map +1 -0
- package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts +71 -0
- package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts.map +1 -0
- package/dist/core/tools/ask-user-question/view/tab-content-strategy.js +129 -0
- package/dist/core/tools/ask-user-question/view/tab-content-strategy.js.map +1 -0
- package/dist/core/tools/bash.d.ts +68 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +338 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +85 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +338 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +49 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +324 -0
- package/dist/core/tools/edit.js.map +1 -0
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +37 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.d.ts +35 -0
- package/dist/core/tools/find.d.ts.map +1 -0
- package/dist/core/tools/find.js +298 -0
- package/dist/core/tools/find.js.map +1 -0
- package/dist/core/tools/grep.d.ts +37 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +304 -0
- package/dist/core/tools/grep.js.map +1 -0
- package/dist/core/tools/index.d.ts +42 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +139 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/ls.d.ts +37 -0
- package/dist/core/tools/ls.d.ts.map +1 -0
- package/dist/core/tools/ls.js +169 -0
- package/dist/core/tools/ls.js.map +1 -0
- package/dist/core/tools/output-accumulator.d.ts +50 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -0
- package/dist/core/tools/output-accumulator.js +172 -0
- package/dist/core/tools/output-accumulator.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts +8 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -0
- package/dist/core/tools/path-utils.js +81 -0
- package/dist/core/tools/path-utils.js.map +1 -0
- package/dist/core/tools/read.d.ts +35 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +289 -0
- package/dist/core/tools/read.js.map +1 -0
- package/dist/core/tools/render-utils.d.ts +21 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -0
- package/dist/core/tools/render-utils.js +49 -0
- package/dist/core/tools/render-utils.js.map +1 -0
- package/dist/core/tools/todos.d.ts +35 -0
- package/dist/core/tools/todos.d.ts.map +1 -0
- package/dist/core/tools/todos.js +906 -0
- package/dist/core/tools/todos.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.js +34 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
- package/dist/core/tools/truncate.d.ts +70 -0
- package/dist/core/tools/truncate.d.ts.map +1 -0
- package/dist/core/tools/truncate.js +205 -0
- package/dist/core/tools/truncate.js.map +1 -0
- package/dist/core/tools/write.d.ts +26 -0
- package/dist/core/tools/write.d.ts.map +1 -0
- package/dist/core/tools/write.js +212 -0
- package/dist/core/tools/write.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +13 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +586 -0
- package/dist/main.js.map +1 -0
- package/dist/migrations.d.ts +33 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +281 -0
- package/dist/migrations.js.map +1 -0
- package/dist/modes/index.d.ts +9 -0
- package/dist/modes/index.d.ts.map +1 -0
- package/dist/modes/index.js +8 -0
- package/dist/modes/index.js.map +1 -0
- package/dist/modes/interactive/assets/clankolas.png +3 -0
- package/dist/modes/interactive/components/armin.d.ts +34 -0
- package/dist/modes/interactive/components/armin.d.ts.map +1 -0
- package/dist/modes/interactive/components/armin.js +329 -0
- package/dist/modes/interactive/components/armin.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +20 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +116 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +34 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/bash-execution.js +170 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.js +51 -0
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.js +42 -0
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +43 -0
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts +71 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +496 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.js +28 -0
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +29 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-editor.js +113 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +20 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-message.js +74 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -0
- package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
- package/dist/modes/interactive/components/daxnuts.js +138 -0
- package/dist/modes/interactive/components/daxnuts.js.map +1 -0
- package/dist/modes/interactive/components/diff.d.ts +12 -0
- package/dist/modes/interactive/components/diff.d.ts.map +1 -0
- package/dist/modes/interactive/components/diff.js +151 -0
- package/dist/modes/interactive/components/diff.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.js +20 -0
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
- package/dist/modes/interactive/components/earendil-announcement.js +40 -0
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +20 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-editor.js +106 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts +23 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-input.js +55 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +26 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-selector.js +75 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +27 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -0
- package/dist/modes/interactive/components/footer.js +199 -0
- package/dist/modes/interactive/components/footer.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +32 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +33 -0
- package/dist/modes/interactive/components/index.js.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.js +36 -0
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +46 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
- package/dist/modes/interactive/components/login-dialog.js +158 -0
- package/dist/modes/interactive/components/login-dialog.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +47 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-selector.js +266 -0
- package/dist/modes/interactive/components/model-selector.js.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +31 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.js +156 -0
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +286 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.js +155 -0
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +96 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector.js +836 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +67 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-selector.js +371 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.js +38 -0
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +45 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/theme-selector.js +48 -0
- package/dist/modes/interactive/components/theme-selector.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.js +50 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +63 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +280 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +89 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/tree-selector.js +1079 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.js +111 -0
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +10 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message.js +28 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.js +33 -0
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +369 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +4709 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -0
- package/dist/modes/interactive/theme/catppuccin-frappe.json +90 -0
- package/dist/modes/interactive/theme/catppuccin-latte.json +90 -0
- package/dist/modes/interactive/theme/catppuccin-macchiato.json +90 -0
- package/dist/modes/interactive/theme/catppuccin-mocha.json +90 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.d.ts +81 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +970 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -0
- package/dist/modes/interactive/whimsical-messages.d.ts +5 -0
- package/dist/modes/interactive/whimsical-messages.d.ts.map +1 -0
- package/dist/modes/interactive/whimsical-messages.js +464 -0
- package/dist/modes/interactive/whimsical-messages.js.map +1 -0
- package/dist/modes/print-mode.d.ts +28 -0
- package/dist/modes/print-mode.d.ts.map +1 -0
- package/dist/modes/print-mode.js +131 -0
- package/dist/modes/print-mode.js.map +1 -0
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +224 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +409 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts +20 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-mode.js +601 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +419 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-types.js +8 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -0
- package/dist/package-manager-cli.d.ts +4 -0
- package/dist/package-manager-cli.d.ts.map +1 -0
- package/dist/package-manager-cli.js +460 -0
- package/dist/package-manager-cli.js.map +1 -0
- package/dist/utils/ansi.d.ts +2 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +52 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/changelog.d.ts +21 -0
- package/dist/utils/changelog.d.ts.map +1 -0
- package/dist/utils/changelog.js +87 -0
- package/dist/utils/changelog.js.map +1 -0
- package/dist/utils/child-process.d.ts +12 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +86 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts +11 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -0
- package/dist/utils/clipboard-image.js +245 -0
- package/dist/utils/clipboard-image.js.map +1 -0
- package/dist/utils/clipboard-native.d.ts +8 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -0
- package/dist/utils/clipboard-native.js +14 -0
- package/dist/utils/clipboard-native.js.map +1 -0
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +117 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +8 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +26 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/fs-watch.d.ts +5 -0
- package/dist/utils/fs-watch.d.ts.map +1 -0
- package/dist/utils/fs-watch.js +25 -0
- package/dist/utils/fs-watch.js.map +1 -0
- package/dist/utils/git.d.ts +26 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +163 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/image-convert.d.ts +9 -0
- package/dist/utils/image-convert.d.ts.map +1 -0
- package/dist/utils/image-convert.js +39 -0
- package/dist/utils/image-convert.js.map +1 -0
- package/dist/utils/image-resize.d.ts +36 -0
- package/dist/utils/image-resize.d.ts.map +1 -0
- package/dist/utils/image-resize.js +137 -0
- package/dist/utils/image-resize.js.map +1 -0
- package/dist/utils/mime.d.ts +3 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +69 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +50 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/photon.d.ts +21 -0
- package/dist/utils/photon.d.ts.map +1 -0
- package/dist/utils/photon.js +121 -0
- package/dist/utils/photon.js.map +1 -0
- package/dist/utils/pi-user-agent.d.ts +2 -0
- package/dist/utils/pi-user-agent.d.ts.map +1 -0
- package/dist/utils/pi-user-agent.js +5 -0
- package/dist/utils/pi-user-agent.js.map +1 -0
- package/dist/utils/shell.d.ts +30 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +190 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +118 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.d.ts.map +1 -0
- package/dist/utils/tools-manager.js +325 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/dist/utils/version-check.d.ts +14 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +76 -0
- package/dist/utils/version-check.js.map +1 -0
- package/docs/compaction.md +394 -0
- package/docs/custom-provider.md +646 -0
- package/docs/development.md +71 -0
- package/docs/docs.json +148 -0
- package/docs/extensions.md +2596 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +3 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/index.md +70 -0
- package/docs/json.md +82 -0
- package/docs/keybindings.md +197 -0
- package/docs/models.md +474 -0
- package/docs/packages.md +223 -0
- package/docs/prompt-templates.md +88 -0
- package/docs/providers.md +243 -0
- package/docs/quickstart.md +142 -0
- package/docs/rpc.md +1407 -0
- package/docs/sdk.md +1129 -0
- package/docs/session-format.md +412 -0
- package/docs/sessions.md +137 -0
- package/docs/settings.md +279 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +232 -0
- package/docs/terminal-setup.md +106 -0
- package/docs/termux.md +127 -0
- package/docs/themes.md +299 -0
- package/docs/tmux.md +61 -0
- package/docs/tui.md +918 -0
- package/docs/usage.md +277 -0
- package/docs/windows.md +17 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +208 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/border-status-editor.ts +150 -0
- package/examples/extensions/built-in-tool-renderer.ts +249 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +127 -0
- package/examples/extensions/custom-footer.ts +64 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/examples/extensions/handoff.ts +191 -0
- package/examples/extensions/hello.ts +26 -0
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +426 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +55 -0
- package/examples/extensions/overlay-qa-tests.ts +1348 -0
- package/examples/extensions/overlay-test.ts +150 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +65 -0
- package/examples/extensions/plan-mode/index.ts +340 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +430 -0
- package/examples/extensions/prompt-customizer.ts +97 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +18 -0
- package/examples/extensions/qna.ts +122 -0
- package/examples/extensions/question.ts +264 -0
- package/examples/extensions/questionnaire.ts +427 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +118 -0
- package/examples/extensions/sandbox/index.ts +321 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +32 -0
- package/examples/extensions/structured-output.ts +65 -0
- package/examples/extensions/subagent/README.md +172 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +126 -0
- package/examples/extensions/subagent/index.ts +987 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +206 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/tic-tac-toe.ts +1008 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +297 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +141 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +9 -0
- package/examples/extensions/with-deps/index.ts +32 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/extensions/working-indicator.ts +123 -0
- package/examples/extensions/working-message-test.ts +25 -0
- package/examples/rpc-extension-ui.ts +632 -0
- package/examples/sdk/01-minimal.ts +26 -0
- package/examples/sdk/02-custom-model.ts +53 -0
- package/examples/sdk/03-custom-prompt.ts +75 -0
- package/examples/sdk/04-skills.ts +55 -0
- package/examples/sdk/05-tools.ts +48 -0
- package/examples/sdk/06-extensions.ts +99 -0
- package/examples/sdk/07-context-files.ts +47 -0
- package/examples/sdk/08-prompt-templates.ts +51 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +52 -0
- package/examples/sdk/10-settings.ts +53 -0
- package/examples/sdk/11-sessions.ts +52 -0
- package/examples/sdk/12-full-control.ts +77 -0
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +144 -0
- package/package.json +94 -19
- package/bin/atomic +0 -82
- /package/{LICENSE → dist/builtin/workflows/LICENSE} +0 -0
|
@@ -0,0 +1,1873 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StageChatView — attached workflow-stage chat surface.
|
|
3
|
+
*
|
|
4
|
+
* The overlay keeps workflow-specific chrome for stage metadata / controls, but
|
|
5
|
+
* the chat body now delegates to packages/coding-agent's exported interactive
|
|
6
|
+
* components instead of maintaining parallel workflow message widgets:
|
|
7
|
+
* - user rows use `UserMessageComponent`
|
|
8
|
+
* - assistant/thinking rows use `AssistantMessageComponent`
|
|
9
|
+
* - tool rows use `ToolExecutionComponent` and built-in tool renderers
|
|
10
|
+
* - input reuses the host's custom editor factory when one is installed,
|
|
11
|
+
* otherwise `CustomEditor`; tests/headless fall back to the historical
|
|
12
|
+
* one-line editor
|
|
13
|
+
* - workflow notices remain lightweight workflow-specific rows because they
|
|
14
|
+
* are not coding-agent chat messages
|
|
15
|
+
*
|
|
16
|
+
* Behaviour:
|
|
17
|
+
* - **Idle** stage (empty transcript, not streaming, not settled): welcome
|
|
18
|
+
* panel describing the attached stage. Enter sends `handle.prompt(text)`.
|
|
19
|
+
* - **Running** stage with a live stream: Enter calls `handle.steer(text)`
|
|
20
|
+
* (interrupt mid-turn). Ctrl+F always queues a follow-up via
|
|
21
|
+
* `handle.followUp(text)`.
|
|
22
|
+
* - **Ctrl+P** calls `handle.pause()`; while paused, Enter calls
|
|
23
|
+
* `handle.resume(text)`.
|
|
24
|
+
* - **Ctrl+D** detaches (back to graph); **Escape** closes the popup.
|
|
25
|
+
* - **Blocked** stage: keystrokes absorbed; BLOCKED banner names the
|
|
26
|
+
* upstream awaiter.
|
|
27
|
+
* - **Settled** stage (no handle, completed/failed): editor renders in a
|
|
28
|
+
* disabled visual state and the hint strip collapses to back/close.
|
|
29
|
+
*
|
|
30
|
+
* cross-ref:
|
|
31
|
+
* - ui/stage-chat-mockup.html (canonical visual)
|
|
32
|
+
* - DESIGN.md §5 (Components — pill / box / banner vocabulary)
|
|
33
|
+
* - src/runs/foreground/stage-control-registry.ts (StageControlHandle)
|
|
34
|
+
* - src/shared/store-types.ts (StageSnapshot.notices, StageNotice)
|
|
35
|
+
* - https://pi.dev/docs/latest/tui (canonical Pi-tui component contract)
|
|
36
|
+
* - node_modules/@earendil-works/pi-tui/src/components/{box,text,spacer}.ts
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import {
|
|
40
|
+
AssistantMessageComponent,
|
|
41
|
+
CustomEditor,
|
|
42
|
+
parseSkillBlock,
|
|
43
|
+
SessionManager,
|
|
44
|
+
SkillInvocationMessageComponent,
|
|
45
|
+
ToolExecutionComponent,
|
|
46
|
+
UserMessageComponent,
|
|
47
|
+
type AgentSession,
|
|
48
|
+
type AgentSessionEvent,
|
|
49
|
+
type SessionMessageEntry,
|
|
50
|
+
} from "@bastani/atomic";
|
|
51
|
+
import { Box, Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
52
|
+
import type { Component, EditorComponent, EditorTheme, TUI } from "@earendil-works/pi-tui";
|
|
53
|
+
import type { Store } from "../shared/store.js";
|
|
54
|
+
import type { StageNotice, StageSnapshot } from "../shared/store-types.js";
|
|
55
|
+
import type { GraphTheme } from "./graph-theme.js";
|
|
56
|
+
import type { StageControlHandle } from "../runs/foreground/stage-control-registry.js";
|
|
57
|
+
import { BOLD, RESET, hexBg, hexToAnsi, lerpColor } from "./color-utils.js";
|
|
58
|
+
import { truncateToWidth, visibleWidth } from "./text-helpers.js";
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Options & types
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
export interface StageChatViewOpts {
|
|
65
|
+
store: Store;
|
|
66
|
+
graphTheme: GraphTheme;
|
|
67
|
+
runId: string;
|
|
68
|
+
stageId: string;
|
|
69
|
+
/** The workflow display name, used in the title chrome `<workflow> / <stage>`. */
|
|
70
|
+
workflowName: string;
|
|
71
|
+
/**
|
|
72
|
+
* Live stage-control handle when available. When absent the chat is
|
|
73
|
+
* inspect-only (settled stage with no live handle).
|
|
74
|
+
*/
|
|
75
|
+
handle?: StageControlHandle;
|
|
76
|
+
/** Called when the user presses Ctrl+D (back to graph). */
|
|
77
|
+
onDetach: () => void;
|
|
78
|
+
/** Called when the user presses Escape (close the whole popup). */
|
|
79
|
+
onClose: () => void;
|
|
80
|
+
/** Request a host TUI repaint after SDK events mutate local chat state. */
|
|
81
|
+
requestRender?: () => void;
|
|
82
|
+
/** Live pi-tui host objects. When present, stage input uses pi's editor UI. */
|
|
83
|
+
piTui?: TUI;
|
|
84
|
+
piKeybindings?: unknown;
|
|
85
|
+
/** Currently installed host editor factory, inherited from extension `ctx.ui.setEditorComponent()`. */
|
|
86
|
+
piEditorFactory?: (tui: TUI, theme: EditorTheme, keybindings: unknown) => EditorComponent;
|
|
87
|
+
/**
|
|
88
|
+
* Optional accessor returning the current terminal row count. The chat
|
|
89
|
+
* surface expands its body band to roughly `viewportRows` minus the fixed
|
|
90
|
+
* header / loader / editor / footer / hint rows so the popup fills the
|
|
91
|
+
* terminal under pi-tui's `width: "100%" / maxHeight: "100%"` geometry.
|
|
92
|
+
* Returning `undefined` falls back to the constant 32-row frame.
|
|
93
|
+
*/
|
|
94
|
+
getViewportRows?: () => number | undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Transcript model. Every variant carries a flat `.text` summary so consumers
|
|
99
|
+
* that read `_transcript` (tests, future serialisers) can recover the
|
|
100
|
+
* canonical user-visible string without knowing about the Pi-box payload.
|
|
101
|
+
*/
|
|
102
|
+
interface BaseEntry {
|
|
103
|
+
readonly role: "user" | "assistant" | "thinking" | "tool" | "notice" | "system";
|
|
104
|
+
readonly text: string;
|
|
105
|
+
}
|
|
106
|
+
interface UserEntry extends BaseEntry {
|
|
107
|
+
readonly role: "user";
|
|
108
|
+
}
|
|
109
|
+
interface AssistantEntry extends BaseEntry {
|
|
110
|
+
readonly role: "assistant";
|
|
111
|
+
}
|
|
112
|
+
interface ThinkingEntry extends BaseEntry {
|
|
113
|
+
readonly role: "thinking";
|
|
114
|
+
}
|
|
115
|
+
interface SystemEntry extends BaseEntry {
|
|
116
|
+
readonly role: "system";
|
|
117
|
+
}
|
|
118
|
+
interface ToolEntry extends BaseEntry {
|
|
119
|
+
readonly role: "tool";
|
|
120
|
+
readonly name: string;
|
|
121
|
+
readonly toolCallId?: string;
|
|
122
|
+
readonly args?: string;
|
|
123
|
+
readonly output?: string;
|
|
124
|
+
readonly state: "pending" | "success" | "error";
|
|
125
|
+
}
|
|
126
|
+
interface NoticeEntry extends BaseEntry {
|
|
127
|
+
readonly role: "notice";
|
|
128
|
+
readonly noticeId: string;
|
|
129
|
+
readonly kind: StageNotice["kind"];
|
|
130
|
+
readonly value: string;
|
|
131
|
+
readonly from?: string;
|
|
132
|
+
readonly meta?: string;
|
|
133
|
+
}
|
|
134
|
+
type TranscriptEntry =
|
|
135
|
+
| UserEntry
|
|
136
|
+
| AssistantEntry
|
|
137
|
+
| ThinkingEntry
|
|
138
|
+
| SystemEntry
|
|
139
|
+
| ToolEntry
|
|
140
|
+
| NoticeEntry;
|
|
141
|
+
type AgentSnapshotMessage = AgentSession["messages"][number];
|
|
142
|
+
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// Frame budget
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Default line budget used when the host doesn't surface terminal dimensions
|
|
149
|
+
* (direct unit renders, lightweight test mocks). The mounted overlay
|
|
150
|
+
* overrides this by passing `getViewportRows()`.
|
|
151
|
+
*/
|
|
152
|
+
const VIEW_LINE_COUNT = 32;
|
|
153
|
+
|
|
154
|
+
/** Header strip — `▎ STAGE wf / stage <meta> ● status` */
|
|
155
|
+
const HEADER_ROWS = 1;
|
|
156
|
+
/** Single dim rule between header and body. */
|
|
157
|
+
const SEP_ROWS = 1;
|
|
158
|
+
/** Loader: top rule + body + bottom rule when streaming. */
|
|
159
|
+
const LOADER_ROWS = 3;
|
|
160
|
+
/** Editor: top rule + ` ❯ … ` + bottom rule, always present. */
|
|
161
|
+
const EDITOR_ROWS = 3;
|
|
162
|
+
/** Footer: two dim lines. */
|
|
163
|
+
const FOOTER_ROWS = 2;
|
|
164
|
+
/** Hint strip: dashed rule + key bindings line. */
|
|
165
|
+
const HINTS_ROWS = 2;
|
|
166
|
+
|
|
167
|
+
/** Spinner glyphs — Braille spinner at 80ms per frame. */
|
|
168
|
+
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
169
|
+
/** Pi's Loader advances at 80ms; use the same cadence for embedded stage chats. */
|
|
170
|
+
const ANIMATION_FRAME_MS = 80;
|
|
171
|
+
|
|
172
|
+
const ITALIC = "\x1b[3m";
|
|
173
|
+
const FG_RESET = "\x1b[39m";
|
|
174
|
+
const WEIGHT_RESET = "\x1b[22m";
|
|
175
|
+
const ITALIC_RESET = "\x1b[23m";
|
|
176
|
+
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Pi chat transcript adapter
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Composes stage transcript rows with the same spacing rules as pi's
|
|
183
|
+
* InteractiveMode chat container. Workflow chrome (header, loader, footer,
|
|
184
|
+
* hints) remains owned by StageChatView; the base chat body is just the
|
|
185
|
+
* canonical coding-agent message components inside a pi-tui Container.
|
|
186
|
+
*/
|
|
187
|
+
class PiChatTranscriptComponent implements Component {
|
|
188
|
+
constructor(
|
|
189
|
+
private readonly entries: readonly TranscriptEntry[],
|
|
190
|
+
private readonly renderEntry: (entry: TranscriptEntry) => Component,
|
|
191
|
+
) {}
|
|
192
|
+
|
|
193
|
+
render(width: number): string[] {
|
|
194
|
+
const container = new Container();
|
|
195
|
+
for (const entry of this.entries) {
|
|
196
|
+
addTranscriptEntry(container, this.renderEntry(entry), entry.role);
|
|
197
|
+
}
|
|
198
|
+
return container.render(width);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
invalidate(): void {}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function addTranscriptEntry(container: Container, component: Component, role: TranscriptEntry["role"]): void {
|
|
205
|
+
// Mirror InteractiveMode.addMessageToChat:
|
|
206
|
+
// - user/custom/system-like rows get a spacer only when something already
|
|
207
|
+
// exists above them;
|
|
208
|
+
// - assistant rows own their leading whitespace internally;
|
|
209
|
+
// - tool rows attach directly below the assistant turn that requested them.
|
|
210
|
+
if ((role === "user" || role === "notice" || role === "system") && container.children.length > 0) {
|
|
211
|
+
container.addChild(new Spacer(1));
|
|
212
|
+
}
|
|
213
|
+
container.addChild(component);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
// StageChatView
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
|
|
220
|
+
export class StageChatView implements Component {
|
|
221
|
+
private store: Store;
|
|
222
|
+
private theme: GraphTheme;
|
|
223
|
+
private runId: string;
|
|
224
|
+
private stageId: string;
|
|
225
|
+
private workflowName: string;
|
|
226
|
+
private handle: StageControlHandle | undefined;
|
|
227
|
+
private onDetach: () => void;
|
|
228
|
+
private onClose: () => void;
|
|
229
|
+
private requestRender: (() => void) | undefined;
|
|
230
|
+
private getViewportRows?: () => number | undefined;
|
|
231
|
+
private editor: EditorComponent | undefined;
|
|
232
|
+
|
|
233
|
+
private inputBuffer = "";
|
|
234
|
+
private transcript: TranscriptEntry[] = [];
|
|
235
|
+
private statusMessage = "";
|
|
236
|
+
/** True while a pending pause request is in flight (between ctrl+p and resolve). */
|
|
237
|
+
private localPaused = false;
|
|
238
|
+
/** De-dup set so the store subscription doesn't re-append known notices. */
|
|
239
|
+
private seenNoticeIds = new Set<string>();
|
|
240
|
+
/** Wall-clock at construction, used to colour the spinner frame stably. */
|
|
241
|
+
private attachedAt = Date.now();
|
|
242
|
+
/** True after SDK `agent_start` until `agent_end`; mirrors Pi's working-loader lifecycle. */
|
|
243
|
+
private sdkBusy = false;
|
|
244
|
+
/** Stable row pointers for the current streaming assistant message. */
|
|
245
|
+
private streamingAssistantIndex: number | undefined;
|
|
246
|
+
private streamingThinkingIndex: number | undefined;
|
|
247
|
+
/** Stable tool-call rows keyed exactly like Pi's `pendingTools` map. */
|
|
248
|
+
private toolEntryIndexes = new Map<string, number>();
|
|
249
|
+
/** User rows optimistically appended by this embedded editor, de-duped on SDK echo. */
|
|
250
|
+
private optimisticUserSignatures = new Set<string>();
|
|
251
|
+
/** Chat-mode repaint driver for Pi-style loaders/spinners. */
|
|
252
|
+
private animationTimer: ReturnType<typeof setInterval> | undefined;
|
|
253
|
+
|
|
254
|
+
private _unsubscribeStore: (() => void) | null = null;
|
|
255
|
+
private _unsubscribeHandle: (() => void) | null = null;
|
|
256
|
+
|
|
257
|
+
constructor(opts: StageChatViewOpts) {
|
|
258
|
+
this.store = opts.store;
|
|
259
|
+
this.theme = opts.graphTheme;
|
|
260
|
+
this.runId = opts.runId;
|
|
261
|
+
this.stageId = opts.stageId;
|
|
262
|
+
this.workflowName = opts.workflowName;
|
|
263
|
+
this.handle = opts.handle;
|
|
264
|
+
this.onDetach = opts.onDetach;
|
|
265
|
+
this.onClose = opts.onClose;
|
|
266
|
+
this.requestRender = opts.requestRender;
|
|
267
|
+
this.getViewportRows = opts.getViewportRows;
|
|
268
|
+
this.editor = this._createEditor(opts.piTui, opts.piKeybindings, opts.piEditorFactory);
|
|
269
|
+
|
|
270
|
+
// Seed transcript from the live SDK session at attach time, plus any
|
|
271
|
+
// stage notices the workflow body has already recorded.
|
|
272
|
+
this._snapshotMessagesFromHandle();
|
|
273
|
+
const initialStage = this._currentStage();
|
|
274
|
+
this._snapshotMessagesFromSessionFile(initialStage);
|
|
275
|
+
this._absorbStageNotices(initialStage);
|
|
276
|
+
|
|
277
|
+
this._unsubscribeStore = this.store.subscribe(() => {
|
|
278
|
+
const stage = this._currentStage();
|
|
279
|
+
let changed = false;
|
|
280
|
+
if (stage && stage.status === "paused" && !this.localPaused) {
|
|
281
|
+
this.localPaused = true;
|
|
282
|
+
changed = true;
|
|
283
|
+
} else if (stage && stage.status === "running" && this.localPaused) {
|
|
284
|
+
this.localPaused = false;
|
|
285
|
+
changed = true;
|
|
286
|
+
}
|
|
287
|
+
// Pick up notices recorded after attach (workflow body calling
|
|
288
|
+
// `stage.setModel`, `stage.compact`, …) so they thread through the
|
|
289
|
+
// transcript without a special render path.
|
|
290
|
+
changed = this._absorbStageNotices(stage) || changed;
|
|
291
|
+
this._syncAnimationTick();
|
|
292
|
+
if (changed) this.requestRender?.();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
if (this.handle) {
|
|
296
|
+
this._unsubscribeHandle = this.handle.subscribe((event) => {
|
|
297
|
+
const changed = this._appendEvent(event);
|
|
298
|
+
this._syncAnimationTick();
|
|
299
|
+
if (changed) this.requestRender?.();
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
this._syncAnimationTick();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
private _createEditor(
|
|
306
|
+
tui: TUI | undefined,
|
|
307
|
+
keybindings: unknown,
|
|
308
|
+
editorFactory: ((tui: TUI, theme: EditorTheme, keybindings: unknown) => EditorComponent) | undefined,
|
|
309
|
+
): EditorComponent | undefined {
|
|
310
|
+
if (!tui || !keybindings) return undefined;
|
|
311
|
+
const editorTheme = editorThemeFromGraphTheme(this.theme);
|
|
312
|
+
const editor = this._createInheritedEditor(tui, editorTheme, keybindings, editorFactory) ??
|
|
313
|
+
new CustomEditor(
|
|
314
|
+
tui,
|
|
315
|
+
editorTheme,
|
|
316
|
+
keybindings as ConstructorParameters<typeof CustomEditor>[2],
|
|
317
|
+
{ paddingX: 1, autocompleteMaxVisible: 5 },
|
|
318
|
+
);
|
|
319
|
+
editor.onChange = (text) => {
|
|
320
|
+
this.inputBuffer = text;
|
|
321
|
+
};
|
|
322
|
+
editor.onSubmit = (text) => {
|
|
323
|
+
void this._submit("auto", text);
|
|
324
|
+
};
|
|
325
|
+
return editor;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private _createInheritedEditor(
|
|
329
|
+
tui: TUI,
|
|
330
|
+
editorTheme: EditorTheme,
|
|
331
|
+
keybindings: unknown,
|
|
332
|
+
editorFactory: ((tui: TUI, theme: EditorTheme, keybindings: unknown) => EditorComponent) | undefined,
|
|
333
|
+
): EditorComponent | undefined {
|
|
334
|
+
if (!editorFactory) return undefined;
|
|
335
|
+
try {
|
|
336
|
+
return editorFactory(tui, editorTheme, keybindings);
|
|
337
|
+
} catch {
|
|
338
|
+
return undefined;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// -------------------------------------------------------------------------
|
|
343
|
+
// Event ingestion
|
|
344
|
+
// -------------------------------------------------------------------------
|
|
345
|
+
|
|
346
|
+
private _snapshotMessagesFromHandle(): void {
|
|
347
|
+
if (!this.handle) return;
|
|
348
|
+
for (const message of this.handle.messages) {
|
|
349
|
+
const entry = transcriptEntryFromSnapshotMessage(message);
|
|
350
|
+
if (entry) this.transcript.push(entry);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private _snapshotMessagesFromSessionFile(stage: StageSnapshot | undefined): void {
|
|
355
|
+
if (this.transcript.length > 0) return;
|
|
356
|
+
const sessionFile = this.handle?.sessionFile ?? stage?.sessionFile;
|
|
357
|
+
if (sessionFile === undefined) return;
|
|
358
|
+
|
|
359
|
+
let entries: ReturnType<SessionManager["getEntries"]>;
|
|
360
|
+
try {
|
|
361
|
+
entries = SessionManager.open(sessionFile).getEntries();
|
|
362
|
+
} catch {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
for (const entry of entries) {
|
|
367
|
+
if (!isSessionMessageEntry(entry)) continue;
|
|
368
|
+
const transcriptEntry = transcriptEntryFromSnapshotMessage(entry.message as AgentSnapshotMessage);
|
|
369
|
+
if (transcriptEntry) this.transcript.push(transcriptEntry);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private _appendEvent(event: AgentSessionEvent): boolean {
|
|
374
|
+
// This mirrors pi-coding-agent InteractiveMode's event controller shape:
|
|
375
|
+
// session events mutate a long-lived chat model, then the host TUI is
|
|
376
|
+
// asked to render. Assistant rows are driven from full message snapshots
|
|
377
|
+
// when present; delta-only events remain supported for SDK/test shims.
|
|
378
|
+
const type = String((event as { type?: unknown }).type ?? "");
|
|
379
|
+
switch (type) {
|
|
380
|
+
case "agent_start":
|
|
381
|
+
this.sdkBusy = true;
|
|
382
|
+
this.toolEntryIndexes.clear();
|
|
383
|
+
this.statusMessage = "";
|
|
384
|
+
return true;
|
|
385
|
+
|
|
386
|
+
case "agent_end":
|
|
387
|
+
this.sdkBusy = false;
|
|
388
|
+
this.streamingAssistantIndex = undefined;
|
|
389
|
+
this.streamingThinkingIndex = undefined;
|
|
390
|
+
this.statusMessage = "";
|
|
391
|
+
return true;
|
|
392
|
+
|
|
393
|
+
case "message_start":
|
|
394
|
+
return this._handleMessageStart((event as { message?: unknown }).message);
|
|
395
|
+
|
|
396
|
+
case "message_update":
|
|
397
|
+
return this._handleMessageUpdate(event);
|
|
398
|
+
|
|
399
|
+
case "message_end":
|
|
400
|
+
return this._handleMessageEnd((event as { message?: unknown }).message);
|
|
401
|
+
|
|
402
|
+
case "tool_execution_start": {
|
|
403
|
+
const payload = event as { toolCallId?: unknown; toolName?: unknown; args?: unknown };
|
|
404
|
+
const name = typeof payload.toolName === "string" ? payload.toolName : "tool";
|
|
405
|
+
const toolCallId = typeof payload.toolCallId === "string" ? payload.toolCallId : undefined;
|
|
406
|
+
const args = summariseArgs(payload.args);
|
|
407
|
+
this._upsertToolEntry({ toolCallId, name, args, state: "pending" });
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
case "tool_execution_update": {
|
|
412
|
+
const payload = event as { toolCallId?: unknown; toolName?: unknown; partialResult?: unknown };
|
|
413
|
+
const partialOutput = extractToolResultText(payload.partialResult);
|
|
414
|
+
if (!partialOutput) return false;
|
|
415
|
+
this._upsertToolEntry({
|
|
416
|
+
toolCallId: typeof payload.toolCallId === "string" ? payload.toolCallId : undefined,
|
|
417
|
+
name: typeof payload.toolName === "string" ? payload.toolName : "tool",
|
|
418
|
+
output: partialOutput,
|
|
419
|
+
state: "pending",
|
|
420
|
+
});
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
case "tool_execution_end": {
|
|
425
|
+
const payload = event as { toolCallId?: unknown; toolName?: unknown; result?: unknown; isError?: unknown };
|
|
426
|
+
const toolCallId = typeof payload.toolCallId === "string" ? payload.toolCallId : undefined;
|
|
427
|
+
const output = extractToolResultText(payload.result);
|
|
428
|
+
this._upsertToolEntry({
|
|
429
|
+
toolCallId,
|
|
430
|
+
name: typeof payload.toolName === "string" ? payload.toolName : "tool",
|
|
431
|
+
output,
|
|
432
|
+
state: payload.isError === true ? "error" : "success",
|
|
433
|
+
});
|
|
434
|
+
if (toolCallId) this.toolEntryIndexes.delete(toolCallId);
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
case "tool_call":
|
|
439
|
+
case "tool_use": {
|
|
440
|
+
const name = String((event as { name?: unknown }).name ?? "tool");
|
|
441
|
+
const args = summariseArgs((event as { input?: unknown }).input);
|
|
442
|
+
this._upsertToolEntry({ name, args, state: "pending" });
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
case "tool_result": {
|
|
447
|
+
const name = String((event as { name?: unknown }).name ?? "tool");
|
|
448
|
+
const rawOutput = (event as { output?: unknown }).output;
|
|
449
|
+
const output = typeof rawOutput === "string" ? rawOutput : extractMessageText(rawOutput);
|
|
450
|
+
this._upsertToolEntry({
|
|
451
|
+
name,
|
|
452
|
+
output,
|
|
453
|
+
state: Boolean((event as { isError?: unknown }).isError) ? "error" : "success",
|
|
454
|
+
});
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
case "thinking_delta":
|
|
459
|
+
case "thinking": {
|
|
460
|
+
const delta = String(
|
|
461
|
+
(event as { delta?: unknown }).delta ?? (event as { text?: unknown }).text ?? "",
|
|
462
|
+
);
|
|
463
|
+
if (!delta) return false;
|
|
464
|
+
this._appendTextDelta("thinking", delta);
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
case "compaction_start":
|
|
469
|
+
this.sdkBusy = true;
|
|
470
|
+
this.statusMessage = "compacting context…";
|
|
471
|
+
return true;
|
|
472
|
+
|
|
473
|
+
case "compaction_end":
|
|
474
|
+
this.sdkBusy = false;
|
|
475
|
+
this.statusMessage = "";
|
|
476
|
+
return true;
|
|
477
|
+
|
|
478
|
+
case "auto_retry_start":
|
|
479
|
+
this.sdkBusy = true;
|
|
480
|
+
this.statusMessage = "retrying…";
|
|
481
|
+
return true;
|
|
482
|
+
|
|
483
|
+
case "auto_retry_end":
|
|
484
|
+
this.statusMessage = "";
|
|
485
|
+
return true;
|
|
486
|
+
|
|
487
|
+
default:
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
private _handleMessageStart(message: unknown): boolean {
|
|
493
|
+
if (!isMessageLike(message)) return false;
|
|
494
|
+
if (message.role === "assistant") {
|
|
495
|
+
this.streamingAssistantIndex = undefined;
|
|
496
|
+
this.streamingThinkingIndex = undefined;
|
|
497
|
+
return this._updateAssistantFromMessage(message);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const entry = transcriptEntryFromSnapshotMessage(message as AgentSnapshotMessage);
|
|
501
|
+
if (!entry) return false;
|
|
502
|
+
if (entry.role === "user") {
|
|
503
|
+
const signature = userMessageSignature(entry.text);
|
|
504
|
+
if (this.optimisticUserSignatures.delete(signature)) return false;
|
|
505
|
+
}
|
|
506
|
+
this.transcript.push(entry);
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
private _handleMessageUpdate(event: AgentSessionEvent): boolean {
|
|
511
|
+
const message = (event as { message?: unknown }).message;
|
|
512
|
+
const hasAssistantSnapshot = isMessageLike(message) && message.role === "assistant";
|
|
513
|
+
const snapshotHasPayload = hasAssistantSnapshot && assistantContentHasRenderablePayload(message.content);
|
|
514
|
+
let changed = false;
|
|
515
|
+
if (hasAssistantSnapshot) {
|
|
516
|
+
changed = this._updateAssistantFromMessage(message) || changed;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const assistantEvent = (event as { assistantMessageEvent?: { type?: unknown; delta?: unknown } }).assistantMessageEvent;
|
|
520
|
+
const streamType = String(assistantEvent?.type ?? "");
|
|
521
|
+
const delta = typeof assistantEvent?.delta === "string" ? assistantEvent.delta : "";
|
|
522
|
+
// Prefer Pi's full assistant message snapshot when it contains visible
|
|
523
|
+
// payload; use deltas only for delta-only SDK shims/events.
|
|
524
|
+
if (!changed && !snapshotHasPayload && streamType === "text_delta" && delta) {
|
|
525
|
+
this._appendTextDelta("assistant", delta);
|
|
526
|
+
changed = true;
|
|
527
|
+
} else if (!changed && !snapshotHasPayload && streamType === "thinking_delta" && delta) {
|
|
528
|
+
this._appendTextDelta("thinking", delta);
|
|
529
|
+
changed = true;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return changed;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
private _handleMessageEnd(message: unknown): boolean {
|
|
536
|
+
let changed = false;
|
|
537
|
+
if (isMessageLike(message) && message.role === "assistant") {
|
|
538
|
+
changed = this._updateAssistantFromMessage(message) || changed;
|
|
539
|
+
for (const [toolCallId, index] of this.toolEntryIndexes.entries()) {
|
|
540
|
+
const entry = this.transcript[index];
|
|
541
|
+
if (entry?.role === "tool" && entry.state === "pending") {
|
|
542
|
+
this.transcript[index] = { ...entry, text: entry.text };
|
|
543
|
+
}
|
|
544
|
+
this.toolEntryIndexes.set(toolCallId, index);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
this.streamingAssistantIndex = undefined;
|
|
548
|
+
this.streamingThinkingIndex = undefined;
|
|
549
|
+
return changed || isMessageLike(message);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
private _updateAssistantFromMessage(message: { role?: unknown; content?: unknown; stopReason?: unknown; errorMessage?: unknown }): boolean {
|
|
553
|
+
const projection = projectAssistantContent(message.content);
|
|
554
|
+
let changed = false;
|
|
555
|
+
if (projection.thinking) {
|
|
556
|
+
changed = this._upsertStreamingText("thinking", projection.thinking) || changed;
|
|
557
|
+
}
|
|
558
|
+
if (projection.text) {
|
|
559
|
+
changed = this._upsertStreamingText("assistant", projection.text) || changed;
|
|
560
|
+
}
|
|
561
|
+
const stopReason = typeof message.stopReason === "string" ? message.stopReason : "";
|
|
562
|
+
if (stopReason === "aborted" || stopReason === "error") {
|
|
563
|
+
const errorText = typeof message.errorMessage === "string" && message.errorMessage
|
|
564
|
+
? message.errorMessage
|
|
565
|
+
: stopReason === "aborted"
|
|
566
|
+
? "Operation aborted"
|
|
567
|
+
: "Unknown error";
|
|
568
|
+
changed = this._failPendingToolEntries(errorText) || changed;
|
|
569
|
+
if (!projection.toolCalls.length) {
|
|
570
|
+
changed = this._upsertStreamingText("system", stopReason === "error" ? `Error: ${errorText}` : errorText) || changed;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
for (const toolCall of projection.toolCalls) {
|
|
574
|
+
changed = this._upsertToolEntry(toolCall) || changed;
|
|
575
|
+
}
|
|
576
|
+
return changed;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
private _upsertStreamingText(
|
|
580
|
+
role: "assistant" | "thinking" | "system",
|
|
581
|
+
text: string,
|
|
582
|
+
): boolean {
|
|
583
|
+
if (!text) return false;
|
|
584
|
+
if (role === "system") {
|
|
585
|
+
this._upsertTextLastByRole("system", text);
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
const index = role === "assistant" ? this.streamingAssistantIndex : this.streamingThinkingIndex;
|
|
589
|
+
if (index !== undefined && this.transcript[index]?.role === role) {
|
|
590
|
+
if (this.transcript[index]?.text === text) return false;
|
|
591
|
+
this.transcript[index] = { role, text } as TranscriptEntry;
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
this.transcript.push({ role, text } as TranscriptEntry);
|
|
595
|
+
const nextIndex = this.transcript.length - 1;
|
|
596
|
+
if (role === "assistant") this.streamingAssistantIndex = nextIndex;
|
|
597
|
+
else this.streamingThinkingIndex = nextIndex;
|
|
598
|
+
return true;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
private _absorbStageNotices(stage: StageSnapshot | undefined): boolean {
|
|
602
|
+
const notices = stage?.notices;
|
|
603
|
+
if (!notices) return false;
|
|
604
|
+
let changed = false;
|
|
605
|
+
for (const n of notices) {
|
|
606
|
+
if (this.seenNoticeIds.has(n.id)) continue;
|
|
607
|
+
this.seenNoticeIds.add(n.id);
|
|
608
|
+
changed = true;
|
|
609
|
+
this.transcript.push({
|
|
610
|
+
role: "notice",
|
|
611
|
+
noticeId: n.id,
|
|
612
|
+
kind: n.kind,
|
|
613
|
+
value: n.to,
|
|
614
|
+
from: n.from,
|
|
615
|
+
meta: n.meta,
|
|
616
|
+
text: noticeSummary(n),
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
return changed;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
private _upsertTextLastByRole(
|
|
623
|
+
role: "user" | "assistant" | "thinking" | "system",
|
|
624
|
+
text: string,
|
|
625
|
+
): void {
|
|
626
|
+
const last = this.transcript[this.transcript.length - 1];
|
|
627
|
+
if (last && last.role === role) {
|
|
628
|
+
this.transcript[this.transcript.length - 1] = { role, text } as TranscriptEntry;
|
|
629
|
+
} else {
|
|
630
|
+
this.transcript.push({ role, text } as TranscriptEntry);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
private _appendTextDelta(
|
|
635
|
+
role: "assistant" | "thinking",
|
|
636
|
+
delta: string,
|
|
637
|
+
): void {
|
|
638
|
+
const index = role === "assistant" ? this.streamingAssistantIndex : this.streamingThinkingIndex;
|
|
639
|
+
if (index !== undefined && this.transcript[index]?.role === role) {
|
|
640
|
+
const current = this.transcript[index];
|
|
641
|
+
this.transcript[index] = { role, text: current.text + delta } as TranscriptEntry;
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
this.transcript.push({ role, text: delta } as TranscriptEntry);
|
|
645
|
+
const nextIndex = this.transcript.length - 1;
|
|
646
|
+
if (role === "assistant") this.streamingAssistantIndex = nextIndex;
|
|
647
|
+
else this.streamingThinkingIndex = nextIndex;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
private _failPendingToolEntries(errorText: string): boolean {
|
|
651
|
+
let changed = false;
|
|
652
|
+
for (const [toolCallId, index] of this.toolEntryIndexes.entries()) {
|
|
653
|
+
const entry = this.transcript[index];
|
|
654
|
+
if (entry?.role !== "tool" || entry.state !== "pending") continue;
|
|
655
|
+
changed = this._upsertToolEntry({
|
|
656
|
+
toolCallId,
|
|
657
|
+
name: entry.name,
|
|
658
|
+
output: errorText,
|
|
659
|
+
state: "error",
|
|
660
|
+
}) || changed;
|
|
661
|
+
}
|
|
662
|
+
this.toolEntryIndexes.clear();
|
|
663
|
+
return changed;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
private _upsertToolEntry(update: {
|
|
667
|
+
toolCallId?: string;
|
|
668
|
+
name: string;
|
|
669
|
+
args?: string;
|
|
670
|
+
output?: string;
|
|
671
|
+
state: "pending" | "success" | "error";
|
|
672
|
+
}): boolean {
|
|
673
|
+
const mappedIndex = update.toolCallId ? this.toolEntryIndexes.get(update.toolCallId) : undefined;
|
|
674
|
+
const index = mappedIndex ?? findToolEntryIndex(this.transcript, update.toolCallId, update.name);
|
|
675
|
+
const existing = index !== undefined && index >= 0 ? this.transcript[index] : undefined;
|
|
676
|
+
const previous = existing?.role === "tool" ? existing : undefined;
|
|
677
|
+
const output = update.output || previous?.output;
|
|
678
|
+
const name = previous?.name ?? update.name;
|
|
679
|
+
const args = update.args ?? previous?.args;
|
|
680
|
+
const summary = output ? truncateToWidth(output.replace(/\s+/g, " "), 80) : "";
|
|
681
|
+
const next: ToolEntry = {
|
|
682
|
+
role: "tool",
|
|
683
|
+
name,
|
|
684
|
+
toolCallId: previous?.toolCallId ?? update.toolCallId,
|
|
685
|
+
args,
|
|
686
|
+
output,
|
|
687
|
+
state: update.state,
|
|
688
|
+
text: summary
|
|
689
|
+
? `← ${name} ${summary}`
|
|
690
|
+
: args
|
|
691
|
+
? `→ ${name} ${args}`
|
|
692
|
+
: `→ ${name}`,
|
|
693
|
+
};
|
|
694
|
+
if (previous && shallowToolEntryEqual(previous, next)) return false;
|
|
695
|
+
if (index !== undefined && index >= 0) {
|
|
696
|
+
this.transcript[index] = next;
|
|
697
|
+
if (next.toolCallId) this.toolEntryIndexes.set(next.toolCallId, index);
|
|
698
|
+
} else {
|
|
699
|
+
this.transcript.push(next);
|
|
700
|
+
if (next.toolCallId) this.toolEntryIndexes.set(next.toolCallId, this.transcript.length - 1);
|
|
701
|
+
}
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
private _currentStage(): StageSnapshot | undefined {
|
|
706
|
+
const snap = this.store.snapshot();
|
|
707
|
+
const run = snap.runs.find((r) => r.id === this.runId);
|
|
708
|
+
return run?.stages.find((s) => s.id === this.stageId);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// -------------------------------------------------------------------------
|
|
712
|
+
// Frame sizing
|
|
713
|
+
// -------------------------------------------------------------------------
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Number of rows the chat surface paints per frame. The mounted overlay
|
|
717
|
+
* passes `terminal.rows` through `getViewportRows`; direct unit renders
|
|
718
|
+
* fall back to the constant `VIEW_LINE_COUNT` so the legacy 32-row frame
|
|
719
|
+
* still applies to lightweight test mocks.
|
|
720
|
+
*/
|
|
721
|
+
private _viewLineCount(): number {
|
|
722
|
+
const reported = this.getViewportRows?.();
|
|
723
|
+
if (typeof reported !== "number" || !Number.isFinite(reported)) {
|
|
724
|
+
return VIEW_LINE_COUNT;
|
|
725
|
+
}
|
|
726
|
+
return Math.max(VIEW_LINE_COUNT, Math.floor(reported));
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
private _isStreaming(): boolean {
|
|
730
|
+
return this.sdkBusy || Boolean(this.handle?.isStreaming);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
private _hasPendingToolEntries(): boolean {
|
|
734
|
+
return this.transcript.some((entry) => entry.role === "tool" && entry.state === "pending");
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
private _syncAnimationTick(): void {
|
|
738
|
+
const shouldAnimate = this._isStreaming() || (this.sdkBusy && this._hasPendingToolEntries());
|
|
739
|
+
if (shouldAnimate && !this.animationTimer) {
|
|
740
|
+
this.animationTimer = setInterval(() => {
|
|
741
|
+
this.requestRender?.();
|
|
742
|
+
}, ANIMATION_FRAME_MS);
|
|
743
|
+
this.animationTimer.unref?.();
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
if (!shouldAnimate && this.animationTimer) {
|
|
747
|
+
clearInterval(this.animationTimer);
|
|
748
|
+
this.animationTimer = undefined;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
private _isBlocked(): boolean {
|
|
753
|
+
return this._currentStage()?.status === "blocked";
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
private _isSettled(stage: StageSnapshot | undefined): boolean {
|
|
757
|
+
if (!stage) return !this.handle;
|
|
758
|
+
return stage.status === "completed" || stage.status === "failed";
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// -------------------------------------------------------------------------
|
|
762
|
+
// Top-level render — composes header / body / loader / editor / footer / hints
|
|
763
|
+
// -------------------------------------------------------------------------
|
|
764
|
+
|
|
765
|
+
render(width: number): string[] {
|
|
766
|
+
const w = Math.max(40, width);
|
|
767
|
+
const stage = this._currentStage();
|
|
768
|
+
const blocked = this._isBlocked();
|
|
769
|
+
const settled = this._isSettled(stage);
|
|
770
|
+
const streaming = this._isStreaming() && !blocked && !settled;
|
|
771
|
+
const paused = this.localPaused || stage?.status === "paused";
|
|
772
|
+
|
|
773
|
+
const headerLines = this._renderHeader(w, stage);
|
|
774
|
+
const sepLines = [this._sepRule(w)];
|
|
775
|
+
const loaderLines = streaming ? this._renderLoader(w, stage) : [];
|
|
776
|
+
// When the loader sits above the editor, the loader's bottom rule and
|
|
777
|
+
// the editor's top rule collapse into a single shared divider — matches
|
|
778
|
+
// the mockup's `pi-loader` + `pi-editor` stack and saves one row.
|
|
779
|
+
const editorLines = this._renderEditor(w, {
|
|
780
|
+
paused,
|
|
781
|
+
streaming,
|
|
782
|
+
settled,
|
|
783
|
+
blocked,
|
|
784
|
+
omitTopRule: loaderLines.length > 0,
|
|
785
|
+
});
|
|
786
|
+
const footerLines = this._renderFooter(w, stage, { paused, streaming, settled });
|
|
787
|
+
const hintsLines = this._renderHints(w, { paused, streaming, settled });
|
|
788
|
+
|
|
789
|
+
const fixed =
|
|
790
|
+
headerLines.length +
|
|
791
|
+
sepLines.length +
|
|
792
|
+
loaderLines.length +
|
|
793
|
+
editorLines.length +
|
|
794
|
+
footerLines.length +
|
|
795
|
+
hintsLines.length;
|
|
796
|
+
const totalRows = this._viewLineCount();
|
|
797
|
+
const bodyBudget = Math.max(1, totalRows - fixed);
|
|
798
|
+
const bodyLines = blocked
|
|
799
|
+
? this._renderBlockedBody(w, bodyBudget, stage)
|
|
800
|
+
: this._renderBody(w, bodyBudget, stage, { paused, streaming, settled });
|
|
801
|
+
|
|
802
|
+
const lines = [
|
|
803
|
+
...headerLines,
|
|
804
|
+
...sepLines,
|
|
805
|
+
...bodyLines,
|
|
806
|
+
...loaderLines,
|
|
807
|
+
...editorLines,
|
|
808
|
+
...footerLines,
|
|
809
|
+
...hintsLines,
|
|
810
|
+
];
|
|
811
|
+
while (lines.length < totalRows) lines.push(this._blank(w));
|
|
812
|
+
if (lines.length > totalRows) lines.length = totalRows;
|
|
813
|
+
return lines;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// -------------------------------------------------------------------------
|
|
817
|
+
// Header
|
|
818
|
+
// -------------------------------------------------------------------------
|
|
819
|
+
|
|
820
|
+
private _renderHeader(width: number, stage: StageSnapshot | undefined): string[] {
|
|
821
|
+
const t = this.theme;
|
|
822
|
+
const stageName = stage?.name ?? "stage";
|
|
823
|
+
const status = stage?.status ?? (this.handle ? "pending" : "completed");
|
|
824
|
+
|
|
825
|
+
// Left side: `▎ STAGE <wf> / <stage>`
|
|
826
|
+
const left =
|
|
827
|
+
paint(" ▎ ", t.mauve, { bold: true }) +
|
|
828
|
+
paint("STAGE", t.textMuted, { bold: true }) +
|
|
829
|
+
" " +
|
|
830
|
+
paint(this.workflowName, t.textMuted) +
|
|
831
|
+
paint(" / ", t.dim) +
|
|
832
|
+
paint(stageName, t.text, { bold: true });
|
|
833
|
+
|
|
834
|
+
// Right side: stage meta · status pill
|
|
835
|
+
const meta = this._headerMeta(stage);
|
|
836
|
+
const pill = this._statusPill(status);
|
|
837
|
+
const right = (meta ? paint(meta, t.dim) + " " : "") + pill.styled + " ";
|
|
838
|
+
|
|
839
|
+
const leftW = visibleWidth(this.workflowName) + visibleWidth(stageName) + visibleWidth(" STAGE / ") + 1;
|
|
840
|
+
const rightW = visibleWidth(meta) + (meta ? 2 : 0) + pill.width + 1;
|
|
841
|
+
const gap = Math.max(1, width - leftW - rightW);
|
|
842
|
+
return [left + " ".repeat(gap) + right];
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
private _headerMeta(stage: StageSnapshot | undefined): string {
|
|
846
|
+
const parts: string[] = [];
|
|
847
|
+
if (stage) {
|
|
848
|
+
const dur = stageDurationText(stage);
|
|
849
|
+
if (dur) parts.push(dur);
|
|
850
|
+
}
|
|
851
|
+
const sid = this.handle?.sessionId ?? stage?.sessionId;
|
|
852
|
+
if (sid) parts.push(`session ${shortenId(sid)}`);
|
|
853
|
+
return parts.join(" · ");
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* Render an inline ` ● status ` pill with the status colour applied to a
|
|
858
|
+
* tinted background. Matches the mockup's `.status-pill` vocabulary.
|
|
859
|
+
*/
|
|
860
|
+
private _statusPill(status: string): { styled: string; width: number } {
|
|
861
|
+
const t = this.theme;
|
|
862
|
+
const map: Record<string, { fg: string; bg: string; label: string }> = {
|
|
863
|
+
pending: { fg: t.dim, bg: blendBg(t.bg, t.dim, 0.18), label: "pending" },
|
|
864
|
+
running: { fg: t.accent, bg: blendBg(t.bg, t.accent, 0.18), label: "running" },
|
|
865
|
+
paused: { fg: t.warning, bg: blendBg(t.bg, t.warning, 0.18), label: "paused" },
|
|
866
|
+
blocked: { fg: t.warning, bg: blendBg(t.bg, t.warning, 0.18), label: "blocked" },
|
|
867
|
+
completed: { fg: t.success, bg: blendBg(t.bg, t.success, 0.18), label: "completed" },
|
|
868
|
+
failed: { fg: t.error, bg: blendBg(t.bg, t.error, 0.18), label: "failed" },
|
|
869
|
+
};
|
|
870
|
+
const cfg = map[status] ?? map.pending!;
|
|
871
|
+
const body = ` ● ${cfg.label} `;
|
|
872
|
+
return {
|
|
873
|
+
styled: hexBg(cfg.bg) + hexToAnsi(cfg.fg) + BOLD + body + RESET,
|
|
874
|
+
width: visibleWidth(body),
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
private _sepRule(width: number): string {
|
|
879
|
+
return hexToAnsi(this.theme.borderDim) + "─".repeat(width) + RESET;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// -------------------------------------------------------------------------
|
|
883
|
+
// Body — welcome panel / banner + transcript / blocked
|
|
884
|
+
// -------------------------------------------------------------------------
|
|
885
|
+
|
|
886
|
+
private _renderBlockedBody(width: number, budget: number, stage: StageSnapshot | undefined): string[] {
|
|
887
|
+
const t = this.theme;
|
|
888
|
+
const upstream = stage?.blockedByStageId ?? "upstream stage";
|
|
889
|
+
const lines: string[] = [];
|
|
890
|
+
// Yellow banner — uses the same chrome vocabulary as paused/completed.
|
|
891
|
+
lines.push(...this._bannerLines(width, "warning", "↑", "BLOCKED", `waiting on ${upstream}`));
|
|
892
|
+
lines.push(this._blank(width));
|
|
893
|
+
lines.push(
|
|
894
|
+
...new Text(
|
|
895
|
+
paint("This stage is waiting for the upstream stage to resume.", t.textMuted),
|
|
896
|
+
2,
|
|
897
|
+
0,
|
|
898
|
+
).render(width),
|
|
899
|
+
);
|
|
900
|
+
lines.push(
|
|
901
|
+
...new Text(
|
|
902
|
+
paint("Press ", t.textMuted) +
|
|
903
|
+
paint("Ctrl+D", t.accent, { bold: true }) +
|
|
904
|
+
paint(" to return to the graph.", t.textMuted),
|
|
905
|
+
2,
|
|
906
|
+
0,
|
|
907
|
+
).render(width),
|
|
908
|
+
);
|
|
909
|
+
while (lines.length < budget) lines.push(this._blank(width));
|
|
910
|
+
if (lines.length > budget) lines.length = budget;
|
|
911
|
+
return lines;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
private _renderBody(
|
|
915
|
+
width: number,
|
|
916
|
+
budget: number,
|
|
917
|
+
stage: StageSnapshot | undefined,
|
|
918
|
+
flags: { paused: boolean; streaming: boolean; settled: boolean },
|
|
919
|
+
): string[] {
|
|
920
|
+
// Empty + not paused + not settled + not streaming → welcome panel.
|
|
921
|
+
const transcriptEmpty = this.transcript.length === 0;
|
|
922
|
+
if (transcriptEmpty && !flags.paused && !flags.settled && !flags.streaming) {
|
|
923
|
+
return this._fitToBudget(this._renderWelcome(width, stage), budget, width);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
const components: Component[] = [];
|
|
927
|
+
if (flags.paused) {
|
|
928
|
+
components.push(
|
|
929
|
+
this._banner(
|
|
930
|
+
"warning",
|
|
931
|
+
"❚❚",
|
|
932
|
+
"PAUSED",
|
|
933
|
+
"stopped between turns · type to resume, or Ctrl+P to release without input",
|
|
934
|
+
),
|
|
935
|
+
);
|
|
936
|
+
components.push(new Spacer(1));
|
|
937
|
+
} else if (flags.settled && stage?.status === "completed") {
|
|
938
|
+
components.push(this._banner("success", "✓", "COMPLETED", this._completedMeta(stage)));
|
|
939
|
+
components.push(new Spacer(1));
|
|
940
|
+
} else if (flags.settled && stage?.status === "failed") {
|
|
941
|
+
components.push(
|
|
942
|
+
this._banner(
|
|
943
|
+
"error",
|
|
944
|
+
"✗",
|
|
945
|
+
"FAILED",
|
|
946
|
+
stage?.error?.replace(/\s+/g, " ") ?? "stage exited with an error",
|
|
947
|
+
),
|
|
948
|
+
);
|
|
949
|
+
components.push(new Spacer(1));
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// Base chat body: delegate transcript composition to the Pi-style
|
|
953
|
+
// transcript component so the attached stage chat uses the same message
|
|
954
|
+
// spacing and coding-agent message widgets as the main interactive chat.
|
|
955
|
+
if (this.transcript.length > 0) {
|
|
956
|
+
components.push(new PiChatTranscriptComponent(this.transcript, (entry) => this._renderEntry(entry)));
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// Stream a static status message (e.g. "pausing…") as a dim trailing row.
|
|
960
|
+
if (this.statusMessage) {
|
|
961
|
+
components.push(new Spacer(1));
|
|
962
|
+
components.push(new Text(paint(this.statusMessage, this.theme.dim), 2, 0));
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// Flatten from the tail + sticky-bottom — show the most recent content.
|
|
966
|
+
// This keeps the 80ms Pi-style spinner tick cheap even after long chats:
|
|
967
|
+
// off-screen history is not rebuilt just to be sliced away.
|
|
968
|
+
return this._renderComponentTail(components, width, budget);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
private _renderComponentTail(components: Component[], width: number, budget: number): string[] {
|
|
972
|
+
const chunks: string[][] = [];
|
|
973
|
+
let lineCount = 0;
|
|
974
|
+
for (let i = components.length - 1; i >= 0; i--) {
|
|
975
|
+
const lines = components[i]!.render(width);
|
|
976
|
+
chunks.push(lines);
|
|
977
|
+
lineCount += lines.length;
|
|
978
|
+
if (lineCount >= budget) break;
|
|
979
|
+
}
|
|
980
|
+
const flat: string[] = [];
|
|
981
|
+
for (let i = chunks.length - 1; i >= 0; i--) flat.push(...chunks[i]!);
|
|
982
|
+
return this._fitToBudget(flat, budget, width);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
private _fitToBudget(lines: string[], budget: number, width: number): string[] {
|
|
986
|
+
if (lines.length >= budget) return lines.slice(lines.length - budget);
|
|
987
|
+
const out = lines.slice();
|
|
988
|
+
while (out.length < budget) out.push(this._blank(width));
|
|
989
|
+
return out;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// -------------------------------------------------------------------------
|
|
993
|
+
// Welcome panel — first attach, no transcript yet
|
|
994
|
+
// -------------------------------------------------------------------------
|
|
995
|
+
|
|
996
|
+
private _renderWelcome(width: number, stage: StageSnapshot | undefined): string[] {
|
|
997
|
+
const t = this.theme;
|
|
998
|
+
const sessionId = this.handle?.sessionId ?? stage?.sessionId;
|
|
999
|
+
const sessionFile = this.handle?.sessionFile ?? stage?.sessionFile;
|
|
1000
|
+
const status = stage?.status ?? "pending";
|
|
1001
|
+
|
|
1002
|
+
const out: string[] = [];
|
|
1003
|
+
out.push(...new Spacer(1).render(width));
|
|
1004
|
+
out.push(centred(paint("▎", t.mauve, { bold: true }), width));
|
|
1005
|
+
out.push(
|
|
1006
|
+
centred(
|
|
1007
|
+
paint("Attached to ", t.text) +
|
|
1008
|
+
paint(this.workflowName, t.textMuted) +
|
|
1009
|
+
paint(" / ", t.dim) +
|
|
1010
|
+
paint(stage?.name ?? "stage", t.text, { bold: true }),
|
|
1011
|
+
width,
|
|
1012
|
+
),
|
|
1013
|
+
);
|
|
1014
|
+
out.push(...new Spacer(1).render(width));
|
|
1015
|
+
const sub =
|
|
1016
|
+
"This stage is idle. Press ↵ to send the first prompt — the SDK session " +
|
|
1017
|
+
"will be created on submit. The workflow body keeps running in the " +
|
|
1018
|
+
"background; closing this overlay does not kill the run.";
|
|
1019
|
+
out.push(...new Text(paint(sub, t.textMuted), 4, 0).render(width));
|
|
1020
|
+
out.push(...new Spacer(1).render(width));
|
|
1021
|
+
|
|
1022
|
+
const grid: Array<[string, string]> = [
|
|
1023
|
+
["session", sessionId ? shortenId(sessionId) : "(not yet realised)"],
|
|
1024
|
+
["status", status],
|
|
1025
|
+
];
|
|
1026
|
+
if (sessionFile) grid.push(["session file", shortenFile(sessionFile)]);
|
|
1027
|
+
for (const [k, v] of grid) {
|
|
1028
|
+
const row = paint(k.padEnd(13), t.dim) + paint(v, t.text);
|
|
1029
|
+
out.push(...new Text(row, 8, 0).render(width));
|
|
1030
|
+
}
|
|
1031
|
+
return out;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
// -------------------------------------------------------------------------
|
|
1035
|
+
// Transcript entry → pi/coding-agent Component. Stage chat deliberately uses
|
|
1036
|
+
// the same exported message/tool components as the main interactive chat
|
|
1037
|
+
// instead of maintaining parallel workflow-specific bubbles.
|
|
1038
|
+
// -------------------------------------------------------------------------
|
|
1039
|
+
|
|
1040
|
+
private _renderEntry(entry: TranscriptEntry): Component {
|
|
1041
|
+
switch (entry.role) {
|
|
1042
|
+
case "user":
|
|
1043
|
+
return this._userMessage(entry.text);
|
|
1044
|
+
case "assistant":
|
|
1045
|
+
return new AssistantMessageComponent(assistantMessageForText(entry.text));
|
|
1046
|
+
case "thinking":
|
|
1047
|
+
return new AssistantMessageComponent(assistantMessageForThinking(entry.text));
|
|
1048
|
+
case "tool":
|
|
1049
|
+
return this._toolExecution(entry);
|
|
1050
|
+
case "notice":
|
|
1051
|
+
return this._noticeRow(entry);
|
|
1052
|
+
case "system":
|
|
1053
|
+
return new Text(paint(entry.text, this.theme.dim), 2, 0);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
private _userMessage(text: string): Component {
|
|
1058
|
+
const skillBlock = parseSkillBlock(text);
|
|
1059
|
+
if (!skillBlock) return new UserMessageComponent(text);
|
|
1060
|
+
|
|
1061
|
+
const container = new Container();
|
|
1062
|
+
container.addChild(new SkillInvocationMessageComponent(skillBlock));
|
|
1063
|
+
if (skillBlock.userMessage) {
|
|
1064
|
+
container.addChild(new UserMessageComponent(skillBlock.userMessage));
|
|
1065
|
+
}
|
|
1066
|
+
return container;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
private _toolExecution(entry: ToolEntry): Component {
|
|
1070
|
+
const component = new ToolExecutionComponent(
|
|
1071
|
+
entry.name,
|
|
1072
|
+
entry.toolCallId ?? `workflow-${entry.name}`,
|
|
1073
|
+
toolArgsForRender(entry),
|
|
1074
|
+
{ showImages: true },
|
|
1075
|
+
undefined,
|
|
1076
|
+
this._toolTui(),
|
|
1077
|
+
process.cwd(),
|
|
1078
|
+
);
|
|
1079
|
+
if (entry.state !== "pending" || entry.output) {
|
|
1080
|
+
component.updateResult(
|
|
1081
|
+
{
|
|
1082
|
+
content: entry.output
|
|
1083
|
+
? [{ type: "text", text: entry.output }]
|
|
1084
|
+
: [],
|
|
1085
|
+
isError: entry.state === "error",
|
|
1086
|
+
details: {},
|
|
1087
|
+
},
|
|
1088
|
+
entry.state === "pending",
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
return component;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
private _toolTui(): TUI {
|
|
1095
|
+
return {
|
|
1096
|
+
requestRender: () => this.requestRender?.(),
|
|
1097
|
+
} as TUI;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
private _noticeRow(entry: NoticeEntry): Component {
|
|
1101
|
+
const t = this.theme;
|
|
1102
|
+
const fromPart = entry.from ? paint(` (was ${entry.from})`, t.dim) : "";
|
|
1103
|
+
const metaPart = entry.meta ? " " + paint(entry.meta, t.dim) : "";
|
|
1104
|
+
const line =
|
|
1105
|
+
paint("~ ", t.borderDim) +
|
|
1106
|
+
paint(entry.kind, t.mauve, { bold: true }) +
|
|
1107
|
+
paint(" → ", t.borderDim) +
|
|
1108
|
+
paint(entry.value, t.text) +
|
|
1109
|
+
fromPart +
|
|
1110
|
+
metaPart;
|
|
1111
|
+
return new Text(line, 2, 0);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
// -------------------------------------------------------------------------
|
|
1115
|
+
// Banners (paused / completed / failed / blocked)
|
|
1116
|
+
// -------------------------------------------------------------------------
|
|
1117
|
+
|
|
1118
|
+
private _banner(
|
|
1119
|
+
kind: "warning" | "success" | "error",
|
|
1120
|
+
glyph: string,
|
|
1121
|
+
label: string,
|
|
1122
|
+
meta: string,
|
|
1123
|
+
): Component {
|
|
1124
|
+
const t = this.theme;
|
|
1125
|
+
const fg = kind === "warning" ? t.warning : kind === "success" ? t.success : t.error;
|
|
1126
|
+
const bg = blendBg(t.bg, fg, 0.10);
|
|
1127
|
+
const head =
|
|
1128
|
+
paintOnFill(glyph, fg, { bold: true }) +
|
|
1129
|
+
" " +
|
|
1130
|
+
paintOnFill(label, fg, { bold: true }) +
|
|
1131
|
+
" " +
|
|
1132
|
+
paintOnFill(stripAnsi(meta), t.dim);
|
|
1133
|
+
const box = new Box(2, 0, bgFn(bg));
|
|
1134
|
+
box.addChild(new Text(head, 0, 0));
|
|
1135
|
+
return box;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/**
|
|
1139
|
+
* Banner rendered directly as string lines. Used by `_renderBlockedBody`
|
|
1140
|
+
* which builds its body out of raw rows rather than a Component[] stack.
|
|
1141
|
+
*/
|
|
1142
|
+
private _bannerLines(
|
|
1143
|
+
width: number,
|
|
1144
|
+
kind: "warning" | "success" | "error",
|
|
1145
|
+
glyph: string,
|
|
1146
|
+
label: string,
|
|
1147
|
+
meta: string,
|
|
1148
|
+
): string[] {
|
|
1149
|
+
return this._banner(kind, glyph, label, meta).render(width);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// -------------------------------------------------------------------------
|
|
1153
|
+
// Loader — top rule + spinner row + bottom rule
|
|
1154
|
+
// -------------------------------------------------------------------------
|
|
1155
|
+
|
|
1156
|
+
private _renderLoader(width: number, stage: StageSnapshot | undefined): string[] {
|
|
1157
|
+
const t = this.theme;
|
|
1158
|
+
const rule = hexToAnsi(t.border) + "─".repeat(width) + RESET;
|
|
1159
|
+
const dur = stageDurationText(stage);
|
|
1160
|
+
const msg = `Working${dur ? " · " + dur : ""}`;
|
|
1161
|
+
const escapeHint = paint("Esc", t.text, { bold: true }) + " " + paint("interrupt", t.dim);
|
|
1162
|
+
const left = " " + paint(spinnerFrame(), t.accent, { bold: true }) + " " + paint(msg, t.textMuted) + " ";
|
|
1163
|
+
const leftW = visibleWidth(spinnerFrame()) + 4 + visibleWidth(msg);
|
|
1164
|
+
const rightW = visibleWidth("Esc interrupt");
|
|
1165
|
+
const gap = Math.max(1, width - leftW - rightW - 2);
|
|
1166
|
+
const body = left + " ".repeat(gap) + escapeHint + " ";
|
|
1167
|
+
// No closing rule — the editor's top rule (or the editor's body when
|
|
1168
|
+
// `omitTopRule: true`) sits directly underneath and provides the divider.
|
|
1169
|
+
return [rule, body];
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// -------------------------------------------------------------------------
|
|
1173
|
+
// Editor — top rule + ` ❯ … ` + bottom rule
|
|
1174
|
+
// -------------------------------------------------------------------------
|
|
1175
|
+
|
|
1176
|
+
private _renderEditor(
|
|
1177
|
+
width: number,
|
|
1178
|
+
flags: {
|
|
1179
|
+
paused: boolean;
|
|
1180
|
+
streaming: boolean;
|
|
1181
|
+
settled: boolean;
|
|
1182
|
+
blocked: boolean;
|
|
1183
|
+
/**
|
|
1184
|
+
* When `true`, drop the editor's top rule — the loader directly above
|
|
1185
|
+
* already paints a horizontal rule and we don't want a doubled border.
|
|
1186
|
+
*/
|
|
1187
|
+
omitTopRule: boolean;
|
|
1188
|
+
},
|
|
1189
|
+
): string[] {
|
|
1190
|
+
const t = this.theme;
|
|
1191
|
+
// Disabled (settled or blocked) uses surface1 rules + dim placeholder.
|
|
1192
|
+
const disabled = flags.settled || flags.blocked || !this.handle;
|
|
1193
|
+
if (!disabled && this.editor) {
|
|
1194
|
+
return this.editor.render(width);
|
|
1195
|
+
}
|
|
1196
|
+
const ruleHex = disabled ? t.borderDim : t.border;
|
|
1197
|
+
const rule = hexToAnsi(ruleHex) + "─".repeat(width) + RESET;
|
|
1198
|
+
|
|
1199
|
+
const glyphHex = disabled ? t.dim : t.accent;
|
|
1200
|
+
const placeholder = flags.blocked
|
|
1201
|
+
? "blocked · upstream stage owns the prompt"
|
|
1202
|
+
: flags.settled || !this.handle
|
|
1203
|
+
? "read-only · stage has no live handle"
|
|
1204
|
+
: flags.paused
|
|
1205
|
+
? "type to resume, or Ctrl+P to release without input…"
|
|
1206
|
+
: flags.streaming
|
|
1207
|
+
? "type to steer the current turn… (queues with ↵)"
|
|
1208
|
+
: "type a message…";
|
|
1209
|
+
|
|
1210
|
+
const value = this.inputBuffer
|
|
1211
|
+
? paint(truncateToWidth(this.inputBuffer, Math.max(8, width - 6)), t.text) + paint("▌", t.text)
|
|
1212
|
+
: paint(placeholder, t.dim, { italic: true });
|
|
1213
|
+
|
|
1214
|
+
const tag = flags.streaming
|
|
1215
|
+
? paint("streaming", t.accent, { bold: true })
|
|
1216
|
+
: flags.paused
|
|
1217
|
+
? paint("paused", t.warning, { bold: true })
|
|
1218
|
+
: flags.settled
|
|
1219
|
+
? paint("settled", t.success, { bold: true })
|
|
1220
|
+
: paint("idle", t.dim);
|
|
1221
|
+
const tagWidth = visibleWidth(stripAnsi(tag));
|
|
1222
|
+
const left = " " + paint("❯", glyphHex, { bold: true }) + " " + value;
|
|
1223
|
+
const valueWidth = visibleWidth(this.inputBuffer || placeholder);
|
|
1224
|
+
const leftWidth = 1 + 1 + 2 + valueWidth + (this.inputBuffer ? 1 : 0);
|
|
1225
|
+
const gap = Math.max(1, width - leftWidth - tagWidth - 2);
|
|
1226
|
+
const body = left + " ".repeat(gap) + tag + " ";
|
|
1227
|
+
return flags.omitTopRule ? [body, rule] : [rule, body, rule];
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
// -------------------------------------------------------------------------
|
|
1231
|
+
// Footer — two dim lines mirroring Pi's FooterComponent
|
|
1232
|
+
// -------------------------------------------------------------------------
|
|
1233
|
+
|
|
1234
|
+
private _renderFooter(
|
|
1235
|
+
width: number,
|
|
1236
|
+
stage: StageSnapshot | undefined,
|
|
1237
|
+
flags: { paused: boolean; streaming: boolean; settled: boolean },
|
|
1238
|
+
): string[] {
|
|
1239
|
+
const t = this.theme;
|
|
1240
|
+
const sessionId = this.handle?.sessionId ?? stage?.sessionId;
|
|
1241
|
+
const messages = this.handle?.messages.length ?? this.transcript.length;
|
|
1242
|
+
const dur = stageDurationText(stage) ?? "";
|
|
1243
|
+
|
|
1244
|
+
// Top line — left: workflow / stage tag; right: session id
|
|
1245
|
+
const lTop = paint(`pi-workflows/${this.workflowName}/${stage?.name ?? "stage"}`, t.dim);
|
|
1246
|
+
const rTop = sessionId
|
|
1247
|
+
? paint("session ", t.dim) + paint(shortenId(sessionId), t.textMuted)
|
|
1248
|
+
: paint("session not yet realised", t.dim);
|
|
1249
|
+
const top = layoutRow(width, " ", " " + lTop, rTop + " ", t);
|
|
1250
|
+
|
|
1251
|
+
// Bottom line — left: messages / duration; right: caption
|
|
1252
|
+
const lBot =
|
|
1253
|
+
paint(`◇ ${messages} messages`, t.dim) +
|
|
1254
|
+
(dur ? " " + paint(`· ${dur}`, t.dim) : "");
|
|
1255
|
+
const rBot = flags.streaming
|
|
1256
|
+
? paint("streaming · live", t.accent)
|
|
1257
|
+
: flags.paused
|
|
1258
|
+
? paint("paused · ready to resume", t.warning)
|
|
1259
|
+
: flags.settled && stage?.status === "completed"
|
|
1260
|
+
? paint("completed · session persisted", t.success)
|
|
1261
|
+
: flags.settled && stage?.status === "failed"
|
|
1262
|
+
? paint("failed · see error", t.error)
|
|
1263
|
+
: paint(this.statusMessage || "idle · awaiting input", t.dim);
|
|
1264
|
+
const bot = layoutRow(width, " ", " " + lBot, rBot + " ", t);
|
|
1265
|
+
return [top, bot];
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// -------------------------------------------------------------------------
|
|
1269
|
+
// Hints — dashed rule + key bindings
|
|
1270
|
+
// -------------------------------------------------------------------------
|
|
1271
|
+
|
|
1272
|
+
private _renderHints(
|
|
1273
|
+
width: number,
|
|
1274
|
+
flags: { paused: boolean; streaming: boolean; settled: boolean },
|
|
1275
|
+
): string[] {
|
|
1276
|
+
const t = this.theme;
|
|
1277
|
+
const dash = hexToAnsi(t.borderDim) + "╌".repeat(width) + RESET;
|
|
1278
|
+
const hints = this._hintSet(flags);
|
|
1279
|
+
const sep = paint(" · ", t.dim);
|
|
1280
|
+
const rendered = hints
|
|
1281
|
+
.map(({ key, label, emphasis }) =>
|
|
1282
|
+
paint(key, t.text, { bold: true }) +
|
|
1283
|
+
" " +
|
|
1284
|
+
paint(label, emphasis ? t.textMuted : t.dim, emphasis ? { bold: true } : {}),
|
|
1285
|
+
)
|
|
1286
|
+
.join(sep);
|
|
1287
|
+
const tagPlain = `pi-workflows/${this.workflowName}`;
|
|
1288
|
+
const renderedW = visibleWidth(stripAnsi(rendered));
|
|
1289
|
+
const tagW = visibleWidth(tagPlain);
|
|
1290
|
+
// Right-side tag is "nice to have". When the hint line + tag overflows
|
|
1291
|
+
// the chrome, drop the tag — the hints are the load-bearing affordance.
|
|
1292
|
+
if (renderedW + tagW + 3 > width) {
|
|
1293
|
+
const gap = Math.max(1, width - renderedW - 1);
|
|
1294
|
+
return [dash, " " + rendered + " ".repeat(gap)];
|
|
1295
|
+
}
|
|
1296
|
+
const tag = paint(tagPlain, t.dim);
|
|
1297
|
+
const gap = Math.max(1, width - renderedW - tagW - 2);
|
|
1298
|
+
return [dash, " " + rendered + " ".repeat(gap) + tag + " "];
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
private _hintSet(flags: {
|
|
1302
|
+
paused: boolean;
|
|
1303
|
+
streaming: boolean;
|
|
1304
|
+
settled: boolean;
|
|
1305
|
+
}): Array<{ key: string; label: string; emphasis?: boolean }> {
|
|
1306
|
+
if (flags.settled) {
|
|
1307
|
+
return [
|
|
1308
|
+
{ key: "Ctrl+D", label: "back to graph", emphasis: true },
|
|
1309
|
+
{ key: "Esc", label: "close" },
|
|
1310
|
+
];
|
|
1311
|
+
}
|
|
1312
|
+
if (flags.paused) {
|
|
1313
|
+
return [
|
|
1314
|
+
{ key: "↵", label: "resume with message", emphasis: true },
|
|
1315
|
+
{ key: "Ctrl+P", label: "resume empty" },
|
|
1316
|
+
{ key: "Ctrl+D", label: "back" },
|
|
1317
|
+
{ key: "Esc", label: "close" },
|
|
1318
|
+
];
|
|
1319
|
+
}
|
|
1320
|
+
if (flags.streaming) {
|
|
1321
|
+
return [
|
|
1322
|
+
{ key: "↵", label: "steer", emphasis: true },
|
|
1323
|
+
{ key: "Ctrl+F", label: "follow-up", emphasis: true },
|
|
1324
|
+
{ key: "Ctrl+P", label: "pause" },
|
|
1325
|
+
{ key: "Ctrl+D", label: "back" },
|
|
1326
|
+
{ key: "Esc", label: "interrupt" },
|
|
1327
|
+
];
|
|
1328
|
+
}
|
|
1329
|
+
return [
|
|
1330
|
+
{ key: "↵", label: "send", emphasis: true },
|
|
1331
|
+
{ key: "Ctrl+F", label: "follow-up" },
|
|
1332
|
+
{ key: "Ctrl+P", label: "pause" },
|
|
1333
|
+
{ key: "Ctrl+D", label: "back" },
|
|
1334
|
+
{ key: "Esc", label: "close" },
|
|
1335
|
+
];
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
// -------------------------------------------------------------------------
|
|
1339
|
+
// Small helpers
|
|
1340
|
+
// -------------------------------------------------------------------------
|
|
1341
|
+
|
|
1342
|
+
private _completedMeta(stage: StageSnapshot | undefined): string {
|
|
1343
|
+
const dur = stageDurationText(stage);
|
|
1344
|
+
const parts: string[] = ["stage settled"];
|
|
1345
|
+
if (dur) parts.push(dur);
|
|
1346
|
+
if (stage?.sessionFile) parts.push(`session ${shortenFile(stage.sessionFile)}`);
|
|
1347
|
+
return parts.join(" · ");
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
private _blank(width: number): string {
|
|
1351
|
+
return " ".repeat(width);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// -------------------------------------------------------------------------
|
|
1355
|
+
// Input
|
|
1356
|
+
// -------------------------------------------------------------------------
|
|
1357
|
+
|
|
1358
|
+
handleInput(data: string): boolean {
|
|
1359
|
+
if (data === "\x04") {
|
|
1360
|
+
this.onDetach();
|
|
1361
|
+
return true;
|
|
1362
|
+
}
|
|
1363
|
+
if (data === "\x1b") {
|
|
1364
|
+
if (this._isStreaming() && !this._isBlocked()) {
|
|
1365
|
+
void this._pause();
|
|
1366
|
+
} else {
|
|
1367
|
+
this.onClose();
|
|
1368
|
+
}
|
|
1369
|
+
return true;
|
|
1370
|
+
}
|
|
1371
|
+
const blocked = this._isBlocked();
|
|
1372
|
+
if (data === "\x10") {
|
|
1373
|
+
if (blocked) return true;
|
|
1374
|
+
void this._pause();
|
|
1375
|
+
return true;
|
|
1376
|
+
}
|
|
1377
|
+
if (data === "\x06") {
|
|
1378
|
+
if (blocked) return true;
|
|
1379
|
+
void this._submit("followUp");
|
|
1380
|
+
return true;
|
|
1381
|
+
}
|
|
1382
|
+
if (this.editor) {
|
|
1383
|
+
if (blocked) return true;
|
|
1384
|
+
this.editor.handleInput(data);
|
|
1385
|
+
return true;
|
|
1386
|
+
}
|
|
1387
|
+
if (data === "\r" || data === "\n") {
|
|
1388
|
+
if (blocked) return true;
|
|
1389
|
+
void this._submit("auto");
|
|
1390
|
+
return true;
|
|
1391
|
+
}
|
|
1392
|
+
if (data === "\x7f" || data === "\b") {
|
|
1393
|
+
if (blocked) return true;
|
|
1394
|
+
this.inputBuffer = this.inputBuffer.slice(0, -1);
|
|
1395
|
+
return true;
|
|
1396
|
+
}
|
|
1397
|
+
if (data.length === 1 && data >= " " && data <= "~") {
|
|
1398
|
+
if (blocked) return true;
|
|
1399
|
+
this.inputBuffer += data;
|
|
1400
|
+
return true;
|
|
1401
|
+
}
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
private async _pause(): Promise<void> {
|
|
1406
|
+
if (!this.handle) {
|
|
1407
|
+
this.statusMessage = "no live handle on this stage";
|
|
1408
|
+
this.requestRender?.();
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
this.localPaused = true;
|
|
1412
|
+
this.statusMessage = "pausing…";
|
|
1413
|
+
this.requestRender?.();
|
|
1414
|
+
try {
|
|
1415
|
+
await this.handle.pause();
|
|
1416
|
+
this.sdkBusy = false;
|
|
1417
|
+
this.statusMessage = "paused";
|
|
1418
|
+
} catch (err) {
|
|
1419
|
+
this.statusMessage = `pause failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
1420
|
+
this.localPaused = false;
|
|
1421
|
+
} finally {
|
|
1422
|
+
this._syncAnimationTick();
|
|
1423
|
+
this.requestRender?.();
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
private async _submit(mode: "auto" | "followUp", submittedText?: string): Promise<void> {
|
|
1428
|
+
const text = (submittedText ?? this.inputBuffer).trim();
|
|
1429
|
+
if (!text) return;
|
|
1430
|
+
this.inputBuffer = "";
|
|
1431
|
+
this.editor?.setText("");
|
|
1432
|
+
if (!this.handle) {
|
|
1433
|
+
this.statusMessage = "no live handle on this stage";
|
|
1434
|
+
this.transcript.push({
|
|
1435
|
+
role: "system",
|
|
1436
|
+
text: "(no live handle — message dropped)",
|
|
1437
|
+
});
|
|
1438
|
+
this.requestRender?.();
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
this.transcript.push({ role: "user", text });
|
|
1442
|
+
this.optimisticUserSignatures.add(userMessageSignature(text));
|
|
1443
|
+
this.requestRender?.();
|
|
1444
|
+
try {
|
|
1445
|
+
if (this.localPaused) {
|
|
1446
|
+
this.sdkBusy = true;
|
|
1447
|
+
this._syncAnimationTick();
|
|
1448
|
+
await this.handle.resume(text);
|
|
1449
|
+
this.localPaused = false;
|
|
1450
|
+
this.statusMessage = "resumed";
|
|
1451
|
+
this.requestRender?.();
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
if (mode === "followUp") {
|
|
1455
|
+
await this.handle.followUp(text);
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
if (this.handle.isStreaming) {
|
|
1459
|
+
await this.handle.steer(text);
|
|
1460
|
+
} else {
|
|
1461
|
+
this.sdkBusy = true;
|
|
1462
|
+
this._syncAnimationTick();
|
|
1463
|
+
await this.handle.ensureAttached();
|
|
1464
|
+
await this.handle.prompt(text);
|
|
1465
|
+
}
|
|
1466
|
+
} catch (err) {
|
|
1467
|
+
this.sdkBusy = false;
|
|
1468
|
+
this.statusMessage = err instanceof Error ? err.message : String(err);
|
|
1469
|
+
this._syncAnimationTick();
|
|
1470
|
+
this.requestRender?.();
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
invalidate(): void {
|
|
1475
|
+
// Stateless render reads directly from snapshot + handle.
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
dispose(): void {
|
|
1479
|
+
this._unsubscribeStore?.();
|
|
1480
|
+
this._unsubscribeStore = null;
|
|
1481
|
+
this._unsubscribeHandle?.();
|
|
1482
|
+
this._unsubscribeHandle = null;
|
|
1483
|
+
if (this.animationTimer) {
|
|
1484
|
+
clearInterval(this.animationTimer);
|
|
1485
|
+
this.animationTimer = undefined;
|
|
1486
|
+
}
|
|
1487
|
+
this.editor = undefined;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// ---- Test seams ----
|
|
1491
|
+
get _inputBuffer(): string {
|
|
1492
|
+
return this.inputBuffer;
|
|
1493
|
+
}
|
|
1494
|
+
get _transcript(): readonly TranscriptEntry[] {
|
|
1495
|
+
return this.transcript;
|
|
1496
|
+
}
|
|
1497
|
+
get _statusMessage(): string {
|
|
1498
|
+
return this.statusMessage;
|
|
1499
|
+
}
|
|
1500
|
+
get _isLocalPaused(): boolean {
|
|
1501
|
+
return this.localPaused;
|
|
1502
|
+
}
|
|
1503
|
+
get _hasAnimationTick(): boolean {
|
|
1504
|
+
return this.animationTimer !== undefined;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// ---------------------------------------------------------------------------
|
|
1509
|
+
// Module-private helpers
|
|
1510
|
+
// ---------------------------------------------------------------------------
|
|
1511
|
+
|
|
1512
|
+
type AssistantComponentMessage = NonNullable<
|
|
1513
|
+
ConstructorParameters<typeof AssistantMessageComponent>[0]
|
|
1514
|
+
>;
|
|
1515
|
+
|
|
1516
|
+
function assistantMessageForText(text: string): AssistantComponentMessage {
|
|
1517
|
+
return {
|
|
1518
|
+
role: "assistant",
|
|
1519
|
+
content: [{ type: "text", text }],
|
|
1520
|
+
stopReason: "stop",
|
|
1521
|
+
} as AssistantComponentMessage;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
function assistantMessageForThinking(text: string): AssistantComponentMessage {
|
|
1525
|
+
return {
|
|
1526
|
+
role: "assistant",
|
|
1527
|
+
content: [{ type: "thinking", thinking: text }],
|
|
1528
|
+
stopReason: "stop",
|
|
1529
|
+
} as AssistantComponentMessage;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
function toolArgsForRender(entry: ToolEntry): Record<string, unknown> {
|
|
1533
|
+
if (!entry.args) return {};
|
|
1534
|
+
if (entry.name === "bash") {
|
|
1535
|
+
return { command: entry.args.replace(/^command=/, "") };
|
|
1536
|
+
}
|
|
1537
|
+
return { input: entry.args };
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
function isMessageLike(message: unknown): message is { role?: unknown; content?: unknown; stopReason?: unknown; errorMessage?: unknown } {
|
|
1541
|
+
return message !== null && typeof message === "object" && "role" in message;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
function userMessageSignature(text: string): string {
|
|
1545
|
+
return text.trim();
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
interface AssistantProjection {
|
|
1549
|
+
text: string;
|
|
1550
|
+
thinking: string;
|
|
1551
|
+
toolCalls: Array<{ toolCallId?: string; name: string; args?: string; state: "pending" }>;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
function assistantContentHasRenderablePayload(content: unknown): boolean {
|
|
1555
|
+
if (typeof content === "string") return content.length > 0;
|
|
1556
|
+
if (!Array.isArray(content)) return false;
|
|
1557
|
+
return content.some((item) => {
|
|
1558
|
+
if (typeof item === "string") return item.length > 0;
|
|
1559
|
+
if (item == null || typeof item !== "object") return false;
|
|
1560
|
+
const obj = item as { type?: unknown; text?: unknown; thinking?: unknown };
|
|
1561
|
+
return (obj.type === "text" && typeof obj.text === "string" && obj.text.length > 0) ||
|
|
1562
|
+
(obj.type === "thinking" && typeof obj.thinking === "string" && obj.thinking.length > 0) ||
|
|
1563
|
+
obj.type === "toolCall";
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
function projectAssistantContent(content: unknown): AssistantProjection {
|
|
1568
|
+
const projection: AssistantProjection = { text: "", thinking: "", toolCalls: [] };
|
|
1569
|
+
if (!Array.isArray(content)) {
|
|
1570
|
+
projection.text = typeof content === "string" ? content : "";
|
|
1571
|
+
return projection;
|
|
1572
|
+
}
|
|
1573
|
+
const textParts: string[] = [];
|
|
1574
|
+
const thinkingParts: string[] = [];
|
|
1575
|
+
for (const item of content) {
|
|
1576
|
+
if (item == null) continue;
|
|
1577
|
+
if (typeof item === "string") {
|
|
1578
|
+
textParts.push(item);
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
if (typeof item !== "object") continue;
|
|
1582
|
+
const obj = item as {
|
|
1583
|
+
type?: unknown;
|
|
1584
|
+
text?: unknown;
|
|
1585
|
+
thinking?: unknown;
|
|
1586
|
+
id?: unknown;
|
|
1587
|
+
name?: unknown;
|
|
1588
|
+
arguments?: unknown;
|
|
1589
|
+
args?: unknown;
|
|
1590
|
+
};
|
|
1591
|
+
if (obj.type === "text" && typeof obj.text === "string") {
|
|
1592
|
+
textParts.push(obj.text);
|
|
1593
|
+
continue;
|
|
1594
|
+
}
|
|
1595
|
+
if (obj.type === "thinking" && typeof obj.thinking === "string") {
|
|
1596
|
+
thinkingParts.push(obj.thinking);
|
|
1597
|
+
continue;
|
|
1598
|
+
}
|
|
1599
|
+
if (obj.type === "toolCall") {
|
|
1600
|
+
const name = typeof obj.name === "string" ? obj.name : "tool";
|
|
1601
|
+
const toolCallId = typeof obj.id === "string" ? obj.id : undefined;
|
|
1602
|
+
const args = summariseArgs(obj.arguments ?? obj.args);
|
|
1603
|
+
projection.toolCalls.push({ toolCallId, name, args, state: "pending" });
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
projection.text = textParts.join("");
|
|
1607
|
+
projection.thinking = thinkingParts.join("\n\n");
|
|
1608
|
+
return projection;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
function shallowToolEntryEqual(a: ToolEntry, b: ToolEntry): boolean {
|
|
1612
|
+
return a.role === b.role &&
|
|
1613
|
+
a.text === b.text &&
|
|
1614
|
+
a.name === b.name &&
|
|
1615
|
+
a.toolCallId === b.toolCallId &&
|
|
1616
|
+
a.args === b.args &&
|
|
1617
|
+
a.output === b.output &&
|
|
1618
|
+
a.state === b.state;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
function transcriptEntryFromSnapshotMessage(
|
|
1622
|
+
message: AgentSnapshotMessage,
|
|
1623
|
+
): TranscriptEntry | undefined {
|
|
1624
|
+
switch (message.role) {
|
|
1625
|
+
case "user": {
|
|
1626
|
+
const text = extractMessageText(message.content);
|
|
1627
|
+
return text ? { role: "user", text } : undefined;
|
|
1628
|
+
}
|
|
1629
|
+
case "assistant": {
|
|
1630
|
+
const text = extractMessageText(message.content);
|
|
1631
|
+
return text ? { role: "assistant", text } : undefined;
|
|
1632
|
+
}
|
|
1633
|
+
case "toolResult": {
|
|
1634
|
+
const output = extractMessageText(message.content);
|
|
1635
|
+
const summary = output ? truncateToWidth(output.replace(/\s+/g, " "), 80) : "";
|
|
1636
|
+
return {
|
|
1637
|
+
role: "tool",
|
|
1638
|
+
name: message.toolName,
|
|
1639
|
+
output,
|
|
1640
|
+
state: message.isError ? "error" : "success",
|
|
1641
|
+
text: summary ? `← ${message.toolName} ${summary}` : `← ${message.toolName}`,
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
case "bashExecution": {
|
|
1645
|
+
const state =
|
|
1646
|
+
message.cancelled || (message.exitCode !== undefined && message.exitCode !== 0)
|
|
1647
|
+
? "error"
|
|
1648
|
+
: "success";
|
|
1649
|
+
const summary = message.output ? truncateToWidth(message.output.replace(/\s+/g, " "), 80) : "";
|
|
1650
|
+
return {
|
|
1651
|
+
role: "tool",
|
|
1652
|
+
name: "bash",
|
|
1653
|
+
args: truncateToWidth(message.command.replace(/\s+/g, " "), 60),
|
|
1654
|
+
output: message.output,
|
|
1655
|
+
state,
|
|
1656
|
+
text: summary ? `← bash ${summary}` : `→ bash ${message.command}`,
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
case "custom": {
|
|
1660
|
+
if (!message.display) return undefined;
|
|
1661
|
+
const text = extractMessageText(message.content);
|
|
1662
|
+
return text ? { role: "system", text } : undefined;
|
|
1663
|
+
}
|
|
1664
|
+
case "branchSummary": {
|
|
1665
|
+
const text = `Branch summary: ${message.summary}`;
|
|
1666
|
+
return { role: "system", text };
|
|
1667
|
+
}
|
|
1668
|
+
case "compactionSummary": {
|
|
1669
|
+
const text = `Compaction summary: ${message.summary}`;
|
|
1670
|
+
return { role: "system", text };
|
|
1671
|
+
}
|
|
1672
|
+
default:
|
|
1673
|
+
// The SDK message union is extensible. Snapshot unknown roles must be
|
|
1674
|
+
// skipped here instead of being cast into `TranscriptEntry`; `_renderBody`
|
|
1675
|
+
// only flattens the closed set of components returned by `_renderEntry`.
|
|
1676
|
+
return undefined;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
function isSessionMessageEntry(entry: unknown): entry is SessionMessageEntry {
|
|
1681
|
+
return entry !== null &&
|
|
1682
|
+
typeof entry === "object" &&
|
|
1683
|
+
(entry as { type?: unknown }).type === "message" &&
|
|
1684
|
+
"message" in entry;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
function extractMessageText(content: unknown): string {
|
|
1688
|
+
if (typeof content === "string") return content;
|
|
1689
|
+
if (!Array.isArray(content)) return "";
|
|
1690
|
+
const parts: string[] = [];
|
|
1691
|
+
for (const item of content) {
|
|
1692
|
+
if (item == null) continue;
|
|
1693
|
+
if (typeof item === "string") {
|
|
1694
|
+
parts.push(item);
|
|
1695
|
+
continue;
|
|
1696
|
+
}
|
|
1697
|
+
const obj = item as { type?: unknown; text?: unknown };
|
|
1698
|
+
if (typeof obj.text === "string") parts.push(obj.text);
|
|
1699
|
+
else if (obj.type === "text" && typeof obj.text === "string") parts.push(obj.text);
|
|
1700
|
+
}
|
|
1701
|
+
return parts.join("");
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
function extractToolResultText(result: unknown): string {
|
|
1705
|
+
if (typeof result === "string") return result;
|
|
1706
|
+
if (result == null || typeof result !== "object") return "";
|
|
1707
|
+
const content = (result as { content?: unknown }).content;
|
|
1708
|
+
return extractMessageText(content);
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
function findToolEntryIndex(
|
|
1712
|
+
entries: readonly TranscriptEntry[],
|
|
1713
|
+
toolCallId: string | undefined,
|
|
1714
|
+
name: string,
|
|
1715
|
+
): number {
|
|
1716
|
+
if (toolCallId !== undefined) {
|
|
1717
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
1718
|
+
const entry = entries[i];
|
|
1719
|
+
if (entry?.role === "tool" && entry.toolCallId === toolCallId) return i;
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
1723
|
+
const entry = entries[i];
|
|
1724
|
+
if (entry?.role === "tool" && entry.name === name && entry.state === "pending") return i;
|
|
1725
|
+
}
|
|
1726
|
+
return -1;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
function summariseArgs(input: unknown): string {
|
|
1730
|
+
if (input == null) return "";
|
|
1731
|
+
if (typeof input === "string") return truncateToWidth(input.replace(/\s+/g, " "), 60);
|
|
1732
|
+
if (typeof input !== "object") return String(input);
|
|
1733
|
+
const obj = input as Record<string, unknown>;
|
|
1734
|
+
const keys = Object.keys(obj);
|
|
1735
|
+
if (keys.length === 0) return "";
|
|
1736
|
+
const head = keys[0]!;
|
|
1737
|
+
const value = obj[head];
|
|
1738
|
+
const summary = typeof value === "string" ? value : JSON.stringify(value);
|
|
1739
|
+
const formatted = `${head}=${summary}`;
|
|
1740
|
+
return truncateToWidth(formatted.replace(/\s+/g, " "), 60);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
function noticeSummary(n: StageNotice): string {
|
|
1744
|
+
const base = `~ ${n.kind} → ${n.to}`;
|
|
1745
|
+
return n.from ? `${base} (was ${n.from})` : base;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
function stageDurationText(stage: StageSnapshot | undefined): string {
|
|
1749
|
+
if (!stage?.startedAt) return "";
|
|
1750
|
+
const end = stage.endedAt ?? Date.now();
|
|
1751
|
+
const ms = Math.max(0, end - stage.startedAt);
|
|
1752
|
+
return formatDuration(ms);
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
function formatDuration(ms: number): string {
|
|
1756
|
+
if (ms < 1000) return `${ms}ms`;
|
|
1757
|
+
const s = Math.floor(ms / 1000);
|
|
1758
|
+
if (s < 60) return `${s}s`;
|
|
1759
|
+
const m = Math.floor(s / 60);
|
|
1760
|
+
const rs = s % 60;
|
|
1761
|
+
if (m < 60) return rs ? `${m}m ${rs}s` : `${m}m`;
|
|
1762
|
+
const h = Math.floor(m / 60);
|
|
1763
|
+
const rm = m % 60;
|
|
1764
|
+
return rm ? `${h}h ${rm}m` : `${h}h`;
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
function shortenId(id: string): string {
|
|
1768
|
+
return id.length > 10 ? id.slice(0, 8) : id;
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
function shortenFile(path: string): string {
|
|
1772
|
+
if (path.length <= 36) return path;
|
|
1773
|
+
// Keep the basename and an ellipsis prefix so the user can still recognise
|
|
1774
|
+
// which session file we're pointing at.
|
|
1775
|
+
const slash = path.lastIndexOf("/");
|
|
1776
|
+
if (slash < 0) return "…" + path.slice(-35);
|
|
1777
|
+
return "…" + path.slice(Math.max(slash - 12, 0));
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
function spinnerFrame(): string {
|
|
1781
|
+
const idx = Math.floor(Date.now() / 80) % SPINNER_FRAMES.length;
|
|
1782
|
+
return SPINNER_FRAMES[idx]!;
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
function bgFn(hex: string): (text: string) => string {
|
|
1786
|
+
const open = hexBg(hex);
|
|
1787
|
+
return (text: string) => open + text + RESET;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
function editorThemeFromGraphTheme(t: GraphTheme): EditorTheme {
|
|
1791
|
+
const selected = (text: string): string => hexBg(t.backgroundPanel) + hexToAnsi(t.text) + text + RESET;
|
|
1792
|
+
const normal = (text: string): string => hexToAnsi(t.text) + text + RESET;
|
|
1793
|
+
return {
|
|
1794
|
+
borderColor: (text: string) => hexToAnsi(t.border) + text + RESET,
|
|
1795
|
+
selectList: {
|
|
1796
|
+
selectedPrefix: selected,
|
|
1797
|
+
selectedText: selected,
|
|
1798
|
+
description: (text: string) => hexToAnsi(t.dim) + text + RESET,
|
|
1799
|
+
scrollInfo: (text: string) => hexToAnsi(t.dim) + text + RESET,
|
|
1800
|
+
noMatch: (text: string) => hexToAnsi(t.warning) + text + RESET,
|
|
1801
|
+
normal,
|
|
1802
|
+
},
|
|
1803
|
+
} as EditorTheme;
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
interface PaintOpts {
|
|
1807
|
+
bold?: boolean;
|
|
1808
|
+
italic?: boolean;
|
|
1809
|
+
bg?: string;
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
function paint(text: string, fg: string, opts: PaintOpts = {}): string {
|
|
1813
|
+
if (!text) return "";
|
|
1814
|
+
let out = hexToAnsi(fg);
|
|
1815
|
+
if (opts.bold) out += BOLD;
|
|
1816
|
+
if (opts.italic) out += ITALIC;
|
|
1817
|
+
if (opts.bg) out = hexBg(opts.bg) + out;
|
|
1818
|
+
return out + text + RESET;
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
/**
|
|
1822
|
+
* Foreground styling for text that will be wrapped by a `Box` background.
|
|
1823
|
+
* A normal `RESET` would also clear the parent background, so close only the
|
|
1824
|
+
* inline foreground/weight/italic state and let `bgFn()` reset the row at end.
|
|
1825
|
+
*/
|
|
1826
|
+
function paintOnFill(text: string, fg: string, opts: PaintOpts = {}): string {
|
|
1827
|
+
if (!text) return "";
|
|
1828
|
+
let out = hexToAnsi(fg);
|
|
1829
|
+
if (opts.bold) out += BOLD;
|
|
1830
|
+
if (opts.italic) out += ITALIC;
|
|
1831
|
+
let close = FG_RESET;
|
|
1832
|
+
if (opts.bold) close += WEIGHT_RESET;
|
|
1833
|
+
if (opts.italic) close += ITALIC_RESET;
|
|
1834
|
+
return out + text + close;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
function stripAnsi(s: string): string {
|
|
1838
|
+
return s.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "");
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
function centred(content: string, width: number): string {
|
|
1842
|
+
const w = visibleWidth(stripAnsi(content));
|
|
1843
|
+
if (w >= width) return content;
|
|
1844
|
+
const left = Math.floor((width - w) / 2);
|
|
1845
|
+
const right = width - w - left;
|
|
1846
|
+
return " ".repeat(left) + content + " ".repeat(right);
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
/**
|
|
1850
|
+
* Compose a two-column row of `${prefix}${left}…${right}` padded to width.
|
|
1851
|
+
* Used by the footer to lay out left/right slabs without losing ANSI runs.
|
|
1852
|
+
*/
|
|
1853
|
+
function layoutRow(
|
|
1854
|
+
width: number,
|
|
1855
|
+
_prefix: string,
|
|
1856
|
+
left: string,
|
|
1857
|
+
right: string,
|
|
1858
|
+
_theme: GraphTheme,
|
|
1859
|
+
): string {
|
|
1860
|
+
const lw = visibleWidth(stripAnsi(left));
|
|
1861
|
+
const rw = visibleWidth(stripAnsi(right));
|
|
1862
|
+
const gap = Math.max(1, width - lw - rw);
|
|
1863
|
+
return left + " ".repeat(gap) + right;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
/**
|
|
1867
|
+
* Approximate a tinted background by mixing the base canvas with a saturated
|
|
1868
|
+
* hue at low alpha. Used for status pills and tool-bar tints. Returns a hex
|
|
1869
|
+
* colour the renderer can feed to `hexBg`.
|
|
1870
|
+
*/
|
|
1871
|
+
function blendBg(baseHex: string, tintHex: string, alpha: number): string {
|
|
1872
|
+
return lerpColor(baseHex, tintHex, Math.max(0, Math.min(1, alpha)));
|
|
1873
|
+
}
|