task-o-matic 0.0.10 → 0.0.11

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 (102) hide show
  1. package/dist/cli/display/progress.d.ts +1 -1
  2. package/dist/cli/display/progress.d.ts.map +1 -1
  3. package/dist/cli/display/progress.js +16 -13
  4. package/dist/commands/benchmark.js +70 -2
  5. package/dist/commands/init.js +48 -27
  6. package/dist/commands/prd.d.ts.map +1 -1
  7. package/dist/commands/prd.js +201 -0
  8. package/dist/commands/tasks/execute-loop.d.ts.map +1 -1
  9. package/dist/commands/tasks/execute-loop.js +10 -0
  10. package/dist/commands/tasks/execute.d.ts.map +1 -1
  11. package/dist/commands/tasks/execute.js +4 -0
  12. package/dist/commands/workflow.d.ts.map +1 -1
  13. package/dist/commands/workflow.js +56 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -0
  16. package/dist/lib/ai-service/ai-operations.d.ts +13 -10
  17. package/dist/lib/ai-service/ai-operations.d.ts.map +1 -1
  18. package/dist/lib/ai-service/ai-operations.js +35 -995
  19. package/dist/lib/ai-service/base-operations.d.ts +13 -0
  20. package/dist/lib/ai-service/base-operations.d.ts.map +1 -0
  21. package/dist/lib/ai-service/base-operations.js +79 -0
  22. package/dist/lib/ai-service/documentation-operations.d.ts +18 -0
  23. package/dist/lib/ai-service/documentation-operations.d.ts.map +1 -0
  24. package/dist/lib/ai-service/documentation-operations.js +291 -0
  25. package/dist/lib/ai-service/prd-operations.d.ts +14 -0
  26. package/dist/lib/ai-service/prd-operations.d.ts.map +1 -0
  27. package/dist/lib/ai-service/prd-operations.js +405 -0
  28. package/dist/lib/ai-service/task-operations.d.ts +12 -0
  29. package/dist/lib/ai-service/task-operations.d.ts.map +1 -0
  30. package/dist/lib/ai-service/task-operations.js +225 -0
  31. package/dist/lib/benchmark/registry.d.ts.map +1 -1
  32. package/dist/lib/benchmark/registry.js +127 -0
  33. package/dist/lib/better-t-stack-cli.d.ts +4 -1
  34. package/dist/lib/better-t-stack-cli.d.ts.map +1 -1
  35. package/dist/lib/better-t-stack-cli.js +126 -5
  36. package/dist/lib/config.d.ts +13 -6
  37. package/dist/lib/config.d.ts.map +1 -1
  38. package/dist/lib/config.js +90 -48
  39. package/dist/lib/context-builder.d.ts +13 -1
  40. package/dist/lib/context-builder.d.ts.map +1 -1
  41. package/dist/lib/context-builder.js +68 -36
  42. package/dist/lib/executors/claude-code-executor.d.ts +5 -2
  43. package/dist/lib/executors/claude-code-executor.d.ts.map +1 -1
  44. package/dist/lib/executors/claude-code-executor.js +30 -3
  45. package/dist/lib/executors/codex-executor.d.ts +5 -2
  46. package/dist/lib/executors/codex-executor.d.ts.map +1 -1
  47. package/dist/lib/executors/codex-executor.js +30 -3
  48. package/dist/lib/executors/executor-factory.d.ts +2 -2
  49. package/dist/lib/executors/executor-factory.d.ts.map +1 -1
  50. package/dist/lib/executors/executor-factory.js +5 -5
  51. package/dist/lib/executors/gemini-executor.d.ts +5 -2
  52. package/dist/lib/executors/gemini-executor.d.ts.map +1 -1
  53. package/dist/lib/executors/gemini-executor.js +30 -3
  54. package/dist/lib/executors/opencode-executor.d.ts +5 -2
  55. package/dist/lib/executors/opencode-executor.d.ts.map +1 -1
  56. package/dist/lib/executors/opencode-executor.js +30 -7
  57. package/dist/lib/prompt-builder.d.ts.map +1 -1
  58. package/dist/lib/prompt-builder.js +1 -0
  59. package/dist/lib/storage/file-system.d.ts +3 -7
  60. package/dist/lib/storage/file-system.d.ts.map +1 -1
  61. package/dist/lib/storage/file-system.js +50 -230
  62. package/dist/lib/storage/storage-callbacks.d.ts +17 -0
  63. package/dist/lib/storage/storage-callbacks.d.ts.map +1 -0
  64. package/dist/lib/storage/storage-callbacks.js +94 -0
  65. package/dist/lib/task-execution.d.ts.map +1 -1
  66. package/dist/lib/task-execution.js +16 -9
  67. package/dist/lib/task-loop-execution.d.ts.map +1 -1
  68. package/dist/lib/task-loop-execution.js +207 -8
  69. package/dist/prompts/index.d.ts +2 -0
  70. package/dist/prompts/index.d.ts.map +1 -1
  71. package/dist/prompts/index.js +2 -0
  72. package/dist/prompts/prd-combination.d.ts +2 -0
  73. package/dist/prompts/prd-combination.d.ts.map +1 -0
  74. package/dist/prompts/prd-combination.js +35 -0
  75. package/dist/prompts/prd-generation.d.ts +2 -0
  76. package/dist/prompts/prd-generation.d.ts.map +1 -0
  77. package/dist/prompts/prd-generation.js +49 -0
  78. package/dist/services/prd.d.ts +43 -0
  79. package/dist/services/prd.d.ts.map +1 -1
  80. package/dist/services/prd.js +121 -0
  81. package/dist/services/workflow-ai-assistant.d.ts.map +1 -1
  82. package/dist/services/workflow-ai-assistant.js +1 -40
  83. package/dist/services/workflow.d.ts +10 -0
  84. package/dist/services/workflow.d.ts.map +1 -1
  85. package/dist/services/workflow.js +118 -40
  86. package/dist/test/integration/callbacks.test.d.ts +2 -0
  87. package/dist/test/integration/callbacks.test.d.ts.map +1 -0
  88. package/dist/test/integration/callbacks.test.js +64 -0
  89. package/dist/types/callbacks.d.ts +9 -6
  90. package/dist/types/callbacks.d.ts.map +1 -1
  91. package/dist/types/index.d.ts +17 -2
  92. package/dist/types/index.d.ts.map +1 -1
  93. package/dist/types/workflow-options.d.ts +7 -0
  94. package/dist/types/workflow-options.d.ts.map +1 -1
  95. package/dist/utils/ai-service-factory.d.ts +15 -1
  96. package/dist/utils/ai-service-factory.d.ts.map +1 -1
  97. package/dist/utils/ai-service-factory.js +29 -1
  98. package/dist/utils/streaming-options.d.ts +1 -1
  99. package/dist/utils/streaming-options.d.ts.map +1 -1
  100. package/dist/utils/streaming-options.js +31 -18
  101. package/docs/agents/cli.md +191 -0
  102. package/package.json +3 -2
@@ -1,4 +1,4 @@
1
- import type { ProgressEvent } from '../../types/callbacks';
1
+ import type { ProgressEvent } from "../../types/callbacks";
2
2
  /**
3
3
  * Display progress events for the CLI
4
4
  * This function is used as a callback for services to report progress
@@ -1 +1 @@
1
- {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/cli/display/progress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAmC1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI,CAGzD"}
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/cli/display/progress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAuC1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI,CAGzD"}
@@ -12,29 +12,32 @@ const chalk_1 = __importDefault(require("chalk"));
12
12
  */
13
13
  function displayProgress(event) {
14
14
  switch (event.type) {
15
- case 'started':
16
- console.log(chalk_1.default.blue('🤖 ' + event.message));
15
+ case "started":
16
+ console.log(chalk_1.default.blue("🤖 " + event.message));
17
17
  break;
18
- case 'progress':
18
+ case "progress":
19
19
  if (event.current && event.total) {
20
20
  const percent = Math.round((event.current / event.total) * 100);
21
21
  console.log(chalk_1.default.cyan(` [${event.current}/${event.total}] ${percent}% - ${event.message}`));
22
22
  }
23
23
  else {
24
- console.log(chalk_1.default.cyan('' + event.message));
24
+ console.log(chalk_1.default.cyan("" + event.message));
25
25
  }
26
26
  break;
27
- case 'stream-chunk':
27
+ case "stream-chunk":
28
28
  process.stdout.write(event.text);
29
29
  break;
30
- case 'completed':
31
- console.log(chalk_1.default.green('✓ ' + event.message));
30
+ case "reasoning-chunk":
31
+ process.stdout.write(chalk_1.default.magenta(event.text));
32
32
  break;
33
- case 'warning':
34
- console.log(chalk_1.default.yellow('⚠️ ' + event.message));
33
+ case "completed":
34
+ console.log(chalk_1.default.green("✓ " + event.message));
35
35
  break;
36
- case 'info':
37
- console.log(chalk_1.default.gray(' ' + event.message));
36
+ case "warning":
37
+ console.log(chalk_1.default.yellow("⚠️ " + event.message));
38
+ break;
39
+ case "info":
40
+ console.log(chalk_1.default.gray(" ℹ " + event.message));
38
41
  break;
39
42
  }
40
43
  }
@@ -42,6 +45,6 @@ function displayProgress(event) {
42
45
  * Display an error message
43
46
  */
44
47
  function displayError(error) {
45
- const message = error instanceof Error ? error.message : 'Unknown error';
46
- console.error(chalk_1.default.red('❌ Error:'), message);
48
+ const message = error instanceof Error ? error.message : "Unknown error";
49
+ console.error(chalk_1.default.red("❌ Error:"), message);
47
50
  }
@@ -63,7 +63,7 @@ function parseModelString(modelStr) {
63
63
  exports.benchmarkCommand
64
64
  .command("run")
65
65
  .description("Run a benchmark operation")
66
- .argument("<operation>", "Operation to benchmark (e.g., prd-parse, task-breakdown)")
66
+ .argument("<operation>", "Operation to benchmark (e.g., prd-parse, task-breakdown, task-create, prd-create)")
67
67
  .requiredOption("--models <list>", "Comma-separated list of models (provider:model[:reasoning=<tokens>])")
68
68
  .option("--file <path>", "Input file path (for PRD ops)")
69
69
  .option("--task-id <id>", "Task ID (for Task ops)")
@@ -72,7 +72,22 @@ exports.benchmarkCommand
72
72
  .option("--prompt <prompt>", "Override prompt")
73
73
  .option("--message <message>", "User message")
74
74
  .option("--tools", "Enable filesystem tools")
75
- .option("--feedback <feedback>", "Feedback (for rework)")
75
+ .option("--feedback <feedback>", "Feedback (for prd-rework)")
76
+ // Task creation options
77
+ .option("--title <title>", "Task title (for task-create)")
78
+ .option("--content <content>", "Task content (for task-create)")
79
+ .option("--parent-id <id>", "Parent task ID (for task-create)")
80
+ .option("--effort <effort>", "Effort estimate: small, medium, large (for task-create)")
81
+ .option("--force", "Force operation (for task-document)")
82
+ // PRD creation options
83
+ .option("--description <desc>", "Project/PRD description (for prd-create, prd-combine)")
84
+ .option("--output-dir <dir>", "Output directory (for prd-create, prd-combine)")
85
+ .option("--filename <name>", "Output filename (for prd-create, prd-combine)")
86
+ // PRD combine options
87
+ .option("--prds <list>", "Comma-separated list of PRD file paths (for prd-combine)")
88
+ // PRD refine options
89
+ .option("--question-mode <mode>", "Question mode: user or ai (for prd-refine)")
90
+ .option("--answers <json>", "JSON string of answers (for prd-refine user mode)")
76
91
  .action(async (operation, options) => {
77
92
  try {
78
93
  const modelStrings = options.models.split(",");
@@ -86,6 +101,7 @@ exports.benchmarkCommand
86
101
  console.log(chalk_1.default.dim(`Models: ${models.length}, Concurrency: ${config.concurrency}, Delay: ${config.delay}ms`));
87
102
  // Construct input object with all potential options
88
103
  const input = {
104
+ // Common options
89
105
  file: options.file,
90
106
  taskId: options.taskId,
91
107
  prompt: options.prompt,
@@ -93,6 +109,20 @@ exports.benchmarkCommand
93
109
  tools: options.tools,
94
110
  feedback: options.feedback,
95
111
  workingDirectory: process.cwd(), // Always pass current working directory
112
+ // Task creation options
113
+ title: options.title,
114
+ content: options.content,
115
+ parentId: options.parentId,
116
+ effort: options.effort,
117
+ force: options.force,
118
+ // PRD creation/combine options
119
+ description: options.description,
120
+ outputDir: options.outputDir,
121
+ filename: options.filename,
122
+ prds: options.prds ? options.prds.split(",").map((p) => p.trim()) : undefined,
123
+ // PRD refine options
124
+ questionMode: options.questionMode,
125
+ answers: options.answers ? JSON.parse(options.answers) : undefined,
96
126
  };
97
127
  // Prepare dashboard
98
128
  console.log(chalk_1.default.bold("\nBenchmark Progress:"));
@@ -181,6 +211,44 @@ exports.benchmarkCommand
181
211
  console.log(`- ${chalk_1.default.cyan(run.id)} (${date}) - ${run.command}`);
182
212
  });
183
213
  });
214
+ exports.benchmarkCommand
215
+ .command("operations")
216
+ .description("List all available benchmark operations")
217
+ .action(() => {
218
+ const { benchmarkRegistry } = require("../lib/benchmark/registry");
219
+ const operations = benchmarkRegistry.list();
220
+ console.log(chalk_1.default.bold("\n📊 Available Benchmark Operations\n"));
221
+ console.log(chalk_1.default.dim("Use these operation IDs with 'benchmark run <operation>'\n"));
222
+ // Group by category
223
+ const taskOps = operations.filter((op) => op.id.startsWith("task-"));
224
+ const prdOps = operations.filter((op) => op.id.startsWith("prd-"));
225
+ const workflowOps = operations.filter((op) => op.id.startsWith("workflow-"));
226
+ if (taskOps.length > 0) {
227
+ console.log(chalk_1.default.cyan.bold("Task Operations:"));
228
+ taskOps.forEach((op) => {
229
+ console.log(` ${chalk_1.default.green(op.id.padEnd(20))} - ${op.description}`);
230
+ });
231
+ console.log();
232
+ }
233
+ if (prdOps.length > 0) {
234
+ console.log(chalk_1.default.cyan.bold("PRD Operations:"));
235
+ prdOps.forEach((op) => {
236
+ console.log(` ${chalk_1.default.green(op.id.padEnd(20))} - ${op.description}`);
237
+ });
238
+ console.log();
239
+ }
240
+ if (workflowOps.length > 0) {
241
+ console.log(chalk_1.default.cyan.bold("Workflow Operations:"));
242
+ workflowOps.forEach((op) => {
243
+ console.log(` ${chalk_1.default.green(op.id.padEnd(20))} - ${op.description}`);
244
+ });
245
+ console.log();
246
+ }
247
+ console.log(chalk_1.default.dim("\nTotal operations: " + operations.length));
248
+ console.log(chalk_1.default.dim("\nExample usage:"));
249
+ console.log(chalk_1.default.gray(" task-o-matic benchmark run task-create --models anthropic:claude-3.5-sonnet --title \"Example task\""));
250
+ console.log(chalk_1.default.gray(" task-o-matic benchmark run prd-parse --models openai:gpt-4 --file ./prd.md"));
251
+ });
184
252
  exports.benchmarkCommand
185
253
  .command("show")
186
254
  .description("Show details of a benchmark run")
@@ -30,6 +30,9 @@ exports.initCommand
30
30
  .option("--auth <auth>", "Authentication for bootstrap", "better-auth")
31
31
  .option("--context7-api-key <key>", "Context7 API key")
32
32
  .option("--directory <dir>", "Working directory for the project")
33
+ .option("--package-manager <pm>", "Package manager (npm/pnpm/bun)", "npm")
34
+ .option("--runtime <runtime>", "Runtime (bun/node)", "node")
35
+ .option("--payment <payment>", "Payment provider (none/polar)", "none")
33
36
  .action(async (options) => {
34
37
  // Handle directory creation/setup first
35
38
  if (options.directory) {
@@ -41,12 +44,53 @@ exports.initCommand
41
44
  }
42
45
  // Set working directory in ConfigManager BEFORE any other operations
43
46
  config_1.configManager.setWorkingDirectory(targetDir);
47
+ await config_1.configManager.load();
44
48
  console.log(chalk_1.default.cyan(` 📁 Working directory: ${targetDir}`));
45
49
  }
50
+ // If project name is provided, run bootstrap FIRST
51
+ if (options.projectName && !options.noBootstrap) {
52
+ console.log(chalk_1.default.blue("\n🚀 Running bootstrap..."));
53
+ // Use working directory for Better-T-Stack execution
54
+ const workingDir = options.directory || process.cwd();
55
+ try {
56
+ const result = await (0, better_t_stack_cli_1.runBetterTStackCLI)(options, workingDir);
57
+ if (result.success && result.projectPath) {
58
+ console.log(chalk_1.default.green(result.message));
59
+ // Update config manager to point to the new project directory
60
+ config_1.configManager.setWorkingDirectory(result.projectPath);
61
+ await config_1.configManager.load();
62
+ // Initialize task-o-matic structure in the new project directory
63
+ await initializeProjectStructure(options);
64
+ }
65
+ else {
66
+ throw new Error(result.message);
67
+ }
68
+ }
69
+ catch (error) {
70
+ console.error(chalk_1.default.red("Bootstrap failed:"), error);
71
+ return; // Stop if bootstrap fails
72
+ }
73
+ }
74
+ else {
75
+ // Standard initialization in current directory
76
+ await initializeProjectStructure(options);
77
+ }
78
+ console.log(chalk_1.default.cyan("\nNext steps:"));
79
+ if (!options.projectName) {
80
+ console.log(" 1. Configure AI provider: task-o-matic config set-ai-provider <provider> <model>");
81
+ console.log(" 2. Bootstrap your project: task-o-matic init bootstrap <project-name>");
82
+ console.log(' 3. Create your first task: task-o-matic tasks create --title "Your first task"');
83
+ }
84
+ else {
85
+ console.log(` 1. cd ${options.projectName}`);
86
+ console.log(' 2. Create your first task: task-o-matic tasks create --title "Your first task"');
87
+ }
88
+ });
89
+ async function initializeProjectStructure(options) {
46
90
  const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
47
91
  console.log(chalk_1.default.blue(`🔍 Checking for task-o-matic directory: ${taskOMaticDir}`));
48
- if ((0, fs_1.existsSync)(taskOMaticDir)) {
49
- console.log(chalk_1.default.yellow("⚠️ This directory is already initialized with task-o-matic."));
92
+ if ((0, fs_1.existsSync)((0, path_1.join)(taskOMaticDir, "config.json"))) {
93
+ console.log(chalk_1.default.yellow("⚠️ This project is already initialized with task-o-matic."));
50
94
  return;
51
95
  }
52
96
  console.log(chalk_1.default.blue("🚀 Initializing task-o-matic project..."));
@@ -88,31 +132,7 @@ exports.initCommand
88
132
  (0, fs_1.writeFileSync)(mcpFilePath, JSON.stringify(mcpConfig, null, 2));
89
133
  console.log(chalk_1.default.green(` ✓ Created ${mcpFilePath}`));
90
134
  console.log(chalk_1.default.green("\n✅ TaskOMatic project initialized successfully!"));
91
- // Run bootstrap by default if project name is provided (unless --no-bootstrap)
92
- if (options.projectName && !options.noBootstrap) {
93
- console.log(chalk_1.default.blue("\n🚀 Running bootstrap..."));
94
- // Use working directory for Better-T-Stack execution
95
- const workingDir = options.directory || process.cwd();
96
- try {
97
- const result = await (0, better_t_stack_cli_1.runBetterTStackCLI)(options, workingDir);
98
- if (result.success) {
99
- console.log(chalk_1.default.green(result.message));
100
- }
101
- else {
102
- throw new Error(result.message);
103
- }
104
- }
105
- catch (error) {
106
- // No chdir needed anymore
107
- }
108
- }
109
- else {
110
- console.log(chalk_1.default.cyan("\nNext steps:"));
111
- console.log(" 1. Configure AI provider: task-o-matic config set-ai-provider <provider> <model>");
112
- console.log(" 2. Bootstrap your project: task-o-matic init bootstrap <project-name>");
113
- console.log(' 3. Create your first task: task-o-matic tasks create --title "Your first task"');
114
- }
115
- });
135
+ }
116
136
  // Bootstrap project with Better-T-Stack
117
137
  exports.initCommand
118
138
  .command("bootstrap")
@@ -131,6 +151,7 @@ exports.initCommand
131
151
  .option("--db-setup <setup>", "Database setup (turso/neon/prisma-postgres/mongodb-atlas)")
132
152
  .option("--runtime <runtime>", "Runtime (bun/node)", "node")
133
153
  .option("--api <type>", "API type (trpc/orpc)")
154
+ .option("--payment <payment>", "Payment provider (none/polar)", "none")
134
155
  .action(async (name, options) => {
135
156
  const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
136
157
  if (!(0, fs_1.existsSync)(taskOMaticDir)) {
@@ -1 +1 @@
1
- {"version":3,"file":"prd.d.ts","sourceRoot":"","sources":["../../src/commands/prd.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,UAAU,SAEtB,CAAC"}
1
+ {"version":3,"file":"prd.d.ts","sourceRoot":"","sources":["../../src/commands/prd.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,UAAU,SAEtB,CAAC"}
@@ -41,10 +41,211 @@ exports.prdCommand = void 0;
41
41
  const commander_1 = require("commander");
42
42
  const chalk_1 = __importDefault(require("chalk"));
43
43
  const inquirer_1 = __importDefault(require("inquirer"));
44
+ const fs_1 = require("fs");
44
45
  const prd_1 = require("../services/prd");
45
46
  const streaming_options_1 = require("../utils/streaming-options");
46
47
  const progress_1 = require("../cli/display/progress");
47
48
  exports.prdCommand = new commander_1.Command("prd").description("Manage PRDs and generate tasks");
49
+ // Helper to parse model string (provider:model)
50
+ function parseModelString(modelStr) {
51
+ const parts = modelStr.split(":");
52
+ if (parts.length < 2) {
53
+ throw new Error(`Invalid model format: ${modelStr}. Expected provider:model`);
54
+ }
55
+ return { provider: parts[0], model: parts[1] };
56
+ }
57
+ // Create PRD command
58
+ exports.prdCommand
59
+ .command("create")
60
+ .description("Generate PRD(s) from a product description")
61
+ .argument("<description>", "Product description")
62
+ .option("--ai <provider:model...>", "AI model(s) to use for generation (can specify multiple)")
63
+ .option("--combine-ai <provider:model>", "AI model to combine multiple PRDs into master PRD")
64
+ .option("--output-dir <path>", "Directory to save PRDs", ".task-o-matic/prd")
65
+ .option("--stream", "Enable streaming output (only for single AI)")
66
+ .action(async (description, options) => {
67
+ try {
68
+ const aiModels = options.ai || ["openrouter:anthropic/claude-3.5-sonnet"];
69
+ const isSingleModel = aiModels.length === 1;
70
+ // For single model, support streaming
71
+ if (isSingleModel) {
72
+ const modelConfig = parseModelString(aiModels[0]);
73
+ const streamingOptions = (0, streaming_options_1.createStreamingOptions)(options.stream, "Generating PRD");
74
+ const result = await prd_1.prdService.generatePRD({
75
+ description,
76
+ outputDir: options.outputDir,
77
+ filename: `prd-${modelConfig.provider}-${modelConfig.model.replace(/\//g, "-")}.md`,
78
+ aiOptions: {
79
+ aiProvider: modelConfig.provider,
80
+ aiModel: modelConfig.model,
81
+ },
82
+ streamingOptions,
83
+ callbacks: {
84
+ onProgress: progress_1.displayProgress,
85
+ onError: progress_1.displayError,
86
+ },
87
+ });
88
+ console.log("");
89
+ console.log(chalk_1.default.green(`✓ PRD generated: ${result.path}`));
90
+ console.log(chalk_1.default.cyan(` Duration: ${result.stats.duration}ms`));
91
+ if (result.stats.tokenUsage) {
92
+ console.log(chalk_1.default.cyan(` Tokens: ${result.stats.tokenUsage.total}`));
93
+ }
94
+ if (result.stats.timeToFirstToken) {
95
+ console.log(chalk_1.default.cyan(` TTFT: ${result.stats.timeToFirstToken}ms`));
96
+ }
97
+ }
98
+ else {
99
+ // Multiple models - use benchmark-style display
100
+ console.log(chalk_1.default.blue(`\nGenerating ${aiModels.length} PRDs concurrently...\n`));
101
+ const modelMap = new Map();
102
+ const modelStatus = new Map();
103
+ const results = [];
104
+ // Print initial lines
105
+ aiModels.forEach((m, i) => {
106
+ modelMap.set(m, i);
107
+ modelStatus.set(m, "Waiting...");
108
+ console.log(chalk_1.default.dim(`- ${m}: Waiting...`));
109
+ });
110
+ const totalModels = aiModels.length;
111
+ // Generate PRDs concurrently
112
+ const promises = aiModels.map(async (modelStr) => {
113
+ const modelConfig = parseModelString(modelStr);
114
+ const index = modelMap.get(modelStr);
115
+ // Update status: Starting
116
+ const up = totalModels - index;
117
+ process.stdout.write(`\x1B[${up}A`);
118
+ process.stdout.write(`\x1B[2K`);
119
+ process.stdout.write(`- ${chalk_1.default.bold(modelStr)}: ${chalk_1.default.yellow("Starting...")}\r`);
120
+ process.stdout.write(`\x1B[${up}B`);
121
+ try {
122
+ const result = await prd_1.prdService.generatePRD({
123
+ description,
124
+ outputDir: options.outputDir,
125
+ filename: `prd-${modelConfig.provider}-${modelConfig.model.replace(/\//g, "-")}.md`,
126
+ aiOptions: {
127
+ aiProvider: modelConfig.provider,
128
+ aiModel: modelConfig.model,
129
+ },
130
+ callbacks: {
131
+ onProgress: (event) => {
132
+ if (event.type === "progress") {
133
+ const up = totalModels - index;
134
+ process.stdout.write(`\x1B[${up}A`);
135
+ process.stdout.write(`\x1B[2K`);
136
+ process.stdout.write(`- ${chalk_1.default.bold(modelStr)}: ${chalk_1.default.blue(event.message)}\r`);
137
+ process.stdout.write(`\x1B[${up}B`);
138
+ }
139
+ },
140
+ },
141
+ });
142
+ // Update status: Completed
143
+ const up2 = totalModels - index;
144
+ process.stdout.write(`\x1B[${up2}A`);
145
+ process.stdout.write(`\x1B[2K`);
146
+ process.stdout.write(`- ${chalk_1.default.bold(modelStr)}: ${chalk_1.default.green(`Completed (${result.stats.duration}ms)`)}\r`);
147
+ process.stdout.write(`\x1B[${up2}B`);
148
+ results.push({
149
+ modelId: modelStr,
150
+ path: result.path,
151
+ stats: result.stats,
152
+ });
153
+ return result;
154
+ }
155
+ catch (error) {
156
+ const up2 = totalModels - index;
157
+ process.stdout.write(`\x1B[${up2}A`);
158
+ process.stdout.write(`\x1B[2K`);
159
+ process.stdout.write(`- ${chalk_1.default.bold(modelStr)}: ${chalk_1.default.red(`Failed: ${error instanceof Error ? error.message : String(error)}`)}\r`);
160
+ process.stdout.write(`\x1B[${up2}B`);
161
+ throw error;
162
+ }
163
+ });
164
+ await Promise.all(promises);
165
+ // Display summary
166
+ console.log(chalk_1.default.green(`\n✓ Generated ${results.length} PRDs\n`));
167
+ console.log(chalk_1.default.bold(`${"Model".padEnd(40)} | ${"Duration".padEnd(10)} | ${"TTFT".padEnd(10)} | ${"Tokens".padEnd(10)}`));
168
+ console.log("-".repeat(80));
169
+ results.forEach((r) => {
170
+ const duration = `${r.stats.duration}ms`;
171
+ const ttft = r.stats.timeToFirstToken
172
+ ? `${r.stats.timeToFirstToken}ms`
173
+ : "N/A";
174
+ const tokens = r.stats.tokenUsage
175
+ ? r.stats.tokenUsage.total.toString()
176
+ : "N/A";
177
+ console.log(`${r.modelId.padEnd(40)} | ${duration.padEnd(10)} | ${ttft.padEnd(10)} | ${tokens.padEnd(10)}`);
178
+ });
179
+ // Combine if requested
180
+ if (options.combineAi) {
181
+ console.log(chalk_1.default.blue("\nCombining PRDs into master PRD..."));
182
+ const combineModelConfig = parseModelString(options.combineAi);
183
+ const prdContents = results.map((r) => (0, fs_1.readFileSync)(r.path, "utf-8"));
184
+ const masterResult = await prd_1.prdService.combinePRDs({
185
+ prds: prdContents,
186
+ originalDescription: description,
187
+ outputDir: options.outputDir,
188
+ filename: "prd-master.md",
189
+ aiOptions: {
190
+ aiProvider: combineModelConfig.provider,
191
+ aiModel: combineModelConfig.model,
192
+ },
193
+ callbacks: {
194
+ onProgress: progress_1.displayProgress,
195
+ onError: progress_1.displayError,
196
+ },
197
+ });
198
+ console.log(chalk_1.default.green(`\n✓ Master PRD created: ${masterResult.path}`));
199
+ console.log(chalk_1.default.cyan(` Duration: ${masterResult.stats.duration}ms`));
200
+ }
201
+ }
202
+ }
203
+ catch (error) {
204
+ (0, progress_1.displayError)(error);
205
+ process.exit(1);
206
+ }
207
+ });
208
+ // Combine PRDs command
209
+ exports.prdCommand
210
+ .command("combine")
211
+ .description("Combine multiple PRD files into a master PRD")
212
+ .requiredOption("--files <paths...>", "PRD files to combine")
213
+ .requiredOption("--description <text>", "Original product description")
214
+ .requiredOption("--ai <provider:model>", "AI model to use for combining")
215
+ .option("--output <path>", "Output file path", "prd-master.md")
216
+ .option("--stream", "Enable streaming output")
217
+ .action(async (options) => {
218
+ try {
219
+ const modelConfig = parseModelString(options.ai);
220
+ const streamingOptions = (0, streaming_options_1.createStreamingOptions)(options.stream, "Combining PRDs");
221
+ // Read all PRD files
222
+ const prdContents = options.files.map((file) => (0, fs_1.readFileSync)(file, "utf-8"));
223
+ const result = await prd_1.prdService.combinePRDs({
224
+ prds: prdContents,
225
+ originalDescription: options.description,
226
+ filename: options.output,
227
+ aiOptions: {
228
+ aiProvider: modelConfig.provider,
229
+ aiModel: modelConfig.model,
230
+ },
231
+ streamingOptions,
232
+ callbacks: {
233
+ onProgress: progress_1.displayProgress,
234
+ onError: progress_1.displayError,
235
+ },
236
+ });
237
+ console.log("");
238
+ console.log(chalk_1.default.green(`✓ Master PRD created: ${result.path}`));
239
+ console.log(chalk_1.default.cyan(` Duration: ${result.stats.duration}ms`));
240
+ if (result.stats.tokenUsage) {
241
+ console.log(chalk_1.default.cyan(` Tokens: ${result.stats.tokenUsage.total}`));
242
+ }
243
+ }
244
+ catch (error) {
245
+ (0, progress_1.displayError)(error);
246
+ process.exit(1);
247
+ }
248
+ });
48
249
  // Parse PRD into tasks
49
250
  exports.prdCommand
50
251
  .command("parse")
@@ -1 +1 @@
1
- {"version":3,"file":"execute-loop.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/execute-loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiDpC,eAAO,MAAM,kBAAkB,SAoI3B,CAAC"}
1
+ {"version":3,"file":"execute-loop.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/execute-loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmDpC,eAAO,MAAM,kBAAkB,SAwJ3B,CAAC"}
@@ -52,6 +52,11 @@ exports.executeLoopCommand = new commander_1.Command("execute-loop")
52
52
  return [...previous, value];
53
53
  })
54
54
  .option("--auto-commit", "Automatically commit changes after each task", false)
55
+ .option("--plan", "Generate an implementation plan before execution", false)
56
+ .option("--plan-model <model>", "Model/executor to use for planning (e.g., 'opencode:gpt-4o')")
57
+ .option("--review-plan", "Pause for human review of the plan", false)
58
+ .option("--review", "Run AI review after execution", false)
59
+ .option("--review-model <model>", "Model/executor to use for review (e.g., 'opencode:gpt-4o')")
55
60
  .option("--dry", "Show what would be executed without running it", false)
56
61
  .action(async (options) => {
57
62
  try {
@@ -99,6 +104,11 @@ exports.executeLoopCommand = new commander_1.Command("execute-loop")
99
104
  verificationCommands: options.verify || [],
100
105
  autoCommit: options.autoCommit,
101
106
  tryModels,
107
+ plan: options.plan,
108
+ planModel: options.planModel,
109
+ reviewPlan: options.reviewPlan,
110
+ review: options.review,
111
+ reviewModel: options.reviewModel,
102
112
  },
103
113
  dry: options.dry,
104
114
  };
@@ -1 +1 @@
1
- {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,cAAc,SAoCvB,CAAC"}
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,cAAc,SA4CvB,CAAC"}
@@ -12,6 +12,8 @@ exports.executeCommand = new commander_1.Command("execute")
12
12
  .requiredOption("--id <id>", "Task ID to execute")
13
13
  .option("--tool <tool>", "External tool to use (opencode/claude/gemini/codex)", "opencode")
14
14
  .option("--message <message>", "Custom message to send to the tool (uses task plan if not provided)")
15
+ .option("-m, --model <model>", "Model to use with the executor")
16
+ .option("--continue-session", "Continue the last session (for error feedback)", false)
15
17
  .option("--dry", "Show what would be executed without running it")
16
18
  .option("--validate <command>", "Validation command to run after execution (can be used multiple times)", (value, previous = []) => {
17
19
  return [...previous, value];
@@ -22,6 +24,8 @@ exports.executeCommand = new commander_1.Command("execute")
22
24
  taskId: options.id,
23
25
  tool: options.tool,
24
26
  message: options.message,
27
+ model: options.model,
28
+ continueSession: options.continueSession,
25
29
  dry: options.dry,
26
30
  validate: options.validate || [],
27
31
  });
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,eAAO,MAAM,eAAe,SAoJxB,CAAC"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,eAAO,MAAM,eAAe,SAsKxB,CAAC"}