@bastani/atomic 0.8.28-alpha.1 → 0.8.28-alpha.2
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 +53 -0
- package/README.md +120 -118
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +8 -0
- package/dist/builtin/workflows/builtin/open-claude-design.ts +150 -13
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/tui/chat-surface.ts +32 -33
- package/dist/builtin/workflows/src/tui/run-detail.ts +11 -4
- package/dist/builtin/workflows/src/tui/status-list.ts +32 -2
- package/dist/cli/args.d.ts +4 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +35 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/project-trust.d.ts +10 -0
- package/dist/cli/project-trust.d.ts.map +1 -0
- package/dist/cli/project-trust.js +36 -0
- package/dist/cli/project-trust.js.map +1 -0
- package/dist/cli/startup-ui.d.ts +7 -0
- package/dist/cli/startup-ui.d.ts.map +1 -0
- package/dist/cli/startup-ui.js +57 -0
- package/dist/cli/startup-ui.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +24 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +3 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +1 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +2 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +5 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +58 -20
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +4 -3
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +3 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +9 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +18 -24
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/experimental.d.ts +2 -0
- package/dist/core/experimental.d.ts.map +1 -0
- package/dist/core/experimental.js +5 -0
- package/dist/core/experimental.js.map +1 -0
- package/dist/core/export-html/template.js +19 -6
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -4
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +11 -4
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +53 -3
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +34 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +2 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +27 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +64 -7
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +1 -0
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js +52 -22
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +20 -8
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/project-trust.d.ts +15 -0
- package/dist/core/project-trust.d.ts.map +1 -0
- package/dist/core/project-trust.js +58 -0
- package/dist/core/project-trust.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +5 -4
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +30 -29
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-attribution.d.ts +4 -0
- package/dist/core/provider-attribution.d.ts.map +1 -0
- package/dist/core/provider-attribution.js +73 -0
- package/dist/core/provider-attribution.js.map +1 -0
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +3 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +9 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +134 -11
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +12 -2
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +108 -18
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +12 -42
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -7
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +99 -35
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +15 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +69 -10
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +0 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +7 -10
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/oversized-tool-result.d.ts +53 -0
- package/dist/core/tools/oversized-tool-result.d.ts.map +1 -0
- package/dist/core/tools/oversized-tool-result.js +206 -0
- package/dist/core/tools/oversized-tool-result.js.map +1 -0
- package/dist/core/tools/read.d.ts +12 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +99 -34
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +6 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +17 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +6 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +2 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/tool-limits.d.ts +25 -0
- package/dist/core/tools/tool-limits.d.ts.map +1 -0
- package/dist/core/tools/tool-limits.js +25 -0
- package/dist/core/tools/tool-limits.js.map +1 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts +31 -0
- package/dist/core/trust-manager.d.ts.map +1 -0
- package/dist/core/trust-manager.js +196 -0
- package/dist/core/trust-manager.js.map +1 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +142 -30
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +3 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +325 -7
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -2
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +6 -0
- 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 +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +9 -16
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +22 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/trust-selector.js +85 -0
- package/dist/modes/interactive/components/trust-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +1 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +130 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +10 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +1 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +3 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +50 -6
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +23 -4
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +1 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +6 -2
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +104 -10
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/changelog.d.ts +1 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +72 -0
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +54 -22
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +22 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/docs/containerization.md +111 -0
- package/docs/custom-provider.md +9 -9
- package/docs/development.md +1 -1
- package/docs/docs.json +2 -0
- package/docs/extensions.md +40 -4
- package/docs/index.md +2 -0
- package/docs/models.md +10 -10
- package/docs/packages.md +1 -1
- package/docs/prompt-templates.md +9 -2
- package/docs/providers.md +18 -5
- package/docs/quickstart.md +1 -0
- package/docs/rpc.md +3 -2
- package/docs/sdk.md +5 -0
- package/docs/security.md +56 -0
- package/docs/session-format.md +2 -2
- package/docs/sessions.md +8 -0
- package/docs/settings.md +21 -4
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +44 -2
- package/docs/themes.md +1 -1
- package/docs/tmux.md +4 -2
- package/docs/tui.md +14 -5
- package/docs/usage.md +17 -3
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +8 -5
- package/examples/extensions/bash-spawn-hook.ts +1 -1
- package/examples/extensions/built-in-tool-renderer.ts +1 -1
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/custom-header.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
- package/examples/extensions/custom-provider-anthropic/package.json +6 -6
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +55 -4
- package/examples/extensions/custom-provider-gitlab-duo/package.json +3 -3
- package/examples/extensions/doom-overlay/README.md +1 -1
- package/examples/extensions/doom-overlay/index.ts +2 -2
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/gondolin/index.ts +523 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +2 -2
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +3 -3
- package/examples/extensions/interactive-shell.ts +2 -2
- package/examples/extensions/mac-system-theme.ts +2 -2
- package/examples/extensions/minimal-mode.ts +1 -1
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/overlay-qa-tests.ts +198 -179
- package/examples/extensions/overlay-test.ts +1 -1
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/preset.ts +14 -12
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/qna.ts +1 -1
- package/examples/extensions/question.ts +1 -1
- package/examples/extensions/questionnaire.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/sandbox/index.ts +16 -14
- package/examples/extensions/sandbox/package-lock.json +90 -90
- package/examples/extensions/sandbox/package.json +17 -17
- package/examples/extensions/snake.ts +1 -1
- package/examples/extensions/space-invaders.ts +1 -1
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/subagent/README.md +13 -13
- package/examples/extensions/subagent/agents.ts +4 -2
- package/examples/extensions/subagent/index.ts +6 -6
- package/examples/extensions/summarize.ts +1 -1
- package/examples/extensions/tic-tac-toe.ts +1 -1
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/todo.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +6 -1
- package/examples/extensions/with-deps/package-lock.json +4 -4
- package/examples/extensions/with-deps/package.json +7 -7
- package/examples/extensions/working-indicator.ts +4 -4
- package/examples/extensions/working-message-test.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/03-custom-prompt.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/06-extensions.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
- package/examples/sdk/README.md +2 -2
- package/package.json +4 -4
|
@@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.8.28-alpha.2] - 2026-06-10
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed the builtin `open-claude-design` workflow not installing the browser skill's `browse` CLI before it is needed. The workflow now runs an initial deterministic, best-effort setup step that probes `PATH` (`which`/`where browse`) and installs the CLI with `npm install -g browse` when missing (skipped under automated tests); per-run bootstrap guidance is derived from the outcome and injected into every browser-using stage (assume-available when ensured, with concrete recovery steps surfaced when the install failed), the install outcome is exposed via a new `browse_cli_status` output, and the read-only `read`/`grep`/`ls` tools are granted to the refinement and pre-export decision gates so they can inspect `preview.html` without mutating it. The step never throws or blocks the run, so stages keep their graceful-degradation fallback ([#1327](https://github.com/bastani-inc/atomic/issues/1327)).
|
|
14
|
+
- Fixed paused workflow run detail cards to surface the natural `workflow resume` action hint while preserving the interrupt hint for non-paused active runs ([#1283](https://github.com/bastani-inc/atomic/issues/1283)).
|
|
15
|
+
- Fixed paused workflow runs being counted as running and displayed as pending/running in `/workflow status` and `/workflow status <id>`, with paused runs now shown separately as `❚❚ paused` ([#1283](https://github.com/bastani-inc/atomic/issues/1283)).
|
|
16
|
+
|
|
9
17
|
## [0.8.28-alpha.1] - 2026-06-09
|
|
10
18
|
|
|
11
19
|
### Added
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
* a real HTML page on disk (`preview.html`). The workflow attempts to open it
|
|
24
24
|
* through the `browser` skill so the user can interactively review;
|
|
25
25
|
* when browser automation is unavailable, the file path is surfaced so the user
|
|
26
|
-
* can open it manually.
|
|
26
|
+
* can open it manually. Before any stage runs, an initial deterministic setup
|
|
27
|
+
* step ensures the browser skill's `browse` CLI is available (`which browse`,
|
|
28
|
+
* then `npm install -g browse` when missing); it is best-effort and never
|
|
29
|
+
* blocks the run. The final exporter produces a rich `spec.html` that
|
|
27
30
|
* embeds the agreed-upon design alongside the implementation handoff.
|
|
28
31
|
*/
|
|
29
32
|
|
|
@@ -33,6 +36,7 @@ import type {
|
|
|
33
36
|
WorkflowTaskResult,
|
|
34
37
|
WorkflowTaskStep,
|
|
35
38
|
} from "../src/shared/types.js";
|
|
39
|
+
import { spawnSync } from "node:child_process";
|
|
36
40
|
import { mkdirSync } from "node:fs";
|
|
37
41
|
import { tmpdir } from "node:os";
|
|
38
42
|
import { join } from "node:path";
|
|
@@ -49,6 +53,15 @@ type OutputType = (typeof OUTPUT_TYPES)[number];
|
|
|
49
53
|
const DEFAULT_OUTPUT_TYPE: OutputType = "prototype";
|
|
50
54
|
const DEFAULT_MAX_REFINEMENTS = 3;
|
|
51
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Read-only builtin tools granted to the structured-decision stages
|
|
58
|
+
* (user-feedback refinement gate and pre-export gate) so they can actually
|
|
59
|
+
* inspect the on-disk `preview.html` before emitting their decision. The
|
|
60
|
+
* artifact stays immutable here — writes/edits belong to apply-changes and
|
|
61
|
+
* forced-fix, so this list deliberately excludes write/edit/bash.
|
|
62
|
+
*/
|
|
63
|
+
const READ_ONLY_TOOLS = ["read", "grep", "ls"] as const;
|
|
64
|
+
|
|
52
65
|
type PromptSection = readonly [tag: string, content: string];
|
|
53
66
|
|
|
54
67
|
function taggedPrompt(sections: readonly PromptSection[]): string {
|
|
@@ -275,11 +288,126 @@ const ANTI_SLOP_RULES = [
|
|
|
275
288
|
"Commit to a specific aesthetic direction; do not hedge with generic SaaS defaults.",
|
|
276
289
|
].join("\n");
|
|
277
290
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
291
|
+
type BrowseCliStatus = {
|
|
292
|
+
/** Whether the `browse` CLI is expected to be available to downstream stages. */
|
|
293
|
+
readonly available: boolean;
|
|
294
|
+
/** True when the CLI was already on PATH and no install was attempted. */
|
|
295
|
+
readonly alreadyPresent: boolean;
|
|
296
|
+
/** True when this step installed the CLI via `npm install -g browse`. */
|
|
297
|
+
readonly installed: boolean;
|
|
298
|
+
/** Human-readable, single-line outcome surfaced as a workflow output. */
|
|
299
|
+
readonly summary: string;
|
|
300
|
+
/** Raw failure reason when the install could not complete; absent on success. */
|
|
301
|
+
readonly error?: string;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Initial deterministic setup step (no LLM): ensure the browser skill's `browse`
|
|
306
|
+
* CLI is available before any design stage runs. Mirrors the browser skill's
|
|
307
|
+
* documented bootstrap (`which browse || npm install -g browse`) but performs it
|
|
308
|
+
* once, deterministically, instead of relying on each stage to probe/install it.
|
|
309
|
+
* The PATH probe always runs, but the actual global install is skipped under
|
|
310
|
+
* automated tests (`NODE_ENV=test`) to avoid slow, networked, environment-
|
|
311
|
+
* mutating side effects.
|
|
312
|
+
*
|
|
313
|
+
* Best-effort by contract: it never throws and never blocks the workflow. When
|
|
314
|
+
* the CLI cannot be located or installed, downstream stages keep their graceful
|
|
315
|
+
* degradation path (surface the manual preview path / URL).
|
|
316
|
+
*/
|
|
317
|
+
function ensureBrowseCli(): BrowseCliStatus {
|
|
318
|
+
const isWindows = process.platform === "win32";
|
|
319
|
+
const onPath = (): boolean => {
|
|
320
|
+
try {
|
|
321
|
+
const probe = spawnSync(isWindows ? "where" : "which", ["browse"], {
|
|
322
|
+
stdio: "ignore",
|
|
323
|
+
timeout: 15_000,
|
|
324
|
+
shell: isWindows,
|
|
325
|
+
});
|
|
326
|
+
return probe.status === 0;
|
|
327
|
+
} catch {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
if (onPath()) {
|
|
333
|
+
return {
|
|
334
|
+
available: true,
|
|
335
|
+
alreadyPresent: true,
|
|
336
|
+
installed: false,
|
|
337
|
+
summary: "browse CLI already on PATH; skipped install.",
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Never perform a real global `npm install` during automated tests: it is
|
|
342
|
+
// slow, network-dependent, and would mutate the test runner's global
|
|
343
|
+
// environment. The PATH probe above and the prompt guidance below are still
|
|
344
|
+
// exercised; only the install side effect is skipped.
|
|
345
|
+
if (process.env.NODE_ENV === "test") {
|
|
346
|
+
return {
|
|
347
|
+
available: false,
|
|
348
|
+
alreadyPresent: false,
|
|
349
|
+
installed: false,
|
|
350
|
+
summary:
|
|
351
|
+
"browse CLI not found; skipped global install under the test environment.",
|
|
352
|
+
error: "global install skipped during tests",
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
try {
|
|
357
|
+
const install = spawnSync("npm", ["install", "-g", "browse"], {
|
|
358
|
+
stdio: "ignore",
|
|
359
|
+
timeout: 180_000,
|
|
360
|
+
shell: isWindows,
|
|
361
|
+
});
|
|
362
|
+
if (install.status === 0) {
|
|
363
|
+
return {
|
|
364
|
+
available: true,
|
|
365
|
+
alreadyPresent: false,
|
|
366
|
+
installed: true,
|
|
367
|
+
summary: "Installed browse CLI via `npm install -g browse`.",
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
const reason =
|
|
371
|
+
install.error?.message ??
|
|
372
|
+
(typeof install.status === "number"
|
|
373
|
+
? `npm install -g browse exited with code ${install.status}`
|
|
374
|
+
: "npm install -g browse did not complete");
|
|
375
|
+
return {
|
|
376
|
+
available: false,
|
|
377
|
+
alreadyPresent: false,
|
|
378
|
+
installed: false,
|
|
379
|
+
summary: `Could not install browse CLI (${reason}); stages will degrade gracefully.`,
|
|
380
|
+
error: reason,
|
|
381
|
+
};
|
|
382
|
+
} catch (error) {
|
|
383
|
+
const reason =
|
|
384
|
+
error instanceof Error ? error.message : String(error);
|
|
385
|
+
return {
|
|
386
|
+
available: false,
|
|
387
|
+
alreadyPresent: false,
|
|
388
|
+
installed: false,
|
|
389
|
+
summary: `Could not install browse CLI (${reason}); stages will degrade gracefully.`,
|
|
390
|
+
error: reason,
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Build the per-run browser bootstrap guidance injected into stage prompts.
|
|
397
|
+
* When the deterministic setup step already ensured `browse` is installed, the
|
|
398
|
+
* guidance tells stages to assume availability and not waste turns reinstalling;
|
|
399
|
+
* otherwise it retains the original probe-and-install fallback.
|
|
400
|
+
*/
|
|
401
|
+
function buildBrowserBootstrapRules(status: BrowseCliStatus): string {
|
|
402
|
+
const probeRule = status.available
|
|
403
|
+
? "The workflow's deterministic setup step already ensured the browser skill's `browse` CLI is installed and on PATH; assume it is available and do NOT reinstall it. Only if a `browse` command reports the executable as missing should you re-probe with `which browse` and run `npm install -g browse` once before retrying. Do not add project dependencies."
|
|
404
|
+
: `The workflow's deterministic setup step attempted to install the browser skill's \`browse\` CLI but it FAILED with: "${status.error ?? "unknown error"}". Treat this as a known starting condition to work around, not a hard blocker. Probe with \`which browse\` and retry once with \`npm install -g browse\`; if it still fails, use the error above to diagnose a workaround (for example: EACCES/permission errors → retry with a user-writable global prefix; missing npm/Node → report it plainly; network/registry errors → surface them). If the CLI still cannot be made available, degrade gracefully and surface the manual file path / URL. Do not add project dependencies.`;
|
|
405
|
+
return [
|
|
406
|
+
probeRule,
|
|
407
|
+
"Use `browse open <url> --local --headed` when a generated local preview should be visible to the user, and use `browse snapshot` plus `browse screenshot --path <file>` for review evidence.",
|
|
408
|
+
"If `browse` is unavailable after three attempts or the browser runtime still fails, degrade gracefully and surface the manual file path / URL.",
|
|
409
|
+
].join("\n");
|
|
410
|
+
}
|
|
283
411
|
|
|
284
412
|
export default defineWorkflow("open-claude-design")
|
|
285
413
|
.description(
|
|
@@ -316,7 +444,15 @@ export default defineWorkflow("open-claude-design")
|
|
|
316
444
|
.output("preview_file_url", Type.Optional(Type.String({ description: "file:// URL for the generated preview.html file." })))
|
|
317
445
|
.output("spec_path", Type.Optional(Type.String({ description: "Absolute path to the generated spec.html file." })))
|
|
318
446
|
.output("spec_file_url", Type.Optional(Type.String({ description: "file:// URL for the generated spec.html file." })))
|
|
447
|
+
.output("browse_cli_status", Type.Optional(Type.String({ description: "Outcome of the initial deterministic step that ensures the browser skill's `browse` CLI is installed." })))
|
|
319
448
|
.run(async (ctx) => {
|
|
449
|
+
// Initial deterministic setup step (no LLM): ensure the browser skill's
|
|
450
|
+
// `browse` CLI is installed before any design stage runs. Best-effort —
|
|
451
|
+
// a failed install never blocks the workflow; downstream stages keep their
|
|
452
|
+
// graceful-degradation fallback (surface the manual preview path / URL).
|
|
453
|
+
const browseCli = ensureBrowseCli();
|
|
454
|
+
const browserBootstrapRules = buildBrowserBootstrapRules(browseCli);
|
|
455
|
+
|
|
320
456
|
const inputs = ctx.inputs;
|
|
321
457
|
|
|
322
458
|
const prompt = inputs.prompt;
|
|
@@ -344,12 +480,12 @@ export default defineWorkflow("open-claude-design")
|
|
|
344
480
|
};
|
|
345
481
|
const refinementDecisionConfig = {
|
|
346
482
|
...designModelConfig,
|
|
347
|
-
tools: [refinementDecisionTool.name],
|
|
483
|
+
tools: [...READ_ONLY_TOOLS, refinementDecisionTool.name],
|
|
348
484
|
customTools: [refinementDecisionTool],
|
|
349
485
|
};
|
|
350
486
|
const exportGateDecisionConfig = {
|
|
351
487
|
...designModelConfig,
|
|
352
|
-
tools: [exportGateDecisionTool.name],
|
|
488
|
+
tools: [...READ_ONLY_TOOLS, exportGateDecisionTool.name],
|
|
353
489
|
customTools: [exportGateDecisionTool],
|
|
354
490
|
};
|
|
355
491
|
|
|
@@ -551,7 +687,7 @@ export default defineWorkflow("open-claude-design")
|
|
|
551
687
|
`Capture transferable design intent from this reference for: ${prompt}. Apply the impeccable \`extract\` sub-skill to lift concrete, citable design traits from the reference URL. Use browser/screenshot tooling if available; never guess about visual traits without observable evidence.`,
|
|
552
688
|
],
|
|
553
689
|
["reference_url", reference],
|
|
554
|
-
["browser_use_guidelines",
|
|
690
|
+
["browser_use_guidelines", browserBootstrapRules],
|
|
555
691
|
[
|
|
556
692
|
"instructions",
|
|
557
693
|
[
|
|
@@ -671,7 +807,7 @@ export default defineWorkflow("open-claude-design")
|
|
|
671
807
|
],
|
|
672
808
|
["preview_path", previewPath],
|
|
673
809
|
["preview_file_url", previewFileUrl],
|
|
674
|
-
["browser_use_guidelines",
|
|
810
|
+
["browser_use_guidelines", browserBootstrapRules],
|
|
675
811
|
[
|
|
676
812
|
"instructions",
|
|
677
813
|
[
|
|
@@ -794,7 +930,7 @@ export default defineWorkflow("open-claude-design")
|
|
|
794
930
|
["current_design_and_feedback", "{previous}"],
|
|
795
931
|
[
|
|
796
932
|
"browser_use_guidelines",
|
|
797
|
-
|
|
933
|
+
browserBootstrapRules,
|
|
798
934
|
],
|
|
799
935
|
[
|
|
800
936
|
"instructions",
|
|
@@ -881,7 +1017,7 @@ export default defineWorkflow("open-claude-design")
|
|
|
881
1017
|
["preview_file_url", previewFileUrl],
|
|
882
1018
|
[
|
|
883
1019
|
"browser_use_bootstrap",
|
|
884
|
-
|
|
1020
|
+
browserBootstrapRules,
|
|
885
1021
|
],
|
|
886
1022
|
[
|
|
887
1023
|
"instructions",
|
|
@@ -1044,7 +1180,7 @@ export default defineWorkflow("open-claude-design")
|
|
|
1044
1180
|
["spec_file_url", specFileUrl],
|
|
1045
1181
|
["preview_path", previewPath],
|
|
1046
1182
|
["preview_file_url", previewFileUrl],
|
|
1047
|
-
["browser_use_guidelines",
|
|
1183
|
+
["browser_use_guidelines", browserBootstrapRules],
|
|
1048
1184
|
[
|
|
1049
1185
|
"instructions",
|
|
1050
1186
|
[
|
|
@@ -1078,6 +1214,7 @@ export default defineWorkflow("open-claude-design")
|
|
|
1078
1214
|
preview_file_url: previewFileUrl,
|
|
1079
1215
|
spec_path: specPath,
|
|
1080
1216
|
spec_file_url: specFileUrl,
|
|
1217
|
+
browse_cli_status: browseCli.summary,
|
|
1081
1218
|
};
|
|
1082
1219
|
})
|
|
1083
1220
|
.compile();
|
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
* left, a `surface0` tag carrying the runId / workflow name, a
|
|
12
12
|
* bolded title beside it, and one optional second row indented past
|
|
13
13
|
* the stripe.
|
|
14
|
-
* - **Progress strip**: bracketed
|
|
15
|
-
* coloured by stage status.
|
|
16
|
-
* rendered
|
|
14
|
+
* - **Progress strip**: bracketed status cells such as `[✓]`, `[●]`,
|
|
15
|
+
* `[○]`, `[✗]`, and `[❚❚]`, coloured by stage status. Cells are
|
|
16
|
+
* measured by visible width per rendered glyph rather than assumed to
|
|
17
|
+
* be a fixed 3 columns, and the strip truncates with a trailing `…`
|
|
18
|
+
* when the rendered cells exceed the available budget.
|
|
17
19
|
* - **Hint rows**: a single grammar — `▸ /slash command verb-phrase
|
|
18
20
|
* hint`.
|
|
19
21
|
*
|
|
@@ -440,7 +442,7 @@ function renderTaggedCardPlain(opts: RenderTaggedCardOpts, width: number): strin
|
|
|
440
442
|
}
|
|
441
443
|
|
|
442
444
|
// ---------------------------------------------------------------------------
|
|
443
|
-
// Progress strip —
|
|
445
|
+
// Progress strip — variable-width bracketed cells, coloured by stage status
|
|
444
446
|
// ---------------------------------------------------------------------------
|
|
445
447
|
|
|
446
448
|
export interface ProgressCell {
|
|
@@ -449,45 +451,40 @@ export interface ProgressCell {
|
|
|
449
451
|
|
|
450
452
|
/**
|
|
451
453
|
* Render a progress strip whose visible width is at most `budget` cells.
|
|
452
|
-
* Each cell renders as a
|
|
453
|
-
* (`[✓]`
|
|
454
|
-
*
|
|
454
|
+
* Each cell renders as a bracketed status glyph whose visible width can
|
|
455
|
+
* vary by status (`[✓]` is 3 cells, `[❚❚]` is 4 cells). Truncation uses
|
|
456
|
+
* the measured width of each rendered cell and appends a trailing `…`
|
|
457
|
+
* when the next whole cell would exceed the budget.
|
|
455
458
|
*
|
|
456
459
|
* Themed mode colours the glyphs by status; plain mode emits the same
|
|
457
|
-
*
|
|
460
|
+
* bracketed shape so logs remain readable.
|
|
458
461
|
*/
|
|
459
462
|
export function progressStrip(
|
|
460
463
|
cells: readonly ProgressCell[],
|
|
461
464
|
budget: number,
|
|
462
465
|
theme?: GraphTheme,
|
|
463
466
|
): string {
|
|
464
|
-
const CELL_WIDTH = 3;
|
|
465
467
|
const usable = Math.max(0, Math.floor(budget));
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
?
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
}
|
|
482
|
-
} else {
|
|
483
|
-
for (const cell of slice) {
|
|
484
|
-
out += renderCellPlain(cell.status);
|
|
485
|
-
}
|
|
468
|
+
if (usable < 3 || cells.length === 0) return "";
|
|
469
|
+
|
|
470
|
+
const ellipsisWidth = visibleWidth(ELLIPSIS);
|
|
471
|
+
const out: string[] = [];
|
|
472
|
+
let used = 0;
|
|
473
|
+
|
|
474
|
+
for (let i = 0; i < cells.length; i++) {
|
|
475
|
+
const rendered = theme ? renderCellThemed(cells[i]!.status, theme) : renderCellPlain(cells[i]!.status);
|
|
476
|
+
const renderedWidth = visibleWidth(rendered);
|
|
477
|
+
const isLast = i === cells.length - 1;
|
|
478
|
+
const reserved = isLast ? 0 : ellipsisWidth;
|
|
479
|
+
if (used + renderedWidth + reserved > usable) break;
|
|
480
|
+
out.push(rendered);
|
|
481
|
+
used += renderedWidth;
|
|
482
|
+
if (isLast) return out.join("");
|
|
486
483
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
return out
|
|
484
|
+
|
|
485
|
+
if (out.length === 0 && ellipsisWidth > usable) return "";
|
|
486
|
+
const suffix = theme ? `${hexToAnsi(theme.dim)}${ELLIPSIS}${RESET}` : ELLIPSIS;
|
|
487
|
+
return `${out.join("")}${suffix}`;
|
|
491
488
|
}
|
|
492
489
|
|
|
493
490
|
function renderCellThemed(status: StageStatus, theme: GraphTheme): string {
|
|
@@ -506,6 +503,7 @@ function stageGlyph(status: StageStatus): string {
|
|
|
506
503
|
switch (status) {
|
|
507
504
|
case "completed": return "✓";
|
|
508
505
|
case "running": return "●";
|
|
506
|
+
case "paused": return "❚❚";
|
|
509
507
|
case "failed": return "✗";
|
|
510
508
|
case "awaiting_input": return "?";
|
|
511
509
|
case "skipped": return "⊘";
|
|
@@ -518,6 +516,7 @@ function stageColor(status: StageStatus, theme: GraphTheme): string {
|
|
|
518
516
|
switch (status) {
|
|
519
517
|
case "completed": return hexToAnsi(theme.success);
|
|
520
518
|
case "running": return hexToAnsi(theme.warning);
|
|
519
|
+
case "paused": return hexToAnsi(theme.warning);
|
|
521
520
|
case "failed": return hexToAnsi(theme.error);
|
|
522
521
|
case "awaiting_input": return hexToAnsi(theme.info);
|
|
523
522
|
case "skipped": return hexToAnsi(theme.dim);
|
|
@@ -90,7 +90,10 @@ function renderPlain(detail: RunDetail, now: number, width: number): string {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
if (detail.endedAt === undefined) {
|
|
93
|
-
|
|
93
|
+
const hint = detail.status === "paused"
|
|
94
|
+
? ` ▸ workflow resume id=${sid} continue workflow `
|
|
95
|
+
: ` ▸ workflow interrupt id=${sid} cancel `;
|
|
96
|
+
out.push(truncateToWidth(hint, width - 2, "…"));
|
|
94
97
|
} else {
|
|
95
98
|
out.push(truncateToWidth(` ▸ workflow resume id=${sid} reopen graph `, width - 2, "…"));
|
|
96
99
|
}
|
|
@@ -143,9 +146,10 @@ function renderThemed(detail: RunDetail, now: number, theme: GraphTheme, width:
|
|
|
143
146
|
}
|
|
144
147
|
|
|
145
148
|
if (detail.endedAt === undefined) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
const hint = detail.status === "paused"
|
|
150
|
+
? ` ${dim}▸${RESET} ${accent}workflow resume id=${sid}${RESET}${dim} continue workflow${RESET} `
|
|
151
|
+
: ` ${dim}▸${RESET} ${accent}workflow interrupt id=${sid}${RESET}${dim} cancel${RESET} `;
|
|
152
|
+
out.push(truncateToWidth(hint, width - 2, "…"));
|
|
149
153
|
} else {
|
|
150
154
|
out.push(
|
|
151
155
|
truncateToWidth(` ${dim}▸${RESET} ${accent}workflow resume id=${sid}${RESET}${dim} reopen graph${RESET} `, width - 2, "…"),
|
|
@@ -295,6 +299,8 @@ function stateBadges(detail: RunDetail, theme: GraphTheme): FlatBandBadge[] {
|
|
|
295
299
|
switch (detail.status) {
|
|
296
300
|
case "running":
|
|
297
301
|
return [{ text: "● running", fg: theme.warning }];
|
|
302
|
+
case "paused":
|
|
303
|
+
return [{ text: "❚❚ paused", fg: theme.warning }];
|
|
298
304
|
case "completed":
|
|
299
305
|
return [{ text: "✓ completed", fg: theme.success }];
|
|
300
306
|
case "failed":
|
|
@@ -310,6 +316,7 @@ function stateBadges(detail: RunDetail, theme: GraphTheme): FlatBandBadge[] {
|
|
|
310
316
|
function stateLabel(detail: RunDetail): string {
|
|
311
317
|
switch (detail.status) {
|
|
312
318
|
case "running": return "● running";
|
|
319
|
+
case "paused": return "❚❚ paused";
|
|
313
320
|
case "completed": return "✓ completed";
|
|
314
321
|
case "failed": return "✗ failed";
|
|
315
322
|
case "killed": return "⊘ killed";
|
|
@@ -160,6 +160,7 @@ function runAccent(run: RunSnapshot, theme?: GraphTheme): string {
|
|
|
160
160
|
switch (run.status) {
|
|
161
161
|
case "completed": return theme.success;
|
|
162
162
|
case "running": return theme.warning;
|
|
163
|
+
case "paused": return theme.warning;
|
|
163
164
|
case "failed": return theme.error;
|
|
164
165
|
case "killed": return theme.error;
|
|
165
166
|
case "pending":
|
|
@@ -171,6 +172,7 @@ function runTrailing(run: RunSnapshot, theme?: GraphTheme): { text: string; fg?:
|
|
|
171
172
|
switch (run.status) {
|
|
172
173
|
case "completed": return { text: "✓ completed", fg: theme?.success };
|
|
173
174
|
case "running": return { text: "● running", fg: theme?.warning };
|
|
175
|
+
case "paused": return { text: "❚❚ paused", fg: theme?.warning };
|
|
174
176
|
case "failed": return { text: "✗ failed", fg: theme?.error };
|
|
175
177
|
case "killed": return { text: "⊘ killed", fg: theme?.error };
|
|
176
178
|
case "pending":
|
|
@@ -181,6 +183,7 @@ function runTrailing(run: RunSnapshot, theme?: GraphTheme): { text: string; fg?:
|
|
|
181
183
|
function runCardMeta(run: RunSnapshot, now: number): string {
|
|
182
184
|
// Builds the right-aligned meta tail.
|
|
183
185
|
// running → `3/8 · review-a · 1m42s`
|
|
186
|
+
// paused → `3/8 · review-a · 1m42s` (elapsed is frozen by pausedAt)
|
|
184
187
|
// failed → `failed at partition · 4m24s ago`
|
|
185
188
|
// killed → `<stage> · <duration> · <when>` (mirrors mockup §2)
|
|
186
189
|
// completed→ `<stage> · <duration> · <when>`
|
|
@@ -204,6 +207,14 @@ function runCardMeta(run: RunSnapshot, now: number): string {
|
|
|
204
207
|
return parts.join(" · ");
|
|
205
208
|
}
|
|
206
209
|
|
|
210
|
+
if (run.status === "paused") {
|
|
211
|
+
if (isChain) parts.push(`${done}/${total}`);
|
|
212
|
+
const labels = pausedStageLabels(run);
|
|
213
|
+
if (labels) parts.push(labels);
|
|
214
|
+
if (ago) parts.push(ago);
|
|
215
|
+
return parts.join(" · ");
|
|
216
|
+
}
|
|
217
|
+
|
|
207
218
|
if (run.status === "failed" || run.status === "killed") {
|
|
208
219
|
const failed = run.stages.find((s) => s.status === "failed");
|
|
209
220
|
if (failed && isChain) parts.push(`failed at ${failed.name}`);
|
|
@@ -235,6 +246,13 @@ function runningStageLabels(run: RunSnapshot): string | undefined {
|
|
|
235
246
|
return truncateToWidth(joined, STAGE_LABEL_BUDGET, ELLIPSIS);
|
|
236
247
|
}
|
|
237
248
|
|
|
249
|
+
function pausedStageLabels(run: RunSnapshot): string | undefined {
|
|
250
|
+
const paused = run.stages.filter((s) => s.status === "paused").map((s) => s.name);
|
|
251
|
+
if (paused.length === 0) return undefined;
|
|
252
|
+
const joined = paused.join(", ");
|
|
253
|
+
return truncateToWidth(joined, STAGE_LABEL_BUDGET, ELLIPSIS);
|
|
254
|
+
}
|
|
255
|
+
|
|
238
256
|
function lastStageDuration(run: RunSnapshot, now: number): string | undefined {
|
|
239
257
|
// Pick a representative stage duration: the most-recent terminal stage,
|
|
240
258
|
// or the running stage if everything's still in flight.
|
|
@@ -263,6 +281,7 @@ function stageStatusFromRun(run: RunSnapshot): StageStatus {
|
|
|
263
281
|
switch (run.status) {
|
|
264
282
|
case "completed": return "completed";
|
|
265
283
|
case "running": return "running";
|
|
284
|
+
case "paused": return "paused";
|
|
266
285
|
case "failed": return "failed";
|
|
267
286
|
case "killed": return "failed";
|
|
268
287
|
case "pending":
|
|
@@ -285,17 +304,21 @@ function effectiveWidth(width?: number): number {
|
|
|
285
304
|
|
|
286
305
|
interface Counts {
|
|
287
306
|
active: number;
|
|
307
|
+
paused: number;
|
|
288
308
|
completed: number;
|
|
289
309
|
failed: number;
|
|
290
310
|
pending: number;
|
|
291
311
|
}
|
|
292
312
|
|
|
293
313
|
function countBuckets(runs: readonly RunSnapshot[]): Counts {
|
|
294
|
-
const c: Counts = { active: 0, completed: 0, failed: 0, pending: 0 };
|
|
314
|
+
const c: Counts = { active: 0, paused: 0, completed: 0, failed: 0, pending: 0 };
|
|
295
315
|
for (const r of runs) {
|
|
296
316
|
if (r.endedAt === undefined) {
|
|
297
317
|
if (r.status === "pending") c.pending++;
|
|
298
|
-
else c.
|
|
318
|
+
else if (r.status === "paused") c.paused++;
|
|
319
|
+
else if (r.status === "running") c.active++;
|
|
320
|
+
else if (r.status === "completed") c.completed++;
|
|
321
|
+
else c.failed++;
|
|
299
322
|
} else if (r.status === "completed") c.completed++;
|
|
300
323
|
else c.failed++;
|
|
301
324
|
}
|
|
@@ -306,6 +329,9 @@ function themedBadges(c: Counts, theme: GraphTheme): FlatBandBadge[] {
|
|
|
306
329
|
const out: FlatBandBadge[] = [];
|
|
307
330
|
if (c.completed > 0) out.push({ text: `✓ ${c.completed}`, fg: theme.success });
|
|
308
331
|
if (c.active > 0) out.push({ text: `● ${c.active}`, fg: theme.warning });
|
|
332
|
+
// Keep the word label: the pause glyph is less familiar than the other
|
|
333
|
+
// status glyphs, so this intentional asymmetry improves scanability.
|
|
334
|
+
if (c.paused > 0) out.push({ text: `❚❚ ${c.paused} paused`, fg: theme.warning });
|
|
309
335
|
if (c.pending > 0) out.push({ text: `○ ${c.pending}`, fg: theme.dim });
|
|
310
336
|
if (c.failed > 0) out.push({ text: `⊘ ${c.failed}`, fg: theme.error });
|
|
311
337
|
return out;
|
|
@@ -315,6 +341,9 @@ function plainBadges(c: Counts): FlatBandBadge[] {
|
|
|
315
341
|
const out: FlatBandBadge[] = [];
|
|
316
342
|
if (c.completed > 0) out.push({ text: `✓ ${c.completed}` });
|
|
317
343
|
if (c.active > 0) out.push({ text: `● ${c.active}` });
|
|
344
|
+
// Keep the word label: the pause glyph is less familiar than the other
|
|
345
|
+
// status glyphs, so this intentional asymmetry improves scanability.
|
|
346
|
+
if (c.paused > 0) out.push({ text: `❚❚ ${c.paused} paused` });
|
|
318
347
|
if (c.pending > 0) out.push({ text: `○ ${c.pending}` });
|
|
319
348
|
if (c.failed > 0) out.push({ text: `⊘ ${c.failed}` });
|
|
320
349
|
return out;
|
|
@@ -344,6 +373,7 @@ function statusIconForRun(run: RunSnapshot): string {
|
|
|
344
373
|
switch (run.status) {
|
|
345
374
|
case "completed": return "✓";
|
|
346
375
|
case "running": return "●";
|
|
376
|
+
case "paused": return "❚❚";
|
|
347
377
|
case "failed": return "✗";
|
|
348
378
|
case "killed": return "⊘";
|
|
349
379
|
case "pending":
|
package/dist/cli/args.d.ts
CHANGED
|
@@ -16,12 +16,15 @@ export interface Args {
|
|
|
16
16
|
help?: boolean;
|
|
17
17
|
version?: boolean;
|
|
18
18
|
mode?: Mode;
|
|
19
|
+
name?: string;
|
|
19
20
|
noSession?: boolean;
|
|
20
21
|
session?: string;
|
|
22
|
+
sessionId?: string;
|
|
21
23
|
fork?: string;
|
|
22
24
|
sessionDir?: string;
|
|
23
25
|
models?: string[];
|
|
24
26
|
tools?: string[];
|
|
27
|
+
excludeTools?: string[];
|
|
25
28
|
noTools?: boolean;
|
|
26
29
|
noBuiltinTools?: boolean;
|
|
27
30
|
extensions?: string[];
|
|
@@ -38,6 +41,7 @@ export interface Args {
|
|
|
38
41
|
listModels?: string | true;
|
|
39
42
|
offline?: boolean;
|
|
40
43
|
verbose?: boolean;
|
|
44
|
+
projectTrustOverride?: boolean;
|
|
41
45
|
messages: string[];
|
|
42
46
|
fileArgs: string[];
|
|
43
47
|
/** Unknown flags (potentially extension flags) - map of flag name to value */
|