@mind-fold/open-flow 0.2.17 → 0.2.19

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.
Files changed (48) hide show
  1. package/dist/cli/index.d.ts.map +1 -1
  2. package/dist/cli/index.js +15 -0
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/dashboard.d.ts +6 -0
  5. package/dist/commands/dashboard.d.ts.map +1 -0
  6. package/dist/commands/dashboard.js +9 -0
  7. package/dist/commands/dashboard.js.map +1 -0
  8. package/dist/tui/components/AgentCard.d.ts +9 -0
  9. package/dist/tui/components/AgentCard.d.ts.map +1 -0
  10. package/dist/tui/components/AgentCard.js +71 -0
  11. package/dist/tui/components/AgentCard.js.map +1 -0
  12. package/dist/tui/components/AgentDashboard.d.ts +6 -0
  13. package/dist/tui/components/AgentDashboard.d.ts.map +1 -0
  14. package/dist/tui/components/AgentDashboard.js +70 -0
  15. package/dist/tui/components/AgentDashboard.js.map +1 -0
  16. package/dist/tui/components/App.d.ts +6 -0
  17. package/dist/tui/components/App.d.ts.map +1 -0
  18. package/dist/tui/components/App.js +76 -0
  19. package/dist/tui/components/App.js.map +1 -0
  20. package/dist/tui/components/FeatureCard.d.ts +8 -0
  21. package/dist/tui/components/FeatureCard.d.ts.map +1 -0
  22. package/dist/tui/components/FeatureCard.js +23 -0
  23. package/dist/tui/components/FeatureCard.js.map +1 -0
  24. package/dist/tui/components/KanbanBoard.d.ts +10 -0
  25. package/dist/tui/components/KanbanBoard.d.ts.map +1 -0
  26. package/dist/tui/components/KanbanBoard.js +11 -0
  27. package/dist/tui/components/KanbanBoard.js.map +1 -0
  28. package/dist/tui/components/StatusBar.d.ts +8 -0
  29. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  30. package/dist/tui/components/StatusBar.js +6 -0
  31. package/dist/tui/components/StatusBar.js.map +1 -0
  32. package/dist/tui/hooks/useAgents.d.ts +25 -0
  33. package/dist/tui/hooks/useAgents.d.ts.map +1 -0
  34. package/dist/tui/hooks/useAgents.js +165 -0
  35. package/dist/tui/hooks/useAgents.js.map +1 -0
  36. package/dist/tui/hooks/useFeatures.d.ts +10 -0
  37. package/dist/tui/hooks/useFeatures.d.ts.map +1 -0
  38. package/dist/tui/hooks/useFeatures.js +126 -0
  39. package/dist/tui/hooks/useFeatures.js.map +1 -0
  40. package/dist/tui/index.d.ts +11 -0
  41. package/dist/tui/index.d.ts.map +1 -0
  42. package/dist/tui/index.js +12 -0
  43. package/dist/tui/index.js.map +1 -0
  44. package/dist/tui/types.d.ts +33 -0
  45. package/dist/tui/types.d.ts.map +1 -0
  46. package/dist/tui/types.js +2 -0
  47. package/dist/tui/types.js.map +1 -0
  48. package/package.json +7 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,OAAO,KAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,OAAO,KAAsB,CAAC"}
package/dist/cli/index.js CHANGED
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
4
4
  import chalk from "chalk";
5
5
  import { Command } from "commander";
6
6
  import { init } from "../commands/init.js";
7
+ import { dashboard } from "../commands/dashboard.js";
7
8
  // Read version from package.json
8
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
10
  const packageJsonPath = path.resolve(__dirname, "../../package.json");
@@ -38,5 +39,19 @@ program
38
39
  .action(async () => {
39
40
  console.log(chalk.yellow("Coming soon: update command"));
40
41
  });
42
+ program
43
+ .command("dashboard")
44
+ .alias("db")
45
+ .description("Open the TUI dashboard to view feature status")
46
+ .option("-p, --path <path>", "Path to the workflow directory")
47
+ .action(async (options) => {
48
+ try {
49
+ await dashboard(options);
50
+ }
51
+ catch (error) {
52
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : error);
53
+ process.exit(1);
54
+ }
55
+ });
41
56
  program.parse();
42
57
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C,iCAAiC;AACjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AACtE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1E,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAE3C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACL,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CACX,+EAA+E,CAC/E;KACA,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,2BAA2B,CAAC,CAAC;AAEjE,OAAO;KACL,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,UAAU,EAAE,yBAAyB,CAAC;KAC7C,MAAM,CAAC,UAAU,EAAE,8BAA8B,CAAC;KAClD,MAAM,CAAC,WAAW,EAAE,+BAA+B,CAAC;KACpD,MAAM,CACN,mBAAmB,EACnB,mDAAmD,CACnD;KACA,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;KAChE,MAAM,CAAC,qBAAqB,EAAE,oCAAoC,CAAC;KACnE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACzB,IAAI,CAAC;QACJ,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CACZ,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC9C,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACF,CAAC,CAAC,CAAC;AAEJ,OAAO;KACL,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,KAAK,IAAI,EAAE;IAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC,CAAC;AAEJ,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface DashboardOptions {
2
+ path?: string;
3
+ }
4
+ export declare function dashboard(options: DashboardOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"AAIA,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQxE"}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import { render } from "ink";
3
+ import { AgentDashboard } from "../tui/components/AgentDashboard.js";
4
+ export async function dashboard(options) {
5
+ const workflowPath = options.path || process.cwd();
6
+ const { waitUntilExit } = render(React.createElement(AgentDashboard, { workflowPath }));
7
+ await waitUntilExit();
8
+ }
9
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAMrE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAyB;IACvD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEnD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAC9B,KAAK,CAAC,aAAa,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,CAAC,CACtD,CAAC;IAEF,MAAM,aAAa,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Agent } from "../hooks/useAgents.js";
2
+ interface AgentCardProps {
3
+ agent: Agent;
4
+ isSelected: boolean;
5
+ compact?: boolean;
6
+ }
7
+ export declare function AgentCard({ agent, isSelected, compact }: AgentCardProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=AgentCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentCard.d.ts","sourceRoot":"","sources":["../../../src/tui/components/AgentCard.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,UAAU,cAAc;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAsBD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,cAAc,2CA8GvE"}
@@ -0,0 +1,71 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ const statusColors = {
4
+ running: "green",
5
+ in_progress: "green",
6
+ blocked: "yellow",
7
+ review: "magenta",
8
+ completed: "cyan",
9
+ failed: "red",
10
+ stopped: "gray",
11
+ };
12
+ const statusIcons = {
13
+ running: "●",
14
+ in_progress: "●",
15
+ blocked: "◐",
16
+ review: "◉",
17
+ completed: "✓",
18
+ failed: "✗",
19
+ stopped: "○",
20
+ };
21
+ export function AgentCard({ agent, isSelected, compact }) {
22
+ const statusColor = statusColors[agent.status] || "white";
23
+ const statusIcon = statusIcons[agent.status] || "?";
24
+ // Format elapsed time
25
+ const elapsed = getElapsedTime(agent.started_at);
26
+ // Compact mode for kanban columns
27
+ if (compact) {
28
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: isSelected ? "bold" : "single", borderColor: isSelected ? "cyan" : "gray", paddingX: 1, marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { color: statusColor, children: [statusIcon, " "] }), _jsx(Text, { bold: isSelected, wrap: "truncate", children: truncate(agent.name, 15) }), !agent.is_alive &&
29
+ (agent.status === "running" || agent.status === "in_progress") && (_jsx(Text, { color: "red", children: " !" }))] }), _jsxs(Text, { color: "gray", dimColor: true, children: ["P", agent.current_phase, " | ", elapsed] }), agent.error && _jsxs(Text, { color: "red", children: ["\u26A0 ", truncate(agent.error, 12)] })] }));
30
+ }
31
+ // Full mode
32
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: isSelected ? "double" : "single", borderColor: isSelected ? "cyan" : "gray", paddingX: 1, marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { color: statusColor, children: [statusIcon, " "] }), _jsx(Text, { bold: isSelected, wrap: "truncate", children: agent.name })] }), agent.branch && (_jsx(Text, { color: "gray", dimColor: true, children: agent.branch })), _jsxs(Box, { children: [_jsxs(Text, { color: "blue", children: ["Phase ", agent.current_phase] }), _jsx(Text, { color: "gray", children: " | " }), _jsx(Text, { color: statusColor, children: agent.status }), !agent.is_alive &&
33
+ (agent.status === "running" || agent.status === "in_progress") && (_jsx(Text, { color: "red", children: " (dead)" }))] }), _jsxs(Box, { children: [_jsx(Text, { color: "gray", dimColor: true, children: elapsed }), _jsxs(Text, { color: "gray", children: [" | PID: ", agent.pid] })] }), agent.last_log_lines && agent.last_log_lines.length > 0 && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", dimColor: true, wrap: "truncate", children: truncate(cleanLogLine(agent.last_log_lines[agent.last_log_lines.length - 1]), 60) }) })), agent.error && (_jsx(Text, { color: "red", wrap: "truncate", children: truncate(agent.error, 50) })), agent.pr_url && (_jsxs(Text, { color: "green", children: ["PR: ", truncate(agent.pr_url, 50)] }))] }));
34
+ }
35
+ function getElapsedTime(startedAt) {
36
+ try {
37
+ const start = new Date(startedAt);
38
+ const now = new Date();
39
+ const diffMs = now.getTime() - start.getTime();
40
+ const seconds = Math.floor(diffMs / 1000);
41
+ const minutes = Math.floor(seconds / 60);
42
+ const hours = Math.floor(minutes / 60);
43
+ if (hours > 0) {
44
+ return `${hours}h ${minutes % 60}m`;
45
+ }
46
+ else if (minutes > 0) {
47
+ return `${minutes}m ${seconds % 60}s`;
48
+ }
49
+ else {
50
+ return `${seconds}s`;
51
+ }
52
+ }
53
+ catch {
54
+ return "unknown";
55
+ }
56
+ }
57
+ function truncate(str, maxLen) {
58
+ if (!str)
59
+ return "";
60
+ if (str.length <= maxLen)
61
+ return str;
62
+ return str.slice(0, maxLen - 3) + "...";
63
+ }
64
+ function cleanLogLine(line) {
65
+ // Remove ANSI color codes and JSON formatting
66
+ return line
67
+ .replace(/\x1b\[[0-9;]*m/g, "")
68
+ .replace(/^\s*\{.*\}\s*$/, "[JSON output]")
69
+ .trim();
70
+ }
71
+ //# sourceMappingURL=AgentCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentCard.js","sourceRoot":"","sources":["../../../src/tui/components/AgentCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface AgentDashboardProps {
2
+ workflowPath?: string;
3
+ }
4
+ export declare function AgentDashboard({ workflowPath }: AgentDashboardProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=AgentDashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentDashboard.d.ts","sourceRoot":"","sources":["../../../src/tui/components/AgentDashboard.tsx"],"names":[],"mappings":"AAMA,UAAU,mBAAmB;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA8BD,wBAAgB,cAAc,CAAC,EAAE,YAAY,EAAE,EAAE,mBAAmB,2CAuHnE"}
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, Text, useApp, useInput } from "ink";
4
+ import { useAgents } from "../hooks/useAgents.js";
5
+ import { AgentCard } from "./AgentCard.js";
6
+ const COLUMNS = [
7
+ {
8
+ id: "running",
9
+ title: "Running",
10
+ statuses: ["running", "in_progress"],
11
+ color: "green",
12
+ },
13
+ {
14
+ id: "blocked",
15
+ title: "Blocked",
16
+ statuses: ["blocked", "stopped", "failed"],
17
+ color: "red",
18
+ },
19
+ {
20
+ id: "review",
21
+ title: "Review",
22
+ statuses: ["review", "completed"],
23
+ color: "magenta",
24
+ },
25
+ ];
26
+ export function AgentDashboard({ workflowPath }) {
27
+ const { exit } = useApp();
28
+ const { agents, loading, error, refresh } = useAgents(workflowPath);
29
+ const [selectedColumn, setSelectedColumn] = useState(0);
30
+ const [selectedIndex, setSelectedIndex] = useState(0);
31
+ // Get agents for each column
32
+ const getColumnAgents = (column) => {
33
+ return agents.filter((agent) => column.statuses.includes(agent.status));
34
+ };
35
+ // Keyboard navigation
36
+ useInput((input, key) => {
37
+ if (input === "q" || (key.ctrl && input === "c")) {
38
+ exit();
39
+ return;
40
+ }
41
+ if (input === "r") {
42
+ refresh();
43
+ return;
44
+ }
45
+ // Navigate between columns
46
+ if (key.leftArrow) {
47
+ setSelectedColumn((prev) => Math.max(0, prev - 1));
48
+ setSelectedIndex(0);
49
+ }
50
+ if (key.rightArrow) {
51
+ setSelectedColumn((prev) => Math.min(COLUMNS.length - 1, prev + 1));
52
+ setSelectedIndex(0);
53
+ }
54
+ // Navigate within column
55
+ const currentColumn = COLUMNS[selectedColumn];
56
+ const columnAgents = getColumnAgents(currentColumn);
57
+ if (key.upArrow) {
58
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
59
+ }
60
+ if (key.downArrow) {
61
+ setSelectedIndex((prev) => Math.min(columnAgents.length - 1, prev + 1));
62
+ }
63
+ });
64
+ return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [_jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: "Multi-Agent Dashboard" }), _jsx(Text, { color: "gray", children: " | " }), _jsxs(Text, { children: [agents.length, " agents"] })] }), _jsxs(Box, { children: [error && _jsxs(Text, { color: "red", children: ["Error: ", error] }), !error && _jsx(Text, { color: "gray", children: "Auto-refresh: 1s" })] })] }), _jsx(Box, { flexDirection: "row", width: "100%", minHeight: 20, children: COLUMNS.map((column, colIndex) => {
65
+ const columnAgents = getColumnAgents(column);
66
+ const isSelected = colIndex === selectedColumn;
67
+ return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, flexBasis: 0, borderStyle: isSelected ? "bold" : "single", borderColor: isSelected ? column.color : "gray", marginRight: colIndex < COLUMNS.length - 1 ? 1 : 0, children: [_jsxs(Box, { justifyContent: "center", paddingX: 1, children: [_jsx(Text, { bold: true, color: column.color, children: column.title }), _jsxs(Text, { color: "gray", children: [" (", columnAgents.length, ")"] })] }), _jsx(Box, { flexDirection: "column", paddingX: 1, paddingY: 1, children: columnAgents.length === 0 ? (_jsx(Text, { color: "gray", dimColor: true, children: "-" })) : (columnAgents.map((agent, agentIndex) => (_jsx(AgentCard, { agent: agent, isSelected: isSelected && agentIndex === selectedIndex, compact: true }, agent.id)))) })] }, column.id));
68
+ }) }), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: _jsx(Text, { color: "gray", children: "\u2190\u2192 Column | \u2191\u2193 Select | r Refresh | q Quit" }) })] }));
69
+ }
70
+ //# sourceMappingURL=AgentDashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentDashboard.js","sourceRoot":"","sources":["../../../src/tui/components/AgentDashboard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface AppProps {
2
+ workflowPath?: string;
3
+ }
4
+ export declare function App({ workflowPath }: AppProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=App.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../src/tui/components/App.tsx"],"names":[],"mappings":"AAyCA,UAAU,QAAQ;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,GAAG,CAAC,EAAE,YAAY,EAAE,EAAE,QAAQ,2CA6D7C"}
@@ -0,0 +1,76 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, useApp, useInput } from "ink";
4
+ import { useFeatures } from "../hooks/useFeatures.js";
5
+ import { KanbanBoard } from "./KanbanBoard.js";
6
+ import { StatusBar } from "./StatusBar.js";
7
+ // Default kanban columns
8
+ const DEFAULT_COLUMNS = [
9
+ {
10
+ id: "backlog",
11
+ title: "Backlog",
12
+ statuses: ["backlog", "pending"],
13
+ color: "gray",
14
+ },
15
+ {
16
+ id: "planning",
17
+ title: "Planning",
18
+ statuses: ["planning"],
19
+ color: "blue",
20
+ },
21
+ {
22
+ id: "in_progress",
23
+ title: "In Progress",
24
+ statuses: ["in_progress", "in-progress"],
25
+ color: "yellow",
26
+ },
27
+ {
28
+ id: "review",
29
+ title: "Review",
30
+ statuses: ["review"],
31
+ color: "magenta",
32
+ },
33
+ {
34
+ id: "completed",
35
+ title: "Completed",
36
+ statuses: ["completed"],
37
+ color: "green",
38
+ },
39
+ ];
40
+ export function App({ workflowPath }) {
41
+ const { exit } = useApp();
42
+ const { features, loading, error, refresh } = useFeatures(workflowPath);
43
+ const [selectedColumn, setSelectedColumn] = useState(0);
44
+ const [selectedFeature, setSelectedFeature] = useState(0);
45
+ // Keyboard navigation
46
+ useInput((input, key) => {
47
+ if (input === "q" || (key.ctrl && input === "c")) {
48
+ exit();
49
+ return;
50
+ }
51
+ if (input === "r") {
52
+ refresh();
53
+ return;
54
+ }
55
+ // Navigate columns
56
+ if (key.leftArrow) {
57
+ setSelectedColumn((prev) => Math.max(0, prev - 1));
58
+ setSelectedFeature(0);
59
+ }
60
+ if (key.rightArrow) {
61
+ setSelectedColumn((prev) => Math.min(DEFAULT_COLUMNS.length - 1, prev + 1));
62
+ setSelectedFeature(0);
63
+ }
64
+ // Navigate features within column
65
+ const currentColumn = DEFAULT_COLUMNS[selectedColumn];
66
+ const columnFeatures = features.filter((f) => currentColumn.statuses.includes(f.status));
67
+ if (key.upArrow) {
68
+ setSelectedFeature((prev) => Math.max(0, prev - 1));
69
+ }
70
+ if (key.downArrow) {
71
+ setSelectedFeature((prev) => Math.min(columnFeatures.length - 1, prev + 1));
72
+ }
73
+ });
74
+ return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [_jsx(StatusBar, { featureCount: features.length, loading: loading, error: error }), _jsx(KanbanBoard, { features: features, columns: DEFAULT_COLUMNS, selectedColumn: selectedColumn, selectedFeature: selectedFeature })] }));
75
+ }
76
+ //# sourceMappingURL=App.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/tui/components/App.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Feature } from "../types.js";
2
+ interface FeatureCardProps {
3
+ feature: Feature;
4
+ isSelected: boolean;
5
+ }
6
+ export declare function FeatureCard({ feature, isSelected }: FeatureCardProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=FeatureCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureCard.d.ts","sourceRoot":"","sources":["../../../src/tui/components/FeatureCard.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,UAAU,gBAAgB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACpB;AAmBD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,gBAAgB,2CAkCpE"}
@@ -0,0 +1,23 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ const priorityColors = {
4
+ critical: "red",
5
+ high: "yellow",
6
+ medium: "blue",
7
+ low: "gray",
8
+ };
9
+ const statusIcons = {
10
+ pending: "○",
11
+ backlog: "○",
12
+ planning: "◐",
13
+ in_progress: "●",
14
+ "in-progress": "●",
15
+ review: "◉",
16
+ completed: "✓",
17
+ };
18
+ export function FeatureCard({ feature, isSelected }) {
19
+ const icon = statusIcons[feature.status] || "○";
20
+ const priorityColor = priorityColors[feature.priority || "medium"] || "white";
21
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: isSelected ? "double" : "single", borderColor: isSelected ? "cyan" : "gray", paddingX: 1, marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { color: priorityColor, children: [icon, " "] }), _jsx(Text, { bold: isSelected, wrap: "truncate", children: feature.name || feature.id })] }), feature.branch && (_jsx(Text, { color: "gray", dimColor: true, children: feature.branch })), feature.next_action && feature.next_action.length > 0 && (_jsxs(Text, { color: "blue", children: ["Phase ", feature.current_phase || 1, "/", feature.next_action.length] })), feature.pr_url && _jsx(Text, { color: "green", children: "PR ready" })] }));
22
+ }
23
+ //# sourceMappingURL=FeatureCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureCard.js","sourceRoot":"","sources":["../../../src/tui/components/FeatureCard.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAQhC,MAAM,cAAc,GAA2B;IAC9C,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,MAAM;IACd,GAAG,EAAE,MAAM;CACX,CAAC;AAEF,MAAM,WAAW,GAA2B;IAC3C,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,GAAG;IACb,WAAW,EAAE,GAAG;IAChB,aAAa,EAAE,GAAG;IAClB,MAAM,EAAE,GAAG;IACX,SAAS,EAAE,GAAG;CACd,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,EAAE,OAAO,EAAE,UAAU,EAAoB;IACpE,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;IAChD,MAAM,aAAa,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,OAAO,CAAC;IAE9E,OAAO,CACN,MAAC,GAAG,IACH,aAAa,EAAC,QAAQ,EACtB,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAC7C,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EACzC,QAAQ,EAAE,CAAC,EACX,YAAY,EAAE,CAAC,aAEf,MAAC,GAAG,eACH,MAAC,IAAI,IAAC,KAAK,EAAE,aAAa,aAAG,IAAI,SAAS,EAC1C,KAAC,IAAI,IAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAC,UAAU,YACrC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,GACrB,IACF,EAEL,OAAO,CAAC,MAAM,IAAI,CAClB,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,QAAQ,kBACzB,OAAO,CAAC,MAAM,GACT,CACP,EAEA,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CACzD,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,uBACV,OAAO,CAAC,aAAa,IAAI,CAAC,OAAG,OAAO,CAAC,WAAW,CAAC,MAAM,IACxD,CACP,EAEA,OAAO,CAAC,MAAM,IAAI,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,yBAAgB,IACjD,CACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Feature, KanbanColumn } from "../types.js";
2
+ interface KanbanBoardProps {
3
+ features: Feature[];
4
+ columns: KanbanColumn[];
5
+ selectedColumn: number;
6
+ selectedFeature: number;
7
+ }
8
+ export declare function KanbanBoard({ features, columns, selectedColumn, selectedFeature, }: KanbanBoardProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=KanbanBoard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KanbanBoard.d.ts","sourceRoot":"","sources":["../../../src/tui/components/KanbanBoard.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGzD,UAAU,gBAAgB;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,WAAW,CAAC,EAC3B,QAAQ,EACR,OAAO,EACP,cAAc,EACd,eAAe,GACf,EAAE,gBAAgB,2CAkDlB"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { FeatureCard } from "./FeatureCard.js";
4
+ export function KanbanBoard({ features, columns, selectedColumn, selectedFeature, }) {
5
+ return (_jsx(Box, { flexDirection: "row", width: "100%", children: columns.map((column, colIndex) => {
6
+ const columnFeatures = features.filter((f) => column.statuses.includes(f.status));
7
+ const isColumnSelected = colIndex === selectedColumn;
8
+ return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, flexBasis: 0, marginRight: 1, borderStyle: isColumnSelected ? "bold" : "single", borderColor: isColumnSelected ? column.color : "gray", children: [_jsxs(Box, { justifyContent: "center", paddingX: 1, children: [_jsx(Text, { bold: true, color: column.color, children: column.title }), _jsxs(Text, { color: "gray", children: [" (", columnFeatures.length, ")"] })] }), _jsx(Box, { flexDirection: "column", paddingX: 1, paddingY: 1, children: columnFeatures.length === 0 ? (_jsx(Text, { color: "gray", dimColor: true, children: "No features" })) : (columnFeatures.map((feature, featureIndex) => (_jsx(FeatureCard, { feature: feature, isSelected: isColumnSelected && featureIndex === selectedFeature }, feature.id)))) })] }, column.id));
9
+ }) }));
10
+ }
11
+ //# sourceMappingURL=KanbanBoard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KanbanBoard.js","sourceRoot":"","sources":["../../../src/tui/components/KanbanBoard.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAS/C,MAAM,UAAU,WAAW,CAAC,EAC3B,QAAQ,EACR,OAAO,EACP,cAAc,EACd,eAAe,GACG;IAClB,OAAO,CACN,KAAC,GAAG,IAAC,aAAa,EAAC,KAAK,EAAC,KAAK,EAAC,MAAM,YACnC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YACjC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5C,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAClC,CAAC;YACF,MAAM,gBAAgB,GAAG,QAAQ,KAAK,cAAc,CAAC;YAErD,OAAO,CACN,MAAC,GAAG,IAEH,aAAa,EAAC,QAAQ,EACtB,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,CAAC,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EACjD,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,aAGrD,MAAC,GAAG,IAAC,cAAc,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,aACvC,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAE,MAAM,CAAC,KAAK,YAC5B,MAAM,CAAC,KAAK,GACP,EACP,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,mBAAI,cAAc,CAAC,MAAM,SAAS,IAC/C,EAGN,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,YAClD,cAAc,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC9B,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,QAAQ,kCAEpB,CACP,CAAC,CAAC,CAAC,CACH,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,CAAC,CAC7C,KAAC,WAAW,IAEX,OAAO,EAAE,OAAO,EAChB,UAAU,EACT,gBAAgB,IAAI,YAAY,KAAK,eAAe,IAHhD,OAAO,CAAC,EAAE,CAKd,CACF,CAAC,CACF,GACI,KAjCD,MAAM,CAAC,EAAE,CAkCT,CACN,CAAC;QACH,CAAC,CAAC,GACG,CACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ interface StatusBarProps {
2
+ featureCount: number;
3
+ loading: boolean;
4
+ error?: string | null;
5
+ }
6
+ export declare function StatusBar({ featureCount, loading, error }: StatusBarProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=StatusBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":"AAGA,UAAU,cAAc;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,cAAc,2CA8BzE"}
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ export function StatusBar({ featureCount, loading, error }) {
4
+ return (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: "Open Flow Dashboard" }), _jsx(Text, { color: "gray", children: " | " }), _jsxs(Text, { children: [featureCount, " features"] })] }), _jsxs(Box, { children: [loading && _jsx(Text, { color: "yellow", children: "Loading..." }), error && _jsxs(Text, { color: "red", children: ["Error: ", error] }), !loading && !error && _jsx(Text, { color: "green", children: "Ready" })] }), _jsx(Box, { children: _jsx(Text, { color: "gray", children: "\u2190\u2191\u2193\u2192 Navigate | r Refresh | q Quit" }) })] }));
5
+ }
6
+ //# sourceMappingURL=StatusBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusBar.js","sourceRoot":"","sources":["../../../src/tui/components/StatusBar.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAQhC,MAAM,UAAU,SAAS,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAkB;IACzE,OAAO,CACN,MAAC,GAAG,IACH,aAAa,EAAC,KAAK,EACnB,cAAc,EAAC,eAAe,EAC9B,WAAW,EAAC,QAAQ,EACpB,WAAW,EAAC,MAAM,EAClB,QAAQ,EAAE,CAAC,aAEX,MAAC,GAAG,eACH,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,0CAEhB,EACP,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,oBAAW,EAC7B,MAAC,IAAI,eAAE,YAAY,iBAAiB,IAC/B,EAEN,MAAC,GAAG,eACF,OAAO,IAAI,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,2BAAkB,EACjD,KAAK,IAAI,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,wBAAS,KAAK,IAAQ,EAChD,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,sBAAa,IAClD,EAEN,KAAC,GAAG,cACH,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,uEAEX,GACF,IACD,CACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface Agent {
2
+ id: string;
3
+ worktree_path: string;
4
+ pid: number;
5
+ started_at: string;
6
+ name: string;
7
+ status: "running" | "in_progress" | "blocked" | "completed" | "review" | "failed" | "stopped";
8
+ branch?: string;
9
+ current_phase: number;
10
+ priority?: string;
11
+ pr_url?: string;
12
+ is_alive: boolean;
13
+ log_file: string;
14
+ last_log_lines: string[];
15
+ error?: string;
16
+ }
17
+ interface UseAgentsResult {
18
+ agents: Agent[];
19
+ loading: boolean;
20
+ error: string | null;
21
+ refresh: () => Promise<void>;
22
+ }
23
+ export declare function useAgents(workflowPath?: string): UseAgentsResult;
24
+ export {};
25
+ //# sourceMappingURL=useAgents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAgents.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useAgents.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,KAAK;IAEpB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IAEnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EACF,SAAS,GACT,aAAa,GACb,SAAS,GACT,WAAW,GACX,QAAQ,GACR,QAAQ,GACR,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe,CAqKhE"}
@@ -0,0 +1,165 @@
1
+ import { useState, useEffect, useCallback } from "react";
2
+ import { readFile, readdir } from "fs/promises";
3
+ import { join } from "path";
4
+ export function useAgents(workflowPath) {
5
+ const [agents, setAgents] = useState([]);
6
+ const [loading, setLoading] = useState(true);
7
+ const [error, setError] = useState(null);
8
+ const basePath = workflowPath || process.cwd();
9
+ const loadAgents = useCallback(async () => {
10
+ setLoading(true);
11
+ setError(null);
12
+ try {
13
+ // Find developer name from .developer file
14
+ const developerFile = join(basePath, "workflow", ".developer");
15
+ let developer = "unknown";
16
+ try {
17
+ const content = await readFile(developerFile, "utf-8");
18
+ const match = content.match(/^name=(.+)$/m);
19
+ if (match) {
20
+ developer = match[1].trim();
21
+ }
22
+ }
23
+ catch {
24
+ // .developer not found, try to find any agent-progress directory
25
+ const agentProgressDir = join(basePath, "workflow", "agent-progress");
26
+ try {
27
+ const dirs = await readdir(agentProgressDir);
28
+ if (dirs.length > 0 && !dirs[0].startsWith(".")) {
29
+ developer = dirs[0];
30
+ }
31
+ }
32
+ catch {
33
+ // No agent-progress directory
34
+ }
35
+ }
36
+ // Read registry.json (just contains worktree locations)
37
+ const registryPath = join(basePath, "workflow", "agent-progress", developer, ".agents", "registry.json");
38
+ let registryData = { agents: [] };
39
+ try {
40
+ const content = await readFile(registryPath, "utf-8");
41
+ registryData = JSON.parse(content);
42
+ }
43
+ catch {
44
+ // Registry doesn't exist yet
45
+ }
46
+ // For each registry entry, read status from worktree/.feature/
47
+ const enrichedAgents = await Promise.all(registryData.agents.map(async (entry) => {
48
+ const agent = {
49
+ // From registry
50
+ id: entry.id,
51
+ worktree_path: entry.worktree_path,
52
+ pid: entry.pid,
53
+ started_at: entry.started_at,
54
+ // Defaults (will be overwritten)
55
+ name: entry.id,
56
+ status: "running",
57
+ current_phase: 1,
58
+ is_alive: false,
59
+ log_file: join(entry.worktree_path, ".agent-log"),
60
+ last_log_lines: [],
61
+ };
62
+ // Check if PID is alive
63
+ agent.is_alive = isPidAlive(entry.pid);
64
+ // Read feature.json from worktree/.feature/
65
+ try {
66
+ const featureJsonPath = join(entry.worktree_path, ".feature", "feature.json");
67
+ const featureContent = await readFile(featureJsonPath, "utf-8");
68
+ const featureJson = JSON.parse(featureContent);
69
+ agent.name = featureJson.name || entry.id;
70
+ agent.status = normalizeStatus(featureJson.status);
71
+ agent.branch = featureJson.branch;
72
+ agent.current_phase = featureJson.current_phase || 1;
73
+ agent.priority = featureJson.priority;
74
+ agent.pr_url = featureJson.pr_url;
75
+ }
76
+ catch {
77
+ // Can't read feature.json
78
+ }
79
+ // Get last few lines of log (needed for status detection)
80
+ try {
81
+ const logContent = await readFile(agent.log_file, "utf-8");
82
+ const lines = logContent.split("\n").filter((l) => l.trim());
83
+ agent.last_log_lines = lines.slice(-10); // Read more lines to find success marker
84
+ }
85
+ catch {
86
+ // Can't read log
87
+ }
88
+ // If process is dead but status is still "running/in_progress"
89
+ // Check log to see if it completed successfully
90
+ if (!agent.is_alive &&
91
+ (agent.status === "running" || agent.status === "in_progress")) {
92
+ // Check if log indicates successful completion
93
+ const lastLines = agent.last_log_lines.join("\n");
94
+ if (lastLines.includes('"subtype":"success"')) {
95
+ agent.status = "completed";
96
+ }
97
+ else {
98
+ agent.status = "stopped";
99
+ }
100
+ }
101
+ // Read blocked.json if exists
102
+ try {
103
+ const blockedPath = join(entry.worktree_path, ".feature", "blocked.json");
104
+ const blockedContent = await readFile(blockedPath, "utf-8");
105
+ const blockedJson = JSON.parse(blockedContent);
106
+ agent.error = blockedJson.message;
107
+ if (blockedJson.type === "blocked") {
108
+ agent.status = "blocked";
109
+ }
110
+ }
111
+ catch {
112
+ // No blocked.json
113
+ }
114
+ return agent;
115
+ }));
116
+ setAgents(enrichedAgents);
117
+ }
118
+ catch (err) {
119
+ setError(err instanceof Error ? err.message : "Failed to load agents");
120
+ }
121
+ finally {
122
+ setLoading(false);
123
+ }
124
+ }, [basePath]);
125
+ // Initial load
126
+ useEffect(() => {
127
+ loadAgents();
128
+ }, [loadAgents]);
129
+ // Auto-refresh every 1 second
130
+ useEffect(() => {
131
+ const interval = setInterval(loadAgents, 1000);
132
+ return () => clearInterval(interval);
133
+ }, [loadAgents]);
134
+ return {
135
+ agents,
136
+ loading,
137
+ error,
138
+ refresh: loadAgents,
139
+ };
140
+ }
141
+ function isPidAlive(pid) {
142
+ try {
143
+ process.kill(pid, 0);
144
+ return true;
145
+ }
146
+ catch {
147
+ return false;
148
+ }
149
+ }
150
+ function normalizeStatus(status) {
151
+ const statusMap = {
152
+ running: "running",
153
+ in_progress: "in_progress",
154
+ "in-progress": "in_progress",
155
+ blocked: "blocked",
156
+ completed: "completed",
157
+ done: "completed",
158
+ review: "review",
159
+ failed: "failed",
160
+ stopped: "stopped",
161
+ planning: "running",
162
+ };
163
+ return statusMap[status?.toLowerCase()] || "running";
164
+ }
165
+ //# sourceMappingURL=useAgents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAgents.js","sourceRoot":"","sources":["../../../src/tui/hooks/useAgents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Feature } from "../types.js";
2
+ interface UseFeaturesResult {
3
+ features: Feature[];
4
+ loading: boolean;
5
+ error: string | null;
6
+ refresh: () => Promise<void>;
7
+ }
8
+ export declare function useFeatures(workflowPath?: string): UseFeaturesResult;
9
+ export {};
10
+ //# sourceMappingURL=useFeatures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFeatures.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useFeatures.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,UAAU,iBAAiB;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAqEpE"}
@@ -0,0 +1,126 @@
1
+ import { useState, useEffect } from "react";
2
+ import { readFile, readdir, stat } from "fs/promises";
3
+ import { join } from "path";
4
+ export function useFeatures(workflowPath) {
5
+ const [features, setFeatures] = useState([]);
6
+ const [loading, setLoading] = useState(true);
7
+ const [error, setError] = useState(null);
8
+ const basePath = workflowPath || process.cwd();
9
+ const loadFeatures = async () => {
10
+ setLoading(true);
11
+ setError(null);
12
+ try {
13
+ // Search in workflow/agent-progress/*/features/ (actual structure)
14
+ const agentProgressDir = join(basePath, "workflow", "agent-progress");
15
+ const featureFiles = await findAllFeatureFiles(agentProgressDir);
16
+ const loadedFeatures = [];
17
+ for (const filePath of featureFiles) {
18
+ try {
19
+ const content = await readFile(filePath, "utf-8");
20
+ const data = JSON.parse(content);
21
+ // Normalize the feature data
22
+ const feature = {
23
+ id: data.id || data.name || "unknown",
24
+ name: data.name || data.id || "Unnamed Feature",
25
+ status: normalizeStatus(data.status),
26
+ branch: data.branch,
27
+ priority: data.priority || "medium",
28
+ developer: data.developer,
29
+ created_at: data.created_at,
30
+ pr_url: data.pr_url,
31
+ next_action: data.next_action,
32
+ current_phase: data.current_phase,
33
+ };
34
+ loadedFeatures.push(feature);
35
+ }
36
+ catch {
37
+ // Skip files that can't be parsed
38
+ }
39
+ }
40
+ // Sort by priority (critical > high > medium > low)
41
+ const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
42
+ loadedFeatures.sort((a, b) => (priorityOrder[a.priority || "medium"] || 2) -
43
+ (priorityOrder[b.priority || "medium"] || 2));
44
+ setFeatures(loadedFeatures);
45
+ }
46
+ catch (err) {
47
+ setError(err instanceof Error ? err.message : "Failed to load features");
48
+ }
49
+ finally {
50
+ setLoading(false);
51
+ }
52
+ };
53
+ useEffect(() => {
54
+ loadFeatures();
55
+ }, [basePath]);
56
+ return {
57
+ features,
58
+ loading,
59
+ error,
60
+ refresh: loadFeatures,
61
+ };
62
+ }
63
+ // Find all feature.json files in workflow/agent-progress/*/features/
64
+ async function findAllFeatureFiles(agentProgressDir) {
65
+ const results = [];
66
+ try {
67
+ // List all user directories (e.g., taosu, other-dev)
68
+ const users = await readdir(agentProgressDir);
69
+ for (const user of users) {
70
+ const userFeaturesDir = join(agentProgressDir, user, "features");
71
+ const userFeatures = await findFeatureFilesRecursive(userFeaturesDir);
72
+ results.push(...userFeatures);
73
+ }
74
+ }
75
+ catch {
76
+ // Directory doesn't exist
77
+ }
78
+ return results;
79
+ }
80
+ // Recursively find feature.json files, skipping archive
81
+ async function findFeatureFilesRecursive(dir) {
82
+ const results = [];
83
+ try {
84
+ const entries = await readdir(dir);
85
+ for (const entry of entries) {
86
+ // Skip archive and node_modules
87
+ if (entry === "archive" || entry === "node_modules") {
88
+ continue;
89
+ }
90
+ const fullPath = join(dir, entry);
91
+ const entryStat = await stat(fullPath);
92
+ if (entryStat.isDirectory()) {
93
+ // Check for feature.json in this directory
94
+ const featureJsonPath = join(fullPath, "feature.json");
95
+ try {
96
+ await stat(featureJsonPath);
97
+ results.push(featureJsonPath);
98
+ }
99
+ catch {
100
+ // No feature.json here, recurse into subdirectory
101
+ const subResults = await findFeatureFilesRecursive(fullPath);
102
+ results.push(...subResults);
103
+ }
104
+ }
105
+ }
106
+ }
107
+ catch {
108
+ // Directory doesn't exist or can't be read
109
+ }
110
+ return results;
111
+ }
112
+ function normalizeStatus(status) {
113
+ const statusMap = {
114
+ pending: "pending",
115
+ backlog: "backlog",
116
+ planning: "planning",
117
+ in_progress: "in_progress",
118
+ "in-progress": "in_progress",
119
+ inprogress: "in_progress",
120
+ review: "review",
121
+ completed: "completed",
122
+ done: "completed",
123
+ };
124
+ return statusMap[status?.toLowerCase()] || "pending";
125
+ }
126
+ //# sourceMappingURL=useFeatures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFeatures.js","sourceRoot":"","sources":["../../../src/tui/hooks/useFeatures.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export { AgentDashboard } from "./components/AgentDashboard.js";
2
+ export { AgentCard } from "./components/AgentCard.js";
3
+ export { App } from "./components/App.js";
4
+ export { KanbanBoard } from "./components/KanbanBoard.js";
5
+ export { FeatureCard } from "./components/FeatureCard.js";
6
+ export { StatusBar } from "./components/StatusBar.js";
7
+ export { useAgents } from "./hooks/useAgents.js";
8
+ export { useFeatures } from "./hooks/useFeatures.js";
9
+ export type { Agent } from "./hooks/useAgents.js";
10
+ export type { Feature, FeatureStatus, PhaseAction, KanbanColumn, DashboardState, } from "./types.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tui/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGtD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGtD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,YAAY,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,YAAY,EACV,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,cAAc,GACf,MAAM,YAAY,CAAC"}
@@ -0,0 +1,12 @@
1
+ // TUI components
2
+ export { AgentDashboard } from "./components/AgentDashboard.js";
3
+ export { AgentCard } from "./components/AgentCard.js";
4
+ // Legacy components (for feature.json based view)
5
+ export { App } from "./components/App.js";
6
+ export { KanbanBoard } from "./components/KanbanBoard.js";
7
+ export { FeatureCard } from "./components/FeatureCard.js";
8
+ export { StatusBar } from "./components/StatusBar.js";
9
+ // Hooks
10
+ export { useAgents } from "./hooks/useAgents.js";
11
+ export { useFeatures } from "./hooks/useFeatures.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tui/index.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,kDAAkD;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,QAAQ;AACR,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,33 @@
1
+ export type FeatureStatus = "pending" | "in_progress" | "in-progress" | "review" | "completed" | "backlog" | "planning";
2
+ export interface Feature {
3
+ id: string;
4
+ name: string;
5
+ status: FeatureStatus;
6
+ branch?: string;
7
+ priority?: "low" | "medium" | "high" | "critical";
8
+ developer?: string;
9
+ created_at?: string;
10
+ pr_url?: string;
11
+ next_action?: PhaseAction[];
12
+ current_phase?: number;
13
+ }
14
+ export interface PhaseAction {
15
+ phase: number;
16
+ action: string;
17
+ target: string;
18
+ detail?: string;
19
+ }
20
+ export interface KanbanColumn {
21
+ id: string;
22
+ title: string;
23
+ statuses: FeatureStatus[];
24
+ color: string;
25
+ }
26
+ export interface DashboardState {
27
+ features: Feature[];
28
+ selectedColumn: number;
29
+ selectedFeature: number;
30
+ loading: boolean;
31
+ error?: string;
32
+ }
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tui/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,aAAa,GACtB,SAAS,GACT,aAAa,GACb,aAAa,GACb,QAAQ,GACR,WAAW,GACX,SAAS,GACT,UAAU,CAAC;AAGd,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tui/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mind-fold/open-flow",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "AI-assisted development workflow initializer for Cursor, Claude Code and more",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,11 +37,16 @@
37
37
  "dependencies": {
38
38
  "chalk": "^5.3.0",
39
39
  "commander": "^12.1.0",
40
- "inquirer": "^9.3.7"
40
+ "ink": "^6.0.0",
41
+ "ink-select-input": "^6.2.0",
42
+ "ink-spinner": "^5.0.0",
43
+ "inquirer": "^9.3.7",
44
+ "react": "^19.2.3"
41
45
  },
42
46
  "devDependencies": {
43
47
  "@types/inquirer": "^9.0.7",
44
48
  "@types/node": "^20.17.10",
49
+ "@types/react": "^19.2.7",
45
50
  "typescript": "^5.7.2"
46
51
  },
47
52
  "engines": {