@bastani/atomic 0.8.13 → 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 +11 -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
|
@@ -1,42 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Renderer for the inline chat-history workflow form.
|
|
3
3
|
*
|
|
4
|
-
* Identity mirrors the
|
|
5
|
-
* -
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
11
|
-
* - 3-row mantle chrome footer with the `EDIT` mode pill and hints
|
|
12
|
-
* anchored at the bottom of the widget.
|
|
4
|
+
* Identity mirrors the multi ask_user_question dialog:
|
|
5
|
+
* - Top/bottom dynamic border rules wrap the live form.
|
|
6
|
+
* - A compact tab row shows each input (`■` valid / `□` missing) plus Submit,
|
|
7
|
+
* matching the multi-question tab bar affordance.
|
|
8
|
+
* - Every declared input is rendered on one page as a question block.
|
|
9
|
+
* - The focused field owns the ask-style pointer/caret.
|
|
10
|
+
* - Footer hints sit below the bottom rule, like ask_user_question hints.
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* ╰──────────╯
|
|
12
|
+
* ───────────────────────────────────────────────────────────────────
|
|
13
|
+
* ← □ prompt ■ iters ✓ Submit →
|
|
17
14
|
*
|
|
18
|
-
*
|
|
19
|
-
* │ build me a TUI for arg-pickers │
|
|
20
|
-
* ╰──────────────────────────────────────────────────────────────────╯
|
|
21
|
-
* text · required · task prompt
|
|
15
|
+
* task prompt
|
|
22
16
|
*
|
|
23
|
-
*
|
|
24
|
-
* │ 5 │
|
|
25
|
-
* ╰──────────────────────────────────────────────────────────────────╯
|
|
26
|
-
* integer · optional · loop count
|
|
17
|
+
* ❯ 1. build me a TUI for arg-pickers
|
|
27
18
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* ╰──────╯
|
|
19
|
+
* ───────────────────────────────────────────────────────────────────
|
|
20
|
+
* Enter to select · ↑/↓ to navigate · Tab to switch input fields · Esc to cancel
|
|
31
21
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
22
|
+
* Submitted forms become a single-line ledger entry in scrollback. Cancelled
|
|
23
|
+
* forms render no rows so cancellation leaves no chat artefact.
|
|
34
24
|
*
|
|
35
25
|
* The card never owns keystrokes — keystrokes are routed by the editor.
|
|
36
26
|
* `renderInlineCard` is a pure function of `state + theme + width`.
|
|
37
27
|
*
|
|
38
28
|
* cross-ref:
|
|
39
|
-
* - src/
|
|
29
|
+
* - packages/coding-agent/src/core/tools/ask-user-question/view/dialog-builder.ts
|
|
40
30
|
* - src/tui/node-card.ts (centred title-in-border pattern)
|
|
41
31
|
* - src/tui/graph-view.ts (statusline + chrome band composition)
|
|
42
32
|
*/
|
|
@@ -44,10 +34,18 @@
|
|
|
44
34
|
import type { InlineFormState } from "./inline-form-store.js";
|
|
45
35
|
import type { WorkflowInputEntry } from "../extension/render-result.js";
|
|
46
36
|
import type { GraphTheme } from "./graph-theme.js";
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
37
|
+
import { computeInvalid } from "./inputs-picker.js";
|
|
38
|
+
import { paint } from "./color-utils.js";
|
|
39
|
+
import { renderCompactBandHeader } from "./header.js";
|
|
40
|
+
import {
|
|
41
|
+
truncateToWidth,
|
|
42
|
+
visibleWidth,
|
|
43
|
+
wrapPlainText,
|
|
44
|
+
} from "./text-helpers.js";
|
|
45
|
+
import {
|
|
46
|
+
renderAskChoiceRows,
|
|
47
|
+
renderSubmitControls,
|
|
48
|
+
} from "./submit-pane.js";
|
|
51
49
|
|
|
52
50
|
export interface InlineCardOpts {
|
|
53
51
|
width: number;
|
|
@@ -111,7 +109,7 @@ function tailToWidth(text: string, width: number): string {
|
|
|
111
109
|
export function renderInlineCard(opts: InlineCardOpts): string[] {
|
|
112
110
|
const { state, theme, width } = opts;
|
|
113
111
|
if (state.status === "submitted") return [fitLine(renderSubmittedLine(state, theme), width)];
|
|
114
|
-
if (state.status === "cancelled") return [
|
|
112
|
+
if (state.status === "cancelled") return [];
|
|
115
113
|
return renderEditingCard(opts).map((line) => fitLine(line, width));
|
|
116
114
|
}
|
|
117
115
|
|
|
@@ -119,24 +117,17 @@ function renderEditingCard(opts: InlineCardOpts): string[] {
|
|
|
119
117
|
const { state, theme, width } = opts;
|
|
120
118
|
const lines: string[] = [];
|
|
121
119
|
|
|
122
|
-
lines.push(...
|
|
123
|
-
if (state.description) {
|
|
124
|
-
lines.push(" " + paint(state.description, theme.textMuted));
|
|
125
|
-
}
|
|
120
|
+
lines.push(...renderWorkflowHeader(state.workflowName, state.fields.length, state.focusedIdx, theme, width));
|
|
126
121
|
lines.push("");
|
|
127
122
|
|
|
128
|
-
for (let i = 0; i < state.fields.length; i
|
|
129
|
-
const
|
|
130
|
-
const raw = state.rawText[
|
|
131
|
-
|
|
132
|
-
// Don't paint a focused field as invalid — the caret is already on it,
|
|
133
|
-
// the user is fixing it now.
|
|
134
|
-
const invalid = focused ? null : invalidForField(f, raw, i);
|
|
135
|
-
lines.push(...renderFieldCard(f, raw, focused, invalid, theme, width, focused ? state.caret : undefined));
|
|
123
|
+
for (let i = 0; i < state.fields.length; i += 1) {
|
|
124
|
+
const field = state.fields[i]!;
|
|
125
|
+
const raw = state.rawText[field.name] ?? "";
|
|
126
|
+
lines.push(...renderField(field, raw, state.caret, state.focusedIdx === i, theme, width));
|
|
136
127
|
lines.push("");
|
|
137
128
|
}
|
|
138
129
|
|
|
139
|
-
lines.push(...renderFooterBand(theme, width));
|
|
130
|
+
lines.push(...renderFooterBand(state, theme, width));
|
|
140
131
|
return lines;
|
|
141
132
|
}
|
|
142
133
|
|
|
@@ -144,215 +135,148 @@ function renderEditingCard(opts: InlineCardOpts): string[] {
|
|
|
144
135
|
// Header / footer chrome bands
|
|
145
136
|
// ---------------------------------------------------------------------------
|
|
146
137
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const focusTargetCount = state.fields.length;
|
|
163
|
-
const counter = `${Math.min(state.focusedIdx + 1, focusTargetCount)} / ${focusTargetCount}`;
|
|
164
|
-
const counterVisible = counter;
|
|
165
|
-
|
|
166
|
-
const leftEdgePad = 1;
|
|
167
|
-
const rightEdgePad = 2;
|
|
168
|
-
const fillerVisible = Math.max(
|
|
169
|
-
1,
|
|
170
|
-
width - leftEdgePad - pillW - nameVisible.length - counterVisible.length - rightEdgePad,
|
|
171
|
-
);
|
|
172
|
-
const blankAcross = " ".repeat(nameVisible.length + fillerVisible + counterVisible.length + rightEdgePad);
|
|
173
|
-
|
|
174
|
-
return [
|
|
175
|
-
`${chromeBg} ${RESET}${top}${chromeBg}${blankAcross}${RESET}`,
|
|
176
|
-
`${chromeBg} ${RESET}${mid}${chromeBg} ${muted}${state.workflowName}${RESET}${chromeBg}${" ".repeat(fillerVisible)}${dim}${counter}${RESET}${chromeBg}${" ".repeat(rightEdgePad)}${RESET}`,
|
|
177
|
-
`${chromeBg} ${RESET}${bot}${chromeBg}${blankAcross}${RESET}`,
|
|
178
|
-
];
|
|
138
|
+
function renderWorkflowHeader(
|
|
139
|
+
workflowName: string,
|
|
140
|
+
fieldCount: number,
|
|
141
|
+
focusedIdx: number,
|
|
142
|
+
theme: GraphTheme,
|
|
143
|
+
width: number,
|
|
144
|
+
): string[] {
|
|
145
|
+
const current = Math.min(fieldCount, Math.max(1, focusedIdx + 1));
|
|
146
|
+
return renderCompactBandHeader({
|
|
147
|
+
label: "WORKFLOW",
|
|
148
|
+
subtitle: workflowName,
|
|
149
|
+
badges: fieldCount > 0 ? [{ text: `${current} / ${fieldCount}`, fg: theme.dim }] : [],
|
|
150
|
+
width,
|
|
151
|
+
theme,
|
|
152
|
+
});
|
|
179
153
|
}
|
|
180
154
|
|
|
181
|
-
function renderFooterBand(theme: GraphTheme, width: number): string[] {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const { top, mid, bot, visibleWidth: pillW } = renderOutlinePill(
|
|
186
|
-
FOOTER_PILL_LABEL,
|
|
187
|
-
theme.accent,
|
|
188
|
-
chromeBg,
|
|
189
|
-
);
|
|
155
|
+
function renderFooterBand(state: InlineFormState, theme: GraphTheme, width: number): string[] {
|
|
156
|
+
return renderInlineSubmitControls(state, theme, width);
|
|
157
|
+
}
|
|
190
158
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
{ key: "tab", label: "Next" },
|
|
195
|
-
{ key: "shift+tab", label: "Prev" },
|
|
196
|
-
{ key: "ctrl+x", label: "Run" },
|
|
197
|
-
{ key: "esc", label: "Cancel" },
|
|
198
|
-
];
|
|
199
|
-
const sep = `${chromeBg} ${dim}·${RESET}${chromeBg} `;
|
|
200
|
-
const segments = hints.map(
|
|
201
|
-
({ key, label }) =>
|
|
202
|
-
`${text}${BOLD}${key}${RESET}${chromeBg} ${muted}${label}${RESET}${chromeBg}`,
|
|
203
|
-
);
|
|
204
|
-
const hintsStyled = segments.join(sep);
|
|
205
|
-
const hintsVisible =
|
|
206
|
-
hints.reduce((sum, h) => sum + h.key.length + 1 + h.label.length, 0) +
|
|
207
|
-
(hints.length - 1) * 5;
|
|
208
|
-
|
|
209
|
-
const leftEdgePad = 1;
|
|
210
|
-
const leadGap = 2; // gap between pill and hints, matching graph statusline
|
|
211
|
-
const rightEdgePad = 2;
|
|
212
|
-
const tailFiller = Math.max(
|
|
213
|
-
0,
|
|
214
|
-
width - leftEdgePad - pillW - leadGap - hintsVisible - rightEdgePad,
|
|
215
|
-
);
|
|
216
|
-
const blankAcross = " ".repeat(leadGap + hintsVisible + tailFiller + rightEdgePad);
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Field body (ask_user_question-style list/input rows)
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
217
162
|
|
|
163
|
+
function renderField(
|
|
164
|
+
field: WorkflowInputEntry,
|
|
165
|
+
raw: string,
|
|
166
|
+
caret: number,
|
|
167
|
+
focused: boolean,
|
|
168
|
+
theme: GraphTheme,
|
|
169
|
+
width: number,
|
|
170
|
+
): string[] {
|
|
171
|
+
const boxWidth = Math.max(4, width);
|
|
172
|
+
const contentWidth = Math.max(1, boxWidth - 2);
|
|
173
|
+
const borderColor = focused ? theme.accent : theme.borderDim;
|
|
174
|
+
const rows = renderAskStyleFieldBody(field, raw, focused ? caret : raw.length, focused, theme, contentWidth);
|
|
218
175
|
return [
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
176
|
+
renderFieldTop(field.name, boxWidth, borderColor, focused, theme),
|
|
177
|
+
...rows.map((row) => renderFieldRow(row, contentWidth, borderColor)),
|
|
178
|
+
renderFieldBottom(boxWidth, borderColor),
|
|
179
|
+
...renderFieldMeta(field, theme, width),
|
|
222
180
|
];
|
|
223
181
|
}
|
|
224
182
|
|
|
225
|
-
|
|
226
|
-
// Field card (orchestrator node-card identity: centred title in top border)
|
|
227
|
-
// ---------------------------------------------------------------------------
|
|
228
|
-
|
|
229
|
-
function renderFieldCard(
|
|
183
|
+
function renderAskStyleFieldBody(
|
|
230
184
|
field: WorkflowInputEntry,
|
|
231
185
|
raw: string,
|
|
186
|
+
caret: number,
|
|
232
187
|
focused: boolean,
|
|
233
|
-
invalid: string | null,
|
|
234
188
|
theme: GraphTheme,
|
|
235
189
|
width: number,
|
|
236
|
-
caret?: number,
|
|
237
190
|
): string[] {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
? theme
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
`${bc}╭${leadDashes}` +
|
|
255
|
-
`${BOLD}${hexToAnsi(titleHex)}${titleRaw}${RESET}${bc}` +
|
|
256
|
-
`${tailDashes}╮${RESET}`;
|
|
257
|
-
const bottom = `${bc}╰${"─".repeat(inner)}╯${RESET}`;
|
|
258
|
-
|
|
259
|
-
const contentLines = renderFieldContent(field, raw, focused, usable, theme, caret).map(
|
|
260
|
-
(row) => `${bc}│${RESET} ${row}${" ".repeat(Math.max(0, usable - visibleWidth(row)))} ${bc}│${RESET}`,
|
|
261
|
-
);
|
|
191
|
+
if (field.type === "select" && field.choices && field.choices.length > 0) {
|
|
192
|
+
const selected = Math.max(0, field.choices.indexOf(raw));
|
|
193
|
+
return field.choices.flatMap((choice, i) =>
|
|
194
|
+
renderAskChoiceRows(i + 1, focused || i !== selected ? choice : `✓ ${choice}`, focused && i === selected, theme, width),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (field.type === "boolean") {
|
|
199
|
+
const normalized = raw.trim().toLowerCase();
|
|
200
|
+
const hasValue = normalized.length > 0;
|
|
201
|
+
const on = normalized === "true" || normalized === "1";
|
|
202
|
+
return [
|
|
203
|
+
...renderAskChoiceRows(1, focused || !hasValue || !on ? "on" : "✓ on", focused && hasValue && on, theme, width),
|
|
204
|
+
...renderAskChoiceRows(2, focused || !hasValue || on ? "off" : "✓ off", focused && hasValue && !on, theme, width),
|
|
205
|
+
];
|
|
206
|
+
}
|
|
262
207
|
|
|
263
|
-
|
|
264
|
-
|
|
208
|
+
return renderAskInputRows(raw, caret, focused, field.placeholder, theme, width);
|
|
209
|
+
}
|
|
265
210
|
|
|
266
|
-
|
|
211
|
+
function renderInlineSubmitControls(state: InlineFormState, theme: GraphTheme, width: number): string[] {
|
|
212
|
+
const invalid = computeInvalid(state.fields, state.rawText);
|
|
213
|
+
return renderSubmitControls({
|
|
214
|
+
invalidFieldNames: invalid.map((i) => state.fields[i]!.name),
|
|
215
|
+
submitFocused: state.focusedIdx === state.fields.length,
|
|
216
|
+
theme,
|
|
217
|
+
width,
|
|
218
|
+
});
|
|
267
219
|
}
|
|
268
220
|
|
|
269
|
-
function
|
|
270
|
-
|
|
271
|
-
|
|
221
|
+
function renderFieldTop(
|
|
222
|
+
title: string,
|
|
223
|
+
width: number,
|
|
224
|
+
borderColor: string,
|
|
225
|
+
focused: boolean,
|
|
272
226
|
theme: GraphTheme,
|
|
273
227
|
): string {
|
|
274
|
-
const
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
? theme.warning
|
|
279
|
-
: theme.dim;
|
|
280
|
-
const tagLabel = invalid ?? (field.required ? "required" : "optional");
|
|
281
|
-
const desc = field.description
|
|
282
|
-
? sep + paint(field.description, theme.dim)
|
|
283
|
-
: "";
|
|
284
|
-
return (
|
|
285
|
-
" " +
|
|
286
|
-
paint(field.type, theme.dim) +
|
|
287
|
-
sep +
|
|
288
|
-
paint(tagLabel, tagColor) +
|
|
289
|
-
desc
|
|
290
|
-
);
|
|
228
|
+
const label = ` ${title} `;
|
|
229
|
+
const labelText = paint(label, focused ? theme.accent : theme.textMuted, { bold: focused });
|
|
230
|
+
const fill = Math.max(0, width - visibleWidth(label) - 2);
|
|
231
|
+
return paint("╭", borderColor) + labelText + paint("─".repeat(fill) + "╮", borderColor);
|
|
291
232
|
}
|
|
292
233
|
|
|
293
|
-
function
|
|
294
|
-
|
|
234
|
+
function renderFieldRow(row: string, contentWidth: number, borderColor: string): string {
|
|
235
|
+
const clipped = truncateToWidth(row, contentWidth, "", true);
|
|
236
|
+
const padded = clipped + " ".repeat(Math.max(0, contentWidth - visibleWidth(clipped)));
|
|
237
|
+
return paint("│", borderColor) + padded + paint("│", borderColor);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function renderFieldBottom(width: number, borderColor: string): string {
|
|
241
|
+
return paint("╰" + "─".repeat(Math.max(0, width - 2)) + "╯", borderColor);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function renderFieldMeta(field: WorkflowInputEntry, theme: GraphTheme, width: number): string[] {
|
|
245
|
+
const required = field.required ? "required" : "optional";
|
|
246
|
+
const text = field.description && field.description.length > 0
|
|
247
|
+
? `${field.type} · ${required} · ${field.description}`
|
|
248
|
+
: `${field.type} · ${required}`;
|
|
249
|
+
return wrapPlainText(text, width).map((line) => paintRequiredMetaLine(line, field.required === true, theme));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function paintRequiredMetaLine(line: string, required: boolean, theme: GraphTheme): string {
|
|
253
|
+
if (!required) return paint(line, theme.textMuted);
|
|
254
|
+
return line
|
|
255
|
+
.split(/(\brequired\b)/g)
|
|
256
|
+
.map((part) => part === "required" ? paint(part, theme.warning) : paint(part, theme.textMuted))
|
|
257
|
+
.join("");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function renderAskInputRows(
|
|
295
261
|
raw: string,
|
|
262
|
+
caret: number,
|
|
296
263
|
focused: boolean,
|
|
297
|
-
|
|
264
|
+
placeholder: string | undefined,
|
|
298
265
|
theme: GraphTheme,
|
|
299
|
-
|
|
266
|
+
width: number,
|
|
300
267
|
): string[] {
|
|
301
|
-
|
|
302
|
-
const cells = field.choices.map((c) => {
|
|
303
|
-
const sel = c === raw;
|
|
304
|
-
const dot = sel
|
|
305
|
-
? paint("●", focused ? theme.accent : theme.success)
|
|
306
|
-
: paint("○", theme.dim);
|
|
307
|
-
const lbl = sel
|
|
308
|
-
? paint(c, focused ? theme.text : theme.textMuted)
|
|
309
|
-
: paint(c, theme.dim);
|
|
310
|
-
return dot + " " + lbl;
|
|
311
|
-
});
|
|
312
|
-
return [clip(cells.join(" "), usable)];
|
|
313
|
-
}
|
|
314
|
-
if (field.type === "boolean") {
|
|
315
|
-
const on = raw === "true";
|
|
316
|
-
const onCell =
|
|
317
|
-
paint(on ? "●" : "○", on ? theme.accent : theme.dim) +
|
|
318
|
-
" " +
|
|
319
|
-
paint("on", on ? theme.text : theme.dim);
|
|
320
|
-
const offCell =
|
|
321
|
-
paint(!on ? "●" : "○", !on ? theme.accent : theme.dim) +
|
|
322
|
-
" " +
|
|
323
|
-
paint("off", !on ? theme.text : theme.dim);
|
|
324
|
-
return [clip(onCell + " " + offCell, usable)];
|
|
325
|
-
}
|
|
326
|
-
// string / number / integer — single-line scalar input.
|
|
327
|
-
if (field.type !== "text") {
|
|
328
|
-
if (raw === "") {
|
|
329
|
-
if (focused) return [paint("▋", theme.accent)];
|
|
330
|
-
return [paint(field.placeholder ?? "", theme.dim)];
|
|
331
|
-
}
|
|
332
|
-
if (focused) {
|
|
333
|
-
return [renderCaretLine(raw, caret ?? raw.length, usable, theme, theme.text)];
|
|
334
|
-
}
|
|
335
|
-
return [clip(paint(raw, theme.textMuted), usable)];
|
|
336
|
-
}
|
|
337
|
-
// text — multi-line prompt-box input. Newlines render as actual visual
|
|
338
|
-
// line breaks (no more `⏎` glyph) and long single lines wrap at the
|
|
339
|
-
// field's usable width. The box height grows to fit every visual row
|
|
340
|
-
// so the user sees their whole prompt; the surrounding card already
|
|
341
|
-
// lives in chat scrollback so vertical space is not at a premium.
|
|
268
|
+
const usable = Math.max(1, width);
|
|
342
269
|
if (raw === "") {
|
|
343
|
-
|
|
344
|
-
|
|
270
|
+
const value = placeholder && placeholder.length > 0
|
|
271
|
+
? paint(placeholder, theme.dim) + (focused ? cursorBlock() : "")
|
|
272
|
+
: focused ? cursorBlock() : "";
|
|
273
|
+
return [truncateToWidth(value, usable, "…", true)];
|
|
345
274
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
if (row !== layout.cursorRow) {
|
|
352
|
-
return paint(line, theme.text);
|
|
353
|
-
}
|
|
354
|
-
return renderCaretLine(line, layout.cursorOffset ?? line.length, usable, theme, theme.text);
|
|
355
|
-
});
|
|
275
|
+
|
|
276
|
+
const layout = layoutTextField(raw, usable, caret);
|
|
277
|
+
return layout.lines.map((line, row) => focused && row === layout.cursorRow
|
|
278
|
+
? renderCaretLine(line, layout.cursorOffset ?? line.length, usable, theme, theme.text)
|
|
279
|
+
: truncateToWidth(paint(line, theme.text), usable, "…", true));
|
|
356
280
|
}
|
|
357
281
|
|
|
358
282
|
function renderCaretLine(
|
|
@@ -365,14 +289,17 @@ function renderCaretLine(
|
|
|
365
289
|
const safe = clampGraphemeOffset(raw, caret);
|
|
366
290
|
const beforeFull = raw.slice(0, safe);
|
|
367
291
|
const afterFull = raw.slice(safe);
|
|
368
|
-
const
|
|
292
|
+
const [at = ""] = graphemes(afterFull);
|
|
293
|
+
const afterRest = at === "" ? "" : afterFull.slice(at.length);
|
|
294
|
+
const cursorPlain = at !== "" ? at : " ";
|
|
295
|
+
const cursorWidth = Math.max(1, visibleWidth(cursorPlain));
|
|
369
296
|
let before = beforeFull;
|
|
370
|
-
let after =
|
|
371
|
-
if (visibleWidth(beforeFull) + cursorWidth + visibleWidth(
|
|
297
|
+
let after = afterRest;
|
|
298
|
+
if (visibleWidth(beforeFull) + cursorWidth + visibleWidth(afterRest) > usable) {
|
|
372
299
|
before = tailToWidth(beforeFull, Math.max(0, usable - cursorWidth));
|
|
373
|
-
after = headToWidth(
|
|
300
|
+
after = headToWidth(afterRest, Math.max(0, usable - visibleWidth(before) - cursorWidth));
|
|
374
301
|
}
|
|
375
|
-
return clip(paint(before, color) +
|
|
302
|
+
return clip(paint(before, color) + cursorBlock(cursorPlain) + paint(after, color), usable);
|
|
376
303
|
}
|
|
377
304
|
|
|
378
305
|
// ---------------------------------------------------------------------------
|
|
@@ -387,14 +314,6 @@ function renderSubmittedLine(state: InlineFormState, theme: GraphTheme): string
|
|
|
387
314
|
);
|
|
388
315
|
}
|
|
389
316
|
|
|
390
|
-
function renderCancelledLine(state: InlineFormState, theme: GraphTheme): string {
|
|
391
|
-
return (
|
|
392
|
-
paint("✗ cancelled", theme.dim) +
|
|
393
|
-
paint(" · ", theme.dim) +
|
|
394
|
-
paint(state.workflowName, theme.textMuted)
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
317
|
function composeCommand(state: InlineFormState): string {
|
|
399
318
|
const parts: string[] = [`/workflow ${state.workflowName}`];
|
|
400
319
|
for (const f of state.fields) {
|
|
@@ -418,6 +337,10 @@ function clip(ansi: string, budget: number): string {
|
|
|
418
337
|
return truncateToWidth(ansi, Math.max(0, budget), "…", true);
|
|
419
338
|
}
|
|
420
339
|
|
|
340
|
+
function cursorBlock(text = " "): string {
|
|
341
|
+
return `\x1b[7m${text}\x1b[0m`;
|
|
342
|
+
}
|
|
343
|
+
|
|
421
344
|
/**
|
|
422
345
|
* Lay out a multi-line text field into visual rows while tracking where the
|
|
423
346
|
* caret should appear on screen. Newlines (`\n`) always start a new visual
|