@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,2143 @@
|
|
|
1
|
+
import { renderCall } from "./render-call.js";
|
|
2
|
+
import { renderResult } from "./render-result.js";
|
|
3
|
+
import type { RenderResultOpts, WorkflowInputEntry, WorkflowToolResult } from "./render-result.js";
|
|
4
|
+
import { renderInputsSchema } from "../shared/render-inputs-schema.js";
|
|
5
|
+
import { WorkflowParametersSchema } from "./workflow-schema.js";
|
|
6
|
+
import { renderRunBanner, renderRunSummary } from "./renderers.js";
|
|
7
|
+
import type { RunEndPayload, RunStartPayload } from "./renderers.js";
|
|
8
|
+
import { store } from "../shared/store.js";
|
|
9
|
+
import { restoreOnSessionStart } from "../shared/persistence-restore.js";
|
|
10
|
+
import type { SessionManager } from "../shared/persistence-restore.js";
|
|
11
|
+
import { installCompactionHook } from "../shared/persistence-compaction-policy.js";
|
|
12
|
+
import {
|
|
13
|
+
killRun,
|
|
14
|
+
killAllRuns,
|
|
15
|
+
resumeRun,
|
|
16
|
+
pauseRun,
|
|
17
|
+
inspectRun,
|
|
18
|
+
} from "../runs/background/status.js";
|
|
19
|
+
import { cancellationRegistry } from "../runs/background/cancellation-registry.js";
|
|
20
|
+
import { registerIntercomParentSession } from "../intercom/intercom-bridge.js";
|
|
21
|
+
import { subscribeIntercomControl } from "../intercom/result-intercom.js";
|
|
22
|
+
import { buildIntercomCallbacks } from "../intercom/intercom-routing.js";
|
|
23
|
+
import {
|
|
24
|
+
installStoreWidget,
|
|
25
|
+
installToolExecutionHooks,
|
|
26
|
+
} from "../tui/store-widget-installer.js";
|
|
27
|
+
import type { WidgetFactory } from "../tui/store-widget-installer.js";
|
|
28
|
+
import { buildGraphOverlayAdapter } from "../tui/overlay-adapter.js";
|
|
29
|
+
import type { OverlayPiSurface } from "../tui/overlay-adapter.js";
|
|
30
|
+
import type { GraphOverlayPort } from "../tui/overlay-adapter.js";
|
|
31
|
+
import { renderSessionList } from "../tui/session-list.js";
|
|
32
|
+
import { selectRunsForPicker } from "../tui/session-picker.js";
|
|
33
|
+
|
|
34
|
+
import { openSessionPicker, openKillConfirm } from "../tui/session-overlays.js";
|
|
35
|
+
import {
|
|
36
|
+
openInlineInputsForm,
|
|
37
|
+
registerInlineFormRenderer,
|
|
38
|
+
} from "../tui/inline-form-overlay.js";
|
|
39
|
+
import {
|
|
40
|
+
registerChatSurfaceRenderer,
|
|
41
|
+
emitChatSurface,
|
|
42
|
+
} from "../tui/chat-surface-message.js";
|
|
43
|
+
import { openInputsPicker } from "../tui/inputs-overlay.js";
|
|
44
|
+
import { deriveGraphTheme } from "../tui/graph-theme.js";
|
|
45
|
+
import { createExtensionRuntime } from "./runtime.js";
|
|
46
|
+
import type { ExtensionRuntime } from "./runtime.js";
|
|
47
|
+
import {
|
|
48
|
+
discoverWorkflows,
|
|
49
|
+
discoverStartupWorkflowsSync,
|
|
50
|
+
} from "./discovery.js";
|
|
51
|
+
import type { DiscoveryResult } from "./discovery.js";
|
|
52
|
+
import {
|
|
53
|
+
loadWorkflowConfig,
|
|
54
|
+
toScopedDiscoveryConfig,
|
|
55
|
+
WORKFLOW_CONFIG_DEFAULTS,
|
|
56
|
+
withWorkflowDefaults,
|
|
57
|
+
} from "./config-loader.js";
|
|
58
|
+
import type { ConfigLoadResult } from "./config-loader.js";
|
|
59
|
+
import type {
|
|
60
|
+
WorkflowPersistencePort,
|
|
61
|
+
WorkflowMcpPort,
|
|
62
|
+
WorkflowRuntimeConfig,
|
|
63
|
+
WorkflowChainStep,
|
|
64
|
+
WorkflowDirectTaskItem,
|
|
65
|
+
WorkflowDetails,
|
|
66
|
+
WorkflowMaxOutput,
|
|
67
|
+
WorkflowModelCatalogPort,
|
|
68
|
+
WorkflowModelInfo,
|
|
69
|
+
} from "../shared/types.js";import { buildRuntimeAdapters } from "./wiring.js";
|
|
70
|
+
import type { PiUISurface } from "./wiring.js";
|
|
71
|
+
import { createStatusWriter } from "./status-writer.js";
|
|
72
|
+
import type { StatusWriter } from "./status-writer.js";
|
|
73
|
+
import { setMcpScope, clearMcpScope } from "./mcp.js";
|
|
74
|
+
import type { PiMcpExtensionAPI, PiEventBus } from "./mcp.js";
|
|
75
|
+
import type { StageSessionRuntime } from "../runs/foreground/stage-runner.js";
|
|
76
|
+
import type { CreateAgentSessionOptions } from "@earendil-works/pi-coding-agent";
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Minimal ExtensionAPI structural types
|
|
80
|
+
// No `any`; all optional fields use explicit union with undefined.
|
|
81
|
+
// cross-ref: pi docs/skills/authoring-extensions.md (ExtensionAPI shape)
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
/** Theme object passed to renderCall/renderResult slots (opaque — not consumed in stubs). */
|
|
85
|
+
export type PiTheme = Record<string, string>;
|
|
86
|
+
|
|
87
|
+
/** Context object passed to renderCall/renderResult slots. */
|
|
88
|
+
export interface PiRenderContext {
|
|
89
|
+
state?: {
|
|
90
|
+
runId?: string;
|
|
91
|
+
stages?: unknown[];
|
|
92
|
+
};
|
|
93
|
+
invalidate?: () => void;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Options bag passed to renderResult. */
|
|
97
|
+
export interface PiRenderResultOpts extends RenderResultOpts {}
|
|
98
|
+
|
|
99
|
+
export interface PiRenderComponent {
|
|
100
|
+
render(width: number): string[];
|
|
101
|
+
invalidate?: () => void;
|
|
102
|
+
includes(searchString: string): boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function textRenderComponent(text: string): PiRenderComponent {
|
|
106
|
+
return {
|
|
107
|
+
render(_width: number): string[] {
|
|
108
|
+
return text.split("\n");
|
|
109
|
+
},
|
|
110
|
+
includes(searchString: string): boolean {
|
|
111
|
+
return text.includes(searchString);
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Completion for a slash-command argument. Matches pi-tui's `AutocompleteItem`.
|
|
118
|
+
* `value` is the text inserted on selection; `label` is the menu display; the
|
|
119
|
+
* optional `description` is the secondary line. Without `value`, pi-tui crashes
|
|
120
|
+
* in `getBestAutocompleteMatchIndex` (`value.startsWith(prefix)`).
|
|
121
|
+
* cross-ref: @earendil-works/pi-tui autocomplete AutocompleteItem
|
|
122
|
+
*/
|
|
123
|
+
export interface PiArgumentCompletion {
|
|
124
|
+
value: string;
|
|
125
|
+
label: string;
|
|
126
|
+
description?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Canonical slash command options for pi.registerCommand(name, options).
|
|
131
|
+
* Mirrors `RegisteredCommand` from pi's `extensibility/extensions/types.ts`
|
|
132
|
+
* minus the `name` field (which is the first arg to registerCommand).
|
|
133
|
+
* cross-ref: research/docs/2026-05-11-pi-coding-agent-reference.md §4.2
|
|
134
|
+
*/
|
|
135
|
+
export type PiArgumentCompletionResult = PiArgumentCompletion[] | null;
|
|
136
|
+
|
|
137
|
+
export interface PiCommandOptions {
|
|
138
|
+
description: string;
|
|
139
|
+
handler: (args: string, ctx: PiCommandContext) => Promise<void> | void;
|
|
140
|
+
getArgumentCompletions?: (
|
|
141
|
+
partial: string,
|
|
142
|
+
) => PiArgumentCompletionResult;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Context provided to slash command handlers. Aligns with pi's
|
|
147
|
+
* `ExtensionCommandContext` (subset of what we actually consume): the
|
|
148
|
+
* host always supplies `ui` and `ui.notify`, so callers print via
|
|
149
|
+
* `ctx.ui.notify("…", "info")` directly — no wrapper indirection.
|
|
150
|
+
*/
|
|
151
|
+
interface PiRuntimeModel {
|
|
152
|
+
readonly provider: string;
|
|
153
|
+
readonly id: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
interface PiRuntimeModelRegistry {
|
|
157
|
+
getAvailable(): PiRuntimeModel[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
interface PiModelContext {
|
|
161
|
+
readonly model?: PiRuntimeModel;
|
|
162
|
+
readonly modelRegistry?: PiRuntimeModelRegistry;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface PiCommandContext extends PiModelContext {
|
|
166
|
+
ui: {
|
|
167
|
+
notify: (message: string, type?: "info" | "warning" | "error") => void;
|
|
168
|
+
} & PiUISurface;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** CLI flag registration options. Mirrors the inline options on `ExtensionAPI.registerFlag`. */
|
|
172
|
+
export interface PiFlagNamedOpts {
|
|
173
|
+
description: string;
|
|
174
|
+
type?: "string" | "boolean";
|
|
175
|
+
default?: unknown;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Pi's AgentToolResult shape — returned by `execute` and consumed by
|
|
180
|
+
* `renderResult`. `details` carries the original workflow result for the
|
|
181
|
+
* renderer; `content` is what the model sees on tool completion.
|
|
182
|
+
*/
|
|
183
|
+
export interface PiAgentToolResult<TDetails> {
|
|
184
|
+
content: Array<
|
|
185
|
+
{ type: "text"; text: string } | { type: "image"; [key: string]: unknown }
|
|
186
|
+
>;
|
|
187
|
+
details: TDetails;
|
|
188
|
+
terminate?: boolean;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Tool registration options aligned with pi's `ToolDefinition`. */
|
|
192
|
+
export interface PiToolOpts<TArgs, TDetails> {
|
|
193
|
+
name: string;
|
|
194
|
+
label: string;
|
|
195
|
+
description: string;
|
|
196
|
+
parameters: unknown; // TypeBox TSchema — pi consumes it opaquely
|
|
197
|
+
/**
|
|
198
|
+
* Pi calls execute positionally: `(toolCallId, params, signal, onUpdate, ctx)`.
|
|
199
|
+
* cross-ref: pi-coding-agent dist/core/extensions/types.d.ts ToolDefinition.execute
|
|
200
|
+
*/
|
|
201
|
+
execute: (
|
|
202
|
+
toolCallId: string,
|
|
203
|
+
params: TArgs,
|
|
204
|
+
signal: AbortSignal | undefined,
|
|
205
|
+
onUpdate: ((partial: PiAgentToolResult<TDetails>) => void) | undefined,
|
|
206
|
+
ctx: PiExecuteContext,
|
|
207
|
+
) => Promise<PiAgentToolResult<TDetails>>;
|
|
208
|
+
/** Pi passes args directly as the first positional arg (not wrapped). */
|
|
209
|
+
renderCall?: (
|
|
210
|
+
args: TArgs,
|
|
211
|
+
theme: PiTheme,
|
|
212
|
+
context: PiRenderContext,
|
|
213
|
+
) => PiRenderComponent | string;
|
|
214
|
+
/** Pi passes the full AgentToolResult as the first positional arg. */
|
|
215
|
+
renderResult?: (
|
|
216
|
+
result: PiAgentToolResult<TDetails>,
|
|
217
|
+
opts: PiRenderResultOpts,
|
|
218
|
+
theme: PiTheme,
|
|
219
|
+
context: PiRenderContext,
|
|
220
|
+
) => PiRenderComponent | string;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Execution context provided to tool execute handlers. */
|
|
224
|
+
export interface PiExecuteContext extends PiModelContext {
|
|
225
|
+
sessionId?: string;
|
|
226
|
+
ui?: PiUISurface;
|
|
227
|
+
hasUI?: boolean;
|
|
228
|
+
sessionManager?: SessionManager & { getSessionFile?: () => string | undefined };
|
|
229
|
+
[key: string]: unknown;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Structural subset of pi's `ExtensionAPI` (see
|
|
234
|
+
* `packages/coding-agent/src/extensibility/extensions/types.ts`) covering
|
|
235
|
+
* the methods this extension consumes. Fields are optional so test
|
|
236
|
+
* mocks can stub a minimal surface; production runtime supplies all of
|
|
237
|
+
* them.
|
|
238
|
+
*/
|
|
239
|
+
export interface ExtensionAPI {
|
|
240
|
+
registerTool?: <TArgs, TResult>(opts: PiToolOpts<TArgs, TResult>) => void;
|
|
241
|
+
/**
|
|
242
|
+
* `pi.registerCommand(name, options)` — sole slash-command registration
|
|
243
|
+
* surface. Mirrors pi's `ExtensionAPI.registerCommand`.
|
|
244
|
+
*/
|
|
245
|
+
registerCommand?: (name: string, options: PiCommandOptions) => void;
|
|
246
|
+
registerMessageRenderer?: (
|
|
247
|
+
event: string,
|
|
248
|
+
renderer: (payload: unknown) => string,
|
|
249
|
+
) => void;
|
|
250
|
+
/**
|
|
251
|
+
* Inject a custom message into the chat history. Used by the inline
|
|
252
|
+
* workflow input form to emit a sticky card under `customType:
|
|
253
|
+
* "workflows:input-form"`. The card stays in scrollback and is
|
|
254
|
+
* re-rendered by the registered renderer on every `tui.requestRender()`.
|
|
255
|
+
*/
|
|
256
|
+
sendMessage?: <T = unknown>(
|
|
257
|
+
message: {
|
|
258
|
+
customType: string;
|
|
259
|
+
content?: string;
|
|
260
|
+
display?: boolean;
|
|
261
|
+
details?: T;
|
|
262
|
+
},
|
|
263
|
+
options?: {
|
|
264
|
+
triggerTurn?: boolean;
|
|
265
|
+
deliverAs?: "steer" | "followUp" | "nextTurn";
|
|
266
|
+
},
|
|
267
|
+
) => void | Promise<void>;
|
|
268
|
+
registerFlag?: (name: string, opts: PiFlagNamedOpts) => void;
|
|
269
|
+
/**
|
|
270
|
+
* Register a keyboard shortcut.
|
|
271
|
+
* Present on pi >= 1.x; absent on older runtimes.
|
|
272
|
+
*/
|
|
273
|
+
registerShortcut?: (
|
|
274
|
+
key: string,
|
|
275
|
+
opts: {
|
|
276
|
+
description: string;
|
|
277
|
+
handler: (ctx?: PiCommandContext) => void | Promise<void>;
|
|
278
|
+
},
|
|
279
|
+
) => void;
|
|
280
|
+
/**
|
|
281
|
+
* Sets the current session name. Present on pi's ExtensionAPI.
|
|
282
|
+
*/
|
|
283
|
+
setSessionName?: (name: string) => void | Promise<void>;
|
|
284
|
+
/**
|
|
285
|
+
* pi events bus — used for workflow-scoped MCP events and subagent
|
|
286
|
+
* lifecycle/result routing.
|
|
287
|
+
*/
|
|
288
|
+
events?: {
|
|
289
|
+
emit?: (event: string, payload: Record<string, unknown>) => void;
|
|
290
|
+
on?: (event: string, handler: (payload: unknown) => void) => void;
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* Execute a shell command and return stdout/stderr/exit code.
|
|
294
|
+
* Present on the pi ExtensionAPI.
|
|
295
|
+
*/
|
|
296
|
+
exec?: (
|
|
297
|
+
command: string,
|
|
298
|
+
args: string[],
|
|
299
|
+
opts?: { signal?: AbortSignal; timeout?: number },
|
|
300
|
+
) => Promise<{
|
|
301
|
+
stdout: string;
|
|
302
|
+
stderr: string;
|
|
303
|
+
code: number;
|
|
304
|
+
killed: boolean;
|
|
305
|
+
}>;
|
|
306
|
+
/** Test seam: inject a stub session factory instead of importing the pi SDK at runtime. */
|
|
307
|
+
createAgentSession?: (
|
|
308
|
+
options?: CreateAgentSessionOptions,
|
|
309
|
+
) => Promise<{ session: StageSessionRuntime }>;
|
|
310
|
+
/** Test/degraded-runtime seam: skip project/global discovery work at startup. */
|
|
311
|
+
disableAsyncDiscovery?: boolean;
|
|
312
|
+
// -------------------------------------------------------------------------
|
|
313
|
+
// Persistence API (§5.6)
|
|
314
|
+
// -------------------------------------------------------------------------
|
|
315
|
+
/** Appends a typed entry to the session transcript. Returns the entry ID. */
|
|
316
|
+
appendEntry?: (
|
|
317
|
+
type: string,
|
|
318
|
+
payload: Record<string, unknown>,
|
|
319
|
+
) => string | undefined;
|
|
320
|
+
/** Labels an entry for /tree bookmark filtering. */
|
|
321
|
+
setLabel?: (entryId: string, label: string) => void;
|
|
322
|
+
/** Appends a synthetic system/assistant message entry. */
|
|
323
|
+
appendCustomMessageEntry?: (
|
|
324
|
+
content: string,
|
|
325
|
+
meta?: Record<string, unknown>,
|
|
326
|
+
) => string | undefined;
|
|
327
|
+
// -------------------------------------------------------------------------
|
|
328
|
+
// Lifecycle events (§5.6, §8.1 Phase D)
|
|
329
|
+
// -------------------------------------------------------------------------
|
|
330
|
+
/** Register a listener for a pi lifecycle event (e.g. session_start, session_before_compact). */
|
|
331
|
+
on?: (
|
|
332
|
+
event: string,
|
|
333
|
+
handler: (
|
|
334
|
+
event?: unknown,
|
|
335
|
+
ctx?: PiCommandContext & {
|
|
336
|
+
sessionManager?: SessionManager;
|
|
337
|
+
hasUI?: boolean;
|
|
338
|
+
},
|
|
339
|
+
) => void | object | Promise<void | object>,
|
|
340
|
+
) => void;
|
|
341
|
+
// -------------------------------------------------------------------------
|
|
342
|
+
// Session manager (§5.6 restore)
|
|
343
|
+
// -------------------------------------------------------------------------
|
|
344
|
+
sessionManager?: SessionManager;
|
|
345
|
+
ui?: {
|
|
346
|
+
setWidget?: (
|
|
347
|
+
key: string,
|
|
348
|
+
factory: WidgetFactory | undefined,
|
|
349
|
+
opts?: { placement?: string },
|
|
350
|
+
) => void;
|
|
351
|
+
/**
|
|
352
|
+
* Spawn a custom TUI component (overlay or inline).
|
|
353
|
+
* When overlay: true, the panel floats over existing content.
|
|
354
|
+
* Returns a handle with close() to dismiss, or undefined when unsupported.
|
|
355
|
+
*/
|
|
356
|
+
custom?: PiUISurface["custom"];
|
|
357
|
+
} & PiUISurface;
|
|
358
|
+
[key: string]: unknown;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ---------------------------------------------------------------------------
|
|
362
|
+
// Workflow tool argument shape
|
|
363
|
+
// ---------------------------------------------------------------------------
|
|
364
|
+
|
|
365
|
+
export interface WorkflowToolArgs {
|
|
366
|
+
/** Canonical named workflow identifier. */
|
|
367
|
+
workflow?: string;
|
|
368
|
+
inputs?: Record<string, unknown>;
|
|
369
|
+
action?: "run" | "list" | "get" | "status" | "interrupt" | "resume" | "inputs";
|
|
370
|
+
/** Canonical run identifier for status/interrupt/resume. */
|
|
371
|
+
runId?: string;
|
|
372
|
+
/** Direct single-task mode, or root task string when chain is present. */
|
|
373
|
+
task?: WorkflowDirectTaskItem | string;
|
|
374
|
+
/** Direct top-level parallel mode. */
|
|
375
|
+
tasks?: WorkflowDirectTaskItem[];
|
|
376
|
+
/** Direct sequential/parallel chain mode. */
|
|
377
|
+
chain?: WorkflowChainStep[];
|
|
378
|
+
chainName?: string;
|
|
379
|
+
context?: "fresh" | "fork";
|
|
380
|
+
/** Internal host-derived parent session file for context:"fork". */
|
|
381
|
+
forkFromSessionFile?: string;
|
|
382
|
+
concurrency?: number;
|
|
383
|
+
async?: boolean;
|
|
384
|
+
intercom?: {
|
|
385
|
+
enabled?: boolean;
|
|
386
|
+
delivery?: "off" | "notify" | "result" | "control-and-result";
|
|
387
|
+
parentSession?: string;
|
|
388
|
+
notifyOn?: Array<"active_long_running" | "needs_attention" | "completed" | "failed">;
|
|
389
|
+
};
|
|
390
|
+
cwd?: string;
|
|
391
|
+
output?: string | false;
|
|
392
|
+
outputMode?: "inline" | "file-only";
|
|
393
|
+
chainDir?: string;
|
|
394
|
+
maxOutput?: WorkflowMaxOutput;
|
|
395
|
+
artifacts?: boolean;
|
|
396
|
+
sessionDir?: string;
|
|
397
|
+
progress?: boolean;
|
|
398
|
+
worktree?: boolean;
|
|
399
|
+
fallbackModels?: string[];
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// ---------------------------------------------------------------------------
|
|
403
|
+
// Tool parameter schema
|
|
404
|
+
// ---------------------------------------------------------------------------
|
|
405
|
+
|
|
406
|
+
const workflowParameters = WorkflowParametersSchema;
|
|
407
|
+
|
|
408
|
+
function hasDirectExecutionMode(args: WorkflowToolArgs): boolean {
|
|
409
|
+
return (
|
|
410
|
+
(args.task !== undefined && typeof args.task === "object") ||
|
|
411
|
+
Array.isArray(args.tasks) ||
|
|
412
|
+
Array.isArray(args.chain)
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function directModeCount(args: WorkflowToolArgs): number {
|
|
417
|
+
return [
|
|
418
|
+
args.task !== undefined && typeof args.task === "object",
|
|
419
|
+
Array.isArray(args.tasks),
|
|
420
|
+
Array.isArray(args.chain),
|
|
421
|
+
].filter(Boolean).length;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function hasNamedExecutionMode(args: WorkflowToolArgs): boolean {
|
|
425
|
+
return (
|
|
426
|
+
typeof args.workflow === "string" && args.workflow.trim().length > 0
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function directRequestsFork(args: WorkflowToolArgs): boolean {
|
|
431
|
+
if (args.context === "fork") return true;
|
|
432
|
+
if (args.task !== undefined && typeof args.task === "object" && args.task.context === "fork") return true;
|
|
433
|
+
if (args.tasks?.some((task) => task.context === "fork")) return true;
|
|
434
|
+
return args.chain?.some((step) =>
|
|
435
|
+
"parallel" in step
|
|
436
|
+
? step.parallel.some((task) => task.context === "fork")
|
|
437
|
+
: step.context === "fork",
|
|
438
|
+
) ?? false;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function withForkParentSession(args: WorkflowToolArgs, ctx: PiExecuteContext): WorkflowToolArgs {
|
|
442
|
+
if (!directRequestsFork(args) || args.forkFromSessionFile !== undefined) return args;
|
|
443
|
+
const sessionFile = ctx.sessionManager?.getSessionFile?.();
|
|
444
|
+
return typeof sessionFile === "string" && sessionFile.length > 0
|
|
445
|
+
? { ...args, forkFromSessionFile: sessionFile }
|
|
446
|
+
: args;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function workflowRunResultFromDetails(details: WorkflowDetails): WorkflowToolResult {
|
|
450
|
+
return {
|
|
451
|
+
action: "run",
|
|
452
|
+
name: `direct-${details.mode}`,
|
|
453
|
+
runId: details.runId ?? "",
|
|
454
|
+
status: details.status,
|
|
455
|
+
result: details.output,
|
|
456
|
+
details,
|
|
457
|
+
error: details.error,
|
|
458
|
+
stages: [],
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function workflowGetResult(runtime: ExtensionRuntime, args: WorkflowToolArgs): WorkflowToolResult {
|
|
463
|
+
const workflow = args.workflow ?? "";
|
|
464
|
+
const def = runtime.registry.get(workflow);
|
|
465
|
+
if (!def) {
|
|
466
|
+
return {
|
|
467
|
+
action: "get",
|
|
468
|
+
workflow,
|
|
469
|
+
error: `Workflow not found: "${workflow}"`,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
const inputs = Object.entries(def.inputs).map(([name, schema]) => ({
|
|
473
|
+
name,
|
|
474
|
+
type: schema.type,
|
|
475
|
+
description: schema.description,
|
|
476
|
+
required: schema.required,
|
|
477
|
+
default: "default" in schema ? schema.default : undefined,
|
|
478
|
+
choices: schema.type === "select" ? schema.choices : undefined,
|
|
479
|
+
}));
|
|
480
|
+
return {
|
|
481
|
+
action: "get",
|
|
482
|
+
workflow: def.normalizedName,
|
|
483
|
+
details: {
|
|
484
|
+
mode: "inspection",
|
|
485
|
+
action: "get",
|
|
486
|
+
status: "completed",
|
|
487
|
+
output: {
|
|
488
|
+
workflow: def.normalizedName,
|
|
489
|
+
name: def.name,
|
|
490
|
+
description: def.description,
|
|
491
|
+
inputs,
|
|
492
|
+
},
|
|
493
|
+
progress: { completed: 0, total: 0 },
|
|
494
|
+
},
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ---------------------------------------------------------------------------
|
|
499
|
+
// Tool execute — dispatch with real registry for list/inputs/run (Phase E)
|
|
500
|
+
// + real status/interrupt/resume (Phase D)
|
|
501
|
+
// ---------------------------------------------------------------------------
|
|
502
|
+
|
|
503
|
+
export function makeExecuteWorkflowTool(
|
|
504
|
+
runtime: ExtensionRuntime | ((ctx: PiExecuteContext) => ExtensionRuntime),
|
|
505
|
+
getPersistence: () => WorkflowPersistencePort | undefined,
|
|
506
|
+
) {
|
|
507
|
+
return async function executeWorkflowTool(
|
|
508
|
+
args: WorkflowToolArgs,
|
|
509
|
+
ctx: PiExecuteContext,
|
|
510
|
+
): Promise<WorkflowToolResult> {
|
|
511
|
+
const action = args.action ?? "run";
|
|
512
|
+
const runId = args.runId ?? "";
|
|
513
|
+
const activeRuntime =
|
|
514
|
+
typeof runtime === "function" ? runtime(ctx) : runtime;
|
|
515
|
+
|
|
516
|
+
switch (action) {
|
|
517
|
+
case "get":
|
|
518
|
+
return workflowGetResult(activeRuntime, args);
|
|
519
|
+
|
|
520
|
+
case "list":
|
|
521
|
+
case "inputs":
|
|
522
|
+
case "run":
|
|
523
|
+
if (action === "run" && hasDirectExecutionMode(args)) {
|
|
524
|
+
const normalModeCount = directModeCount(args) + (hasNamedExecutionMode(args) ? 1 : 0);
|
|
525
|
+
if (normalModeCount !== 1) {
|
|
526
|
+
throw new Error("Workflow extension: specify exactly one normal execution mode: workflow, task, tasks, or chain");
|
|
527
|
+
}
|
|
528
|
+
const details = await activeRuntime.runDirect(withForkParentSession(args, ctx));
|
|
529
|
+
return workflowRunResultFromDetails(details);
|
|
530
|
+
}
|
|
531
|
+
// Delegate to registry-backed dispatcher.
|
|
532
|
+
// Real errors propagate — no broad catch.
|
|
533
|
+
return activeRuntime.dispatch(args);
|
|
534
|
+
|
|
535
|
+
case "status": {
|
|
536
|
+
// Detail mode — single-run lookup via id.
|
|
537
|
+
const target = args.runId;
|
|
538
|
+
if (target !== undefined) {
|
|
539
|
+
const result = inspectRun(target);
|
|
540
|
+
if (result.ok) {
|
|
541
|
+
return {
|
|
542
|
+
action: "statusDetail",
|
|
543
|
+
runId: result.runId,
|
|
544
|
+
detail: result.detail,
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
action: "statusDetail",
|
|
549
|
+
runId: target,
|
|
550
|
+
error: `run not found: ${target}`,
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
// List mode — emit live snapshots; the renderer produces the
|
|
554
|
+
// canonical band + card surface.
|
|
555
|
+
const snapshots = store.runs().filter((r) => r.endedAt === undefined);
|
|
556
|
+
return {
|
|
557
|
+
action: "status",
|
|
558
|
+
snapshots: snapshots.map(
|
|
559
|
+
(s) => JSON.parse(JSON.stringify(s)) as typeof s,
|
|
560
|
+
),
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
case "interrupt": {
|
|
565
|
+
// Support canonical interrupt-all via runId sentinel.
|
|
566
|
+
if (runId === "--all") {
|
|
567
|
+
const results = killAllRuns({
|
|
568
|
+
cancellation: cancellationRegistry,
|
|
569
|
+
persistence: getPersistence(),
|
|
570
|
+
});
|
|
571
|
+
const killed = results.filter((r) => r.ok).length;
|
|
572
|
+
return {
|
|
573
|
+
action,
|
|
574
|
+
runId: "--all",
|
|
575
|
+
status: killed > 0 ? "killed" : "noop",
|
|
576
|
+
message:
|
|
577
|
+
killed > 0
|
|
578
|
+
? `Interrupted ${killed} run(s).`
|
|
579
|
+
: "No in-flight runs to interrupt.",
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
const result = killRun(runId, {
|
|
583
|
+
cancellation: cancellationRegistry,
|
|
584
|
+
persistence: getPersistence(),
|
|
585
|
+
});
|
|
586
|
+
if (result.ok) {
|
|
587
|
+
return {
|
|
588
|
+
action,
|
|
589
|
+
runId: result.runId,
|
|
590
|
+
status: "killed",
|
|
591
|
+
message: `Run ${result.runId} interrupted (was ${result.previousStatus}).`,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
return {
|
|
595
|
+
action,
|
|
596
|
+
runId,
|
|
597
|
+
status: "noop",
|
|
598
|
+
message:
|
|
599
|
+
result.reason === "not_found"
|
|
600
|
+
? `Run not found: ${runId}`
|
|
601
|
+
: `Run already ended: ${runId}`,
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
case "resume": {
|
|
606
|
+
const result = resumeRun(runId);
|
|
607
|
+
if (result.ok) {
|
|
608
|
+
return {
|
|
609
|
+
action: "resume",
|
|
610
|
+
runId: result.runId,
|
|
611
|
+
status: "ok",
|
|
612
|
+
message: `Snapshot available: run ${result.runId} (${result.snapshot.name}) \u2014 status: ${result.snapshot.status}, stages: ${result.snapshot.stages.length}`,
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
return {
|
|
616
|
+
action: "resume",
|
|
617
|
+
runId,
|
|
618
|
+
status: "noop",
|
|
619
|
+
message: `Run not found: ${runId}`,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
default: {
|
|
624
|
+
// Exhaustive — all action variants handled above.
|
|
625
|
+
const _exhaustive: never = action;
|
|
626
|
+
throw new Error(`Workflow extension: unknown action "${_exhaustive}"`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// ---------------------------------------------------------------------------
|
|
633
|
+
// Slash command helpers
|
|
634
|
+
// ---------------------------------------------------------------------------
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Local registry of workflow command (name → handler). Populated by
|
|
638
|
+
* `registerWorkflowCommand` alongside the host registration so the
|
|
639
|
+
* `on("input", …)` interceptor below can dispatch our commands directly
|
|
640
|
+
* — bypassing pi's optimistic `startPendingSubmission` flow which
|
|
641
|
+
* fires the `Working… (esc to interrupt)` loader before the host knows
|
|
642
|
+
* the input is a synchronous picker/connect UI, not a streaming turn.
|
|
643
|
+
*
|
|
644
|
+
* See `installInputInterceptor()` for the dispatch path and rationale.
|
|
645
|
+
*/
|
|
646
|
+
type WorkflowCommandHandler = PiCommandOptions["handler"];
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Register a slash command with the host AND remember the handler so
|
|
650
|
+
* the input interceptor can dispatch directly.
|
|
651
|
+
*
|
|
652
|
+
* `pi.registerCommand` is the sole supported registration surface
|
|
653
|
+
* (mirrors pi's `ExtensionAPI.registerCommand`). When the host
|
|
654
|
+
* lacks `registerCommand` (degraded runtime — RPC mode, headless, or a
|
|
655
|
+
* mock that didn't stub it) we still populate the registry so the
|
|
656
|
+
* input interceptor can intercept the command text the user typed.
|
|
657
|
+
*
|
|
658
|
+
* We forward to `pi.registerCommand` first so any host-side wrapping
|
|
659
|
+
* (telemetry, logging, sandboxing) of `options.handler` lands in the
|
|
660
|
+
* registry; the input interceptor then dispatches the same callable
|
|
661
|
+
* the host would dispatch from `session.prompt`.
|
|
662
|
+
*/
|
|
663
|
+
function registerWorkflowCommand(
|
|
664
|
+
pi: ExtensionAPI,
|
|
665
|
+
name: string,
|
|
666
|
+
options: PiCommandOptions,
|
|
667
|
+
registry: Map<string, WorkflowCommandHandler>,
|
|
668
|
+
): void {
|
|
669
|
+
pi.registerCommand?.(name, options);
|
|
670
|
+
registry.set(name, options.handler);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Install an `on("input", …)` interceptor that short-circuits the host
|
|
675
|
+
* submission pipeline for our registered workflow commands.
|
|
676
|
+
*
|
|
677
|
+
* Why this exists
|
|
678
|
+
* ---------------
|
|
679
|
+
* pi's editor `onSubmit` handler unconditionally calls
|
|
680
|
+
* `startPendingSubmission` for any text that isn't a built-in slash /
|
|
681
|
+
* skill / bash / python command — this echoes the message into chat
|
|
682
|
+
* scrollback AND starts the `Working… (esc to interrupt)` loader in
|
|
683
|
+
* `statusContainer` before `session.prompt` even runs. The loader is
|
|
684
|
+
* an optimistic affordance for the agent-streaming case; for our
|
|
685
|
+
* synchronous picker/connect UIs (`/workflow connect`, `/workflow run`,
|
|
686
|
+
* `/workflow pause`, …) it's noise — the
|
|
687
|
+
* spinner sits above the picker until the handler returns.
|
|
688
|
+
*
|
|
689
|
+
* `runner.emitInput` runs BEFORE `startPendingSubmission` (see
|
|
690
|
+
* `packages/coding-agent/src/modes/controllers/input-controller.ts`
|
|
691
|
+
* `setupEditorSubmitHandler`). Returning `{ action: "handled" }` from an
|
|
692
|
+
* `on("input", …)` handler short-circuits the function: the host
|
|
693
|
+
* clears the editor and returns without echoing or starting the
|
|
694
|
+
* loader. We dispatch the command handler ourselves with the same
|
|
695
|
+
* context the host would have passed.
|
|
696
|
+
*
|
|
697
|
+
* Shape note: pi's `InputEventResult` is `{ action: "continue" } |
|
|
698
|
+
* { action: "transform"; text; images? } | { action: "handled" }`. The
|
|
699
|
+
* older `{ handled: true }` shape is silently ignored by the runner
|
|
700
|
+
* (`result?.action === "handled"` check), which lets the loader fire.
|
|
701
|
+
*
|
|
702
|
+
* cross-ref:
|
|
703
|
+
* - pi docs/extensions.md (input event)
|
|
704
|
+
* - pi docs/slash-command-internals.md (#tryExecuteExtensionCommand)
|
|
705
|
+
* - pi packages/coding-agent/src/modes/interactive-mode.ts
|
|
706
|
+
* `startPendingSubmission` / `ensureLoadingAnimation`
|
|
707
|
+
*/
|
|
708
|
+
function installInputInterceptor(
|
|
709
|
+
pi: ExtensionAPI,
|
|
710
|
+
commands: Map<string, WorkflowCommandHandler>,
|
|
711
|
+
): void {
|
|
712
|
+
if (typeof pi.on !== "function") return;
|
|
713
|
+
|
|
714
|
+
pi.on("input", async (event, ctx) => {
|
|
715
|
+
const text = (event as { text?: unknown } | undefined)?.text;
|
|
716
|
+
if (typeof text !== "string") return undefined;
|
|
717
|
+
const trimmed = text.trim();
|
|
718
|
+
if (!trimmed.startsWith("/")) return undefined;
|
|
719
|
+
|
|
720
|
+
// First token (after `/`) is the command name. Whitespace splits
|
|
721
|
+
// command from args; quote handling lives inside the command
|
|
722
|
+
// handler itself (`tokenizeWorkflowArgs`).
|
|
723
|
+
const firstSpace = trimmed.indexOf(" ");
|
|
724
|
+
const name = firstSpace === -1 ? trimmed.slice(1) : trimmed.slice(1, firstSpace);
|
|
725
|
+
const handler = commands.get(name);
|
|
726
|
+
if (!handler) return undefined; // not ours — let host run its normal flow.
|
|
727
|
+
|
|
728
|
+
const args = firstSpace === -1 ? "" : trimmed.slice(firstSpace + 1);
|
|
729
|
+
const commandCtx = ctx as PiCommandContext;
|
|
730
|
+
try {
|
|
731
|
+
await handler(args, commandCtx);
|
|
732
|
+
} catch (err) {
|
|
733
|
+
// Match the host command runner: swallow handler exceptions so a
|
|
734
|
+
// throw never bubbles out and crashes the editor submit pipeline.
|
|
735
|
+
// Surface the failure via `ctx.ui.notify` so the user sees it.
|
|
736
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
737
|
+
commandCtx.ui.notify(`/${name} failed: ${message}`, "error");
|
|
738
|
+
}
|
|
739
|
+
return { action: "handled" };
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Resolve a user-supplied run identifier (full UUID or unique prefix) to
|
|
746
|
+
* a concrete runId. The widget surfaces an 8-char prefix to keep the
|
|
747
|
+
* status line scannable; users copy that prefix straight into the interrupt
|
|
748
|
+
* slash command, so prefix matching is the expected affordance.
|
|
749
|
+
*/
|
|
750
|
+
type RunIdResolution =
|
|
751
|
+
| { kind: "exact"; runId: string }
|
|
752
|
+
| { kind: "ambiguous"; matches: string[] }
|
|
753
|
+
| { kind: "not_found" };
|
|
754
|
+
|
|
755
|
+
function resolveRunIdPrefix(target: string): RunIdResolution {
|
|
756
|
+
const runs = store.runs();
|
|
757
|
+
const exact = runs.find((r) => r.id === target);
|
|
758
|
+
if (exact) return { kind: "exact", runId: exact.id };
|
|
759
|
+
|
|
760
|
+
const prefixed = runs.filter((r) => r.id.startsWith(target));
|
|
761
|
+
if (prefixed.length === 0) return { kind: "not_found" };
|
|
762
|
+
if (prefixed.length === 1) return { kind: "exact", runId: prefixed[0]!.id };
|
|
763
|
+
return { kind: "ambiguous", matches: prefixed.map((r) => r.id) };
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
function overlaySurfaceFromContext(ctx?: {
|
|
767
|
+
ui?: PiUISurface;
|
|
768
|
+
}): OverlayPiSurface | undefined {
|
|
769
|
+
// Only forward `ctx.ui` to the overlay adapter when it actually
|
|
770
|
+
// carries the `custom` mount surface. Inline pickers (replace-editor)
|
|
771
|
+
// hand us a print-only `ui.notify` which would otherwise shadow
|
|
772
|
+
// `pi.ui` inside the adapter and short-circuit the open.
|
|
773
|
+
return typeof ctx?.ui?.custom === "function" ? { ui: ctx.ui } : undefined;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Strip the clack-style `--yes` / `-y` confirmation skip flag from a token
|
|
778
|
+
* list. Used by `/workflow interrupt` to skip the confirmation overlay.
|
|
779
|
+
*/
|
|
780
|
+
export function stripYesFlag(tokens: string[]): { tokens: string[]; yes: boolean } {
|
|
781
|
+
const yes = tokens.some((t) => t === "--yes" || t === "-y");
|
|
782
|
+
return { tokens: tokens.filter((t) => t !== "--yes" && t !== "-y"), yes };
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Shell-aware split for `/workflow <name> [args…]` chat tokens.
|
|
787
|
+
*
|
|
788
|
+
* `prompt="map the codebase"` is one token, not three. Both single and
|
|
789
|
+
* double quotes are honoured; the quote characters themselves are kept
|
|
790
|
+
* inside the token so {@link parseWorkflowArgs} can `JSON.parse` the
|
|
791
|
+
* value and the wrapping quotes coerce it back to a plain string.
|
|
792
|
+
* Backslash-escaping is **not** supported — workflow inputs are short,
|
|
793
|
+
* the picker overlay is always available as a fallback for anything
|
|
794
|
+
* exotic, and the simpler grammar matches what users type in shells.
|
|
795
|
+
*
|
|
796
|
+
* An unterminated quote is treated as if a closing quote sat at EOL —
|
|
797
|
+
* we never throw on user input mid-stream; the parser downstream sees
|
|
798
|
+
* a partial JSON literal and falls back to keeping it as a string.
|
|
799
|
+
*/
|
|
800
|
+
export function tokenizeWorkflowArgs(args: string): string[] {
|
|
801
|
+
const tokens: string[] = [];
|
|
802
|
+
let buf = "";
|
|
803
|
+
let quote: '"' | "'" | undefined;
|
|
804
|
+
let hasBuf = false;
|
|
805
|
+
for (let i = 0; i < args.length; i++) {
|
|
806
|
+
const ch = args[i]!;
|
|
807
|
+
if (quote !== undefined) {
|
|
808
|
+
buf += ch;
|
|
809
|
+
if (ch === quote) quote = undefined;
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
if (ch === '"' || ch === "'") {
|
|
813
|
+
buf += ch;
|
|
814
|
+
hasBuf = true;
|
|
815
|
+
quote = ch;
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
|
|
819
|
+
if (hasBuf) {
|
|
820
|
+
tokens.push(buf);
|
|
821
|
+
buf = "";
|
|
822
|
+
hasBuf = false;
|
|
823
|
+
}
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
buf += ch;
|
|
827
|
+
hasBuf = true;
|
|
828
|
+
}
|
|
829
|
+
if (hasBuf) tokens.push(buf);
|
|
830
|
+
return tokens;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/**
|
|
834
|
+
* Parse remaining args tokens as key=value pairs.
|
|
835
|
+
* Tokens matching `key=value` are split on the first `=`.
|
|
836
|
+
* Tokens that are standalone valid JSON objects/arrays are merged in.
|
|
837
|
+
* All other tokens are ignored (non-kv positional args not supported).
|
|
838
|
+
*/
|
|
839
|
+
export function parseWorkflowArgs(tokens: string[]): Record<string, unknown> {
|
|
840
|
+
const result: Record<string, unknown> = {};
|
|
841
|
+
for (const token of tokens) {
|
|
842
|
+
// Try JSON object/array merge
|
|
843
|
+
if (
|
|
844
|
+
(token.startsWith("{") && token.endsWith("}")) ||
|
|
845
|
+
(token.startsWith("[") && token.endsWith("]"))
|
|
846
|
+
) {
|
|
847
|
+
try {
|
|
848
|
+
const parsed = JSON.parse(token) as unknown;
|
|
849
|
+
if (
|
|
850
|
+
parsed !== null &&
|
|
851
|
+
typeof parsed === "object" &&
|
|
852
|
+
!Array.isArray(parsed)
|
|
853
|
+
) {
|
|
854
|
+
Object.assign(result, parsed as Record<string, unknown>);
|
|
855
|
+
}
|
|
856
|
+
continue;
|
|
857
|
+
} catch {
|
|
858
|
+
// not valid JSON — fall through to kv parse
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
// key=value
|
|
862
|
+
const eqIdx = token.indexOf("=");
|
|
863
|
+
if (eqIdx > 0) {
|
|
864
|
+
const key = token.slice(0, eqIdx);
|
|
865
|
+
const raw = token.slice(eqIdx + 1);
|
|
866
|
+
// Try to parse value as JSON for typed values (numbers, booleans, objects)
|
|
867
|
+
let value: unknown = raw;
|
|
868
|
+
try {
|
|
869
|
+
value = JSON.parse(raw) as unknown;
|
|
870
|
+
} catch {
|
|
871
|
+
// keep as string
|
|
872
|
+
}
|
|
873
|
+
result[key] = value;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
return result;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
// ---------------------------------------------------------------------------
|
|
881
|
+
// Persistence port builder
|
|
882
|
+
// ---------------------------------------------------------------------------
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Build a WorkflowPersistencePort from the pi ExtensionAPI when persistence
|
|
886
|
+
* is enabled. Returns undefined when:
|
|
887
|
+
* - persistRuns is false, OR
|
|
888
|
+
* - pi.appendEntry is absent (older pi runtime without persistence API).
|
|
889
|
+
*/
|
|
890
|
+
export function makePersistencePort(
|
|
891
|
+
pi: ExtensionAPI,
|
|
892
|
+
persistRuns: boolean,
|
|
893
|
+
): WorkflowPersistencePort | undefined {
|
|
894
|
+
if (!persistRuns) return undefined;
|
|
895
|
+
if (typeof pi.appendEntry !== "function") return undefined;
|
|
896
|
+
|
|
897
|
+
const port: WorkflowPersistencePort = {
|
|
898
|
+
appendEntry: (type, payload) => pi.appendEntry!(type, payload),
|
|
899
|
+
};
|
|
900
|
+
if (typeof pi.setLabel === "function") {
|
|
901
|
+
port.setLabel = (entryId, label) => pi.setLabel!(entryId, label);
|
|
902
|
+
}
|
|
903
|
+
if (typeof pi.appendCustomMessageEntry === "function") {
|
|
904
|
+
port.appendCustomMessageEntry = (content, meta) =>
|
|
905
|
+
pi.appendCustomMessageEntry!(content, meta);
|
|
906
|
+
}
|
|
907
|
+
return port;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// ---------------------------------------------------------------------------
|
|
911
|
+
// MCP port builder
|
|
912
|
+
// ---------------------------------------------------------------------------
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Build a WorkflowMcpPort from the pi ExtensionAPI when MCP scope gating is
|
|
916
|
+
* supported. Returns undefined when pi.events?.emit is absent (adapter not
|
|
917
|
+
* installed or older runtime without events bus) — scoping becomes a no-op.
|
|
918
|
+
*/
|
|
919
|
+
export function makeMcpPort(pi: ExtensionAPI): WorkflowMcpPort | undefined {
|
|
920
|
+
if (typeof pi.events?.emit !== "function") return undefined;
|
|
921
|
+
|
|
922
|
+
// Adapt ExtensionAPI to the minimal PiMcpExtensionAPI shape expected by
|
|
923
|
+
// setMcpScope / clearMcpScope. We only forward events.emit (confirmed above).
|
|
924
|
+
const piForMcp: PiMcpExtensionAPI = {
|
|
925
|
+
events: { emit: pi.events.emit as PiEventBus["emit"] },
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
return {
|
|
929
|
+
setScope(stageId: string, allow: string[] | null, deny: string[] | null) {
|
|
930
|
+
setMcpScope(piForMcp, {
|
|
931
|
+
stageId,
|
|
932
|
+
allow: allow ?? undefined,
|
|
933
|
+
deny: deny ?? undefined,
|
|
934
|
+
});
|
|
935
|
+
},
|
|
936
|
+
clearScope(stageId: string) {
|
|
937
|
+
clearMcpScope(piForMcp, stageId);
|
|
938
|
+
},
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// ---------------------------------------------------------------------------
|
|
943
|
+
// Factory — the default export consumed by the pi runtime
|
|
944
|
+
// ---------------------------------------------------------------------------
|
|
945
|
+
|
|
946
|
+
function factory(pi: ExtensionAPI): void {
|
|
947
|
+
// -------------------------------------------------------------------------
|
|
948
|
+
// 0. Build StageAdapters from pi runtime surfaces. Stage prompting uses
|
|
949
|
+
// pi's in-process SDK `createAgentSession()` surface; HIL prompts
|
|
950
|
+
// flow through the store-backed background adapter built inside
|
|
951
|
+
// `runDetached()` — they never touch pi.ui.
|
|
952
|
+
// -------------------------------------------------------------------------
|
|
953
|
+
const adapters = buildRuntimeAdapters(pi);
|
|
954
|
+
|
|
955
|
+
// Local registry of workflow command (name → handler). Populated by
|
|
956
|
+
// `registerWorkflowCommand` calls below and consumed by the
|
|
957
|
+
// `pi.on("input", …)` interceptor at the end of the factory — see
|
|
958
|
+
// `installInputInterceptor` for the rationale.
|
|
959
|
+
const workflowCommands = new Map<string, WorkflowCommandHandler>();
|
|
960
|
+
|
|
961
|
+
// Build graph overlay adapter — wraps GraphView + pi.ui.custom.
|
|
962
|
+
// noopOverlay returned when pi.ui?.custom is absent (degraded runtime).
|
|
963
|
+
const overlay: GraphOverlayPort = buildGraphOverlayAdapter(pi, store);
|
|
964
|
+
|
|
965
|
+
// -------------------------------------------------------------------------
|
|
966
|
+
// 1. Create ExtensionRuntime — mutable ref seeded from startup discovery,
|
|
967
|
+
// upgraded to unified async discovery once discoverWorkflows() resolves.
|
|
968
|
+
//
|
|
969
|
+
// runtimeProxy delegates all calls to runtimeRef.current so every
|
|
970
|
+
// registration closure automatically uses the most-current registry without
|
|
971
|
+
// needing to be re-registered.
|
|
972
|
+
// -------------------------------------------------------------------------
|
|
973
|
+
const persistenceRef: { current: WorkflowPersistencePort | undefined } = {
|
|
974
|
+
current: makePersistencePort(pi, WORKFLOW_CONFIG_DEFAULTS.persistRuns),
|
|
975
|
+
};
|
|
976
|
+
const mcpPort: WorkflowMcpPort | undefined = makeMcpPort(pi);
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* Mutable ref for the resolved runtime config.
|
|
980
|
+
* Seeded with WORKFLOW_CONFIG_DEFAULTS at startup; replaced after async config load.
|
|
981
|
+
* Injected into every createExtensionRuntime() call so the dispatcher, executor,
|
|
982
|
+
* and detached runner all receive the same resolved tunables.
|
|
983
|
+
*/
|
|
984
|
+
const runtimeConfigRef: { current: WorkflowRuntimeConfig } = {
|
|
985
|
+
current: {
|
|
986
|
+
maxDepth: WORKFLOW_CONFIG_DEFAULTS.maxDepth,
|
|
987
|
+
defaultConcurrency: WORKFLOW_CONFIG_DEFAULTS.defaultConcurrency,
|
|
988
|
+
persistRuns: WORKFLOW_CONFIG_DEFAULTS.persistRuns,
|
|
989
|
+
statusFile: WORKFLOW_CONFIG_DEFAULTS.statusFile,
|
|
990
|
+
resumeInFlight: WORKFLOW_CONFIG_DEFAULTS.resumeInFlight,
|
|
991
|
+
},
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Mutable ref for the status writer instance.
|
|
996
|
+
* Replaced (old unsubscribed) each time runtimeConfigRef is updated after
|
|
997
|
+
* async config resolution. Starts as a no-op (statusFile defaults to false).
|
|
998
|
+
*/
|
|
999
|
+
let statusWriterRef: StatusWriter = createStatusWriter(
|
|
1000
|
+
store,
|
|
1001
|
+
runtimeConfigRef.current,
|
|
1002
|
+
);
|
|
1003
|
+
let intercomParentSession: string | null = null;
|
|
1004
|
+
const intercomPort = {
|
|
1005
|
+
emit:
|
|
1006
|
+
typeof pi.events?.emit === "function"
|
|
1007
|
+
? (event: string, payload: Record<string, unknown>) => pi.events!.emit!(event, payload)
|
|
1008
|
+
: undefined,
|
|
1009
|
+
parentSession: () => intercomParentSession ?? undefined,
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
const runtimeRef: { current: ExtensionRuntime } = {
|
|
1013
|
+
current: createExtensionRuntime({
|
|
1014
|
+
registry: discoverStartupWorkflowsSync().registry,
|
|
1015
|
+
adapters,
|
|
1016
|
+
cancellation: cancellationRegistry,
|
|
1017
|
+
persistence: persistenceRef.current,
|
|
1018
|
+
mcp: mcpPort,
|
|
1019
|
+
intercom: intercomPort,
|
|
1020
|
+
config: runtimeConfigRef.current,
|
|
1021
|
+
}),
|
|
1022
|
+
};
|
|
1023
|
+
const discoveryRef: { current: DiscoveryResult | null } = { current: null };
|
|
1024
|
+
const configLoadRef: { current: ConfigLoadResult | null } = { current: null };
|
|
1025
|
+
|
|
1026
|
+
/** Stable proxy — all registrations close over this; delegates to runtimeRef.current. */
|
|
1027
|
+
const runtimeProxy: ExtensionRuntime = {
|
|
1028
|
+
get registry() {
|
|
1029
|
+
return runtimeRef.current.registry;
|
|
1030
|
+
},
|
|
1031
|
+
dispatch(args) {
|
|
1032
|
+
return runtimeRef.current.dispatch(args);
|
|
1033
|
+
},
|
|
1034
|
+
runDirect(args) {
|
|
1035
|
+
return runtimeRef.current.runDirect(args);
|
|
1036
|
+
},
|
|
1037
|
+
};
|
|
1038
|
+
|
|
1039
|
+
function modelFullId(model: PiRuntimeModel): string {
|
|
1040
|
+
return `${String(model.provider)}/${model.id}`;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
function workflowModelCatalogFromContext(ctx?: PiModelContext): WorkflowModelCatalogPort | undefined {
|
|
1044
|
+
if (ctx?.modelRegistry === undefined && ctx?.model === undefined) return undefined;
|
|
1045
|
+
return {
|
|
1046
|
+
listModels: async (): Promise<readonly WorkflowModelInfo[]> => {
|
|
1047
|
+
const available = ctx.modelRegistry?.getAvailable() ?? (ctx.model === undefined ? [] : [ctx.model]);
|
|
1048
|
+
return available.map((model) => ({
|
|
1049
|
+
provider: String(model.provider),
|
|
1050
|
+
id: model.id,
|
|
1051
|
+
fullId: modelFullId(model),
|
|
1052
|
+
model: model as NonNullable<CreateAgentSessionOptions["model"]>,
|
|
1053
|
+
}));
|
|
1054
|
+
},
|
|
1055
|
+
...(ctx.model !== undefined
|
|
1056
|
+
? {
|
|
1057
|
+
currentModel: ctx.model as NonNullable<CreateAgentSessionOptions["model"]>,
|
|
1058
|
+
preferredProvider: String(ctx.model.provider),
|
|
1059
|
+
}
|
|
1060
|
+
: {}),
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
function runtimeWithModels(models: WorkflowModelCatalogPort | undefined): ExtensionRuntime {
|
|
1065
|
+
if (models === undefined) return runtimeProxy;
|
|
1066
|
+
return createExtensionRuntime({
|
|
1067
|
+
registry: runtimeRef.current.registry,
|
|
1068
|
+
adapters,
|
|
1069
|
+
cancellation: cancellationRegistry,
|
|
1070
|
+
persistence: persistenceRef.current,
|
|
1071
|
+
mcp: mcpPort,
|
|
1072
|
+
intercom: intercomPort,
|
|
1073
|
+
config: runtimeConfigRef.current,
|
|
1074
|
+
models,
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// The runtime normally does not depend on per-command UI, but model fallback
|
|
1079
|
+
// resolution uses the live command/tool context when pi exposes modelRegistry.
|
|
1080
|
+
function runtimeForContext(ctx?: ({ ui?: PiUISurface } & PiModelContext)): ExtensionRuntime {
|
|
1081
|
+
return runtimeWithModels(workflowModelCatalogFromContext(ctx));
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
let intercomControlUnsubscribe: (() => void) | null = null;
|
|
1085
|
+
|
|
1086
|
+
const executeWorkflowTool = makeExecuteWorkflowTool(
|
|
1087
|
+
(ctx) => runtimeForContext(ctx),
|
|
1088
|
+
() => persistenceRef.current,
|
|
1089
|
+
);
|
|
1090
|
+
let storeWidgetUnsubscribe: (() => void) | null = null;
|
|
1091
|
+
|
|
1092
|
+
// Start unified async discovery immediately.
|
|
1093
|
+
// On resolve: swap runtime ref so /workflow completions and dispatch see
|
|
1094
|
+
// project-local, user-global, and settings-provided workflows.
|
|
1095
|
+
// Load startup config before discovery so workflow paths and tunables are applied.
|
|
1096
|
+
const discoveryPromise = pi.disableAsyncDiscovery ? Promise.resolve() : loadWorkflowConfig().then(async (configResult) => {
|
|
1097
|
+
configLoadRef.current = configResult;
|
|
1098
|
+
|
|
1099
|
+
// Build scope-aware DiscoveryConfig: global entries → globalWorkflows (resolved
|
|
1100
|
+
// under <homeDir>/.atomic/agent), project entries → projectWorkflows (resolved under
|
|
1101
|
+
// projectRoot). Project keys override global keys. Paths pre-resolved to absolute.
|
|
1102
|
+
const { homedir } = await import("node:os");
|
|
1103
|
+
const hasGlobal = configResult.globalConfig != null;
|
|
1104
|
+
const hasProject = configResult.projectConfig != null;
|
|
1105
|
+
const discoveryConfig =
|
|
1106
|
+
hasGlobal || hasProject
|
|
1107
|
+
? toScopedDiscoveryConfig(
|
|
1108
|
+
configResult.globalConfig ?? null,
|
|
1109
|
+
configResult.projectConfig ?? null,
|
|
1110
|
+
{ projectRoot: process.cwd(), homeDir: homedir() },
|
|
1111
|
+
)
|
|
1112
|
+
: undefined;
|
|
1113
|
+
|
|
1114
|
+
const result = await discoverWorkflows({ config: discoveryConfig });
|
|
1115
|
+
discoveryRef.current = result;
|
|
1116
|
+
|
|
1117
|
+
// Resolve effective config (fills in all defaults) and build WorkflowRuntimeConfig.
|
|
1118
|
+
const effectiveConfig = withWorkflowDefaults(configResult.config ?? {});
|
|
1119
|
+
runtimeConfigRef.current = {
|
|
1120
|
+
maxDepth: effectiveConfig.maxDepth,
|
|
1121
|
+
defaultConcurrency: effectiveConfig.defaultConcurrency,
|
|
1122
|
+
persistRuns: effectiveConfig.persistRuns,
|
|
1123
|
+
statusFile: effectiveConfig.statusFile,
|
|
1124
|
+
resumeInFlight: effectiveConfig.resumeInFlight,
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
// Replace status writer with one that reflects the resolved config.
|
|
1128
|
+
// Unsubscribe the prior (no-op) writer before creating the new one.
|
|
1129
|
+
statusWriterRef.unsubscribe();
|
|
1130
|
+
statusWriterRef = createStatusWriter(store, runtimeConfigRef.current);
|
|
1131
|
+
|
|
1132
|
+
persistenceRef.current = makePersistencePort(
|
|
1133
|
+
pi,
|
|
1134
|
+
effectiveConfig.persistRuns,
|
|
1135
|
+
);
|
|
1136
|
+
runtimeRef.current = createExtensionRuntime({
|
|
1137
|
+
registry: result.registry,
|
|
1138
|
+
adapters,
|
|
1139
|
+
cancellation: cancellationRegistry,
|
|
1140
|
+
persistence: persistenceRef.current,
|
|
1141
|
+
mcp: mcpPort,
|
|
1142
|
+
intercom: intercomPort,
|
|
1143
|
+
config: runtimeConfigRef.current,
|
|
1144
|
+
});
|
|
1145
|
+
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
// -------------------------------------------------------------------------
|
|
1149
|
+
// 1. Register the `workflow` tool
|
|
1150
|
+
// Pi's ToolDefinition.execute is positional: (toolCallId, params, signal,
|
|
1151
|
+
// onUpdate, ctx) → Promise<AgentToolResult<TDetails>>. The internal
|
|
1152
|
+
// `executeWorkflowTool` keeps its (args, ctx) shape for test ergonomics;
|
|
1153
|
+
// we adapt here at the registration boundary only.
|
|
1154
|
+
// cross-ref: pi-coding-agent dist/core/extensions/types.d.ts ToolDefinition
|
|
1155
|
+
// -------------------------------------------------------------------------
|
|
1156
|
+
if (typeof pi.registerTool === "function") {
|
|
1157
|
+
pi.registerTool<WorkflowToolArgs, WorkflowToolResult>({
|
|
1158
|
+
name: "workflow",
|
|
1159
|
+
label: "workflow",
|
|
1160
|
+
description: "Run a defined multi-stage workflow by name.",
|
|
1161
|
+
parameters: workflowParameters,
|
|
1162
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => {
|
|
1163
|
+
// Overlay is opt-in via F2 / ctrl+h; do not auto-open from a
|
|
1164
|
+
// tool-call dispatch path.
|
|
1165
|
+
const details = await executeWorkflowTool(params, ctx);
|
|
1166
|
+
return {
|
|
1167
|
+
content: [{ type: "text", text: renderResult(details, {}) }],
|
|
1168
|
+
details,
|
|
1169
|
+
};
|
|
1170
|
+
},
|
|
1171
|
+
renderCall: (args, _theme, _context) =>
|
|
1172
|
+
textRenderComponent(renderCall(args)),
|
|
1173
|
+
renderResult: (result, opts, _theme, _context) =>
|
|
1174
|
+
textRenderComponent(renderResult(result.details, opts)),
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
// -------------------------------------------------------------------------
|
|
1180
|
+
// 2. Register /workflow slash command
|
|
1181
|
+
// -------------------------------------------------------------------------
|
|
1182
|
+
/**
|
|
1183
|
+
* Shared top-level run-control handler.
|
|
1184
|
+
*
|
|
1185
|
+
* connect [runId|prefix] no arg → picker overlay; arg → attach to graph
|
|
1186
|
+
* attach [runId|prefix [stageId]] open the in-place attach pane on a stage
|
|
1187
|
+
* interrupt [runId|prefix|--all] [-y] confirmation overlay unless -y
|
|
1188
|
+
* pause [runId|prefix [stageId]] pause a run or specific stage
|
|
1189
|
+
* resume [runId|prefix [stageId] …] resume paused work or reopen snapshot
|
|
1190
|
+
*/
|
|
1191
|
+
async function handleRunControlCommand(
|
|
1192
|
+
action: "connect" | "interrupt" | "attach" | "pause" | "resume",
|
|
1193
|
+
rest: string[],
|
|
1194
|
+
ctx: PiCommandContext,
|
|
1195
|
+
): Promise<boolean> {
|
|
1196
|
+
const print = (msg: string): void => ctx.ui.notify(msg, "info");
|
|
1197
|
+
const theme = deriveGraphTheme({});
|
|
1198
|
+
|
|
1199
|
+
if (action === "connect") {
|
|
1200
|
+
const target = rest.find((t) => !t.startsWith("--"));
|
|
1201
|
+
if (!target) {
|
|
1202
|
+
// Picker mode — mount the overlay and route the resolved action.
|
|
1203
|
+
const ui = ctx.ui;
|
|
1204
|
+
if (!ui || typeof ui.custom !== "function") {
|
|
1205
|
+
print(
|
|
1206
|
+
`${renderSessionList(store.runs(), { theme, includeAll: false })}\n\nPicker requires a UI surface. Pass a runId: /workflow connect <id>`,
|
|
1207
|
+
);
|
|
1208
|
+
return true;
|
|
1209
|
+
}
|
|
1210
|
+
const result = await openSessionPicker(ui, store, theme, "connect");
|
|
1211
|
+
if (result.kind === "close") return true;
|
|
1212
|
+
if (result.kind === "connect") {
|
|
1213
|
+
overlay.open(result.runId, overlaySurfaceFromContext(ctx));
|
|
1214
|
+
return true;
|
|
1215
|
+
}
|
|
1216
|
+
if (result.kind === "kill") {
|
|
1217
|
+
const run = store.runs().find((r) => r.id === result.runId);
|
|
1218
|
+
if (!run) {
|
|
1219
|
+
print(`Run not found: ${result.runId}`);
|
|
1220
|
+
return true;
|
|
1221
|
+
}
|
|
1222
|
+
const confirmed = await openKillConfirm(ui, run, theme);
|
|
1223
|
+
if (!confirmed) {
|
|
1224
|
+
print(`Cancelled. Run ${result.runId.slice(0, 8)} is still active.`);
|
|
1225
|
+
return true;
|
|
1226
|
+
}
|
|
1227
|
+
const killed = killRun(result.runId, {
|
|
1228
|
+
cancellation: cancellationRegistry,
|
|
1229
|
+
persistence: persistenceRef.current,
|
|
1230
|
+
});
|
|
1231
|
+
print(
|
|
1232
|
+
killed.ok
|
|
1233
|
+
? `Run ${killed.runId.slice(0, 8)} interrupted.`
|
|
1234
|
+
: `Run ${result.runId.slice(0, 8)} already ended.`,
|
|
1235
|
+
);
|
|
1236
|
+
return true;
|
|
1237
|
+
}
|
|
1238
|
+
return true;
|
|
1239
|
+
}
|
|
1240
|
+
const resolved = resolveRunIdPrefix(target);
|
|
1241
|
+
if (resolved.kind === "not_found") {
|
|
1242
|
+
print(`Run not found: ${target}\n\n${renderSessionList(store.runs(), { theme, includeAll: true })}`);
|
|
1243
|
+
return true;
|
|
1244
|
+
}
|
|
1245
|
+
if (resolved.kind === "ambiguous") {
|
|
1246
|
+
print(
|
|
1247
|
+
`Ambiguous run prefix "${target}" matches: ${resolved.matches
|
|
1248
|
+
.map((id) => id.slice(0, 12))
|
|
1249
|
+
.join(", ")}`,
|
|
1250
|
+
);
|
|
1251
|
+
return true;
|
|
1252
|
+
}
|
|
1253
|
+
overlay.open(resolved.runId, overlaySurfaceFromContext(ctx));
|
|
1254
|
+
print(`Attached to ${resolved.runId.slice(0, 8)}. Press "h" or ctrl+d to hide, "q" to interrupt, esc to close.`);
|
|
1255
|
+
return true;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
if (action === "interrupt") {
|
|
1259
|
+
const { tokens: interruptArgs, yes } = stripYesFlag(rest);
|
|
1260
|
+
let target = interruptArgs.find((t) => !t.startsWith("--"));
|
|
1261
|
+
const wantsAll = interruptArgs.includes("--all");
|
|
1262
|
+
if (!target && !wantsAll) {
|
|
1263
|
+
target = store.activeRunId() ?? undefined;
|
|
1264
|
+
if (!target) {
|
|
1265
|
+
print("No in-flight runs to interrupt.");
|
|
1266
|
+
return true;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
if (wantsAll) {
|
|
1270
|
+
const inFlight = store.runs().filter((r) => r.endedAt === undefined);
|
|
1271
|
+
if (inFlight.length === 0) {
|
|
1272
|
+
print("No in-flight runs to interrupt.");
|
|
1273
|
+
return true;
|
|
1274
|
+
}
|
|
1275
|
+
if (!yes && ctx.ui && typeof ctx.ui.confirm === "function") {
|
|
1276
|
+
const ok = await ctx.ui.confirm(
|
|
1277
|
+
`Interrupt all ${inFlight.length} in-flight workflow runs?`,
|
|
1278
|
+
`Aborts: ${inFlight.map((r) => `${r.name} (${r.id.slice(0, 8)})`).join(", ")}`,
|
|
1279
|
+
);
|
|
1280
|
+
if (!ok) {
|
|
1281
|
+
print("Cancelled.");
|
|
1282
|
+
return true;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
const results = killAllRuns({
|
|
1286
|
+
cancellation: cancellationRegistry,
|
|
1287
|
+
persistence: persistenceRef.current,
|
|
1288
|
+
});
|
|
1289
|
+
const killed = results.filter((r) => r.ok).length;
|
|
1290
|
+
print(killed > 0 ? `Interrupted ${killed} run(s).` : "No in-flight runs to interrupt.");
|
|
1291
|
+
return true;
|
|
1292
|
+
}
|
|
1293
|
+
const resolved = resolveRunIdPrefix(target!);
|
|
1294
|
+
if (resolved.kind === "not_found") {
|
|
1295
|
+
print(`Run not found: ${target}`);
|
|
1296
|
+
return true;
|
|
1297
|
+
}
|
|
1298
|
+
if (resolved.kind === "ambiguous") {
|
|
1299
|
+
print(
|
|
1300
|
+
`Ambiguous run prefix "${target}" matches multiple runs: ${resolved.matches
|
|
1301
|
+
.map((id) => id.slice(0, 12))
|
|
1302
|
+
.join(", ")}`,
|
|
1303
|
+
);
|
|
1304
|
+
return true;
|
|
1305
|
+
}
|
|
1306
|
+
const run = store.runs().find((r) => r.id === resolved.runId);
|
|
1307
|
+
if (!yes && run && run.endedAt === undefined && ctx.ui) {
|
|
1308
|
+
const confirmed = await openKillConfirm(ctx.ui, run, theme);
|
|
1309
|
+
if (!confirmed) {
|
|
1310
|
+
print(`Cancelled. Run ${resolved.runId.slice(0, 8)} is still active.`);
|
|
1311
|
+
return true;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
const result = killRun(resolved.runId, {
|
|
1315
|
+
cancellation: cancellationRegistry,
|
|
1316
|
+
persistence: persistenceRef.current,
|
|
1317
|
+
});
|
|
1318
|
+
if (result.ok) {
|
|
1319
|
+
print(`Run ${result.runId.slice(0, 8)} interrupted (was ${result.previousStatus}).`);
|
|
1320
|
+
} else {
|
|
1321
|
+
print(
|
|
1322
|
+
result.reason === "not_found"
|
|
1323
|
+
? `Run not found: ${target}`
|
|
1324
|
+
: `Run already ended: ${target}`,
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
return true;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
if (action === "attach") {
|
|
1331
|
+
const target = rest[0];
|
|
1332
|
+
const stageTarget = rest[1];
|
|
1333
|
+
let runId: string;
|
|
1334
|
+
if (!target) {
|
|
1335
|
+
const ui = ctx.ui;
|
|
1336
|
+
if (!ui || typeof ui.custom !== "function") {
|
|
1337
|
+
print(`${renderSessionList(store.runs(), { theme, includeAll: false })}\n\nPicker requires a UI surface. Pass a runId: /workflow attach <id> [stageId]`);
|
|
1338
|
+
return true;
|
|
1339
|
+
}
|
|
1340
|
+
const picked = await openSessionPicker(ui, store, theme, "connect");
|
|
1341
|
+
if (picked.kind === "close") return true;
|
|
1342
|
+
if (picked.kind !== "connect") {
|
|
1343
|
+
// The picker may have surfaced interrupt from the `x` shortcut.
|
|
1344
|
+
// Forward through the existing interrupt flow for clarity.
|
|
1345
|
+
if (picked.kind === "kill") {
|
|
1346
|
+
return handleRunControlCommand("interrupt", [picked.runId, "-y"], ctx);
|
|
1347
|
+
}
|
|
1348
|
+
return true;
|
|
1349
|
+
}
|
|
1350
|
+
runId = picked.runId;
|
|
1351
|
+
} else {
|
|
1352
|
+
const resolved = resolveRunIdPrefix(target);
|
|
1353
|
+
if (resolved.kind === "not_found") {
|
|
1354
|
+
print(`Run not found: ${target}`);
|
|
1355
|
+
return true;
|
|
1356
|
+
}
|
|
1357
|
+
if (resolved.kind === "ambiguous") {
|
|
1358
|
+
print(`Ambiguous run prefix "${target}" matches: ${resolved.matches.map((id) => id.slice(0, 12)).join(", ")}`);
|
|
1359
|
+
return true;
|
|
1360
|
+
}
|
|
1361
|
+
runId = resolved.runId;
|
|
1362
|
+
}
|
|
1363
|
+
const run = store.runs().find((r) => r.id === runId);
|
|
1364
|
+
let stageId: string | undefined;
|
|
1365
|
+
if (stageTarget && run) {
|
|
1366
|
+
const exact = run.stages.find((s) => s.id === stageTarget);
|
|
1367
|
+
const prefix = exact ?? run.stages.find((s) => s.id.startsWith(stageTarget));
|
|
1368
|
+
const byName = prefix ?? run.stages.find((s) => s.name === stageTarget);
|
|
1369
|
+
if (!byName) {
|
|
1370
|
+
print(`Stage not found in run ${runId.slice(0, 8)}: ${stageTarget}`);
|
|
1371
|
+
return true;
|
|
1372
|
+
}
|
|
1373
|
+
stageId = byName.id;
|
|
1374
|
+
}
|
|
1375
|
+
overlay.open(runId, overlaySurfaceFromContext(ctx), stageId);
|
|
1376
|
+
print(
|
|
1377
|
+
stageId
|
|
1378
|
+
? `Attached to ${runId.slice(0, 8)} stage ${stageId.slice(0, 8)}. Ctrl+D returns to graph, Escape closes.`
|
|
1379
|
+
: `Attached to ${runId.slice(0, 8)}. Press ↵ on a node to chat, Ctrl+D to detach.`,
|
|
1380
|
+
);
|
|
1381
|
+
return true;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
if (action === "pause") {
|
|
1385
|
+
const target = rest[0];
|
|
1386
|
+
const stageTarget = rest[1];
|
|
1387
|
+
let runId: string;
|
|
1388
|
+
if (!target) {
|
|
1389
|
+
const ui = ctx.ui;
|
|
1390
|
+
if (!ui || typeof ui.custom !== "function") {
|
|
1391
|
+
const active = store.runs().filter((r) => r.endedAt === undefined);
|
|
1392
|
+
if (active.length === 0) {
|
|
1393
|
+
print("No active runs to pause.");
|
|
1394
|
+
return true;
|
|
1395
|
+
}
|
|
1396
|
+
print(
|
|
1397
|
+
`Picker requires a UI surface. Active runs:\n${active.map((r) => ` ${r.id.slice(0, 8)} ${r.name}`).join("\n")}\n\nUsage: /workflow pause <runId> [stageId]`,
|
|
1398
|
+
);
|
|
1399
|
+
return true;
|
|
1400
|
+
}
|
|
1401
|
+
const picked = await openSessionPicker(ui, store, theme, "pause");
|
|
1402
|
+
if (picked.kind !== "pause") return true;
|
|
1403
|
+
runId = picked.runId;
|
|
1404
|
+
} else {
|
|
1405
|
+
const resolved = resolveRunIdPrefix(target);
|
|
1406
|
+
if (resolved.kind === "not_found") {
|
|
1407
|
+
print(`Run not found: ${target}`);
|
|
1408
|
+
return true;
|
|
1409
|
+
}
|
|
1410
|
+
if (resolved.kind === "ambiguous") {
|
|
1411
|
+
print(`Ambiguous run prefix "${target}" matches: ${resolved.matches.map((id) => id.slice(0, 12)).join(", ")}`);
|
|
1412
|
+
return true;
|
|
1413
|
+
}
|
|
1414
|
+
runId = resolved.runId;
|
|
1415
|
+
}
|
|
1416
|
+
let stageId: string | undefined;
|
|
1417
|
+
if (stageTarget) {
|
|
1418
|
+
const run = store.runs().find((r) => r.id === runId);
|
|
1419
|
+
const stage = run?.stages.find((s) => s.id === stageTarget || s.id.startsWith(stageTarget) || s.name === stageTarget);
|
|
1420
|
+
if (!stage) {
|
|
1421
|
+
print(`Stage not found in run ${runId.slice(0, 8)}: ${stageTarget}`);
|
|
1422
|
+
return true;
|
|
1423
|
+
}
|
|
1424
|
+
stageId = stage.id;
|
|
1425
|
+
}
|
|
1426
|
+
const result = pauseRun(runId, { stageId });
|
|
1427
|
+
if (!result.ok) {
|
|
1428
|
+
const why =
|
|
1429
|
+
result.reason === "not_found"
|
|
1430
|
+
? `Run not found: ${runId.slice(0, 8)}`
|
|
1431
|
+
: result.reason === "already_ended"
|
|
1432
|
+
? `Run ${runId.slice(0, 8)} already ended.`
|
|
1433
|
+
: result.reason === "no_active_stages"
|
|
1434
|
+
? `No pausable stages on run ${runId.slice(0, 8)}.`
|
|
1435
|
+
: `Stage not found: ${stageTarget ?? "(unknown)"}`;
|
|
1436
|
+
print(why);
|
|
1437
|
+
return true;
|
|
1438
|
+
}
|
|
1439
|
+
// Open the orchestrator overlay (graph for run-level pause, stage
|
|
1440
|
+
// chat when a stage was named). This mirrors connect/attach/resume:
|
|
1441
|
+
// the full-screen overlay hides Pi's "Working… (esc to interrupt)"
|
|
1442
|
+
// spinner, which otherwise stays visible because the host session
|
|
1443
|
+
// is still streaming whatever was happening before the pause hit.
|
|
1444
|
+
if (typeof ctx.ui?.custom === "function") {
|
|
1445
|
+
overlay.open(runId, overlaySurfaceFromContext(ctx), stageId);
|
|
1446
|
+
}
|
|
1447
|
+
print(
|
|
1448
|
+
result.paused.length === 0
|
|
1449
|
+
? `No stages were paused on run ${runId.slice(0, 8)}.`
|
|
1450
|
+
: `Paused ${result.paused.length} stage(s) on run ${runId.slice(0, 8)}: ${result.paused.map((s) => s.name).join(", ")}`,
|
|
1451
|
+
);
|
|
1452
|
+
return true;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
if (action === "resume") {
|
|
1456
|
+
const target = rest[0];
|
|
1457
|
+
const stageTarget = rest[1];
|
|
1458
|
+
const message = rest.slice(2).join(" ").trim() || undefined;
|
|
1459
|
+
let runId: string;
|
|
1460
|
+
if (!target) {
|
|
1461
|
+
const ui = ctx.ui;
|
|
1462
|
+
if (!ui || typeof ui.custom !== "function") {
|
|
1463
|
+
print(`Usage: /workflow resume <runId> [stageId] [message…]`);
|
|
1464
|
+
return true;
|
|
1465
|
+
}
|
|
1466
|
+
const picked = await openSessionPicker(ui, store, theme, "resume");
|
|
1467
|
+
if (picked.kind !== "resume") return true;
|
|
1468
|
+
runId = picked.runId;
|
|
1469
|
+
} else {
|
|
1470
|
+
const resolved = resolveRunIdPrefix(target);
|
|
1471
|
+
if (resolved.kind === "not_found") {
|
|
1472
|
+
print(`Run not found: ${target}`);
|
|
1473
|
+
return true;
|
|
1474
|
+
}
|
|
1475
|
+
if (resolved.kind === "ambiguous") {
|
|
1476
|
+
print(`Ambiguous run prefix "${target}" matches: ${resolved.matches.map((id) => id.slice(0, 12)).join(", ")}`);
|
|
1477
|
+
return true;
|
|
1478
|
+
}
|
|
1479
|
+
runId = resolved.runId;
|
|
1480
|
+
}
|
|
1481
|
+
let stageId: string | undefined;
|
|
1482
|
+
const run = store.runs().find((r) => r.id === runId);
|
|
1483
|
+
if (stageTarget) {
|
|
1484
|
+
const stage = run?.stages.find((s) => s.id === stageTarget || s.id.startsWith(stageTarget) || s.name === stageTarget);
|
|
1485
|
+
if (!stage) {
|
|
1486
|
+
print(`Stage not found in run ${runId.slice(0, 8)}: ${stageTarget}`);
|
|
1487
|
+
return true;
|
|
1488
|
+
}
|
|
1489
|
+
stageId = stage.id;
|
|
1490
|
+
}
|
|
1491
|
+
const isPaused =
|
|
1492
|
+
run?.status === "paused" || (run?.stages.some((s) => s.status === "paused") ?? false);
|
|
1493
|
+
const result = resumeRun(runId, { stageId, message });
|
|
1494
|
+
if (!result.ok) {
|
|
1495
|
+
print(`Run not found: ${runId.slice(0, 8)}`);
|
|
1496
|
+
return true;
|
|
1497
|
+
}
|
|
1498
|
+
if (!isPaused) {
|
|
1499
|
+
// Non-paused fallback: reopen the orchestrator overlay as before.
|
|
1500
|
+
overlay.open(result.runId, overlaySurfaceFromContext(ctx));
|
|
1501
|
+
print(
|
|
1502
|
+
`Snapshot available: run ${result.runId} (${result.snapshot.name}) \u2014 status: ${result.snapshot.status}, stages: ${result.snapshot.stages.length}`,
|
|
1503
|
+
);
|
|
1504
|
+
return true;
|
|
1505
|
+
}
|
|
1506
|
+
// Paused live resume: when no message was provided and the picker
|
|
1507
|
+
// is available, open the attached chat so the user can talk to
|
|
1508
|
+
// the freshly-resumed stage.
|
|
1509
|
+
if (!message && stageId && ctx.ui?.custom) {
|
|
1510
|
+
overlay.open(runId, overlaySurfaceFromContext(ctx), stageId);
|
|
1511
|
+
}
|
|
1512
|
+
print(
|
|
1513
|
+
result.resumed.length === 0
|
|
1514
|
+
? `No paused stages on run ${runId.slice(0, 8)}.`
|
|
1515
|
+
: `Resumed ${result.resumed.length} stage(s) on run ${runId.slice(0, 8)}${message ? ` with message: "${message}"` : ""}.`,
|
|
1516
|
+
);
|
|
1517
|
+
return true;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
registerWorkflowCommand(pi, "workflow", {
|
|
1524
|
+
description:
|
|
1525
|
+
"Run or inspect pi workflows. Usage: /workflow <name> [key=value…] | /workflow [list|status|connect|attach|interrupt|pause|resume|inputs] [args]",
|
|
1526
|
+
handler: async (args: string, ctx: PiCommandContext) => {
|
|
1527
|
+
const print = (msg: string): void => ctx.ui.notify(msg, "info");
|
|
1528
|
+
// Quote-aware split so `prompt="map the codebase"` stays a single
|
|
1529
|
+
// token. Plain `.split(/\s+/)` would mangle quoted multi-word values
|
|
1530
|
+
// into `prompt="map`, `the`, `codebase"` — the dispatch confirm then
|
|
1531
|
+
// renders `prompt=""map"` (see ui/qa-current-render-2.png).
|
|
1532
|
+
const parts = tokenizeWorkflowArgs(args);
|
|
1533
|
+
const subcommand = parts[0] ?? "";
|
|
1534
|
+
|
|
1535
|
+
// -----------------------------------------------------------------------
|
|
1536
|
+
// connect — open the orchestrator pane (picker if no id).
|
|
1537
|
+
// attach — open the in-place attach pane on a stage (or pick run).
|
|
1538
|
+
// pause — pause a run or specific stage.
|
|
1539
|
+
// -----------------------------------------------------------------------
|
|
1540
|
+
if (subcommand === "connect") {
|
|
1541
|
+
await handleRunControlCommand("connect", parts.slice(1), ctx);
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
if (subcommand === "attach") {
|
|
1545
|
+
await handleRunControlCommand("attach", parts.slice(1), ctx);
|
|
1546
|
+
return;
|
|
1547
|
+
}
|
|
1548
|
+
if (subcommand === "pause") {
|
|
1549
|
+
await handleRunControlCommand("pause", parts.slice(1), ctx);
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
// -----------------------------------------------------------------------
|
|
1554
|
+
// list (default when no subcommand) — render the workflow catalogue
|
|
1555
|
+
// via the same renderer used by the LLM tool path.
|
|
1556
|
+
// -----------------------------------------------------------------------
|
|
1557
|
+
if (!subcommand || subcommand === "list") {
|
|
1558
|
+
const items = runtimeProxy.registry.all().map((def) => ({
|
|
1559
|
+
name: def.normalizedName,
|
|
1560
|
+
description: def.description,
|
|
1561
|
+
inputs: Object.entries(def.inputs).map(([iname, schema]) => ({
|
|
1562
|
+
name: iname,
|
|
1563
|
+
required: schema.required === true,
|
|
1564
|
+
})),
|
|
1565
|
+
}));
|
|
1566
|
+
emitChatSurface(pi, { kind: "list", entries: items });
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
// -----------------------------------------------------------------------
|
|
1571
|
+
// status — band-header rich list, or per-run detail when an id is
|
|
1572
|
+
// supplied. `/workflow status` lists everything in-flight (`--all`
|
|
1573
|
+
// includes ended runs older than an hour); `/workflow status <id>`
|
|
1574
|
+
// drills into a single run via the inspectRun detail block.
|
|
1575
|
+
// -----------------------------------------------------------------------
|
|
1576
|
+
if (subcommand === "status") {
|
|
1577
|
+
const target = parts[1];
|
|
1578
|
+
if (target && !target.startsWith("--")) {
|
|
1579
|
+
const resolved = resolveRunIdPrefix(target);
|
|
1580
|
+
if (resolved.kind === "not_found") {
|
|
1581
|
+
print(`Run not found: ${target}`);
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
if (resolved.kind === "ambiguous") {
|
|
1585
|
+
print(
|
|
1586
|
+
`Ambiguous run prefix "${target}" matches: ${resolved.matches
|
|
1587
|
+
.map((id) => id.slice(0, 12))
|
|
1588
|
+
.join(", ")}`,
|
|
1589
|
+
);
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
const inspected = inspectRun(resolved.runId);
|
|
1593
|
+
if (!inspected.ok) {
|
|
1594
|
+
print(`Run not found: ${target}`);
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
emitChatSurface(pi, { kind: "detail", detail: inspected.detail });
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
// Mirror renderSessionList's filter: keep `--all` semantics, then
|
|
1601
|
+
// hand the already-filtered snapshot to the chat-surface renderer.
|
|
1602
|
+
const includeAll = parts.includes("--all");
|
|
1603
|
+
const rows = selectRunsForPicker(store.runs(), "", includeAll, Date.now());
|
|
1604
|
+
emitChatSurface(pi, { kind: "status", runs: rows.map((r) => r.run) });
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
// -----------------------------------------------------------------------
|
|
1609
|
+
// interrupt — top-level chat fast path (no confirmation overlay).
|
|
1610
|
+
// -----------------------------------------------------------------------
|
|
1611
|
+
if (subcommand === "interrupt") {
|
|
1612
|
+
// The top-level chat command is the fast interrupt path surfaced by the
|
|
1613
|
+
// widget hint (`/workflow interrupt <id>`). The user's explicit slash
|
|
1614
|
+
// command should abort immediately, even when a confirm surface is
|
|
1615
|
+
// unavailable or would steal focus from the running workflow.
|
|
1616
|
+
const interruptArgs = parts.slice(1);
|
|
1617
|
+
const hasYes = interruptArgs.some((t) => t === "--yes" || t === "-y");
|
|
1618
|
+
await handleRunControlCommand(
|
|
1619
|
+
"interrupt",
|
|
1620
|
+
hasYes ? interruptArgs : [...interruptArgs, "-y"],
|
|
1621
|
+
ctx,
|
|
1622
|
+
);
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
// -----------------------------------------------------------------------
|
|
1627
|
+
// resume — non-paused runs reopen the orchestrator pane (legacy
|
|
1628
|
+
// behaviour); paused runs resume live work through the registry.
|
|
1629
|
+
// -----------------------------------------------------------------------
|
|
1630
|
+
if (subcommand === "resume") {
|
|
1631
|
+
await handleRunControlCommand("resume", parts.slice(1), ctx);
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
// -----------------------------------------------------------------------
|
|
1636
|
+
// inputs — pretty-printed via theme; falls back to plain in non-TTY tests.
|
|
1637
|
+
// -----------------------------------------------------------------------
|
|
1638
|
+
if (subcommand === "inputs") {
|
|
1639
|
+
const workflowName = parts[1] ?? "";
|
|
1640
|
+
if (!workflowName) {
|
|
1641
|
+
print("Usage: /workflow inputs <name>");
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
const result = await runtimeForContext(ctx).dispatch({
|
|
1645
|
+
workflow: workflowName,
|
|
1646
|
+
inputs: {},
|
|
1647
|
+
action: "inputs",
|
|
1648
|
+
});
|
|
1649
|
+
if (result.action === "inputs" && "inputs" in result) {
|
|
1650
|
+
const r = result as Extract<WorkflowToolResult, { action: "inputs" }>;
|
|
1651
|
+
if (r.error) {
|
|
1652
|
+
const available = runtimeProxy.registry.names();
|
|
1653
|
+
print(
|
|
1654
|
+
`${r.error}\nAvailable: ${available.length > 0 ? available.join(", ") : "(none)"}`,
|
|
1655
|
+
);
|
|
1656
|
+
} else {
|
|
1657
|
+
print(renderInputsSchema(workflowName, r.inputs, { theme: deriveGraphTheme({}) }));
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
// -----------------------------------------------------------------------
|
|
1664
|
+
// Workflow name dispatch — workflows always run as background tasks.
|
|
1665
|
+
// The chat editor remains usable; HIL prompts surface through the graph
|
|
1666
|
+
// viewer overlay (F2 / `/workflow connect`).
|
|
1667
|
+
// -----------------------------------------------------------------------
|
|
1668
|
+
const workflowName = subcommand;
|
|
1669
|
+
const inputTokens = parts.slice(1);
|
|
1670
|
+
|
|
1671
|
+
if (inputTokens.includes("--help")) {
|
|
1672
|
+
const helpResult = await runtimeForContext(ctx).dispatch({
|
|
1673
|
+
workflow: workflowName,
|
|
1674
|
+
inputs: {},
|
|
1675
|
+
action: "inputs",
|
|
1676
|
+
});
|
|
1677
|
+
if (helpResult.action === "inputs" && "inputs" in helpResult) {
|
|
1678
|
+
const r = helpResult as Extract<
|
|
1679
|
+
WorkflowToolResult,
|
|
1680
|
+
{ action: "inputs" }
|
|
1681
|
+
>;
|
|
1682
|
+
if (r.error) {
|
|
1683
|
+
const available = runtimeProxy.registry.names();
|
|
1684
|
+
print(
|
|
1685
|
+
`${r.error}\nAvailable: ${available.length > 0 ? available.join(", ") : "(none)"}`,
|
|
1686
|
+
);
|
|
1687
|
+
} else {
|
|
1688
|
+
print(renderInputsSchema(workflowName, r.inputs, { theme: deriveGraphTheme({}) }));
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
const inputs = parseWorkflowArgs(inputTokens);
|
|
1695
|
+
// -----------------------------------------------------------------------
|
|
1696
|
+
// Interactive argument picker.
|
|
1697
|
+
//
|
|
1698
|
+
// Triggers when:
|
|
1699
|
+
// - the workflow has at least one declared input (zero-input
|
|
1700
|
+
// workflows go straight to dispatch — there's nothing to ask),
|
|
1701
|
+
// - the user did not pass `--no-picker`,
|
|
1702
|
+
// - an interactive TUI surface is available,
|
|
1703
|
+
// - AND either no key=value was supplied or one of the required
|
|
1704
|
+
// inputs is still missing after parsing.
|
|
1705
|
+
//
|
|
1706
|
+
// The picker is seeded with whatever the user *did* type, so a
|
|
1707
|
+
// partial invocation like `/workflow gen-spec research_doc=notes.md`
|
|
1708
|
+
// pre-fills that field and focuses the next unfilled required one.
|
|
1709
|
+
// -----------------------------------------------------------------------
|
|
1710
|
+
const wantsPickerSkip = inputTokens.includes("--no-picker");
|
|
1711
|
+
let mergedInputs = inputs;
|
|
1712
|
+
// Track whether the inputs picker actually showed a UI to the user.
|
|
1713
|
+
// We use this below to mount the orchestrator overlay on dispatch
|
|
1714
|
+
// success — same UX as `/workflow connect|attach|pause|resume`,
|
|
1715
|
+
// which all cover Pi's `⠴ Working… (esc to interrupt)` spinner
|
|
1716
|
+
// with the full-screen overlay instead of leaving it visible in
|
|
1717
|
+
// the chat while the workflow runs in the background.
|
|
1718
|
+
let pickerWasShown = false;
|
|
1719
|
+
// Prefer the sticky inline form when the host can install a custom
|
|
1720
|
+
// editor. If the host rejects that editor contract at runtime, fall
|
|
1721
|
+
// back to the supported overlay picker rather than surfacing the host
|
|
1722
|
+
// exception as a workflow command error.
|
|
1723
|
+
const canOpenPicker =
|
|
1724
|
+
!wantsPickerSkip &&
|
|
1725
|
+
(typeof ctx.ui?.setEditorComponent === "function" ||
|
|
1726
|
+
typeof ctx.ui?.custom === "function");
|
|
1727
|
+
if (canOpenPicker) {
|
|
1728
|
+
const schemaResult = await runtimeForContext(ctx).dispatch({
|
|
1729
|
+
workflow: workflowName,
|
|
1730
|
+
inputs: {},
|
|
1731
|
+
action: "inputs",
|
|
1732
|
+
});
|
|
1733
|
+
const schema =
|
|
1734
|
+
schemaResult.action === "inputs" && "inputs" in schemaResult
|
|
1735
|
+
? (schemaResult as Extract<WorkflowToolResult, { action: "inputs" }>)
|
|
1736
|
+
: undefined;
|
|
1737
|
+
const fields = schema?.inputs ?? [];
|
|
1738
|
+
const hasFields = fields.length > 0;
|
|
1739
|
+
const missingRequired = fields.some(
|
|
1740
|
+
(f: WorkflowInputEntry) =>
|
|
1741
|
+
f.required === true &&
|
|
1742
|
+
(inputs[f.name] === undefined ||
|
|
1743
|
+
(typeof inputs[f.name] === "string" &&
|
|
1744
|
+
(inputs[f.name] as string).trim() === "")),
|
|
1745
|
+
);
|
|
1746
|
+
const noTokensAtAll = inputTokens.length === 0;
|
|
1747
|
+
if (hasFields && (noTokensAtAll || missingRequired)) {
|
|
1748
|
+
pickerWasShown = true;
|
|
1749
|
+
const pickerTheme = deriveGraphTheme({});
|
|
1750
|
+
let pickerResult =
|
|
1751
|
+
typeof ctx.ui?.setEditorComponent === "function"
|
|
1752
|
+
? await openInlineInputsForm(pi, ctx, {
|
|
1753
|
+
workflowName,
|
|
1754
|
+
fields,
|
|
1755
|
+
prefilled: inputs,
|
|
1756
|
+
theme: pickerTheme,
|
|
1757
|
+
})
|
|
1758
|
+
: { kind: "unsupported" as const };
|
|
1759
|
+
if (
|
|
1760
|
+
pickerResult.kind === "unsupported" &&
|
|
1761
|
+
typeof ctx.ui?.custom === "function"
|
|
1762
|
+
) {
|
|
1763
|
+
pickerResult = await openInputsPicker(ctx.ui, {
|
|
1764
|
+
workflowName,
|
|
1765
|
+
fields,
|
|
1766
|
+
prefilled: inputs,
|
|
1767
|
+
theme: pickerTheme,
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
if (pickerResult.kind === "cancel") {
|
|
1771
|
+
print(`Cancelled. /workflow ${workflowName} not started.`);
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
if (pickerResult.kind === "run") {
|
|
1775
|
+
mergedInputs = pickerResult.values;
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
const result = await runtimeForContext(ctx).dispatch({
|
|
1781
|
+
workflow: workflowName,
|
|
1782
|
+
inputs: mergedInputs,
|
|
1783
|
+
action: "run",
|
|
1784
|
+
});
|
|
1785
|
+
if (result.action === "run" && "runId" in result) {
|
|
1786
|
+
const r = result as Extract<
|
|
1787
|
+
WorkflowToolResult,
|
|
1788
|
+
{ action: "run"; runId: string }
|
|
1789
|
+
>;
|
|
1790
|
+
if (r.status === "failed" && r.runId === "") {
|
|
1791
|
+
const available = runtimeProxy.registry.names();
|
|
1792
|
+
print(
|
|
1793
|
+
`Workflow not found: ${workflowName}\nAvailable: ${available.length > 0 ? available.join(", ") : "(none)"}`,
|
|
1794
|
+
);
|
|
1795
|
+
} else if (r.status === "failed") {
|
|
1796
|
+
print(
|
|
1797
|
+
`Workflow "${workflowName}" failed: ${r.error ?? "unknown error"}`,
|
|
1798
|
+
);
|
|
1799
|
+
} else {
|
|
1800
|
+
// Always-background — the run is alive, the chat is free.
|
|
1801
|
+
// Route via emitChatSurface so the band+card chrome receives the
|
|
1802
|
+
// real chat content width via pi-tui's Component contract
|
|
1803
|
+
// (registered renderer returns `{ render(width): string[] }`),
|
|
1804
|
+
// not a `process.stdout.columns - 2` heuristic.
|
|
1805
|
+
emitChatSurface(pi, {
|
|
1806
|
+
kind: "dispatch",
|
|
1807
|
+
workflowName,
|
|
1808
|
+
runId: r.runId,
|
|
1809
|
+
inputs: mergedInputs,
|
|
1810
|
+
});
|
|
1811
|
+
// When the user reached this path via the inputs picker (i.e.
|
|
1812
|
+
// they didn't pre-supply all required args), open the
|
|
1813
|
+
// orchestrator overlay. The full-screen overlay covers the
|
|
1814
|
+
// chat statusContainer so Pi's working spinner is not left
|
|
1815
|
+
// visible behind the dispatch card. Direct invocations with
|
|
1816
|
+
// complete args remain opt-in via F2 / `/workflow connect`.
|
|
1817
|
+
if (pickerWasShown && typeof ctx.ui?.custom === "function") {
|
|
1818
|
+
overlay.open(r.runId, overlaySurfaceFromContext(ctx));
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
return;
|
|
1823
|
+
},
|
|
1824
|
+
getArgumentCompletions: (
|
|
1825
|
+
partial: string,
|
|
1826
|
+
): PiArgumentCompletionResult => {
|
|
1827
|
+
const completeToken = (
|
|
1828
|
+
argumentText: string,
|
|
1829
|
+
candidates: PiArgumentCompletion[],
|
|
1830
|
+
): PiArgumentCompletionResult => {
|
|
1831
|
+
const tokenStart = /\s$/.test(argumentText)
|
|
1832
|
+
? argumentText.length
|
|
1833
|
+
: Math.max(argumentText.lastIndexOf(" "), argumentText.lastIndexOf("\t")) + 1;
|
|
1834
|
+
const head = argumentText.slice(0, tokenStart);
|
|
1835
|
+
const token = argumentText.slice(tokenStart);
|
|
1836
|
+
const filtered = candidates
|
|
1837
|
+
.filter((candidate) => candidate.value.startsWith(token))
|
|
1838
|
+
.map((candidate) => ({
|
|
1839
|
+
...candidate,
|
|
1840
|
+
value: `${head}${candidate.value}`,
|
|
1841
|
+
}));
|
|
1842
|
+
return filtered.length > 0 ? filtered : null;
|
|
1843
|
+
};
|
|
1844
|
+
|
|
1845
|
+
const workflowNameItems = (): PiArgumentCompletion[] =>
|
|
1846
|
+
runtimeProxy.registry.names().map((name) => ({
|
|
1847
|
+
value: `${name} `,
|
|
1848
|
+
label: name,
|
|
1849
|
+
description: `Run workflow: ${name}`,
|
|
1850
|
+
}));
|
|
1851
|
+
|
|
1852
|
+
const runIdItems = (): PiArgumentCompletion[] =>
|
|
1853
|
+
store.runs().map((run) => ({
|
|
1854
|
+
value: `${run.id} `,
|
|
1855
|
+
label: run.id.slice(0, 8),
|
|
1856
|
+
description: `${run.name} — ${run.status}`,
|
|
1857
|
+
}));
|
|
1858
|
+
|
|
1859
|
+
const adminCompletions: PiArgumentCompletion[] = [
|
|
1860
|
+
{
|
|
1861
|
+
value: "connect ",
|
|
1862
|
+
label: "connect",
|
|
1863
|
+
description: "Attach to a run (picker if no id)",
|
|
1864
|
+
},
|
|
1865
|
+
{
|
|
1866
|
+
value: "attach ",
|
|
1867
|
+
label: "attach",
|
|
1868
|
+
description: "Open the in-place attach pane on a node",
|
|
1869
|
+
},
|
|
1870
|
+
{
|
|
1871
|
+
value: "list ",
|
|
1872
|
+
label: "list",
|
|
1873
|
+
description: "List registered workflows",
|
|
1874
|
+
},
|
|
1875
|
+
{
|
|
1876
|
+
value: "status ",
|
|
1877
|
+
label: "status",
|
|
1878
|
+
description: "List in-flight runs",
|
|
1879
|
+
},
|
|
1880
|
+
{ value: "interrupt ", label: "interrupt", description: "Interrupt a run" },
|
|
1881
|
+
{ value: "pause ", label: "pause", description: "Pause a run or stage" },
|
|
1882
|
+
{
|
|
1883
|
+
value: "resume ",
|
|
1884
|
+
label: "resume",
|
|
1885
|
+
description: "Re-open overlay for a run",
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
value: "inputs ",
|
|
1889
|
+
label: "inputs",
|
|
1890
|
+
description: "Show a workflow's input schema",
|
|
1891
|
+
},
|
|
1892
|
+
];
|
|
1893
|
+
|
|
1894
|
+
const parts = partial.trim().split(/\s+/).filter(Boolean);
|
|
1895
|
+
const subcommand = parts[0] ?? "";
|
|
1896
|
+
if (!partial.includes(" ")) {
|
|
1897
|
+
return completeToken(partial, [...adminCompletions, ...workflowNameItems()]);
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
if (subcommand === "inputs") {
|
|
1901
|
+
return completeToken(partial, workflowNameItems());
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
if (subcommand === "status") {
|
|
1905
|
+
return completeToken(partial, [
|
|
1906
|
+
{ value: "--all ", label: "--all", description: "Include recently ended runs" },
|
|
1907
|
+
...runIdItems(),
|
|
1908
|
+
]);
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
if (subcommand === "connect") {
|
|
1912
|
+
return completeToken(partial, runIdItems());
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
if (subcommand === "resume") {
|
|
1916
|
+
return completeToken(partial, runIdItems());
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
if (subcommand === "attach" || subcommand === "pause") {
|
|
1920
|
+
return completeToken(partial, runIdItems());
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
if (subcommand === "interrupt") {
|
|
1924
|
+
return completeToken(partial, [
|
|
1925
|
+
{ value: "--all ", label: "--all", description: "Interrupt all in-flight runs" },
|
|
1926
|
+
{ value: "--yes ", label: "--yes", description: "Skip confirmation" },
|
|
1927
|
+
{ value: "-y ", label: "-y", description: "Skip confirmation" },
|
|
1928
|
+
...runIdItems(),
|
|
1929
|
+
]);
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
// `partial` ends with whitespace and no subcommand was typed yet
|
|
1933
|
+
// (e.g. `/workflow `). pi's autocomplete is asking what to suggest
|
|
1934
|
+
// after the trailing space; offer the same admin + workflow-name
|
|
1935
|
+
// menu as the no-space branch above. Skipping this guard would call
|
|
1936
|
+
// `registry.get("")`, which throws TypeError from normalizeWorkflowName.
|
|
1937
|
+
if (!subcommand) {
|
|
1938
|
+
return completeToken(partial, [...adminCompletions, ...workflowNameItems()]);
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
const workflow = runtimeProxy.registry.get(subcommand);
|
|
1942
|
+
if (!workflow) return null;
|
|
1943
|
+
|
|
1944
|
+
const tokenStart = /\s$/.test(partial)
|
|
1945
|
+
? partial.length
|
|
1946
|
+
: Math.max(partial.lastIndexOf(" "), partial.lastIndexOf("\t")) + 1;
|
|
1947
|
+
const token = partial.slice(tokenStart);
|
|
1948
|
+
const equalsIndex = token.indexOf("=");
|
|
1949
|
+
if (equalsIndex > 0) {
|
|
1950
|
+
const inputName = token.slice(0, equalsIndex);
|
|
1951
|
+
const schema = workflow.inputs[inputName];
|
|
1952
|
+
if (schema?.type === "select") {
|
|
1953
|
+
return completeToken(
|
|
1954
|
+
partial,
|
|
1955
|
+
schema.choices.map((choice) => ({
|
|
1956
|
+
value: `${inputName}=${choice} `,
|
|
1957
|
+
label: choice,
|
|
1958
|
+
description: inputName,
|
|
1959
|
+
})),
|
|
1960
|
+
);
|
|
1961
|
+
}
|
|
1962
|
+
if (schema?.type === "boolean") {
|
|
1963
|
+
return completeToken(partial, [
|
|
1964
|
+
{ value: `${inputName}=true `, label: "true", description: inputName },
|
|
1965
|
+
{ value: `${inputName}=false `, label: "false", description: inputName },
|
|
1966
|
+
]);
|
|
1967
|
+
}
|
|
1968
|
+
return null;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
const inputCompletions: PiArgumentCompletion[] = Object.entries(workflow.inputs)
|
|
1972
|
+
.map(([name, schema]) => ({
|
|
1973
|
+
value: `${name}=`,
|
|
1974
|
+
label: name,
|
|
1975
|
+
description: schema.description,
|
|
1976
|
+
}));
|
|
1977
|
+
return completeToken(partial, [
|
|
1978
|
+
{ value: "--no-picker ", label: "--no-picker", description: "Skip interactive input picker" },
|
|
1979
|
+
{ value: "--help ", label: "--help", description: "Show this workflow's input schema" },
|
|
1980
|
+
...inputCompletions,
|
|
1981
|
+
]);
|
|
1982
|
+
},
|
|
1983
|
+
}, workflowCommands);
|
|
1984
|
+
|
|
1985
|
+
// -------------------------------------------------------------------------
|
|
1986
|
+
// 3. Register message renderers for lifecycle events (§5.6)
|
|
1987
|
+
// -------------------------------------------------------------------------
|
|
1988
|
+
// Chat-scroll renderers are deliberately limited to run-level events
|
|
1989
|
+
// (start + end). Per-stage chatter is owned by the orchestrator pane —
|
|
1990
|
+
// duplicating it into chat scroll just creates visual noise and pushes
|
|
1991
|
+
// older chat content out of view every time a stage transitions.
|
|
1992
|
+
if (typeof pi.registerMessageRenderer === "function") {
|
|
1993
|
+
pi.registerMessageRenderer("workflow.run.start", (payload) =>
|
|
1994
|
+
renderRunBanner(payload as RunStartPayload),
|
|
1995
|
+
);
|
|
1996
|
+
pi.registerMessageRenderer("workflow.run.end", (payload) =>
|
|
1997
|
+
renderRunSummary(payload as RunEndPayload),
|
|
1998
|
+
);
|
|
1999
|
+
// Inline workflow-input form (Option C in the design conversation):
|
|
2000
|
+
// a sticky chat-history card driven by a custom EditorComponent. The
|
|
2001
|
+
// renderer reads form state from the module-level store keyed by
|
|
2002
|
+
// `details.formId`. Registered once; openInlineInputsForm() emits the
|
|
2003
|
+
// card via pi.sendMessage on each invocation.
|
|
2004
|
+
registerInlineFormRenderer(pi, deriveGraphTheme({}));
|
|
2005
|
+
|
|
2006
|
+
// Chat-scroll surfaces for /workflow run|list|status|status <id>. Bypasses
|
|
2007
|
+
// the default `notify`/`Text(paddingX=1)` path so band+card chrome
|
|
2008
|
+
// receives the *real* chat content width instead of a `cols - 2` heuristic.
|
|
2009
|
+
// See src/tui/chat-surface-message.ts for the contract.
|
|
2010
|
+
registerChatSurfaceRenderer(pi, deriveGraphTheme({}));
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
// -------------------------------------------------------------------------
|
|
2014
|
+
// 4. Persistence: session_start restore + session_before_compact hook (§5.6, Phase D)
|
|
2015
|
+
// -------------------------------------------------------------------------
|
|
2016
|
+
if (typeof pi.on === "function") {
|
|
2017
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
2018
|
+
// Workflow lifecycle is scoped to the originating chat session.
|
|
2019
|
+
// A new session inherits a clean store; any leftover runs from a
|
|
2020
|
+
// previous session in the same pi process are killed (subprocess
|
|
2021
|
+
// aborted) and dropped. `restoreOnSessionStart` below then loads
|
|
2022
|
+
// *this* session's persisted runs from disk.
|
|
2023
|
+
killAllRuns({
|
|
2024
|
+
store,
|
|
2025
|
+
cancellation: cancellationRegistry,
|
|
2026
|
+
persistence: persistenceRef.current,
|
|
2027
|
+
});
|
|
2028
|
+
store.clear();
|
|
2029
|
+
|
|
2030
|
+
// pi-intercom session naming lives here so we don't trip the
|
|
2031
|
+
// loader's "Action methods cannot be called during extension
|
|
2032
|
+
// loading" guard.
|
|
2033
|
+
intercomParentSession = registerIntercomParentSession(pi);
|
|
2034
|
+
|
|
2035
|
+
// Ensure config+discovery are ready before restoring in-flight runs —
|
|
2036
|
+
// tunables must be resolved first.
|
|
2037
|
+
await discoveryPromise;
|
|
2038
|
+
if (ctx?.ui) {
|
|
2039
|
+
storeWidgetUnsubscribe?.();
|
|
2040
|
+
storeWidgetUnsubscribe = installStoreWidget({ ui: ctx.ui }, store);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
const sessionManager = ctx?.sessionManager ?? pi.sessionManager;
|
|
2044
|
+
if (sessionManager) {
|
|
2045
|
+
const cfg = configLoadRef.current?.config;
|
|
2046
|
+
restoreOnSessionStart(
|
|
2047
|
+
sessionManager,
|
|
2048
|
+
{
|
|
2049
|
+
resumeInFlight: cfg?.resumeInFlight ?? "ask",
|
|
2050
|
+
persistRuns: cfg?.persistRuns ?? true,
|
|
2051
|
+
},
|
|
2052
|
+
store,
|
|
2053
|
+
);
|
|
2054
|
+
}
|
|
2055
|
+
});
|
|
2056
|
+
|
|
2057
|
+
installCompactionHook(pi, store);
|
|
2058
|
+
pi.on("session_shutdown", () => {
|
|
2059
|
+
// Tie workflow lifecycle to the chat: when the chat ends, every
|
|
2060
|
+
// in-flight workflow is killed so we don't leave subprocesses
|
|
2061
|
+
// burning tokens with no UI to surface their progress.
|
|
2062
|
+
intercomControlUnsubscribe?.();
|
|
2063
|
+
intercomControlUnsubscribe = null;
|
|
2064
|
+
killAllRuns({
|
|
2065
|
+
store,
|
|
2066
|
+
cancellation: cancellationRegistry,
|
|
2067
|
+
persistence: persistenceRef.current,
|
|
2068
|
+
});
|
|
2069
|
+
storeWidgetUnsubscribe?.();
|
|
2070
|
+
storeWidgetUnsubscribe = null;
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
storeWidgetUnsubscribe = installStoreWidget(pi, store);
|
|
2075
|
+
installToolExecutionHooks(pi, store);
|
|
2076
|
+
|
|
2077
|
+
// -------------------------------------------------------------------------
|
|
2078
|
+
// 5. Register F2 keyboard shortcut — open graph overlay for active run.
|
|
2079
|
+
// Falls back to noop when pi.registerShortcut is absent (degraded runtime).
|
|
2080
|
+
// Existing API shape: (key, { description, handler }).
|
|
2081
|
+
//
|
|
2082
|
+
// Note: the historical `ctrl+h` toggle was removed when workflow runs
|
|
2083
|
+
// became background-by-default — a global toggle is no longer the
|
|
2084
|
+
// primary way to manage visibility. Inside the pane, press `h` to
|
|
2085
|
+
// hide (calls setHidden(true) on the overlay handle); re-open via
|
|
2086
|
+
// `F2` or `/workflow connect <id>`.
|
|
2087
|
+
// -------------------------------------------------------------------------
|
|
2088
|
+
if (typeof pi.registerShortcut === "function") {
|
|
2089
|
+
// Prefer the in-flight run; if nothing's active, fall back to the
|
|
2090
|
+
// most recently observed run so users can still review what just
|
|
2091
|
+
// finished without typing `/workflow resume <id>`.
|
|
2092
|
+
const openPane = (ctx?: PiCommandContext): void => {
|
|
2093
|
+
const activeRunId = store.activeRunId();
|
|
2094
|
+
const fallback = activeRunId ?? store.runs().at(-1)?.id ?? null;
|
|
2095
|
+
overlay.open(fallback, overlaySurfaceFromContext(ctx));
|
|
2096
|
+
};
|
|
2097
|
+
|
|
2098
|
+
pi.registerShortcut("F2", {
|
|
2099
|
+
description: "Open workflow orchestrator pane",
|
|
2100
|
+
handler: openPane,
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
// -------------------------------------------------------------------------
|
|
2105
|
+
// 6. Register sibling integrations (Phase G — §5.8, §5.9, §5.10)
|
|
2106
|
+
// All registration calls are guarded; no throw when sibling is absent.
|
|
2107
|
+
// Note: registerIntercomParentSession (pi-intercom session naming) calls
|
|
2108
|
+
// pi.setSessionName which is an action method — see session_start handler
|
|
2109
|
+
// above for that registration.
|
|
2110
|
+
// -------------------------------------------------------------------------
|
|
2111
|
+
|
|
2112
|
+
// pi-intercom: route subagent:control-intercom events to overlay/store callbacks.
|
|
2113
|
+
// buildIntercomCallbacks wires store.recordNotice, pi.ui.confirm (when present),
|
|
2114
|
+
// and pi.events.emit (when present) so escalations are never silently dropped.
|
|
2115
|
+
intercomControlUnsubscribe = subscribeIntercomControl(
|
|
2116
|
+
pi,
|
|
2117
|
+
buildIntercomCallbacks({
|
|
2118
|
+
store,
|
|
2119
|
+
emit:
|
|
2120
|
+
typeof pi.events?.emit === "function"
|
|
2121
|
+
? (event, payload) => pi.events!.emit!(event, payload)
|
|
2122
|
+
: undefined,
|
|
2123
|
+
confirm:
|
|
2124
|
+
typeof pi.ui?.confirm === "function"
|
|
2125
|
+
? (title, message) => pi.ui!.confirm!(title, message)
|
|
2126
|
+
: undefined,
|
|
2127
|
+
}),
|
|
2128
|
+
);
|
|
2129
|
+
|
|
2130
|
+
// -------------------------------------------------------------------------
|
|
2131
|
+
// 7. Suppress pi's optimistic "Working… (esc to interrupt)" loader
|
|
2132
|
+
// for our slash commands. Workflow commands are synchronous picker /
|
|
2133
|
+
// connect / inspect UIs, not streaming turns — the loader is noise
|
|
2134
|
+
// that pads chrome above the picker. The `on("input")` hook fires
|
|
2135
|
+
// BEFORE `startPendingSubmission`, so returning `{ action: "handled" }`
|
|
2136
|
+
// short-circuits the host before the loader starts. We dispatch the
|
|
2137
|
+
// registered handler ourselves. See `installInputInterceptor` for
|
|
2138
|
+
// the full rationale and host pipeline reference.
|
|
2139
|
+
// -------------------------------------------------------------------------
|
|
2140
|
+
installInputInterceptor(pi, workflowCommands);
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
export default factory;
|