@bastani/atomic 0.8.13-0 → 0.8.14-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 +24 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/host-html-template.ts +1 -1
- package/dist/builtin/mcp/init.ts +15 -2
- package/dist/builtin/mcp/mcp-callback-server.ts +10 -9
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/mcp/ui-session.ts +9 -6
- package/dist/builtin/subagents/CHANGELOG.md +8 -1
- package/dist/builtin/subagents/README.md +39 -32
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/skills/subagent/SKILL.md +11 -11
- package/dist/builtin/subagents/src/agents/agent-management.ts +6 -1
- package/dist/builtin/subagents/src/agents/agent-serializer.ts +2 -0
- package/dist/builtin/subagents/src/agents/agents.ts +44 -19
- package/dist/builtin/subagents/src/extension/config.ts +16 -0
- package/dist/builtin/subagents/src/extension/fanout-child.ts +246 -0
- package/dist/builtin/subagents/src/extension/index.ts +466 -603
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +6 -4
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +109 -1
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +124 -19
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +41 -6
- package/dist/builtin/subagents/src/runs/background/async-resume.ts +28 -15
- package/dist/builtin/subagents/src/runs/background/async-status.ts +60 -30
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +111 -54
- package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +83 -0
- package/dist/builtin/subagents/src/runs/background/run-status.ts +79 -3
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +46 -1
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +66 -14
- package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +10 -3
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +14 -2
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +320 -23
- package/dist/builtin/subagents/src/runs/shared/completion-guard.ts +23 -1
- package/dist/builtin/subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +369 -0
- package/dist/builtin/subagents/src/runs/shared/nested-events.ts +935 -0
- package/dist/builtin/subagents/src/runs/shared/nested-path.ts +52 -0
- package/dist/builtin/subagents/src/runs/shared/nested-render.ts +115 -0
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +1 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +82 -9
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +1 -1
- package/dist/builtin/subagents/src/runs/shared/single-output.ts +12 -2
- package/dist/builtin/subagents/src/runs/shared/subagent-prompt-runtime.ts +32 -10
- package/dist/builtin/subagents/src/runs/shared/worktree.ts +3 -2
- package/dist/builtin/subagents/src/shared/artifacts.ts +0 -1
- package/dist/builtin/subagents/src/shared/types.ts +96 -1
- package/dist/builtin/subagents/src/shared/utils.ts +10 -2
- package/dist/builtin/subagents/src/slash/slash-commands.ts +468 -625
- package/dist/builtin/subagents/src/tui/render.ts +1227 -2093
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +24 -0
- package/dist/builtin/workflows/README.md +28 -11
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +323 -40
- package/dist/builtin/workflows/builtin/ralph.ts +362 -176
- package/dist/builtin/workflows/package.json +2 -5
- package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
- package/dist/builtin/workflows/skills/skill-creator/LICENSE.txt +202 -0
- package/dist/builtin/workflows/skills/skill-creator/SKILL.md +489 -0
- package/dist/builtin/workflows/skills/skill-creator/agents/analyzer.md +274 -0
- package/dist/builtin/workflows/skills/skill-creator/agents/comparator.md +202 -0
- package/dist/builtin/workflows/skills/skill-creator/agents/grader.md +223 -0
- package/dist/builtin/workflows/skills/skill-creator/assets/eval_review.html +146 -0
- package/dist/builtin/workflows/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/dist/builtin/workflows/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/dist/builtin/workflows/skills/skill-creator/references/schemas.md +430 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/__init__.py +0 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/generate_report.py +326 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/improve_description.py +247 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/package_skill.py +136 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/run_eval.py +310 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/run_loop.py +328 -0
- package/dist/builtin/workflows/skills/skill-creator/scripts/utils.py +47 -0
- package/dist/builtin/workflows/src/extension/index.ts +869 -93
- package/dist/builtin/workflows/src/extension/render-call.ts +34 -1
- package/dist/builtin/workflows/src/extension/render-result.ts +126 -21
- package/dist/builtin/workflows/src/extension/runtime.ts +91 -3
- package/dist/builtin/workflows/src/extension/wiring.ts +38 -12
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +62 -5
- package/dist/builtin/workflows/src/runs/background/runner.ts +3 -3
- package/dist/builtin/workflows/src/runs/background/status.ts +42 -8
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +410 -95
- package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +5 -2
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +8 -0
- package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +6 -4
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +3 -2
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +138 -5
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +30 -0
- package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +78 -120
- package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +193 -0
- package/dist/builtin/workflows/src/shared/store-types.ts +26 -1
- package/dist/builtin/workflows/src/shared/store.ts +145 -17
- package/dist/builtin/workflows/src/shared/timing.ts +6 -2
- package/dist/builtin/workflows/src/shared/workflow-failures.ts +375 -0
- package/dist/builtin/workflows/src/tui/chat-surface.ts +68 -17
- package/dist/builtin/workflows/src/tui/connectors.ts +2 -2
- package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +24 -26
- package/dist/builtin/workflows/src/tui/graph-canvas.ts +4 -8
- package/dist/builtin/workflows/src/tui/graph-view.ts +17 -14
- package/dist/builtin/workflows/src/tui/header.ts +38 -0
- package/dist/builtin/workflows/src/tui/inline-form-card.ts +161 -238
- package/dist/builtin/workflows/src/tui/inline-form-editor.ts +68 -73
- package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +2 -3
- package/dist/builtin/workflows/src/tui/inline-form-store.ts +2 -1
- package/dist/builtin/workflows/src/tui/inputs-overlay.ts +1 -3
- package/dist/builtin/workflows/src/tui/inputs-picker.ts +286 -399
- package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +11 -0
- package/dist/builtin/workflows/src/tui/node-card.ts +2 -1
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +9 -1
- package/dist/builtin/workflows/src/tui/prompt-card.ts +46 -19
- package/dist/builtin/workflows/src/tui/run-detail.ts +63 -80
- package/dist/builtin/workflows/src/tui/session-confirm.ts +9 -3
- package/dist/builtin/workflows/src/tui/session-picker.ts +19 -16
- package/dist/builtin/workflows/src/tui/stage-chat-layout.ts +88 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +368 -879
- package/dist/builtin/workflows/src/tui/status-helpers.ts +4 -0
- package/dist/builtin/workflows/src/tui/status-list.ts +67 -75
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +50 -12
- package/dist/builtin/workflows/src/tui/submit-pane.ts +164 -0
- package/dist/builtin/workflows/src/tui/switcher.ts +27 -4
- package/dist/builtin/workflows/src/tui/text-helpers.ts +98 -4
- package/dist/builtin/workflows/src/tui/widget.ts +90 -68
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +23 -2
- package/dist/builtin/workflows/src/tui/workflow-list.ts +44 -68
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +2 -3
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -10
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +2 -1
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +3 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +6 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +16 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +8 -9
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +2 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +8 -6
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.js +6 -3
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +12 -29
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +5 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-manager.d.ts +8 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +145 -58
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +6 -20
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +38 -31
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +9 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +32 -24
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +8 -15
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +8 -22
- package/dist/core/skills.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +5 -4
- package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/questionnaire-session.js +34 -11
- package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/contract.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/selectors/projections.js +1 -0
- package/dist/core/tools/ask-user-question/state/selectors/projections.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/state-reducer.d.ts +1 -2
- package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/state-reducer.js +26 -9
- package/dist/core/tools/ask-user-question/state/state-reducer.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/state.d.ts +4 -0
- package/dist/core/tools/ask-user-question/state/state.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/state/state.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts +1 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/option-list-view.js +1 -0
- package/dist/core/tools/ask-user-question/view/components/option-list-view.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts +9 -6
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +28 -7
- package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/props-adapter.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/view/props-adapter.js +4 -1
- package/dist/core/tools/ask-user-question/view/props-adapter.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +56 -53
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +3 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +8 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +3 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +44 -81
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +27 -12
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +2 -3
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +3 -3
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -5
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +2 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +11 -4
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts +2 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js +39 -21
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +9 -8
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js +12 -2
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +20 -35
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +5 -6
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/chat-input-actions.d.ts +24 -0
- package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -0
- package/dist/modes/interactive/chat-input-actions.js +179 -0
- package/dist/modes/interactive/chat-input-actions.js.map +1 -0
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -0
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +14 -3
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts +157 -0
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -0
- package/dist/modes/interactive/components/chat-session-host.js +1007 -0
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +1 -1
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +14 -5
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +9 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +29 -4
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +18 -67
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/child-process.d.ts +1 -0
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +8 -0
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +3 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js +14 -8
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +30 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -0
- package/dist/utils/image-resize-core.js +124 -0
- package/dist/utils/image-resize-core.js.map +1 -0
- package/dist/utils/image-resize-worker.d.ts +2 -0
- package/dist/utils/image-resize-worker.d.ts.map +1 -0
- package/dist/utils/image-resize-worker.js +31 -0
- package/dist/utils/image-resize-worker.js.map +1 -0
- package/dist/utils/image-resize.d.ts +7 -27
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +75 -115
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/paths.d.ts +16 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +49 -7
- package/dist/utils/paths.js.map +1 -1
- package/docs/changelog.mdx +29 -0
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +2 -2
- package/docs/development.md +1 -1
- package/docs/docs.json +98 -143
- package/docs/extensions.md +29 -16
- package/docs/favicon.svg +29 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/images/workflow-command.png +0 -0
- package/docs/images/workflow-graph.png +0 -0
- package/docs/images/workflow-input-picker.png +0 -0
- package/docs/images/workflow-list.png +0 -0
- package/docs/index.md +10 -1
- package/docs/logo.svg +59 -0
- package/docs/packages.md +3 -3
- package/docs/providers.md +1 -1
- package/docs/quickstart.md +98 -2
- package/docs/rpc.md +8 -8
- package/docs/sdk.md +23 -12
- package/docs/sessions.md +1 -1
- package/docs/skills.md +15 -1
- package/docs/termux.md +11 -1
- package/docs/themes.md +6 -6
- package/docs/tui.md +18 -18
- package/docs/usage.md +1 -1
- package/docs/workflows.md +172 -2
- package/examples/extensions/subagent/index.ts +2 -1
- package/package.json +6 -6
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/SKILL.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/element-attributes.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/playwright-tests.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/request-mocking.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/running-code.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/session-management.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/spec-driven-testing.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/storage-state.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/test-generation.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/tracing.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/playwright-cli/references/video-recording.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/SKILL.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/deep-modules.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/interface-design.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/mocking.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/refactoring.md +0 -0
- /package/dist/builtin/{workflows → subagents}/skills/tdd/tests.md +0 -0
|
@@ -34,7 +34,8 @@ export type StageControlStatus =
|
|
|
34
34
|
| "paused"
|
|
35
35
|
| "blocked"
|
|
36
36
|
| "completed"
|
|
37
|
-
| "failed"
|
|
37
|
+
| "failed"
|
|
38
|
+
| "skipped";
|
|
38
39
|
|
|
39
40
|
export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
|
|
40
41
|
|
|
@@ -53,6 +54,8 @@ export interface StageControlHandle {
|
|
|
53
54
|
readonly sessionId: string | undefined;
|
|
54
55
|
readonly sessionFile: string | undefined;
|
|
55
56
|
readonly isStreaming: boolean;
|
|
57
|
+
/** True after the executor has released the live SDK session behind this handle. */
|
|
58
|
+
readonly isDisposed?: boolean;
|
|
56
59
|
readonly messages: AgentSession["messages"];
|
|
57
60
|
/** Live coding-agent session when available, used by embedded chat/footer UI. */
|
|
58
61
|
readonly agentSession?: AgentSession;
|
|
@@ -190,7 +193,7 @@ export function createStageControlRegistry(): StageControlRegistry {
|
|
|
190
193
|
);
|
|
191
194
|
for (const handle of targets) {
|
|
192
195
|
if (handle.status === "paused") continue;
|
|
193
|
-
if (handle.status === "completed" || handle.status === "failed") continue;
|
|
196
|
+
if (handle.status === "completed" || handle.status === "failed" || handle.status === "skipped") continue;
|
|
194
197
|
await handle.pause();
|
|
195
198
|
}
|
|
196
199
|
return controlledEntries(runId)
|
|
@@ -45,6 +45,8 @@ export interface StageSessionRuntime {
|
|
|
45
45
|
readonly thinkingLevel: AgentSession["thinkingLevel"];
|
|
46
46
|
readonly messages: AgentSession["messages"];
|
|
47
47
|
readonly isStreaming: AgentSession["isStreaming"];
|
|
48
|
+
/** Number of SDK-level queued steering/follow-up messages, when supported. */
|
|
49
|
+
readonly pendingMessageCount?: number;
|
|
48
50
|
navigateTree: AgentSession["navigateTree"];
|
|
49
51
|
compact: AgentSession["compact"];
|
|
50
52
|
abortCompaction(): void;
|
|
@@ -114,6 +116,8 @@ export interface InternalStageContext extends StageContext {
|
|
|
114
116
|
__sessionMeta(): { sessionId: string | undefined; sessionFile: string | undefined };
|
|
115
117
|
/** Internal: live coding-agent session when the adapter returned one. */
|
|
116
118
|
__agentSession(): AgentSession | undefined;
|
|
119
|
+
/** Internal: SDK queued steering/follow-up message count, when available. */
|
|
120
|
+
__pendingMessageCount(): number;
|
|
117
121
|
/** Internal: selected/effective model and fallback attempt metadata. */
|
|
118
122
|
__modelFallbackMeta(): StageModelFallbackMeta;
|
|
119
123
|
/**
|
|
@@ -711,6 +715,10 @@ export function createStageContext(opts: StageRunnerOpts): InternalStageContext
|
|
|
711
715
|
return asAgentSession(session);
|
|
712
716
|
},
|
|
713
717
|
|
|
718
|
+
__pendingMessageCount() {
|
|
719
|
+
return typeof session?.pendingMessageCount === "number" ? session.pendingMessageCount : 0;
|
|
720
|
+
},
|
|
721
|
+
|
|
714
722
|
__modelFallbackMeta() {
|
|
715
723
|
const attemptedModels = modelAttempts.map((attempt) => attempt.model);
|
|
716
724
|
const model = selectedModel ?? workflowModelId(session?.model);
|
|
@@ -214,13 +214,15 @@ export async function validateWorkflowModels(input: {
|
|
|
214
214
|
};
|
|
215
215
|
|
|
216
216
|
const failures: ModelResolutionFailure[] = [];
|
|
217
|
-
|
|
218
|
-
if (input.catalog !== undefined
|
|
219
|
-
|
|
217
|
+
let availableModels: readonly WorkflowModelInfo[] | undefined;
|
|
218
|
+
if (input.catalog !== undefined) {
|
|
219
|
+
try {
|
|
220
|
+
availableModels = await input.catalog.listModels();
|
|
221
|
+
} catch (err) {
|
|
222
|
+
if (input.catalog.currentModel === undefined) throw err;
|
|
220
223
|
recordWarning(catalogUnavailableWarning());
|
|
221
224
|
return warnings;
|
|
222
225
|
}
|
|
223
|
-
throw new WorkflowModelValidationError([{ input: "model catalog", reason: "unavailable and no current model is configured" }]);
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
for (const request of relevant) {
|
|
@@ -2,6 +2,7 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as os from "node:os";
|
|
4
4
|
import * as path from "node:path";
|
|
5
|
+
import { APP_NAME } from "@bastani/atomic";
|
|
5
6
|
|
|
6
7
|
export interface WorktreeSetup {
|
|
7
8
|
cwd: string;
|
|
@@ -149,11 +150,11 @@ function safePatchAgentName(agent: string): string {
|
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
function buildWorktreeBranch(runId: string, index: number): string {
|
|
152
|
-
return
|
|
153
|
+
return `${APP_NAME}-parallel-${runId}-${index}`;
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
function buildWorktreePath(runId: string, index: number): string {
|
|
156
|
-
return path.join(os.tmpdir(),
|
|
157
|
+
return path.join(os.tmpdir(), `${APP_NAME}-worktree-${runId}-${index}`);
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
function resolveRepoCwdRelative(cwd: string): string {
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Store } from "./store.js";
|
|
10
|
-
import type { RunSnapshot, StageSnapshot } from "./store-types.js";
|
|
10
|
+
import type { RunSnapshot, StageSnapshot, StageStatus } from "./store-types.js";
|
|
11
|
+
import { isWorkflowFailureKind } from "./workflow-failures.js";
|
|
11
12
|
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Config option
|
|
@@ -161,10 +162,15 @@ export function restoreOnSessionStart(
|
|
|
161
162
|
if (typeof getEntries !== "function") return;
|
|
162
163
|
|
|
163
164
|
const entries = getEntries.call(sessionManager);
|
|
164
|
-
const
|
|
165
|
+
const sessionEntries = entries as readonly SessionEntry[];
|
|
166
|
+
restoreEndedFailedRuns(sessionEntries, store);
|
|
167
|
+
const inFlight = scanInFlightRuns(sessionEntries);
|
|
165
168
|
if (inFlight.length === 0) return;
|
|
166
169
|
|
|
167
170
|
for (const run of inFlight) {
|
|
171
|
+
const runMeta = findRunStartMetadata(sessionEntries, run.runId);
|
|
172
|
+
const stages = _buildStageSnapshots(sessionEntries, run.runId);
|
|
173
|
+
|
|
168
174
|
if (config.resumeInFlight === "auto") {
|
|
169
175
|
// Re-hydrate the run into the store as "running"
|
|
170
176
|
const runSnapshot: RunSnapshot = {
|
|
@@ -172,8 +178,10 @@ export function restoreOnSessionStart(
|
|
|
172
178
|
name: run.name,
|
|
173
179
|
inputs: run.inputs,
|
|
174
180
|
status: "running",
|
|
175
|
-
stages
|
|
181
|
+
stages,
|
|
176
182
|
startedAt: run.startTs,
|
|
183
|
+
...(runMeta.resumedFromRunId !== undefined ? { resumedFromRunId: runMeta.resumedFromRunId } : {}),
|
|
184
|
+
...(runMeta.resumeFromStageId !== undefined ? { resumeFromStageId: runMeta.resumeFromStageId } : {}),
|
|
177
185
|
};
|
|
178
186
|
store.recordRunStart(runSnapshot);
|
|
179
187
|
callbacks.onResume?.(run);
|
|
@@ -184,10 +192,14 @@ export function restoreOnSessionStart(
|
|
|
184
192
|
name: run.name,
|
|
185
193
|
inputs: run.inputs,
|
|
186
194
|
status: "failed",
|
|
187
|
-
stages
|
|
195
|
+
stages,
|
|
188
196
|
startedAt: run.startTs,
|
|
189
197
|
endedAt: Date.now(),
|
|
190
198
|
error: "Run did not complete — process was interrupted.",
|
|
199
|
+
failureKind: "unknown",
|
|
200
|
+
resumable: false,
|
|
201
|
+
...(runMeta.resumedFromRunId !== undefined ? { resumedFromRunId: runMeta.resumedFromRunId } : {}),
|
|
202
|
+
...(runMeta.resumeFromStageId !== undefined ? { resumeFromStageId: runMeta.resumeFromStageId } : {}),
|
|
191
203
|
};
|
|
192
204
|
store.recordRunStart(runSnapshot);
|
|
193
205
|
store.recordRunEnd(run.runId, "failed");
|
|
@@ -224,6 +236,7 @@ function _buildStageSnapshots(
|
|
|
224
236
|
status: "running",
|
|
225
237
|
parentIds: Array.isArray(parentIds) ? (parentIds as string[]) : [],
|
|
226
238
|
startedAt: typeof ts === "number" ? ts : undefined,
|
|
239
|
+
...replayMetadata(entry.payload),
|
|
227
240
|
toolEvents: [],
|
|
228
241
|
});
|
|
229
242
|
}
|
|
@@ -234,13 +247,22 @@ function _buildStageSnapshots(
|
|
|
234
247
|
const status = entry.payload["status"];
|
|
235
248
|
const durationMs = entry.payload["durationMs"];
|
|
236
249
|
const summary = entry.payload["summary"];
|
|
250
|
+
const error = entry.payload["error"];
|
|
251
|
+
const failureKind = entry.payload["failureKind"];
|
|
252
|
+
const failureMessage = entry.payload["failureMessage"];
|
|
253
|
+
const skippedReason = entry.payload["skippedReason"];
|
|
237
254
|
if (typeof stageId !== "string") continue;
|
|
238
255
|
endedStages.add(stageId);
|
|
239
256
|
const snap = stageMap.get(stageId);
|
|
240
257
|
if (snap) {
|
|
241
|
-
snap.status = (status
|
|
258
|
+
snap.status = restoreStageStatus(status);
|
|
242
259
|
if (typeof durationMs === "number") snap.durationMs = durationMs;
|
|
243
260
|
if (typeof summary === "string") snap.result = summary;
|
|
261
|
+
if (typeof error === "string") snap.error = error;
|
|
262
|
+
if (typeof failureKind === "string" && isWorkflowFailureKind(failureKind)) snap.failureKind = failureKind;
|
|
263
|
+
if (typeof failureMessage === "string") snap.failureMessage = failureMessage;
|
|
264
|
+
if (typeof skippedReason === "string") snap.skippedReason = skippedReason;
|
|
265
|
+
Object.assign(snap, replayMetadata(entry.payload));
|
|
244
266
|
}
|
|
245
267
|
}
|
|
246
268
|
}
|
|
@@ -255,3 +277,114 @@ function _buildStageSnapshots(
|
|
|
255
277
|
|
|
256
278
|
return [...stageMap.values()];
|
|
257
279
|
}
|
|
280
|
+
|
|
281
|
+
function replayMetadata(payload: Record<string, unknown>): Pick<StageSnapshot, "replayedFromStageId" | "replayed"> {
|
|
282
|
+
const replayedFromStageId = payload["replayedFromStageId"];
|
|
283
|
+
const replayed = payload["replayed"];
|
|
284
|
+
return {
|
|
285
|
+
...(typeof replayedFromStageId === "string" ? { replayedFromStageId } : {}),
|
|
286
|
+
...(typeof replayed === "boolean" ? { replayed } : {}),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function restoreStageStatus(status: unknown): StageStatus {
|
|
291
|
+
switch (status) {
|
|
292
|
+
case "completed":
|
|
293
|
+
case "failed":
|
|
294
|
+
case "skipped":
|
|
295
|
+
return status;
|
|
296
|
+
default:
|
|
297
|
+
return "failed";
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function restoreEndedFailedRuns(entries: readonly SessionEntry[], store: Store): void {
|
|
302
|
+
const started = new Map<string, { readonly name: string; readonly inputs: Readonly<Record<string, unknown>>; readonly startTs: number }>();
|
|
303
|
+
const ended = new Map<string, Record<string, unknown>>();
|
|
304
|
+
|
|
305
|
+
for (const entry of entries) {
|
|
306
|
+
if (entry.type === "workflow.run.start") {
|
|
307
|
+
const runId = entry.payload["runId"];
|
|
308
|
+
const name = entry.payload["name"];
|
|
309
|
+
const inputs = entry.payload["inputs"];
|
|
310
|
+
const ts = entry.payload["ts"];
|
|
311
|
+
if (typeof runId === "string" && typeof name === "string" && typeof ts === "number") {
|
|
312
|
+
started.set(runId, {
|
|
313
|
+
name,
|
|
314
|
+
inputs: (inputs !== null && typeof inputs === "object" && !Array.isArray(inputs))
|
|
315
|
+
? (inputs as Record<string, unknown>)
|
|
316
|
+
: {},
|
|
317
|
+
startTs: ts,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (entry.type === "workflow.run.end") {
|
|
322
|
+
const runId = entry.payload["runId"];
|
|
323
|
+
if (typeof runId === "string") ended.set(runId, entry.payload);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
for (const [runId, start] of started) {
|
|
328
|
+
if (store.runs().some((run) => run.id === runId)) continue;
|
|
329
|
+
const end = ended.get(runId);
|
|
330
|
+
const status = restoreTerminalRunStatus(end?.["status"]);
|
|
331
|
+
if (end === undefined || status === undefined) continue;
|
|
332
|
+
|
|
333
|
+
const runMeta = findRunStartMetadata(entries, runId);
|
|
334
|
+
const stages = _buildStageSnapshots(entries, runId);
|
|
335
|
+
store.recordRunStart({
|
|
336
|
+
id: runId,
|
|
337
|
+
name: start.name,
|
|
338
|
+
inputs: start.inputs,
|
|
339
|
+
status: "running",
|
|
340
|
+
stages,
|
|
341
|
+
startedAt: start.startTs,
|
|
342
|
+
...(runMeta.resumedFromRunId !== undefined ? { resumedFromRunId: runMeta.resumedFromRunId } : {}),
|
|
343
|
+
...(runMeta.resumeFromStageId !== undefined ? { resumeFromStageId: runMeta.resumeFromStageId } : {}),
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const error = end["error"];
|
|
347
|
+
const failureKind = end["failureKind"];
|
|
348
|
+
const failureMessage = end["failureMessage"];
|
|
349
|
+
const failedStageId = end["failedStageId"];
|
|
350
|
+
const resumable = end["resumable"];
|
|
351
|
+
store.recordRunEnd(
|
|
352
|
+
runId,
|
|
353
|
+
status,
|
|
354
|
+
undefined,
|
|
355
|
+
typeof error === "string" ? error : undefined,
|
|
356
|
+
{
|
|
357
|
+
...(typeof failureKind === "string" && isWorkflowFailureKind(failureKind) ? { failureKind } : {}),
|
|
358
|
+
...(typeof failureMessage === "string" ? { failureMessage } : {}),
|
|
359
|
+
...(typeof failedStageId === "string" ? { failedStageId } : {}),
|
|
360
|
+
...(typeof resumable === "boolean" ? { resumable } : {}),
|
|
361
|
+
},
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function restoreTerminalRunStatus(status: unknown): "failed" | "killed" | undefined {
|
|
367
|
+
switch (status) {
|
|
368
|
+
case "failed":
|
|
369
|
+
case "killed":
|
|
370
|
+
return status;
|
|
371
|
+
default:
|
|
372
|
+
return undefined;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function findRunStartMetadata(
|
|
377
|
+
entries: readonly SessionEntry[],
|
|
378
|
+
runId: string,
|
|
379
|
+
): { readonly resumedFromRunId?: string; readonly resumeFromStageId?: string } {
|
|
380
|
+
for (const entry of entries) {
|
|
381
|
+
if (entry.type !== "workflow.run.start" || entry.payload["runId"] !== runId) continue;
|
|
382
|
+
const resumedFromRunId = entry.payload["resumedFromRunId"];
|
|
383
|
+
const resumeFromStageId = entry.payload["resumeFromStageId"];
|
|
384
|
+
return {
|
|
385
|
+
...(typeof resumedFromRunId === "string" ? { resumedFromRunId } : {}),
|
|
386
|
+
...(typeof resumeFromStageId === "string" ? { resumeFromStageId } : {}),
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
return {};
|
|
390
|
+
}
|
|
@@ -31,6 +31,8 @@ export interface RunStartPayload {
|
|
|
31
31
|
readonly runId: string;
|
|
32
32
|
readonly name: string;
|
|
33
33
|
readonly inputs: Readonly<Record<string, unknown>>;
|
|
34
|
+
readonly resumedFromRunId?: string;
|
|
35
|
+
readonly resumeFromStageId?: string;
|
|
34
36
|
readonly ts: number;
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -40,6 +42,8 @@ export interface StageStartPayload {
|
|
|
40
42
|
readonly name: string;
|
|
41
43
|
readonly parentIds: readonly string[];
|
|
42
44
|
readonly model?: string;
|
|
45
|
+
readonly replayedFromStageId?: string;
|
|
46
|
+
readonly replayed?: boolean;
|
|
43
47
|
readonly ts: number;
|
|
44
48
|
}
|
|
45
49
|
|
|
@@ -56,12 +60,23 @@ export interface StageEndPayload {
|
|
|
56
60
|
readonly status: string;
|
|
57
61
|
readonly durationMs?: number;
|
|
58
62
|
readonly summary?: string;
|
|
63
|
+
readonly error?: string;
|
|
64
|
+
readonly failureKind?: string;
|
|
65
|
+
readonly failureMessage?: string;
|
|
66
|
+
readonly skippedReason?: string;
|
|
67
|
+
readonly replayedFromStageId?: string;
|
|
68
|
+
readonly replayed?: boolean;
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
export interface RunEndPayload {
|
|
62
72
|
readonly runId: string;
|
|
63
73
|
readonly status: string;
|
|
64
74
|
readonly result?: unknown;
|
|
75
|
+
readonly error?: string;
|
|
76
|
+
readonly failureKind?: string;
|
|
77
|
+
readonly failureMessage?: string;
|
|
78
|
+
readonly failedStageId?: string;
|
|
79
|
+
readonly resumable?: boolean;
|
|
65
80
|
readonly ts: number;
|
|
66
81
|
}
|
|
67
82
|
|
|
@@ -79,6 +94,8 @@ export function appendRunStart(api: PersistenceAPI, payload: RunStartPayload): v
|
|
|
79
94
|
runId: payload.runId,
|
|
80
95
|
name: payload.name,
|
|
81
96
|
inputs: payload.inputs,
|
|
97
|
+
...(payload.resumedFromRunId !== undefined ? { resumedFromRunId: payload.resumedFromRunId } : {}),
|
|
98
|
+
...(payload.resumeFromStageId !== undefined ? { resumeFromStageId: payload.resumeFromStageId } : {}),
|
|
82
99
|
ts: payload.ts,
|
|
83
100
|
});
|
|
84
101
|
if (entryId && typeof api.setLabel === "function") {
|
|
@@ -96,6 +113,8 @@ export function appendStageStart(api: PersistenceAPI, payload: StageStartPayload
|
|
|
96
113
|
name: payload.name,
|
|
97
114
|
parentIds: [...payload.parentIds],
|
|
98
115
|
...(payload.model !== undefined ? { model: payload.model } : {}),
|
|
116
|
+
...(payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {}),
|
|
117
|
+
...(payload.replayed !== undefined ? { replayed: payload.replayed } : {}),
|
|
99
118
|
ts: payload.ts,
|
|
100
119
|
});
|
|
101
120
|
}
|
|
@@ -124,6 +143,12 @@ export function appendStageEnd(
|
|
|
124
143
|
status: payload.status,
|
|
125
144
|
...(payload.durationMs !== undefined ? { durationMs: payload.durationMs } : {}),
|
|
126
145
|
...(payload.summary !== undefined ? { summary: payload.summary } : {}),
|
|
146
|
+
...(payload.error !== undefined ? { error: payload.error } : {}),
|
|
147
|
+
...(payload.failureKind !== undefined ? { failureKind: payload.failureKind } : {}),
|
|
148
|
+
...(payload.failureMessage !== undefined ? { failureMessage: payload.failureMessage } : {}),
|
|
149
|
+
...(payload.skippedReason !== undefined ? { skippedReason: payload.skippedReason } : {}),
|
|
150
|
+
...(payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {}),
|
|
151
|
+
...(payload.replayed !== undefined ? { replayed: payload.replayed } : {}),
|
|
127
152
|
});
|
|
128
153
|
if (opts?.emitMessage === true && payload.summary && typeof api.appendCustomMessageEntry === "function") {
|
|
129
154
|
api.appendCustomMessageEntry(
|
|
@@ -140,6 +165,11 @@ export function appendRunEnd(api: PersistenceAPI, payload: RunEndPayload): void
|
|
|
140
165
|
runId: payload.runId,
|
|
141
166
|
status: payload.status,
|
|
142
167
|
...(payload.result !== undefined ? { result: payload.result as Record<string, unknown> } : {}),
|
|
168
|
+
...(payload.error !== undefined ? { error: payload.error } : {}),
|
|
169
|
+
...(payload.failureKind !== undefined ? { failureKind: payload.failureKind } : {}),
|
|
170
|
+
...(payload.failureMessage !== undefined ? { failureMessage: payload.failureMessage } : {}),
|
|
171
|
+
...(payload.failedStageId !== undefined ? { failedStageId: payload.failedStageId } : {}),
|
|
172
|
+
...(payload.resumable !== undefined ? { resumable: payload.resumable } : {}),
|
|
143
173
|
ts: payload.ts,
|
|
144
174
|
});
|
|
145
175
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* The renderer has two output modes:
|
|
12
12
|
*
|
|
13
13
|
* - **pretty** (default when a GraphTheme is supplied) — emits ANSI-coloured
|
|
14
|
-
* blocks that match the
|
|
14
|
+
* blocks that match the indented `INPUTS` aesthetic established in
|
|
15
15
|
* `src/tui/session-list.ts`. Drawn for any interactive surface where the
|
|
16
16
|
* terminal supports colour.
|
|
17
17
|
* - **plain** (used when no theme is supplied) — emits the
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* The layout in pretty mode mirrors flora131/atomic's `renderInputsText` so a
|
|
23
23
|
* dev moving between the atomic CLI and the pi extension feels at home:
|
|
24
24
|
*
|
|
25
|
-
*
|
|
25
|
+
* INPUTS FOR ralph
|
|
26
26
|
*
|
|
27
27
|
* prompt text · required
|
|
28
28
|
* The high-level task to plan and execute.
|
|
@@ -41,11 +41,12 @@
|
|
|
41
41
|
|
|
42
42
|
import type { GraphTheme } from "../tui/graph-theme.js";
|
|
43
43
|
import { paint } from "../tui/color-utils.js";
|
|
44
|
+
import { renderRoundedBox, chatWidth } from "../tui/chat-surface.js";
|
|
44
45
|
import { truncateToWidth } from "../tui/text-helpers.js";
|
|
45
46
|
import type { WorkflowInputEntry } from "../extension/render-result.js";
|
|
46
47
|
|
|
47
48
|
export interface RenderInputsSchemaOptions {
|
|
48
|
-
/** When provided, output uses ANSI colours and
|
|
49
|
+
/** When provided, output uses ANSI colours and indented `INPUTS` chrome. */
|
|
49
50
|
theme?: GraphTheme;
|
|
50
51
|
/** Optional host render width in terminal cells. */
|
|
51
52
|
width?: number;
|
|
@@ -61,49 +62,42 @@ export function renderInputsSchema(
|
|
|
61
62
|
inputs: WorkflowInputEntry[],
|
|
62
63
|
opts: RenderInputsSchemaOptions = {},
|
|
63
64
|
): string {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const rendered = opts.theme === undefined
|
|
68
|
-
? renderPlain(name, inputs)
|
|
69
|
-
: renderPretty(name, inputs, opts.theme);
|
|
70
|
-
return fitBlock(rendered, opts.width);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function fitBlock(block: string, width?: number): string {
|
|
74
|
-
if (width === undefined || width <= 0) return block;
|
|
75
|
-
return block
|
|
76
|
-
.split("\n")
|
|
77
|
-
.map((line) => truncateToWidth(line, width, "…"))
|
|
78
|
-
.join("\n");
|
|
65
|
+
return opts.theme === undefined
|
|
66
|
+
? renderPlain(name, inputs, opts.width)
|
|
67
|
+
: renderPretty(name, inputs, opts.theme, opts.width);
|
|
79
68
|
}
|
|
80
69
|
|
|
81
70
|
// ---------------------------------------------------------------------------
|
|
82
|
-
// Plain renderer —
|
|
83
|
-
// non-TTY consumers. Stable byte-for-byte so existing snapshots keep passing.
|
|
71
|
+
// Plain renderer — rounded, marker-free workflow-tool output without ANSI.
|
|
84
72
|
// ---------------------------------------------------------------------------
|
|
85
73
|
|
|
86
|
-
function renderPlain(name: string, inputs: WorkflowInputEntry[]): string {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
74
|
+
function renderPlain(name: string, inputs: WorkflowInputEntry[], width?: number): string {
|
|
75
|
+
const boxWidth = chatWidth(width);
|
|
76
|
+
const body: string[] = [];
|
|
77
|
+
|
|
78
|
+
if (inputs.length === 0) {
|
|
79
|
+
body.push(` Workflow has no declared inputs. Workflow: "${name}". `);
|
|
80
|
+
} else {
|
|
81
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
82
|
+
if (i > 0) body.push("");
|
|
83
|
+
body.push(...renderInputRows(inputs[i]!));
|
|
84
|
+
}
|
|
85
|
+
body.push("");
|
|
86
|
+
body.push(` ${inputsSummary(name, inputs)} `);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return renderRoundedBox({
|
|
90
|
+
title: `INPUTS FOR ${name}`,
|
|
91
|
+
bodyLines: body,
|
|
92
|
+
width: boxWidth,
|
|
97
93
|
});
|
|
98
|
-
return `Inputs for "${name}":\n${lines.join("\n")}`;
|
|
99
94
|
}
|
|
100
95
|
|
|
101
96
|
// ---------------------------------------------------------------------------
|
|
102
97
|
// Pretty renderer — ANSI-coloured, themed, matches the session-list aesthetic.
|
|
103
98
|
//
|
|
104
|
-
// Section labels lead with
|
|
105
|
-
//
|
|
106
|
-
// the eye scans the form top-to-bottom. The `required` tag is yellow
|
|
99
|
+
// Section labels lead with a two-cell indent and the field name is rendered
|
|
100
|
+
// bold-bright so the eye scans the form top-to-bottom. The `required` tag is yellow
|
|
107
101
|
// (theme.warning) — yellow draws attention to "you must fill this in"
|
|
108
102
|
// without being alarming the way red would.
|
|
109
103
|
// ---------------------------------------------------------------------------
|
|
@@ -112,100 +106,64 @@ function renderPretty(
|
|
|
112
106
|
name: string,
|
|
113
107
|
inputs: WorkflowInputEntry[],
|
|
114
108
|
theme: GraphTheme,
|
|
109
|
+
width?: number,
|
|
115
110
|
): string {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
// Section header — mauve indicator bar + bold caps label, matching
|
|
119
|
-
// session-list.ts. Includes the workflow name so the block is
|
|
120
|
-
// self-titling when printed inline in a chat surface.
|
|
121
|
-
out.push("");
|
|
122
|
-
out.push(
|
|
123
|
-
`${paint("▎", theme.mauve)} ${paint(
|
|
124
|
-
`INPUTS FOR ${name.toUpperCase()}`,
|
|
125
|
-
theme.textMuted,
|
|
126
|
-
{ bold: true },
|
|
127
|
-
)}`,
|
|
128
|
-
);
|
|
129
|
-
out.push("");
|
|
130
|
-
|
|
131
|
-
// Compute a stable left column for the name so types/required tags
|
|
132
|
-
// line up vertically — the form should *look* like a form, not a
|
|
133
|
-
// ragged paragraph. Cap at 24 chars so a stray long input name
|
|
134
|
-
// doesn't push everything off the right edge.
|
|
135
|
-
const nameWidth = Math.min(
|
|
136
|
-
24,
|
|
137
|
-
Math.max(...inputs.map((i) => i.name.length)),
|
|
138
|
-
);
|
|
139
|
-
const dimDot = paint(" · ", theme.dim);
|
|
140
|
-
|
|
141
|
-
for (const field of inputs) {
|
|
142
|
-
const namePad = field.name.padEnd(nameWidth);
|
|
143
|
-
const tagColour = field.required ? theme.warning : theme.dim;
|
|
144
|
-
const tagLabel = field.required ? "required" : "optional";
|
|
145
|
-
|
|
146
|
-
// Row 1: name · type · required|optional
|
|
147
|
-
out.push(
|
|
148
|
-
" " +
|
|
149
|
-
paint(namePad, theme.text, { bold: true }) +
|
|
150
|
-
" " +
|
|
151
|
-
paint(field.type, theme.dim) +
|
|
152
|
-
dimDot +
|
|
153
|
-
paint(tagLabel, tagColour),
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
// Row 2: description (when present)
|
|
157
|
-
if (field.description) {
|
|
158
|
-
out.push(" " + paint(field.description, theme.textMuted));
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Row 3: choices for selects — dot-separator style so the values
|
|
162
|
-
// read as a clear closed set.
|
|
163
|
-
if (field.choices && field.choices.length > 0) {
|
|
164
|
-
const joined = field.choices
|
|
165
|
-
.map((v) => paint(v, theme.text))
|
|
166
|
-
.join(dimDot);
|
|
167
|
-
out.push(" " + paint("values: ", theme.dim) + joined);
|
|
168
|
-
}
|
|
111
|
+
const boxWidth = chatWidth(width);
|
|
112
|
+
const body: string[] = [];
|
|
169
113
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
);
|
|
114
|
+
if (inputs.length === 0) {
|
|
115
|
+
body.push(` ${paint(`Workflow has no declared inputs. Workflow: "${name}".`, theme.dim)} `);
|
|
116
|
+
} else {
|
|
117
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
118
|
+
if (i > 0) body.push("");
|
|
119
|
+
body.push(...renderInputRows(inputs[i]!, theme));
|
|
177
120
|
}
|
|
121
|
+
body.push("");
|
|
122
|
+
body.push(` ${paint(inputsSummary(name, inputs), theme.dim)} `);
|
|
123
|
+
}
|
|
178
124
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
125
|
+
return renderRoundedBox({
|
|
126
|
+
title: `INPUTS FOR ${name.toUpperCase()}`,
|
|
127
|
+
bodyLines: body,
|
|
128
|
+
accent: theme.mauve,
|
|
129
|
+
theme,
|
|
130
|
+
width: boxWidth,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
187
133
|
|
|
188
|
-
|
|
134
|
+
function renderInputRows(
|
|
135
|
+
field: WorkflowInputEntry,
|
|
136
|
+
theme?: GraphTheme,
|
|
137
|
+
): string[] {
|
|
138
|
+
const tagLabel = field.required ? "required" : "optional";
|
|
139
|
+
const heading = theme
|
|
140
|
+
? ` ${paint(field.name, theme.text, { bold: true })} ${paint(field.type, theme.dim)} · ${paint(tagLabel, field.required ? theme.warning : theme.dim)} `
|
|
141
|
+
: ` ${field.name} ${field.type} · ${tagLabel} `;
|
|
142
|
+
const lines: string[] = [heading];
|
|
143
|
+
|
|
144
|
+
if (field.description) {
|
|
145
|
+
lines.push(` ${theme ? paint(field.description, theme.textMuted) : field.description} `);
|
|
146
|
+
}
|
|
147
|
+
if (field.choices && field.choices.length > 0) {
|
|
148
|
+
const values = field.choices.join(" · ");
|
|
149
|
+
lines.push(` ${theme ? paint("values: ", theme.dim) + paint(values, theme.text) : `values: ${values}`} `);
|
|
150
|
+
}
|
|
151
|
+
if (field.default !== undefined) {
|
|
152
|
+
const value = JSON.stringify(field.default);
|
|
153
|
+
lines.push(` ${theme ? paint("default: ", theme.dim) + paint(value, theme.text) : `default: ${value}`} `);
|
|
154
|
+
}
|
|
155
|
+
if (field.placeholder) {
|
|
156
|
+
lines.push(` ${theme ? paint("placeholder: ", theme.dim) + paint(field.placeholder, theme.textMuted) : `placeholder: ${field.placeholder}`} `);
|
|
189
157
|
}
|
|
190
158
|
|
|
191
|
-
|
|
192
|
-
|
|
159
|
+
return lines;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function inputsSummary(name: string, inputs: readonly WorkflowInputEntry[]): string {
|
|
193
163
|
const required = inputs.filter((i) => i.required).length;
|
|
194
164
|
const total = inputs.length;
|
|
195
165
|
const totalLabel = `${total} input${total === 1 ? "" : "s"}`;
|
|
196
166
|
const reqLabel = `${required} required`;
|
|
197
|
-
|
|
198
|
-
" " +
|
|
199
|
-
paint(totalLabel, theme.dim) +
|
|
200
|
-
dimDot +
|
|
201
|
-
paint(reqLabel, theme.dim) +
|
|
202
|
-
dimDot +
|
|
203
|
-
paint(
|
|
204
|
-
`pass via key=value or run \`/workflow ${name}\` with no args for picker`,
|
|
205
|
-
theme.dim,
|
|
206
|
-
),
|
|
207
|
-
);
|
|
208
|
-
out.push("");
|
|
209
|
-
|
|
210
|
-
return out.join("\n");
|
|
167
|
+
return `${totalLabel} · ${reqLabel} · pass via key=value or run \`/workflow ${name}\` with no args for picker`;
|
|
211
168
|
}
|
|
169
|
+
|