task-o-matic 0.0.7 → 0.0.9

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 (78) hide show
  1. package/README.md +286 -23
  2. package/dist/commands/benchmark.d.ts +3 -0
  3. package/dist/commands/benchmark.d.ts.map +1 -0
  4. package/dist/commands/benchmark.js +569 -0
  5. package/dist/commands/prd.d.ts.map +1 -1
  6. package/dist/commands/prd.js +203 -9
  7. package/dist/commands/tasks/execute-loop.d.ts +3 -0
  8. package/dist/commands/tasks/execute-loop.d.ts.map +1 -0
  9. package/dist/commands/tasks/execute-loop.js +118 -0
  10. package/dist/commands/tasks/index.d.ts +1 -0
  11. package/dist/commands/tasks/index.d.ts.map +1 -1
  12. package/dist/commands/tasks/index.js +1 -0
  13. package/dist/commands/tasks.d.ts.map +1 -1
  14. package/dist/commands/tasks.js +1 -0
  15. package/dist/commands/workflow.d.ts.map +1 -1
  16. package/dist/commands/workflow.js +491 -331
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -0
  19. package/dist/lib/ai-service/ai-operations.d.ts +5 -0
  20. package/dist/lib/ai-service/ai-operations.d.ts.map +1 -1
  21. package/dist/lib/ai-service/ai-operations.js +167 -0
  22. package/dist/lib/benchmark/registry.d.ts +11 -0
  23. package/dist/lib/benchmark/registry.d.ts.map +1 -0
  24. package/dist/lib/benchmark/registry.js +89 -0
  25. package/dist/lib/benchmark/runner.d.ts +6 -0
  26. package/dist/lib/benchmark/runner.d.ts.map +1 -0
  27. package/dist/lib/benchmark/runner.js +150 -0
  28. package/dist/lib/benchmark/storage.d.ts +13 -0
  29. package/dist/lib/benchmark/storage.d.ts.map +1 -0
  30. package/dist/lib/benchmark/storage.js +99 -0
  31. package/dist/lib/benchmark/types.d.ts +104 -0
  32. package/dist/lib/benchmark/types.d.ts.map +1 -0
  33. package/dist/lib/benchmark/types.js +2 -0
  34. package/dist/lib/index.d.ts +9 -0
  35. package/dist/lib/index.d.ts.map +1 -1
  36. package/dist/lib/index.js +7 -1
  37. package/dist/lib/prompt-registry.d.ts.map +1 -1
  38. package/dist/lib/prompt-registry.js +23 -0
  39. package/dist/lib/task-loop-execution.d.ts +25 -0
  40. package/dist/lib/task-loop-execution.d.ts.map +1 -0
  41. package/dist/lib/task-loop-execution.js +473 -0
  42. package/dist/prompts/index.d.ts +7 -6
  43. package/dist/prompts/index.d.ts.map +1 -1
  44. package/dist/prompts/index.js +1 -0
  45. package/dist/prompts/prd-question.d.ts +3 -0
  46. package/dist/prompts/prd-question.d.ts.map +1 -0
  47. package/dist/prompts/prd-question.js +40 -0
  48. package/dist/services/benchmark.d.ts +12 -0
  49. package/dist/services/benchmark.d.ts.map +1 -0
  50. package/dist/services/benchmark.js +18 -0
  51. package/dist/services/prd.d.ts +25 -0
  52. package/dist/services/prd.d.ts.map +1 -1
  53. package/dist/services/prd.js +224 -29
  54. package/dist/services/tasks.d.ts.map +1 -1
  55. package/dist/services/tasks.js +90 -3
  56. package/dist/services/workflow-benchmark.d.ts +34 -0
  57. package/dist/services/workflow-benchmark.d.ts.map +1 -0
  58. package/dist/services/workflow-benchmark.js +317 -0
  59. package/dist/services/workflow.d.ts +85 -0
  60. package/dist/services/workflow.d.ts.map +1 -0
  61. package/dist/services/workflow.js +476 -0
  62. package/dist/test/task-loop-git.test.d.ts +2 -0
  63. package/dist/test/task-loop-git.test.d.ts.map +1 -0
  64. package/dist/test/task-loop-git.test.js +62 -0
  65. package/dist/types/index.d.ts +53 -0
  66. package/dist/types/index.d.ts.map +1 -1
  67. package/dist/types/options.d.ts +2 -1
  68. package/dist/types/options.d.ts.map +1 -1
  69. package/dist/types/options.js +16 -0
  70. package/dist/types/results.d.ts +29 -1
  71. package/dist/types/results.d.ts.map +1 -1
  72. package/dist/types/workflow-options.d.ts +45 -0
  73. package/dist/types/workflow-options.d.ts.map +1 -0
  74. package/dist/types/workflow-options.js +2 -0
  75. package/dist/types/workflow-results.d.ts +82 -0
  76. package/dist/types/workflow-results.d.ts.map +1 -0
  77. package/dist/types/workflow-results.js +2 -0
  78. package/package.json +1 -1
@@ -0,0 +1,473 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractCommitInfo = extractCommitInfo;
7
+ exports.executeTaskLoop = executeTaskLoop;
8
+ const tasks_1 = require("../services/tasks");
9
+ const executor_factory_1 = require("./executors/executor-factory");
10
+ const ai_service_factory_1 = require("../utils/ai-service-factory");
11
+ const hooks_1 = require("./hooks");
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ const child_process_1 = require("child_process");
14
+ const util_1 = require("util");
15
+ const ai_service_factory_2 = require("../utils/ai-service-factory");
16
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
17
+ /**
18
+ * Extract commit message and file list from AI conversation/output
19
+ * This function analyzes the executor's work and generates appropriate commit info
20
+ */
21
+ /**
22
+ * Extract commit message and file list from git state
23
+ * This function analyzes the actual git state to generate appropriate commit info
24
+ */
25
+ async function extractCommitInfo(taskId, taskTitle, executionMessage, gitState, execFn = execAsync, aiOps = (0, ai_service_factory_2.getAIOperations)()) {
26
+ try {
27
+ // Case 1: Executor created a commit
28
+ if (gitState.beforeHead !== gitState.afterHead) {
29
+ console.log(chalk_1.default.blue("📝 Executor created a commit, extracting info..."));
30
+ const { stdout } = await execFn(`git show --stat --format="%s%n%b" ${gitState.afterHead}`);
31
+ const lines = stdout.trim().split("\n");
32
+ const message = lines[0].trim();
33
+ // Parse files from stat output (e.g. " src/file.ts | 10 +")
34
+ const files = lines
35
+ .slice(1)
36
+ .filter((line) => line.includes("|"))
37
+ .map((line) => line.split("|")[0].trim());
38
+ return {
39
+ message,
40
+ files,
41
+ };
42
+ }
43
+ // Case 2: Executor left uncommitted changes
44
+ if (gitState.hasUncommittedChanges) {
45
+ console.log(chalk_1.default.blue("📝 Uncommitted changes detected, generating commit message..."));
46
+ // Get the diff to send to AI
47
+ const { stdout: diff } = await execFn("git diff HEAD");
48
+ // Get list of changed files
49
+ const { stdout: status } = await execFn("git status --porcelain");
50
+ const files = status
51
+ .split("\n")
52
+ .filter((line) => line.length > 0)
53
+ .map((line) => line.substring(3).trim())
54
+ .filter((file) => file.length > 0);
55
+ // Use AI to generate commit message based on the diff
56
+ // const aiOps = getAIOperations(); // Injected
57
+ const prompt = `Based on the following git diff, generate a concise git commit message.
58
+
59
+ Task: ${taskTitle}
60
+
61
+ Git Diff:
62
+ ${diff.substring(0, 10000)} // Limit diff size
63
+
64
+ Please respond in JSON format:
65
+ {
66
+ "message": "concise commit message following conventional commits format"
67
+ }
68
+
69
+ The commit message should:
70
+ - Follow conventional commits format (feat:, fix:, refactor:, etc.)
71
+ - Be concise and descriptive
72
+ - Focus on what changed
73
+ `;
74
+ const response = await aiOps.streamText(prompt, undefined, "You are a helpful assistant that generates git commit messages.");
75
+ // Try to parse JSON from response
76
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
77
+ let message = `feat: complete task ${taskTitle}`;
78
+ if (jsonMatch) {
79
+ try {
80
+ const parsed = JSON.parse(jsonMatch[0]);
81
+ if (parsed.message) {
82
+ message = parsed.message;
83
+ }
84
+ }
85
+ catch (e) {
86
+ // Ignore parse error
87
+ }
88
+ }
89
+ return {
90
+ message,
91
+ files,
92
+ };
93
+ }
94
+ // Case 3: No changes detected
95
+ return {
96
+ message: `feat: complete task ${taskTitle}`,
97
+ files: [],
98
+ };
99
+ }
100
+ catch (error) {
101
+ console.warn(chalk_1.default.yellow(`⚠️ Failed to extract commit info: ${error instanceof Error ? error.message : "Unknown error"}`));
102
+ // Fallback commit info
103
+ return {
104
+ message: `feat: complete task ${taskTitle}`,
105
+ files: [],
106
+ };
107
+ }
108
+ }
109
+ /**
110
+ * Run verification commands and return results
111
+ */
112
+ async function runVerificationCommands(commands, dry) {
113
+ const results = [];
114
+ if (dry) {
115
+ console.log(chalk_1.default.yellow("🔍 DRY RUN - Verification commands:"));
116
+ commands.forEach((cmd) => {
117
+ console.log(chalk_1.default.cyan(` ${cmd}`));
118
+ results.push({
119
+ command: cmd,
120
+ success: true,
121
+ output: "DRY RUN - not executed",
122
+ });
123
+ });
124
+ return results;
125
+ }
126
+ for (const command of commands) {
127
+ console.log(chalk_1.default.blue(`🧪 Running verification: ${command}`));
128
+ try {
129
+ const { stdout, stderr } = await execAsync(command);
130
+ console.log(chalk_1.default.green(`✅ Verification passed: ${command}`));
131
+ results.push({
132
+ command,
133
+ success: true,
134
+ output: stdout.trim(),
135
+ });
136
+ }
137
+ catch (error) {
138
+ console.error(chalk_1.default.red(`❌ Verification failed: ${command}`));
139
+ const errorOutput = error.stderr || error.stdout || error.message;
140
+ console.error(chalk_1.default.red(` Error: ${errorOutput}`));
141
+ results.push({
142
+ command,
143
+ success: false,
144
+ error: errorOutput,
145
+ });
146
+ // Return early on first failure
147
+ break;
148
+ }
149
+ }
150
+ return results;
151
+ }
152
+ /**
153
+ * Execute a single task with retry logic and error correction
154
+ */
155
+ async function executeTaskWithRetry(task, tool, verificationCommands, maxRetries, dry, tryModels) {
156
+ const attempts = [];
157
+ let currentAttempt = 1;
158
+ let lastError;
159
+ while (currentAttempt <= maxRetries) {
160
+ // Determine which executor and model to use for this attempt
161
+ let currentExecutor = tool;
162
+ let currentModel;
163
+ if (tryModels && tryModels.length > 0) {
164
+ // Use the model config for this attempt (or last one if we've exceeded the list)
165
+ const modelConfigIndex = Math.min(currentAttempt - 1, tryModels.length - 1);
166
+ const modelConfig = tryModels[modelConfigIndex];
167
+ // Override executor if specified
168
+ if (modelConfig.executor) {
169
+ currentExecutor = modelConfig.executor;
170
+ }
171
+ // Store model name if specified
172
+ if (modelConfig.model) {
173
+ currentModel = modelConfig.model;
174
+ }
175
+ }
176
+ console.log(chalk_1.default.blue(`\n🎯 Attempt ${currentAttempt}/${maxRetries} for task: ${task.title} (${task.id})`));
177
+ if (currentModel) {
178
+ console.log(chalk_1.default.cyan(` Using executor: ${currentExecutor} with model: ${currentModel}`));
179
+ }
180
+ else {
181
+ console.log(chalk_1.default.cyan(` Using executor: ${currentExecutor}`));
182
+ }
183
+ const attemptStartTime = Date.now();
184
+ // Capture git state before execution
185
+ let beforeHead = "";
186
+ try {
187
+ const { stdout } = await execAsync("git rev-parse HEAD");
188
+ beforeHead = stdout.trim();
189
+ }
190
+ catch (e) {
191
+ // Git might not be initialized or no commits yet
192
+ }
193
+ try {
194
+ // Build execution message with context
195
+ const contextBuilder = (0, ai_service_factory_1.getContextBuilder)();
196
+ const taskContext = await contextBuilder.buildContext(task.id);
197
+ const messageParts = [];
198
+ // Add retry context if this is a retry attempt
199
+ if (currentAttempt > 1 && lastError) {
200
+ messageParts.push(`# RETRY ATTEMPT ${currentAttempt}/${maxRetries}\n\n`);
201
+ // Add model escalation context
202
+ if (currentModel) {
203
+ messageParts.push(`**Note**: You are ${currentExecutor} using the ${currentModel} model. This is a more capable model than the previous attempt.\n\n`);
204
+ }
205
+ messageParts.push(`## Previous Attempt Failed With Error:\n\n${lastError}\n\n`);
206
+ messageParts.push(`Please analyze the error carefully and fix it. The error might be due to:\n`);
207
+ messageParts.push(`- Syntax errors\n`);
208
+ messageParts.push(`- Logic errors\n`);
209
+ messageParts.push(`- Missing dependencies or imports\n`);
210
+ messageParts.push(`- Incorrect configuration\n`);
211
+ messageParts.push(`- Build or test failures\n\n`);
212
+ messageParts.push(`Please fix the error above and complete the task successfully.\n\n`);
213
+ }
214
+ // Add task plan if available
215
+ const planData = await tasks_1.taskService.getTaskPlan(task.id);
216
+ if (planData) {
217
+ messageParts.push(`# Task Plan\n\n${planData.plan}\n`);
218
+ }
219
+ else {
220
+ messageParts.push(`# Task: ${task.title}\n\n${task.description || "No description"}\n`);
221
+ }
222
+ // Add PRD context if available
223
+ if (taskContext.prdContent) {
224
+ messageParts.push(`\n# Product Requirements Document\n\n${taskContext.prdContent}\n`);
225
+ }
226
+ // Add stack/technology context
227
+ if (taskContext.stack) {
228
+ messageParts.push(`\n# Technology Stack\n\n`);
229
+ messageParts.push(`- **Project**: ${taskContext.stack.projectName}\n`);
230
+ messageParts.push(`- **Frontend**: ${taskContext.stack.frontend}\n`);
231
+ messageParts.push(`- **Backend**: ${taskContext.stack.backend}\n`);
232
+ if (taskContext.stack.database !== "none") {
233
+ messageParts.push(`- **Database**: ${taskContext.stack.database}\n`);
234
+ }
235
+ messageParts.push(`- **Auth**: ${taskContext.stack.auth}\n`);
236
+ }
237
+ // Add documentation context if available
238
+ if (taskContext.documentation) {
239
+ messageParts.push(`\n# Documentation Context\n\n`);
240
+ messageParts.push(`${taskContext.documentation.recap}\n`);
241
+ }
242
+ const executionMessage = messageParts.join("");
243
+ // Update task status to in-progress
244
+ if (!dry) {
245
+ await tasks_1.taskService.setTaskStatus(task.id, "in-progress");
246
+ console.log(chalk_1.default.yellow("⏳ Task status updated to in-progress"));
247
+ }
248
+ // Emit execution:start event
249
+ await hooks_1.hooks.emit("execution:start", {
250
+ taskId: task.id,
251
+ tool: currentExecutor,
252
+ });
253
+ // Create executor and run
254
+ const executor = executor_factory_1.ExecutorFactory.create(currentExecutor);
255
+ // Add model info to execution message if specified
256
+ let finalExecutionMessage = executionMessage;
257
+ if (currentModel) {
258
+ finalExecutionMessage =
259
+ `**Model Configuration**: Using ${currentModel}\n\n` +
260
+ executionMessage;
261
+ }
262
+ await executor.execute(finalExecutionMessage, dry);
263
+ // Run verification commands
264
+ const verificationResults = await runVerificationCommands(verificationCommands, dry);
265
+ // Check if all verifications passed
266
+ const allVerificationsPassed = verificationResults.every((r) => r.success);
267
+ if (!allVerificationsPassed) {
268
+ // Verification failed - prepare error message for retry
269
+ const failedVerification = verificationResults.find((r) => !r.success);
270
+ lastError = `Verification command "${failedVerification?.command}" failed:\n${failedVerification?.error}`;
271
+ attempts.push({
272
+ attemptNumber: currentAttempt,
273
+ success: false,
274
+ error: lastError,
275
+ executor: currentExecutor,
276
+ model: currentModel,
277
+ verificationResults,
278
+ timestamp: Date.now() - attemptStartTime,
279
+ });
280
+ console.log(chalk_1.default.red(`❌ Task execution failed verification on attempt ${currentAttempt}`));
281
+ currentAttempt++;
282
+ continue;
283
+ }
284
+ // Success! Extract commit info
285
+ let commitInfo;
286
+ if (!dry) {
287
+ console.log(chalk_1.default.blue("📝 Extracting commit information..."));
288
+ // Capture git state after execution
289
+ let afterHead = "";
290
+ let hasUncommittedChanges = false;
291
+ try {
292
+ const { stdout: headStdout } = await execAsync("git rev-parse HEAD");
293
+ afterHead = headStdout.trim();
294
+ const { stdout: statusStdout } = await execAsync("git status --porcelain");
295
+ hasUncommittedChanges = statusStdout.trim().length > 0;
296
+ }
297
+ catch (e) {
298
+ // Git issues
299
+ }
300
+ commitInfo = await extractCommitInfo(task.id, task.title, executionMessage, {
301
+ beforeHead,
302
+ afterHead,
303
+ hasUncommittedChanges,
304
+ });
305
+ console.log(chalk_1.default.green(`✅ Commit message: ${commitInfo.message}`));
306
+ if (commitInfo.files.length > 0) {
307
+ console.log(chalk_1.default.green(`📁 Changed files: ${commitInfo.files.join(", ")}`));
308
+ }
309
+ }
310
+ // Update task status to completed
311
+ if (!dry) {
312
+ await tasks_1.taskService.setTaskStatus(task.id, "completed");
313
+ console.log(chalk_1.default.green("✅ Task execution completed successfully"));
314
+ }
315
+ // Record successful attempt
316
+ attempts.push({
317
+ attemptNumber: currentAttempt,
318
+ success: true,
319
+ executor: currentExecutor,
320
+ model: currentModel,
321
+ verificationResults,
322
+ commitInfo,
323
+ timestamp: Date.now() - attemptStartTime,
324
+ });
325
+ // Emit execution:end event
326
+ await hooks_1.hooks.emit("execution:end", { taskId: task.id, success: true });
327
+ return attempts; // Success - exit retry loop
328
+ }
329
+ catch (error) {
330
+ lastError = error instanceof Error ? error.message : String(error);
331
+ attempts.push({
332
+ attemptNumber: currentAttempt,
333
+ success: false,
334
+ error: lastError,
335
+ executor: currentExecutor,
336
+ model: currentModel,
337
+ timestamp: Date.now() - attemptStartTime,
338
+ });
339
+ // Emit execution:error event
340
+ await hooks_1.hooks.emit("execution:error", {
341
+ taskId: task.id,
342
+ error: error instanceof Error ? error : new Error(String(error)),
343
+ });
344
+ console.log(chalk_1.default.red(`❌ Task execution failed on attempt ${currentAttempt}: ${lastError}`));
345
+ if (!dry && currentAttempt < maxRetries) {
346
+ // Reset task status to todo for retry
347
+ await tasks_1.taskService.setTaskStatus(task.id, "todo");
348
+ console.log(chalk_1.default.yellow("⏸ Task status reset to todo for retry"));
349
+ }
350
+ currentAttempt++;
351
+ }
352
+ }
353
+ // All retries exhausted
354
+ if (!dry) {
355
+ await tasks_1.taskService.setTaskStatus(task.id, "todo");
356
+ console.log(chalk_1.default.red("❌ All retry attempts exhausted, task status reset to todo"));
357
+ }
358
+ return attempts;
359
+ }
360
+ /**
361
+ * Execute multiple tasks in a loop with retry and verification
362
+ */
363
+ async function executeTaskLoop(options) {
364
+ const startTime = Date.now();
365
+ const { filters = {}, tool = "opencode", config = {}, dry = false } = options;
366
+ const { maxRetries = 3, verificationCommands = [], autoCommit = false, } = config;
367
+ console.log(chalk_1.default.blue.bold("\n🔄 Starting Task Loop Execution\n"));
368
+ console.log(chalk_1.default.cyan(`Executor Tool: ${tool}`));
369
+ console.log(chalk_1.default.cyan(`Max Retries per Task: ${maxRetries}`));
370
+ console.log(chalk_1.default.cyan(`Verification Commands: ${verificationCommands.length > 0
371
+ ? verificationCommands.join(", ")
372
+ : "None"}`));
373
+ console.log(chalk_1.default.cyan(`Auto Commit: ${autoCommit ? "Yes" : "No"}`));
374
+ console.log(chalk_1.default.cyan(`Dry Run: ${dry ? "Yes" : "No"}\n`));
375
+ // Get tasks to execute
376
+ let tasksToExecute = [];
377
+ if (filters.taskIds && filters.taskIds.length > 0) {
378
+ // Execute specific tasks by ID
379
+ for (const taskId of filters.taskIds) {
380
+ const task = await tasks_1.taskService.getTask(taskId);
381
+ if (task) {
382
+ tasksToExecute.push(task);
383
+ }
384
+ else {
385
+ console.warn(chalk_1.default.yellow(`⚠️ Task ${taskId} not found, skipping`));
386
+ }
387
+ }
388
+ }
389
+ else {
390
+ // Get all tasks matching filters
391
+ tasksToExecute = await tasks_1.taskService.listTasks({
392
+ status: filters.status,
393
+ tag: filters.tag,
394
+ });
395
+ }
396
+ if (tasksToExecute.length === 0) {
397
+ console.log(chalk_1.default.yellow("⚠️ No tasks found matching the filters"));
398
+ return {
399
+ totalTasks: 0,
400
+ completedTasks: 0,
401
+ failedTasks: 0,
402
+ taskResults: [],
403
+ duration: Date.now() - startTime,
404
+ };
405
+ }
406
+ console.log(chalk_1.default.blue(`📋 Found ${tasksToExecute.length} task(s) to execute\n`));
407
+ const taskResults = [];
408
+ let completedTasks = 0;
409
+ let failedTasks = 0;
410
+ // Execute tasks sequentially
411
+ for (let i = 0; i < tasksToExecute.length; i++) {
412
+ const task = tasksToExecute[i];
413
+ console.log(chalk_1.default.blue.bold(`\n${"=".repeat(60)}\n📌 Task ${i + 1}/${tasksToExecute.length}: ${task.title} (${task.id})\n${"=".repeat(60)}\n`));
414
+ // Execute task with retry logic
415
+ const attempts = await executeTaskWithRetry(task, tool, verificationCommands, maxRetries, dry, config.tryModels);
416
+ // Check if task succeeded
417
+ const lastAttempt = attempts[attempts.length - 1];
418
+ const succeeded = lastAttempt.success;
419
+ if (succeeded) {
420
+ completedTasks++;
421
+ console.log(chalk_1.default.green.bold(`\n✅ Task ${task.title} completed successfully after ${attempts.length} attempt(s)\n`));
422
+ }
423
+ else {
424
+ failedTasks++;
425
+ console.log(chalk_1.default.red.bold(`\n❌ Task ${task.title} failed after ${attempts.length} attempt(s)\n`));
426
+ }
427
+ taskResults.push({
428
+ taskId: task.id,
429
+ taskTitle: task.title,
430
+ attempts,
431
+ finalStatus: succeeded ? "completed" : "failed",
432
+ });
433
+ // Auto-commit if enabled and task succeeded
434
+ if (autoCommit && succeeded && !dry && lastAttempt.commitInfo) {
435
+ try {
436
+ const { message, files } = lastAttempt.commitInfo;
437
+ if (files.length > 0) {
438
+ // Stage specific files
439
+ const gitAdd = `git add ${files.join(" ")}`;
440
+ console.log(chalk_1.default.blue(`📦 Staging files: ${gitAdd}`));
441
+ await execAsync(gitAdd);
442
+ }
443
+ else {
444
+ // Stage all changes
445
+ console.log(chalk_1.default.blue("📦 Staging all changes"));
446
+ await execAsync("git add .");
447
+ }
448
+ // Commit
449
+ const gitCommit = `git commit -m "${message}"`;
450
+ console.log(chalk_1.default.blue(`💾 Committing: ${message}`));
451
+ await execAsync(gitCommit);
452
+ console.log(chalk_1.default.green("✅ Changes committed successfully\n"));
453
+ }
454
+ catch (error) {
455
+ console.warn(chalk_1.default.yellow(`⚠️ Auto-commit failed: ${error instanceof Error ? error.message : "Unknown error"}\n`));
456
+ }
457
+ }
458
+ }
459
+ const duration = Date.now() - startTime;
460
+ // Print summary
461
+ console.log(chalk_1.default.blue.bold(`\n${"=".repeat(60)}\n📊 Execution Summary\n${"=".repeat(60)}`));
462
+ console.log(chalk_1.default.cyan(`Total Tasks: ${tasksToExecute.length}`));
463
+ console.log(chalk_1.default.green(`✅ Completed: ${completedTasks}`));
464
+ console.log(chalk_1.default.red(`❌ Failed: ${failedTasks}`));
465
+ console.log(chalk_1.default.cyan(`⏱ Duration: ${(duration / 1000).toFixed(2)} seconds\n`));
466
+ return {
467
+ totalTasks: tasksToExecute.length,
468
+ completedTasks,
469
+ failedTasks,
470
+ taskResults,
471
+ duration,
472
+ };
473
+ }
@@ -1,7 +1,8 @@
1
- export * from './prd-parsing';
2
- export * from './task-breakdown';
3
- export * from './task-enhancement';
4
- export * from './prd-rework';
5
- export * from './documentation-detection';
6
- export * from './task-planning';
1
+ export * from "./prd-parsing";
2
+ export * from "./task-breakdown";
3
+ export * from "./task-enhancement";
4
+ export * from "./prd-rework";
5
+ export * from "./documentation-detection";
6
+ export * from "./task-planning";
7
+ export * from "./prd-question";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
@@ -20,3 +20,4 @@ __exportStar(require("./task-enhancement"), exports);
20
20
  __exportStar(require("./prd-rework"), exports);
21
21
  __exportStar(require("./documentation-detection"), exports);
22
22
  __exportStar(require("./task-planning"), exports);
23
+ __exportStar(require("./prd-question"), exports);
@@ -0,0 +1,3 @@
1
+ export declare const PRD_QUESTION_PROMPT = "\nAnalyze this PRD and generate meaningful clarifying questions to help improve its quality and completeness.\n\n## Current PRD:\n{PRD_CONTENT}\n\n## Project Technology Stack:\n{STACK_INFO}\n\nIdentify ambiguities, missing requirements, technical gaps, or potential conflicts.\nFocus on questions that will help:\n- Clarify user intent\n- Define edge cases\n- Specify technical implementation details aligned with the stack\n- Resolve potential architectural issues\n\nReturn a JSON object with a \"questions\" array, where each item is a string containing a question.\n";
2
+ export declare const PRD_QUESTION_SYSTEM_PROMPT = "\nYou are an expert Product Manager and Technical Architect. Your goal is to analyze Product Requirements Documents (PRDs) and ask insightful questions to clarify requirements and ensure technical feasibility.\n\nOutput Format:\nYou must return a valid JSON object with the following structure:\n{\n \"questions\": [\n \"Question 1?\",\n \"Question 2?\",\n ...\n ]\n}\n\nGuidelines:\n1. Ask 3-5 most critical questions. Do not overwhelm the user.\n2. Focus on \"what\" and \"why\" rather than \"how\" unless it affects feasibility.\n3. Be specific and reference parts of the PRD.\n4. Consider the technology stack constraints.\n";
3
+ //# sourceMappingURL=prd-question.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prd-question.d.ts","sourceRoot":"","sources":["../../src/prompts/prd-question.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,+jBAiB/B,CAAC;AAEF,eAAO,MAAM,0BAA0B,ooBAkBtC,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PRD_QUESTION_SYSTEM_PROMPT = exports.PRD_QUESTION_PROMPT = void 0;
4
+ exports.PRD_QUESTION_PROMPT = `
5
+ Analyze this PRD and generate meaningful clarifying questions to help improve its quality and completeness.
6
+
7
+ ## Current PRD:
8
+ {PRD_CONTENT}
9
+
10
+ ## Project Technology Stack:
11
+ {STACK_INFO}
12
+
13
+ Identify ambiguities, missing requirements, technical gaps, or potential conflicts.
14
+ Focus on questions that will help:
15
+ - Clarify user intent
16
+ - Define edge cases
17
+ - Specify technical implementation details aligned with the stack
18
+ - Resolve potential architectural issues
19
+
20
+ Return a JSON object with a "questions" array, where each item is a string containing a question.
21
+ `;
22
+ exports.PRD_QUESTION_SYSTEM_PROMPT = `
23
+ You are an expert Product Manager and Technical Architect. Your goal is to analyze Product Requirements Documents (PRDs) and ask insightful questions to clarify requirements and ensure technical feasibility.
24
+
25
+ Output Format:
26
+ You must return a valid JSON object with the following structure:
27
+ {
28
+ "questions": [
29
+ "Question 1?",
30
+ "Question 2?",
31
+ ...
32
+ ]
33
+ }
34
+
35
+ Guidelines:
36
+ 1. Ask 3-5 most critical questions. Do not overwhelm the user.
37
+ 2. Focus on "what" and "why" rather than "how" unless it affects feasibility.
38
+ 3. Be specific and reference parts of the PRD.
39
+ 4. Consider the technology stack constraints.
40
+ `;
@@ -0,0 +1,12 @@
1
+ import { BenchmarkConfig, BenchmarkRun, BenchmarkProgressEvent } from "../lib/benchmark/types";
2
+ export declare class BenchmarkService {
3
+ runBenchmark(operationId: string, input: any, config: BenchmarkConfig, onProgress?: (event: BenchmarkProgressEvent) => void): Promise<BenchmarkRun>;
4
+ getRun(id: string): BenchmarkRun | null;
5
+ listRuns(): Array<{
6
+ id: string;
7
+ timestamp: number;
8
+ command: string;
9
+ }>;
10
+ }
11
+ export declare const benchmarkService: BenchmarkService;
12
+ //# sourceMappingURL=benchmark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark.d.ts","sourceRoot":"","sources":["../../src/services/benchmark.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,gBAAgB;IACrB,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,eAAe,EACvB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,GACnD,OAAO,CAAC,YAAY,CAAC;IAIxB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAIvC,QAAQ,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAGtE;AAED,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.benchmarkService = exports.BenchmarkService = void 0;
4
+ const runner_1 = require("../lib/benchmark/runner");
5
+ const storage_1 = require("../lib/benchmark/storage");
6
+ class BenchmarkService {
7
+ async runBenchmark(operationId, input, config, onProgress) {
8
+ return await runner_1.benchmarkRunner.run(operationId, input, config, onProgress);
9
+ }
10
+ getRun(id) {
11
+ return storage_1.benchmarkStorage.getRun(id);
12
+ }
13
+ listRuns() {
14
+ return storage_1.benchmarkStorage.listRuns();
15
+ }
16
+ }
17
+ exports.BenchmarkService = BenchmarkService;
18
+ exports.benchmarkService = new BenchmarkService();
@@ -17,6 +17,16 @@ export declare class PRDService {
17
17
  streamingOptions?: StreamingOptions;
18
18
  callbacks?: ProgressCallback;
19
19
  }): Promise<PRDParseResult>;
20
+ generateQuestions(input: {
21
+ file: string;
22
+ workingDirectory?: string;
23
+ enableFilesystemTools?: boolean;
24
+ aiOptions?: AIOptions;
25
+ promptOverride?: string;
26
+ messageOverride?: string;
27
+ streamingOptions?: StreamingOptions;
28
+ callbacks?: ProgressCallback;
29
+ }): Promise<string[]>;
20
30
  reworkPRD(input: {
21
31
  file: string;
22
32
  feedback: string;
@@ -29,6 +39,21 @@ export declare class PRDService {
29
39
  streamingOptions?: StreamingOptions;
30
40
  callbacks?: ProgressCallback;
31
41
  }): Promise<string>;
42
+ refinePRDWithQuestions(input: {
43
+ file: string;
44
+ questionMode: "user" | "ai";
45
+ answers?: Record<string, string>;
46
+ questionAIOptions?: AIOptions;
47
+ workingDirectory?: string;
48
+ enableFilesystemTools?: boolean;
49
+ aiOptions?: AIOptions;
50
+ streamingOptions?: StreamingOptions;
51
+ callbacks?: ProgressCallback;
52
+ }): Promise<{
53
+ questions: string[];
54
+ answers: Record<string, string>;
55
+ refinedPRDPath: string;
56
+ }>;
32
57
  }
33
58
  export declare const prdService: PRDService;
34
59
  //# sourceMappingURL=prd.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prd.d.ts","sourceRoot":"","sources":["../../src/services/prd.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAY,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;GAGG;AACH,qBAAa,UAAU;IAEf,QAAQ,CAAC,KAAK,EAAE;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAC9B,GAAG,OAAO,CAAC,cAAc,CAAC;IAgLrB,SAAS,CAAC,KAAK,EAAE;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAC9B,GAAG,OAAO,CAAC,MAAM,CAAC;CA6DpB;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC"}
1
+ {"version":3,"file":"prd.d.ts","sourceRoot":"","sources":["../../src/services/prd.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAY,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;GAGG;AACH,qBAAa,UAAU;IACf,QAAQ,CAAC,KAAK,EAAE;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAC9B,GAAG,OAAO,CAAC,cAAc,CAAC;IA6NrB,iBAAiB,CAAC,KAAK,EAAE;QAC7B,IAAI,EAAE,MAAM,CAAC;QACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAC9B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAqDf,SAAS,CAAC,KAAK,EAAE;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAC9B,GAAG,OAAO,CAAC,MAAM,CAAC;IAiEb,sBAAsB,CAAC,KAAK,EAAE;QAClC,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,iBAAiB,CAAC,EAAE,SAAS,CAAC;QAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAC9B,GAAG,OAAO,CAAC;QACV,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CAwHH;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC"}