Skip to content

Commit 5ee0022

Browse files
committed
feat(workflow): add read-only project TUI
1 parent a499c2e commit 5ee0022

5 files changed

Lines changed: 384 additions & 1 deletion

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"dev": "node scripts/dev-server.mjs",
2929
"postinstall": "node scripts/fix-node-pty-permissions.mjs",
3030
"start": "node dist/cli.js serve",
31-
"test": "tsx src/config.test.ts && tsx src/ui/card-types.test.ts && tsx src/ui/patch-display.test.ts && tsx src/ui/tool-display.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/mcp-sessions.test.ts && tsx src/server-shutdown.test.ts && tsx src/local-agent-runtime.test.ts && tsx src/local-agent-adapters.test.ts && tsx src/local-agent-availability.test.ts && tsx src/local-agent-profiles.test.ts && tsx src/local-agent-targets.test.ts && tsx src/local-agent-store.test.ts && tsx src/roots.test.ts && tsx src/skills.test.ts && tsx src/workspaces.test.ts && tsx src/review-checkpoints.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts && tsx src/workflow-contracts.test.ts && tsx src/workflow-errors.test.ts && tsx src/workflow-types.test.ts && tsx src/workflow-store.test.ts && tsx src/workflow-view.test.ts && tsx src/workflow-script.test.ts && tsx src/workflow-sandbox.test.ts && tsx src/workflow-engine.test.ts && tsx src/workflow-files.test.ts && tsx src/workflow-replay.test.ts && tsx src/workflow-schema.test.ts",
31+
"test": "tsx src/config.test.ts && tsx src/ui/card-types.test.ts && tsx src/ui/patch-display.test.ts && tsx src/ui/tool-display.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/mcp-sessions.test.ts && tsx src/server-shutdown.test.ts && tsx src/local-agent-runtime.test.ts && tsx src/local-agent-adapters.test.ts && tsx src/local-agent-availability.test.ts && tsx src/local-agent-profiles.test.ts && tsx src/local-agent-targets.test.ts && tsx src/local-agent-store.test.ts && tsx src/roots.test.ts && tsx src/skills.test.ts && tsx src/workspaces.test.ts && tsx src/review-checkpoints.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts && tsx src/workflow-contracts.test.ts && tsx src/workflow-errors.test.ts && tsx src/workflow-types.test.ts && tsx src/workflow-store.test.ts && tsx src/workflow-view.test.ts && tsx src/workflow-tui.test.ts && tsx src/workflow-script.test.ts && tsx src/workflow-sandbox.test.ts && tsx src/workflow-engine.test.ts && tsx src/workflow-files.test.ts && tsx src/workflow-replay.test.ts && tsx src/workflow-schema.test.ts",
3232
"typecheck": "tsc -p tsconfig.json --noEmit"
3333
},
3434
"keywords": [],

skills/dynamic-workflows/SKILL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ devspace workflow cancel <runId>
2525
devspace workflow ls
2626
devspace workflow calls <runId>
2727
devspace workflow call <runId> <callIndex>
28+
devspace workflow tui [runId]
2829
```
2930

3031
Named scripts: `.devspace/workflows/<name>.js` or `workflows/<name>.js`.
@@ -115,6 +116,7 @@ depending on a replayed mutating call.
115116
## When to use CLI vs MCP
116117

117118
- **CLI**: host agent can shell; prefer for long runs + `--follow`.
119+
- **TUI**: `devspace workflow tui` opens a read-only live view for workflows associated with the current working directory.
118120
- **MCP**: ChatGPT plans; call `run_workflow`, then `workflow_status` until terminal. Disconnecting MCP does **not** kill the worker.
119121

120122
## Worked mini-examples

src/workflow-cli.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ export async function runWorkflowCommand(
6969
case "call":
7070
await runWorkflowCall(rest, config);
7171
return;
72+
case "tui": {
73+
const { runWorkflowTui } = await import("./workflow-tui.js");
74+
await runWorkflowTui(rest, config);
75+
return;
76+
}
7277
case "__worker":
7378
await runWorkflowWorker(rest, config);
7479
return;
@@ -96,6 +101,7 @@ export function printWorkflowHelp(): void {
96101
" devspace workflow ls",
97102
" devspace workflow calls <runId>",
98103
" devspace workflow call <runId> <callIndex>",
104+
" devspace workflow tui [runId] # current working directory",
99105
].join("\n"),
100106
);
101107
}

src/workflow-tui.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import assert from "node:assert/strict";
2+
import {
3+
renderWorkflowTui,
4+
resolveWorkflowTuiWorkspaceRoot,
5+
} from "./workflow-tui.js";
6+
import type { WorkflowProjectView } from "./workflow-view.js";
7+
8+
const project: WorkflowProjectView = {
9+
workspaceRoot: "/tmp/project",
10+
version: "1",
11+
runs: [
12+
{
13+
id: "wfr_1",
14+
name: "Review auth",
15+
status: "running",
16+
source: "named",
17+
scriptPath: "/tmp/review.js",
18+
scriptHash: "abc",
19+
workspaceRoot: "/tmp/project",
20+
currentPhase: "Implementation",
21+
calls: {
22+
running: 1,
23+
completed: 1,
24+
cached: 0,
25+
failed: 0,
26+
cancelled: 0,
27+
observed: 2,
28+
},
29+
phases: [
30+
{
31+
title: "Implementation",
32+
calls: [
33+
{
34+
callIndex: 1,
35+
status: "running",
36+
provider: "codex",
37+
label: "Patch auth",
38+
isolation: "worktree",
39+
fromCache: false,
40+
updatedAt: "2026-07-26T10:00:02.000Z",
41+
},
42+
],
43+
},
44+
],
45+
unphasedCalls: [],
46+
recentActivity: [
47+
{
48+
seq: 1,
49+
type: "log",
50+
detail: "Running tests",
51+
createdAt: "2026-07-26T10:00:03.000Z",
52+
},
53+
],
54+
latestEventSeq: 1,
55+
version: "v1",
56+
createdAt: "2026-07-26T10:00:00.000Z",
57+
startedAt: "2026-07-26T10:00:00.000Z",
58+
updatedAt: "2026-07-26T10:00:03.000Z",
59+
},
60+
],
61+
};
62+
63+
const rendered = renderWorkflowTui(project, 0, 100, 30, { ansi: false });
64+
assert.match(rendered, /DevSpace workflows · \/tmp\/project/);
65+
assert.match(rendered, /Review auth · Implementation/);
66+
assert.match(rendered, /Patch auth codex · worktree/);
67+
assert.match(rendered, /Running tests/);
68+
assert.match(rendered, /refreshes automatically/);
69+
assert.equal(resolveWorkflowTuiWorkspaceRoot("./test-project").endsWith("test-project"), true);
70+
71+
console.log("workflow-tui.test.ts: ok");

0 commit comments

Comments
 (0)