ralph-wiggum-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/cli/commands/add.d.ts +10 -0
  2. package/dist/cli/commands/add.d.ts.map +1 -0
  3. package/dist/cli/commands/add.js +87 -0
  4. package/dist/cli/commands/add.js.map +1 -0
  5. package/dist/cli/commands/init.d.ts +5 -0
  6. package/dist/cli/commands/init.d.ts.map +1 -0
  7. package/dist/cli/commands/init.js +91 -0
  8. package/dist/cli/commands/init.js.map +1 -0
  9. package/dist/cli/commands/list.d.ts +9 -0
  10. package/dist/cli/commands/list.d.ts.map +1 -0
  11. package/dist/cli/commands/list.js +90 -0
  12. package/dist/cli/commands/list.js.map +1 -0
  13. package/dist/cli/commands/run.d.ts +10 -0
  14. package/dist/cli/commands/run.d.ts.map +1 -0
  15. package/dist/cli/commands/run.js +200 -0
  16. package/dist/cli/commands/run.js.map +1 -0
  17. package/dist/cli/commands/serve.d.ts +10 -0
  18. package/dist/cli/commands/serve.d.ts.map +1 -0
  19. package/dist/cli/commands/serve.js +57 -0
  20. package/dist/cli/commands/serve.js.map +1 -0
  21. package/dist/cli/commands/status.d.ts +5 -0
  22. package/dist/cli/commands/status.d.ts.map +1 -0
  23. package/dist/cli/commands/status.js +63 -0
  24. package/dist/cli/commands/status.js.map +1 -0
  25. package/dist/cli/index.d.ts +6 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +76 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/lib/config.d.ts +53 -0
  30. package/dist/lib/config.d.ts.map +1 -0
  31. package/dist/lib/config.js +164 -0
  32. package/dist/lib/config.js.map +1 -0
  33. package/dist/lib/index.d.ts +11 -0
  34. package/dist/lib/index.d.ts.map +1 -0
  35. package/dist/lib/index.js +18 -0
  36. package/dist/lib/index.js.map +1 -0
  37. package/dist/lib/logger.d.ts +72 -0
  38. package/dist/lib/logger.d.ts.map +1 -0
  39. package/dist/lib/logger.js +159 -0
  40. package/dist/lib/logger.js.map +1 -0
  41. package/dist/lib/preflight.d.ts +45 -0
  42. package/dist/lib/preflight.d.ts.map +1 -0
  43. package/dist/lib/preflight.js +173 -0
  44. package/dist/lib/preflight.js.map +1 -0
  45. package/dist/lib/progress.d.ts +41 -0
  46. package/dist/lib/progress.d.ts.map +1 -0
  47. package/dist/lib/progress.js +122 -0
  48. package/dist/lib/progress.js.map +1 -0
  49. package/dist/lib/tasks.d.ts +77 -0
  50. package/dist/lib/tasks.d.ts.map +1 -0
  51. package/dist/lib/tasks.js +259 -0
  52. package/dist/lib/tasks.js.map +1 -0
  53. package/dist/lib/templates.d.ts +25 -0
  54. package/dist/lib/templates.d.ts.map +1 -0
  55. package/dist/lib/templates.js +86 -0
  56. package/dist/lib/templates.js.map +1 -0
  57. package/dist/server/api.d.ts +7 -0
  58. package/dist/server/api.d.ts.map +1 -0
  59. package/dist/server/api.js +258 -0
  60. package/dist/server/api.js.map +1 -0
  61. package/dist/server/index.d.ts +15 -0
  62. package/dist/server/index.d.ts.map +1 -0
  63. package/dist/server/index.js +59 -0
  64. package/dist/server/index.js.map +1 -0
  65. package/dist/server/runner.d.ts +15 -0
  66. package/dist/server/runner.d.ts.map +1 -0
  67. package/dist/server/runner.js +265 -0
  68. package/dist/server/runner.js.map +1 -0
  69. package/dist/types/index.d.ts +129 -0
  70. package/dist/types/index.d.ts.map +1 -0
  71. package/dist/types/index.js +37 -0
  72. package/dist/types/index.js.map +1 -0
  73. package/dist/ui/assets/index-DBOjIoHW.js +137 -0
  74. package/dist/ui/assets/index-mu6cQFl4.css +1 -0
  75. package/dist/ui/favicon.svg +3 -0
  76. package/dist/ui/index.html +14 -0
  77. package/package.json +78 -0
  78. package/templates/AGENTS.md +48 -0
  79. package/templates/prompt.md +64 -0
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Task (User Story) management for Ralph Wiggum UI
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
5
+ import { PRD_FILE } from '../types/index.js';
6
+ import { getRalphFilePath } from './config.js';
7
+ /**
8
+ * Generate a new task ID
9
+ */
10
+ export function generateTaskId(existingIds) {
11
+ // Find the highest existing number
12
+ const numbers = existingIds
13
+ .map((id) => {
14
+ const match = id.match(/^US-(\d+)$/);
15
+ return match ? parseInt(match[1] ?? '0', 10) : 0;
16
+ })
17
+ .filter((n) => n > 0);
18
+ const nextNumber = numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
19
+ return `US-${String(nextNumber).padStart(3, '0')}`;
20
+ }
21
+ /**
22
+ * Create an empty PRD
23
+ */
24
+ export function createEmptyPRD(project, branch) {
25
+ return {
26
+ version: '1.0.0',
27
+ project,
28
+ branchName: branch,
29
+ description: '',
30
+ createdAt: new Date().toISOString(),
31
+ userStories: [],
32
+ };
33
+ }
34
+ /**
35
+ * Load the PRD file
36
+ */
37
+ export function loadPRD(cwd) {
38
+ const prdPath = getRalphFilePath(cwd, PRD_FILE);
39
+ if (!existsSync(prdPath)) {
40
+ throw new Error(`PRD file not found: ${prdPath}`);
41
+ }
42
+ try {
43
+ const content = readFileSync(prdPath, 'utf-8');
44
+ return JSON.parse(content);
45
+ }
46
+ catch (error) {
47
+ if (error instanceof SyntaxError) {
48
+ throw new Error(`Invalid JSON in PRD file: ${prdPath}`);
49
+ }
50
+ throw error;
51
+ }
52
+ }
53
+ /**
54
+ * Save the PRD file
55
+ */
56
+ export function savePRD(cwd, prd) {
57
+ const prdPath = getRalphFilePath(cwd, PRD_FILE);
58
+ prd.updatedAt = new Date().toISOString();
59
+ const content = JSON.stringify(prd, null, 2);
60
+ writeFileSync(prdPath, content, 'utf-8');
61
+ }
62
+ /**
63
+ * Check if PRD file exists
64
+ */
65
+ export function prdExists(cwd) {
66
+ const prdPath = getRalphFilePath(cwd, PRD_FILE);
67
+ return existsSync(prdPath);
68
+ }
69
+ /**
70
+ * Add a new task to the PRD
71
+ */
72
+ export function addTask(cwd, task) {
73
+ const prd = loadPRD(cwd);
74
+ const existingIds = prd.userStories.map((s) => s.id);
75
+ const id = generateTaskId(existingIds);
76
+ // Get the next priority (highest + 1)
77
+ const priorities = prd.userStories.map((s) => s.priority);
78
+ const nextPriority = priorities.length > 0 ? Math.max(...priorities) + 1 : 1;
79
+ const newTask = {
80
+ id,
81
+ title: task.title,
82
+ description: task.description,
83
+ acceptanceCriteria: task.acceptanceCriteria,
84
+ priority: nextPriority,
85
+ status: 'pending',
86
+ createdAt: new Date().toISOString(),
87
+ ...(task.notes ? { notes: task.notes } : {}),
88
+ };
89
+ prd.userStories.push(newTask);
90
+ savePRD(cwd, prd);
91
+ return newTask;
92
+ }
93
+ /**
94
+ * Update an existing task
95
+ */
96
+ export function updateTask(cwd, taskId, updates) {
97
+ const prd = loadPRD(cwd);
98
+ const taskIndex = prd.userStories.findIndex((s) => s.id === taskId);
99
+ if (taskIndex === -1) {
100
+ throw new Error(`Task not found: ${taskId}`);
101
+ }
102
+ const task = prd.userStories[taskIndex];
103
+ if (!task) {
104
+ throw new Error(`Task not found: ${taskId}`);
105
+ }
106
+ const updatedTask = {
107
+ ...task,
108
+ ...updates,
109
+ updatedAt: new Date().toISOString(),
110
+ };
111
+ // If marking as completed, add completedAt
112
+ if (updates.status === 'completed' && task.status !== 'completed') {
113
+ updatedTask.completedAt = new Date().toISOString();
114
+ }
115
+ prd.userStories[taskIndex] = updatedTask;
116
+ savePRD(cwd, prd);
117
+ return updatedTask;
118
+ }
119
+ /**
120
+ * Delete a task
121
+ */
122
+ export function deleteTask(cwd, taskId) {
123
+ const prd = loadPRD(cwd);
124
+ const taskIndex = prd.userStories.findIndex((s) => s.id === taskId);
125
+ if (taskIndex === -1) {
126
+ throw new Error(`Task not found: ${taskId}`);
127
+ }
128
+ prd.userStories.splice(taskIndex, 1);
129
+ savePRD(cwd, prd);
130
+ }
131
+ /**
132
+ * Get all tasks
133
+ */
134
+ export function getAllTasks(cwd) {
135
+ const prd = loadPRD(cwd);
136
+ return prd.userStories;
137
+ }
138
+ /**
139
+ * Get tasks by status
140
+ */
141
+ export function getTasksByStatus(cwd, status) {
142
+ const prd = loadPRD(cwd);
143
+ return prd.userStories.filter((s) => s.status === status);
144
+ }
145
+ /**
146
+ * Get the next pending task (highest priority)
147
+ */
148
+ export function getNextTask(cwd) {
149
+ const pendingTasks = getTasksByStatus(cwd, 'pending');
150
+ if (pendingTasks.length === 0) {
151
+ return null;
152
+ }
153
+ // Sort by priority (lower number = higher priority)
154
+ pendingTasks.sort((a, b) => a.priority - b.priority);
155
+ return pendingTasks[0] ?? null;
156
+ }
157
+ /**
158
+ * Get a task by ID
159
+ */
160
+ export function getTaskById(cwd, taskId) {
161
+ const prd = loadPRD(cwd);
162
+ return prd.userStories.find((s) => s.id === taskId) ?? null;
163
+ }
164
+ /**
165
+ * Reorder tasks (update priorities)
166
+ */
167
+ export function reorderTasks(cwd, taskIds) {
168
+ const prd = loadPRD(cwd);
169
+ // Update priorities based on the new order
170
+ taskIds.forEach((taskId, index) => {
171
+ const task = prd.userStories.find((s) => s.id === taskId);
172
+ if (task) {
173
+ task.priority = index + 1;
174
+ task.updatedAt = new Date().toISOString();
175
+ }
176
+ });
177
+ savePRD(cwd, prd);
178
+ }
179
+ /**
180
+ * Get status summary
181
+ */
182
+ export function getStatusSummary(cwd) {
183
+ if (!prdExists(cwd)) {
184
+ return {
185
+ initialized: false,
186
+ totalTasks: 0,
187
+ completedTasks: 0,
188
+ pendingTasks: 0,
189
+ inProgressTasks: 0,
190
+ };
191
+ }
192
+ const prd = loadPRD(cwd);
193
+ const tasks = prd.userStories;
194
+ const completedTasks = tasks.filter((t) => t.status === 'completed').length;
195
+ const pendingTasks = tasks.filter((t) => t.status === 'pending').length;
196
+ const inProgressTasks = tasks.filter((t) => t.status === 'in_progress').length;
197
+ const nextTask = getNextTask(cwd);
198
+ const response = {
199
+ initialized: true,
200
+ project: prd.project,
201
+ branch: prd.branchName,
202
+ totalTasks: tasks.length,
203
+ completedTasks,
204
+ pendingTasks,
205
+ inProgressTasks,
206
+ };
207
+ if (nextTask) {
208
+ response.nextTask = nextTask;
209
+ }
210
+ return response;
211
+ }
212
+ /**
213
+ * Mark a task as in progress
214
+ */
215
+ export function markTaskInProgress(cwd, taskId) {
216
+ return updateTask(cwd, taskId, { status: 'in_progress' });
217
+ }
218
+ /**
219
+ * Mark a task as completed
220
+ */
221
+ export function markTaskCompleted(cwd, taskId, notes) {
222
+ const updates = {
223
+ status: 'completed',
224
+ };
225
+ if (notes) {
226
+ updates.notes = notes;
227
+ }
228
+ return updateTask(cwd, taskId, updates);
229
+ }
230
+ /**
231
+ * Mark a task as failed
232
+ */
233
+ export function markTaskFailed(cwd, taskId, error) {
234
+ const updates = {
235
+ status: 'failed',
236
+ };
237
+ if (error) {
238
+ updates.notes = error;
239
+ }
240
+ return updateTask(cwd, taskId, updates);
241
+ }
242
+ /**
243
+ * Reset a failed task back to pending
244
+ */
245
+ export function resetTask(cwd, taskId) {
246
+ // Get the current task to clear notes
247
+ const prd = loadPRD(cwd);
248
+ const task = prd.userStories.find((s) => s.id === taskId);
249
+ if (!task) {
250
+ throw new Error(`Task not found: ${taskId}`);
251
+ }
252
+ // Remove notes and set to pending
253
+ delete task.notes;
254
+ task.status = 'pending';
255
+ task.updatedAt = new Date().toISOString();
256
+ savePRD(cwd, prd);
257
+ return task;
258
+ }
259
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/lib/tasks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Template loading and processing for Ralph Wiggum UI
3
+ */
4
+ import type { Config } from '../types/index.js';
5
+ /**
6
+ * Load a template file
7
+ */
8
+ export declare function loadTemplate(templateName: string): string;
9
+ /**
10
+ * Process template variables
11
+ */
12
+ export declare function processTemplate(template: string, variables: Record<string, string>): string;
13
+ /**
14
+ * Generate the AGENTS.md file from template
15
+ */
16
+ export declare function generateAgentsFile(config: Config): string;
17
+ /**
18
+ * Generate the prompt.md file from template
19
+ */
20
+ export declare function generatePromptFile(): string;
21
+ /**
22
+ * Write all template files to the Ralph directory
23
+ */
24
+ export declare function writeTemplateFiles(cwd: string, config: Config, branch: string): void;
25
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA+BhD;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAczD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,IAAI,CAmBN"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Template loading and processing for Ralph Wiggum UI
3
+ */
4
+ import { readFileSync, writeFileSync } from 'fs';
5
+ import { join, dirname } from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { AGENTS_FILE, PROMPT_FILE, PRD_FILE, } from '../types/index.js';
8
+ import { getRalphFilePath } from './config.js';
9
+ import { createEmptyPRD } from './tasks.js';
10
+ import { createProgressFile } from './progress.js';
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ /**
14
+ * Get the path to a template file
15
+ */
16
+ function getTemplatePath(templateName) {
17
+ // Templates are at the package root in ./templates/
18
+ // From dist/lib/, go up two levels to reach package root
19
+ const rootPath = join(__dirname, '..', '..', 'templates', templateName);
20
+ // In development, templates might be in src/templates
21
+ const srcPath = join(__dirname, '..', 'templates', templateName);
22
+ try {
23
+ readFileSync(rootPath);
24
+ return rootPath;
25
+ }
26
+ catch {
27
+ return srcPath;
28
+ }
29
+ }
30
+ /**
31
+ * Load a template file
32
+ */
33
+ export function loadTemplate(templateName) {
34
+ const templatePath = getTemplatePath(templateName);
35
+ return readFileSync(templatePath, 'utf-8');
36
+ }
37
+ /**
38
+ * Process template variables
39
+ */
40
+ export function processTemplate(template, variables) {
41
+ let result = template;
42
+ for (const [key, value] of Object.entries(variables)) {
43
+ const pattern = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
44
+ result = result.replace(pattern, value);
45
+ }
46
+ return result;
47
+ }
48
+ /**
49
+ * Generate the AGENTS.md file from template
50
+ */
51
+ export function generateAgentsFile(config) {
52
+ const template = loadTemplate('AGENTS.md');
53
+ const variables = {
54
+ INSTALL_COMMAND: 'npm install',
55
+ DEV_COMMAND: 'npm run dev',
56
+ BUILD_COMMAND: config.commands.build || 'npm run build',
57
+ TEST_COMMAND: config.commands.test || 'npm test',
58
+ TYPECHECK_COMMAND: config.commands.typecheck || 'npm run typecheck',
59
+ LINT_COMMAND: config.commands.lint || 'npm run lint',
60
+ SOURCE_DIR: config.sourceDir,
61
+ };
62
+ return processTemplate(template, variables);
63
+ }
64
+ /**
65
+ * Generate the prompt.md file from template
66
+ */
67
+ export function generatePromptFile() {
68
+ return loadTemplate('prompt.md');
69
+ }
70
+ /**
71
+ * Write all template files to the Ralph directory
72
+ */
73
+ export function writeTemplateFiles(cwd, config, branch) {
74
+ // Write AGENTS.md
75
+ const agentsContent = generateAgentsFile(config);
76
+ writeFileSync(getRalphFilePath(cwd, AGENTS_FILE), agentsContent, 'utf-8');
77
+ // Write prompt.md
78
+ const promptContent = generatePromptFile();
79
+ writeFileSync(getRalphFilePath(cwd, PROMPT_FILE), promptContent, 'utf-8');
80
+ // Write empty prd.json
81
+ const prd = createEmptyPRD(config.project, branch);
82
+ writeFileSync(getRalphFilePath(cwd, PRD_FILE), JSON.stringify(prd, null, 2), 'utf-8');
83
+ // Write progress.txt
84
+ createProgressFile(cwd, config.project);
85
+ }
86
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Ralph Wiggum UI - REST API Routes
3
+ */
4
+ import { Router } from 'express';
5
+ import type { ServerContext } from './index.js';
6
+ export declare function createApiRouter(context: ServerContext): Router;
7
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/server/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAejC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAiR9D"}
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Ralph Wiggum UI - REST API Routes
3
+ */
4
+ import { Router } from 'express';
5
+ import { getAllTasks, getTasksByStatus, getNextTask, addTask, updateTask, deleteTask, reorderTasks, getStatusSummary, loadConfig, getCurrentBranch, listLogFiles, readLogFile, } from '../lib/index.js';
6
+ export function createApiRouter(context) {
7
+ const router = Router();
8
+ const { cwd, taskRunner } = context;
9
+ // ============================================================================
10
+ // Status & Config
11
+ // ============================================================================
12
+ /**
13
+ * GET /api/status
14
+ * Get overall project status
15
+ */
16
+ router.get('/status', (_req, res) => {
17
+ try {
18
+ const status = getStatusSummary(cwd);
19
+ res.json({ success: true, data: status });
20
+ }
21
+ catch (error) {
22
+ const message = error instanceof Error ? error.message : 'Unknown error';
23
+ res.status(500).json({ success: false, error: message });
24
+ }
25
+ });
26
+ /**
27
+ * GET /api/config
28
+ * Get current configuration
29
+ */
30
+ router.get('/config', (_req, res) => {
31
+ try {
32
+ const config = loadConfig(cwd);
33
+ const branch = getCurrentBranch(cwd);
34
+ res.json({ success: true, data: { config, branch } });
35
+ }
36
+ catch (error) {
37
+ const message = error instanceof Error ? error.message : 'Unknown error';
38
+ res.status(500).json({ success: false, error: message });
39
+ }
40
+ });
41
+ // ============================================================================
42
+ // Tasks CRUD
43
+ // ============================================================================
44
+ /**
45
+ * GET /api/tasks
46
+ * Get all tasks, optionally filtered by status
47
+ */
48
+ router.get('/tasks', (req, res) => {
49
+ try {
50
+ const status = req.query.status;
51
+ let tasks;
52
+ if (status) {
53
+ tasks = getTasksByStatus(cwd, status);
54
+ }
55
+ else {
56
+ tasks = getAllTasks(cwd);
57
+ }
58
+ res.json({ success: true, data: tasks });
59
+ }
60
+ catch (error) {
61
+ const message = error instanceof Error ? error.message : 'Unknown error';
62
+ res.status(500).json({ success: false, error: message });
63
+ }
64
+ });
65
+ /**
66
+ * GET /api/tasks/next
67
+ * Get the next task to work on
68
+ */
69
+ router.get('/tasks/next', (_req, res) => {
70
+ try {
71
+ const task = getNextTask(cwd);
72
+ res.json({ success: true, data: task });
73
+ }
74
+ catch (error) {
75
+ const message = error instanceof Error ? error.message : 'Unknown error';
76
+ res.status(500).json({ success: false, error: message });
77
+ }
78
+ });
79
+ /**
80
+ * POST /api/tasks
81
+ * Create a new task
82
+ */
83
+ router.post('/tasks', (req, res) => {
84
+ try {
85
+ const { title, description, acceptanceCriteria } = req.body;
86
+ if (!title) {
87
+ res.status(400).json({ success: false, error: 'Title is required' });
88
+ return;
89
+ }
90
+ const task = addTask(cwd, {
91
+ title,
92
+ description: description || '',
93
+ acceptanceCriteria: acceptanceCriteria || [],
94
+ });
95
+ // Notify connected clients
96
+ context.io.emit('task_created', task);
97
+ res.json({ success: true, data: task });
98
+ }
99
+ catch (error) {
100
+ const message = error instanceof Error ? error.message : 'Unknown error';
101
+ res.status(500).json({ success: false, error: message });
102
+ }
103
+ });
104
+ /**
105
+ * PUT /api/tasks/:id
106
+ * Update a task
107
+ */
108
+ router.put('/tasks/:id', (req, res) => {
109
+ try {
110
+ const { id } = req.params;
111
+ const updates = req.body;
112
+ const task = updateTask(cwd, id, updates);
113
+ // Notify connected clients
114
+ context.io.emit('task_updated', task);
115
+ res.json({ success: true, data: task });
116
+ }
117
+ catch (error) {
118
+ const message = error instanceof Error ? error.message : 'Unknown error';
119
+ res.status(500).json({ success: false, error: message });
120
+ }
121
+ });
122
+ /**
123
+ * DELETE /api/tasks/:id
124
+ * Delete a task
125
+ */
126
+ router.delete('/tasks/:id', (req, res) => {
127
+ try {
128
+ const { id } = req.params;
129
+ deleteTask(cwd, id);
130
+ // Notify connected clients
131
+ context.io.emit('task_deleted', { id });
132
+ res.json({ success: true });
133
+ }
134
+ catch (error) {
135
+ const message = error instanceof Error ? error.message : 'Unknown error';
136
+ res.status(500).json({ success: false, error: message });
137
+ }
138
+ });
139
+ /**
140
+ * POST /api/tasks/reorder
141
+ * Reorder tasks (for drag-and-drop)
142
+ */
143
+ router.post('/tasks/reorder', (req, res) => {
144
+ try {
145
+ const { taskIds } = req.body;
146
+ if (!Array.isArray(taskIds)) {
147
+ res.status(400).json({ success: false, error: 'taskIds must be an array' });
148
+ return;
149
+ }
150
+ reorderTasks(cwd, taskIds);
151
+ // Notify connected clients
152
+ context.io.emit('tasks_reordered', { taskIds });
153
+ res.json({ success: true });
154
+ }
155
+ catch (error) {
156
+ const message = error instanceof Error ? error.message : 'Unknown error';
157
+ res.status(500).json({ success: false, error: message });
158
+ }
159
+ });
160
+ // ============================================================================
161
+ // Task Execution
162
+ // ============================================================================
163
+ /**
164
+ * POST /api/run
165
+ * Start running tasks
166
+ */
167
+ router.post('/run', (req, res) => {
168
+ try {
169
+ const { count, all, stopOnFailure } = req.body;
170
+ if (taskRunner.isRunning()) {
171
+ res.status(400).json({ success: false, error: 'Already running tasks' });
172
+ return;
173
+ }
174
+ let taskCount;
175
+ if (all) {
176
+ taskCount = 'all';
177
+ }
178
+ else if (count && typeof count === 'number') {
179
+ taskCount = count;
180
+ }
181
+ else {
182
+ taskCount = 1;
183
+ }
184
+ taskRunner.start({
185
+ taskCount,
186
+ stopOnFailure: stopOnFailure !== false,
187
+ notifications: true,
188
+ });
189
+ res.json({ success: true, data: taskRunner.getState() });
190
+ }
191
+ catch (error) {
192
+ const message = error instanceof Error ? error.message : 'Unknown error';
193
+ res.status(500).json({ success: false, error: message });
194
+ }
195
+ });
196
+ /**
197
+ * POST /api/run/stop
198
+ * Stop running tasks
199
+ */
200
+ router.post('/run/stop', (_req, res) => {
201
+ try {
202
+ taskRunner.stop();
203
+ res.json({ success: true });
204
+ }
205
+ catch (error) {
206
+ const message = error instanceof Error ? error.message : 'Unknown error';
207
+ res.status(500).json({ success: false, error: message });
208
+ }
209
+ });
210
+ /**
211
+ * GET /api/run/status
212
+ * Get current execution status
213
+ */
214
+ router.get('/run/status', (_req, res) => {
215
+ try {
216
+ const state = taskRunner.getState();
217
+ res.json({ success: true, data: state });
218
+ }
219
+ catch (error) {
220
+ const message = error instanceof Error ? error.message : 'Unknown error';
221
+ res.status(500).json({ success: false, error: message });
222
+ }
223
+ });
224
+ // ============================================================================
225
+ // Logs
226
+ // ============================================================================
227
+ /**
228
+ * GET /api/logs
229
+ * List all log files
230
+ */
231
+ router.get('/logs', (_req, res) => {
232
+ try {
233
+ const logs = listLogFiles(cwd);
234
+ res.json({ success: true, data: logs });
235
+ }
236
+ catch (error) {
237
+ const message = error instanceof Error ? error.message : 'Unknown error';
238
+ res.status(500).json({ success: false, error: message });
239
+ }
240
+ });
241
+ /**
242
+ * GET /api/logs/:filename
243
+ * Read a specific log file
244
+ */
245
+ router.get('/logs/:filename', (req, res) => {
246
+ try {
247
+ const { filename } = req.params;
248
+ const content = readLogFile(cwd, filename);
249
+ res.json({ success: true, data: { filename, content } });
250
+ }
251
+ catch (error) {
252
+ const message = error instanceof Error ? error.message : 'Unknown error';
253
+ res.status(500).json({ success: false, error: message });
254
+ }
255
+ });
256
+ return router;
257
+ }
258
+ //# sourceMappingURL=api.js.map