Skip to content

Commit 4bc9558

Browse files
committed
feat(ui): add live workspace and workflow dashboards
1 parent 57296a6 commit 4bc9558

8 files changed

Lines changed: 905 additions & 41 deletions

File tree

src/server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -725,10 +725,10 @@ function createMcpServer(
725725

726726
registerAppResource(
727727
server,
728-
"DevSpace Diff Card",
728+
"DevSpace App",
729729
WORKSPACE_APP_URI,
730730
{
731-
description: "Interactive card for viewing DevSpace file diffs.",
731+
description: "Interactive DevSpace workspace, workflow, and file-change views.",
732732
_meta: {
733733
ui: {
734734
csp: appCsp(config),

src/ui/card-types.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ import {
77
isToolName,
88
} from "./card-types.js";
99

10-
for (const tool of ["apply_patch", "exec_command", "write_stdin"]) {
10+
for (const tool of [
11+
"apply_patch",
12+
"exec_command",
13+
"write_stdin",
14+
"run_workflow",
15+
"workflow_status",
16+
]) {
1117
assert.equal(isToolName(tool), true, `${tool} should be a recognized card tool`);
1218
}
1319

@@ -23,3 +29,26 @@ assert.equal(
2329
true,
2430
);
2531
assert.equal(isExpandableCard({ tool: "apply_patch" }), false);
32+
assert.equal(isExpandableCard({ tool: "run_workflow", runId: "wfr_1" }), true);
33+
assert.equal(
34+
isExpandableCard({
35+
tool: "open_workspace",
36+
activeWorkflows: [
37+
{
38+
id: "wfr_1",
39+
name: "Review",
40+
status: "running",
41+
calls: {
42+
running: 1,
43+
completed: 0,
44+
cached: 0,
45+
failed: 0,
46+
cancelled: 0,
47+
observed: 1,
48+
},
49+
updatedAt: "2026-07-26T00:00:00.000Z",
50+
},
51+
],
52+
}),
53+
true,
54+
);

src/ui/card-types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ export interface ToolResultCard {
2626
workspaceId?: string;
2727
path?: string;
2828
root?: string;
29+
mode?: "checkout" | "worktree";
30+
sourceRoot?: string;
31+
worktree?: {
32+
path?: string;
33+
baseRef?: string;
34+
baseSha?: string;
35+
dirtySource?: boolean;
36+
detached?: boolean;
37+
managed?: boolean;
38+
};
2939
status?: string;
3040
name?: string;
3141
runId?: string;
@@ -174,6 +184,9 @@ export function isExpandableCard(card: ToolResultCard): boolean {
174184
Boolean(card.agentsFiles?.length) ||
175185
Boolean(card.availableAgentsFiles?.length) ||
176186
Boolean(card.skills?.length) ||
187+
Boolean(card.activeWorkflows?.length) ||
188+
Boolean(card.agentProviders?.length) ||
189+
Boolean(card.agents?.length) ||
177190
Boolean(card.skillDiagnostics?.length)
178191
);
179192
}

src/ui/tool-display.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export function getToolHeaderSummary(card: ToolResultCard): ToolHeaderSummary {
138138
if (card.tool === "open_workspace") {
139139
const parts = [
140140
typeof summary.mode === "string" ? summary.mode : undefined,
141+
countLabel(summaryNumber(summary, "activeWorkflows"), "workflow"),
141142
countLabel(summaryNumber(summary, "agentsFiles"), "instruction"),
142143
countLabel(summaryNumber(summary, "skills"), "skill"),
143144
].filter((part): part is string => Boolean(part));

0 commit comments

Comments
 (0)