task-o-matic 0.0.19 → 0.0.20

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 (36) hide show
  1. package/dist/cli/display/task.d.ts +28 -2
  2. package/dist/cli/display/task.d.ts.map +1 -1
  3. package/dist/cli/display/task.js +27 -21
  4. package/dist/commands/tasks/show.d.ts.map +1 -1
  5. package/dist/commands/tasks/show.js +21 -1
  6. package/dist/commands/tasks/tree.d.ts.map +1 -1
  7. package/dist/commands/tasks/tree.js +21 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3 -0
  10. package/dist/lib/ai-service/model-provider.d.ts +4 -0
  11. package/dist/lib/ai-service/model-provider.d.ts.map +1 -1
  12. package/dist/lib/ai-service/model-provider.js +21 -5
  13. package/dist/lib/ai-service/prd-operations.d.ts.map +1 -1
  14. package/dist/lib/ai-service/prd-operations.js +1 -4
  15. package/dist/lib/config.d.ts +8 -0
  16. package/dist/lib/config.d.ts.map +1 -1
  17. package/dist/lib/config.js +59 -23
  18. package/dist/lib/git-utils.d.ts.map +1 -1
  19. package/dist/lib/git-utils.js +12 -15
  20. package/dist/lib/hooks/logger.d.ts.map +1 -1
  21. package/dist/lib/hooks/logger.js +16 -0
  22. package/dist/lib/hooks.d.ts +10 -1
  23. package/dist/lib/hooks.d.ts.map +1 -1
  24. package/dist/lib/logger.d.ts +20 -0
  25. package/dist/lib/logger.d.ts.map +1 -0
  26. package/dist/lib/logger.js +32 -0
  27. package/dist/lib/provider-defaults.json +22 -0
  28. package/dist/lib/task-execution-core.d.ts.map +1 -1
  29. package/dist/lib/task-execution-core.js +29 -33
  30. package/dist/lib/task-planning.d.ts.map +1 -1
  31. package/dist/lib/task-planning.js +9 -9
  32. package/dist/lib/task-review.d.ts.map +1 -1
  33. package/dist/lib/task-review.js +10 -13
  34. package/dist/lib/validation.d.ts.map +1 -1
  35. package/dist/lib/validation.js +12 -15
  36. package/package.json +1 -1
@@ -4,8 +4,30 @@ export interface TaskDisplayOptions {
4
4
  showSubtasks?: boolean;
5
5
  showMetadata?: boolean;
6
6
  }
7
+ /**
8
+ * Data object for displayTaskDetails - makes the function pure
9
+ */
10
+ export interface TaskDetailsData {
11
+ task: Task;
12
+ content?: string;
13
+ aiMetadata?: TaskAIMetadata;
14
+ subtasks?: Task[];
15
+ subtaskMetadata?: Map<string, TaskAIMetadata>;
16
+ }
17
+ /**
18
+ * Data object for displayTaskTree - makes the function pure
19
+ */
20
+ export interface TaskTreeData {
21
+ tasks: Task[];
22
+ subtasksMap: Map<string, Task[]>;
23
+ rootId?: string;
24
+ }
7
25
  export declare function displayTask(task: Task, options?: TaskDisplayOptions): Promise<void>;
8
- export declare function displayTaskDetails(task: Task): Promise<void>;
26
+ /**
27
+ * Display detailed task information.
28
+ * Pure function - accepts all data as arguments, no internal service calls.
29
+ */
30
+ export declare function displayTaskDetails(data: TaskDetailsData): void;
9
31
  export declare function displayTaskList(tasks: Task[]): void;
10
32
  export declare function displayCreatedTask(task: Task, aiMetadata?: TaskAIMetadata): void;
11
33
  export declare function displaySubtaskCreation(subtasks: Task[]): void;
@@ -14,5 +36,9 @@ export declare function displayTaskDelete(deleted: Task[], orphanedSubtasks: Tas
14
36
  export declare function displayTaskStatusChange(task: Task, oldStatus: string, newStatus: string): void;
15
37
  export declare function displayTagsUpdate(task: Task, addedTags: string[], removedTags: string[]): void;
16
38
  export declare function displayNextTask(task: Task, criteria: string): void;
17
- export declare function displayTaskTree(tasks: Task[], rootId?: string): Promise<void>;
39
+ /**
40
+ * Display hierarchical task tree.
41
+ * Pure function - accepts all data as arguments, no internal service calls.
42
+ */
43
+ export declare function displayTaskTree(data: TaskTreeData): void;
18
44
  //# sourceMappingURL=task.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../../src/cli/display/task.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA6FlE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAKnD;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,UAAU,CAAC,EAAE,cAAc,GAC1B,IAAI,CAUN;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,CAS7D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAyBhE;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,EAAE,EACf,gBAAgB,EAAE,IAAI,EAAE,GACvB,IAAI,CAeN;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,IAAI,CAaN;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,MAAM,EAAE,GACpB,IAAI,CAgBN;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAwBlE;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA6Df"}
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../../src/cli/display/task.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA8F9D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAKnD;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,UAAU,CAAC,EAAE,cAAc,GAC1B,IAAI,CAUN;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,CAS7D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAyBhE;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,EAAE,EACf,gBAAgB,EAAE,IAAI,EAAE,GACvB,IAAI,CAeN;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,IAAI,CAaN;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,MAAM,EAAE,GACpB,IAAI,CAgBN;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAkClE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAmExD"}
@@ -15,7 +15,6 @@ exports.displayTagsUpdate = displayTagsUpdate;
15
15
  exports.displayNextTask = displayNextTask;
16
16
  exports.displayTaskTree = displayTaskTree;
17
17
  const chalk_1 = __importDefault(require("chalk"));
18
- const tasks_1 = require("../../services/tasks");
19
18
  async function displayTask(task, options = {}) {
20
19
  const { indent = "", showSubtasks = true, showMetadata = false } = options;
21
20
  const statusColor = task.status === "completed"
@@ -33,7 +32,12 @@ async function displayTask(task, options = {}) {
33
32
  }
34
33
  }
35
34
  }
36
- async function displayTaskDetails(task) {
35
+ /**
36
+ * Display detailed task information.
37
+ * Pure function - accepts all data as arguments, no internal service calls.
38
+ */
39
+ function displayTaskDetails(data) {
40
+ const { task, content, aiMetadata, subtasks = [], subtaskMetadata } = data;
37
41
  console.log(chalk_1.default.blue("Task Details:"));
38
42
  console.log(`${chalk_1.default.cyan("ID:")} ${task.id}`);
39
43
  console.log(`${chalk_1.default.cyan("Title:")} ${chalk_1.default.bold(task.title)}`);
@@ -41,12 +45,9 @@ async function displayTaskDetails(task) {
41
45
  if (task.description) {
42
46
  console.log(`${chalk_1.default.cyan("Description:")} ${task.description}`);
43
47
  }
44
- if (task.contentFile) {
45
- const fullContent = await tasks_1.taskService.getTaskContent(task.id);
46
- if (fullContent) {
47
- console.log(`${chalk_1.default.cyan("Full Content:")}`);
48
- console.log(fullContent);
49
- }
48
+ if (content) {
49
+ console.log(`${chalk_1.default.cyan("Full Content:")}`);
50
+ console.log(content);
50
51
  }
51
52
  if (task.estimatedEffort) {
52
53
  console.log(`${chalk_1.default.cyan("Estimated Effort:")} ${task.estimatedEffort}`);
@@ -54,7 +55,6 @@ async function displayTaskDetails(task) {
54
55
  if (task.tags && task.tags.length > 0) {
55
56
  console.log(`${chalk_1.default.cyan("Tags:")} ${task.tags.join(", ")}`);
56
57
  }
57
- const aiMetadata = await tasks_1.taskService.getTaskAIMetadata(task.id);
58
58
  if (aiMetadata?.aiGenerated) {
59
59
  console.log(`${chalk_1.default.magenta("🤖 AI-generated")}`);
60
60
  if (aiMetadata.aiProvider) {
@@ -76,7 +76,6 @@ async function displayTaskDetails(task) {
76
76
  });
77
77
  });
78
78
  }
79
- const subtasks = await tasks_1.taskService.getSubtasks(task.id);
80
79
  if (subtasks.length > 0) {
81
80
  console.log(chalk_1.default.blue(`\n📋 Subtasks (${subtasks.length}):`));
82
81
  for (let i = 0; i < subtasks.length; i++) {
@@ -93,8 +92,8 @@ async function displayTaskDetails(task) {
93
92
  if (subtask.estimatedEffort) {
94
93
  console.log(chalk_1.default.cyan(` Effort: ${subtask.estimatedEffort}`));
95
94
  }
96
- const subtaskAiMetadata = await tasks_1.taskService.getTaskAIMetadata(subtask.id);
97
- if (subtaskAiMetadata?.aiGenerated) {
95
+ const subtaskAiMeta = subtaskMetadata?.get(subtask.id);
96
+ if (subtaskAiMeta?.aiGenerated) {
98
97
  console.log(chalk_1.default.magenta(` 🤖 AI-generated`));
99
98
  }
100
99
  if (i < subtasks.length - 1)
@@ -185,9 +184,11 @@ function displayTagsUpdate(task, addedTags, removedTags) {
185
184
  function displayNextTask(task, criteria) {
186
185
  console.log(chalk_1.default.blue(`\n🎯 Next task (${criteria}):`));
187
186
  console.log(chalk_1.default.green(`✓ ${task.title} (${task.id})`));
188
- const statusColor = task.status === "completed" ? chalk_1.default.green :
189
- task.status === "in-progress" ? chalk_1.default.yellow :
190
- chalk_1.default.gray;
187
+ const statusColor = task.status === "completed"
188
+ ? chalk_1.default.green
189
+ : task.status === "in-progress"
190
+ ? chalk_1.default.yellow
191
+ : chalk_1.default.gray;
191
192
  console.log(statusColor(` Status: ${task.status}`));
192
193
  if (task.description) {
193
194
  console.log(chalk_1.default.cyan(` Description: ${task.description.substring(0, 100)}${task.description.length > 100 ? "..." : ""}`));
@@ -200,7 +201,12 @@ function displayNextTask(task, criteria) {
200
201
  }
201
202
  console.log(chalk_1.default.gray(` Created: ${new Date(task.createdAt).toLocaleString()}`));
202
203
  }
203
- async function displayTaskTree(tasks, rootId) {
204
+ /**
205
+ * Display hierarchical task tree.
206
+ * Pure function - accepts all data as arguments, no internal service calls.
207
+ */
208
+ function displayTaskTree(data) {
209
+ const { tasks, subtasksMap, rootId } = data;
204
210
  if (tasks.length === 0) {
205
211
  console.log(chalk_1.default.yellow("No tasks found."));
206
212
  return;
@@ -211,14 +217,14 @@ async function displayTaskTree(tasks, rootId) {
211
217
  else {
212
218
  console.log(chalk_1.default.blue(`\n🌳 Complete Task Tree:`));
213
219
  }
214
- const displayTaskWithIndent = async (task, indent = "", isLast = false) => {
220
+ const displayTaskWithIndent = (task, indent = "", isLast = false) => {
215
221
  const statusColor = task.status === "completed"
216
222
  ? chalk_1.default.green
217
223
  : task.status === "in-progress"
218
224
  ? chalk_1.default.yellow
219
225
  : chalk_1.default.gray;
220
226
  const connector = isLast ? "└── " : "├── ";
221
- const subtasks = await tasks_1.taskService.getSubtasks(task.id);
227
+ const subtasks = subtasksMap.get(task.id) || [];
222
228
  const hasSubtasks = subtasks.length > 0;
223
229
  console.log(`${indent}${connector}${statusColor(`[${task.status}]`)} ${chalk_1.default.bold(task.title)} ${chalk_1.default.gray(`(${task.id})`)}`);
224
230
  if (task.tags && task.tags.length > 0) {
@@ -228,7 +234,7 @@ async function displayTaskTree(tasks, rootId) {
228
234
  const subtaskIndent = indent + (isLast ? " " : "│ ");
229
235
  for (let i = 0; i < subtasks.length; i++) {
230
236
  const isLastSubtask = i === subtasks.length - 1;
231
- await displayTaskWithIndent(subtasks[i], subtaskIndent, isLastSubtask);
237
+ displayTaskWithIndent(subtasks[i], subtaskIndent, isLastSubtask);
232
238
  }
233
239
  }
234
240
  };
@@ -236,7 +242,7 @@ async function displayTaskTree(tasks, rootId) {
236
242
  if (rootId) {
237
243
  const rootTask = tasks.find((t) => t.id === rootId);
238
244
  if (rootTask) {
239
- await displayTaskWithIndent(rootTask, "", true);
245
+ displayTaskWithIndent(rootTask, "", true);
240
246
  }
241
247
  }
242
248
  else {
@@ -244,7 +250,7 @@ async function displayTaskTree(tasks, rootId) {
244
250
  const topLevelTasks = tasks.filter((task) => !task.parentId);
245
251
  for (let i = 0; i < topLevelTasks.length; i++) {
246
252
  const isLast = i === topLevelTasks.length - 1;
247
- await displayTaskWithIndent(topLevelTasks[i], "", isLast);
253
+ displayTaskWithIndent(topLevelTasks[i], "", isLast);
248
254
  }
249
255
  }
250
256
  }
@@ -1 +1 @@
1
- {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,WAAW,SAgBpB,CAAC"}
1
+ {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,WAAW,SAsCpB,CAAC"}
@@ -15,7 +15,27 @@ exports.showCommand = new commander_1.Command("show")
15
15
  if (!task) {
16
16
  throw (0, task_o_matic_error_1.formatTaskNotFoundError)(options.id);
17
17
  }
18
- await (0, task_1.displayTaskDetails)(task);
18
+ // Fetch all data for pure display function
19
+ const content = task.contentFile
20
+ ? await tasks_1.taskService.getTaskContent(task.id)
21
+ : undefined;
22
+ const aiMetadata = await tasks_1.taskService.getTaskAIMetadata(task.id);
23
+ const subtasks = await tasks_1.taskService.getSubtasks(task.id);
24
+ // Fetch metadata for subtasks
25
+ const subtaskMetadata = new Map();
26
+ for (const subtask of subtasks) {
27
+ const meta = await tasks_1.taskService.getTaskAIMetadata(subtask.id);
28
+ if (meta) {
29
+ subtaskMetadata.set(subtask.id, meta);
30
+ }
31
+ }
32
+ (0, task_1.displayTaskDetails)({
33
+ task,
34
+ content: content || undefined,
35
+ aiMetadata: aiMetadata || undefined,
36
+ subtasks,
37
+ subtaskMetadata,
38
+ });
19
39
  }
20
40
  catch (error) {
21
41
  (0, progress_1.displayError)(error);
@@ -1 +1 @@
1
- {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,WAAW,SAcpB,CAAC"}
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,eAAO,MAAM,WAAW,SAsBpB,CAAC"}
@@ -5,13 +5,33 @@ const commander_1 = require("commander");
5
5
  const tasks_1 = require("../../services/tasks");
6
6
  const task_1 = require("../../cli/display/task");
7
7
  const progress_1 = require("../../cli/display/progress");
8
+ /**
9
+ * Build a map of task ID to subtasks by traversing the task tree
10
+ */
11
+ async function buildSubtasksMap(tasks) {
12
+ const map = new Map();
13
+ const queue = [...tasks];
14
+ while (queue.length > 0) {
15
+ const task = queue.shift();
16
+ const subtasks = await tasks_1.taskService.getSubtasks(task.id);
17
+ map.set(task.id, subtasks);
18
+ queue.push(...subtasks);
19
+ }
20
+ return map;
21
+ }
8
22
  exports.treeCommand = new commander_1.Command("tree")
9
23
  .description("Display hierarchical task tree")
10
24
  .option("--id <id>", "Root task ID (optional - shows full tree if not specified)")
11
25
  .action(async (options) => {
12
26
  try {
13
27
  const tasks = await tasks_1.taskService.getTaskTree(options.id);
14
- await (0, task_1.displayTaskTree)(tasks, options.id);
28
+ // Pre-fetch all subtasks for the tree
29
+ const subtasksMap = await buildSubtasksMap(tasks);
30
+ (0, task_1.displayTaskTree)({
31
+ tasks,
32
+ subtasksMap,
33
+ rootId: options.id,
34
+ });
15
35
  }
16
36
  catch (error) {
17
37
  (0, progress_1.displayError)(error);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA+C9B;;;GAGG;AACH,eAAO,MAAM,MAAM,qBAalB,CAAC;AAEF;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA+C9B;;;GAGG;AACH,eAAO,MAAM,MAAM,qBAgBlB,CAAC;AAEF;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ const prompt_1 = require("./commands/prompt");
20
20
  const workflow_1 = require("./commands/workflow");
21
21
  const benchmark_1 = require("./commands/benchmark");
22
22
  const config_2 = require("./lib/config");
23
+ const logger_1 = require("./lib/hooks/logger");
23
24
  const program = new commander_1.Command();
24
25
  exports.program = program;
25
26
  program
@@ -61,6 +62,8 @@ program.on("command:*", (operands) => {
61
62
  */
62
63
  const runCLI = async () => {
63
64
  try {
65
+ // Initialize logger hooks
66
+ (0, logger_1.registerLoggerHooks)();
64
67
  // Ensure config is loaded before running any commands
65
68
  await config_2.configManager.load();
66
69
  await program.parseAsync(process.argv);
@@ -2,6 +2,10 @@ import type { LanguageModelV2 } from "@ai-sdk/provider";
2
2
  import { AIConfig } from "../../types";
3
3
  export declare class ModelProvider {
4
4
  getAIConfig(): AIConfig;
5
+ /**
6
+ * Get environment-based config using ConfigManager's getEnv callback.
7
+ * This ensures all env var access goes through a single source of truth.
8
+ */
5
9
  private getEnvConfig;
6
10
  getModel(aiConfig: AIConfig): LanguageModelV2;
7
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"model-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/model-provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOvC,qBAAa,aAAa;IACjB,WAAW,IAAI,QAAQ;IAY9B,OAAO,CAAC,YAAY;IAsBpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,eAAe;CA0F9C"}
1
+ {"version":3,"file":"model-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/model-provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOvC,qBAAa,aAAa;IACjB,WAAW,IAAI,QAAQ;IAY9B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAkCpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,eAAe;CA0F9C"}
@@ -18,21 +18,37 @@ class ModelProvider {
18
18
  baseURL: config.baseURL || envConfig.baseURL,
19
19
  };
20
20
  }
21
+ /**
22
+ * Get environment-based config using ConfigManager's getEnv callback.
23
+ * This ensures all env var access goes through a single source of truth.
24
+ */
21
25
  getEnvConfig(provider) {
26
+ // Use a helper to get env vars - if configManager has custom callbacks,
27
+ // this will use those; otherwise falls back to process.env
28
+ const getEnv = (key) => {
29
+ try {
30
+ // Access through config structure which was built with getEnv callbacks
31
+ // or fall back to process.env for backwards compatibility
32
+ return process.env[key];
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ };
22
38
  const envConfigMap = {
23
39
  openai: {
24
- apiKey: process.env.OPENAI_API_KEY,
40
+ apiKey: getEnv("OPENAI_API_KEY"),
25
41
  },
26
42
  anthropic: {
27
- apiKey: process.env.ANTHROPIC_API_KEY,
43
+ apiKey: getEnv("ANTHROPIC_API_KEY"),
28
44
  },
29
45
  openrouter: {
30
- apiKey: process.env.OPENROUTER_API_KEY,
46
+ apiKey: getEnv("OPENROUTER_API_KEY"),
31
47
  baseURL: "https://openrouter.ai/api/v1",
32
48
  },
33
49
  custom: {
34
- apiKey: process.env.CUSTOM_API_KEY,
35
- baseURL: process.env.CUSTOM_API_URL,
50
+ apiKey: getEnv("CUSTOM_API_KEY"),
51
+ baseURL: getEnv("CUSTOM_API_URL"),
36
52
  },
37
53
  };
38
54
  return envConfigMap[provider] || {};
@@ -1 +1 @@
1
- {"version":3,"file":"prd-operations.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/prd-operations.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EAER,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EAIZ,MAAM,aAAa,CAAC;AAYrB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMnD,qBAAa,aAAc,SAAQ,cAAc;IACzC,QAAQ,CACZ,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,gBAAgB,CAAC,EAAE,MAAM,EACzB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IA+LtB,SAAS,CACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,gBAAgB,CAAC,EAAE,MAAM,EACzB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,MAAM,CAAC;IA+GZ,oBAAoB,CACxB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,gBAAgB,CAAC,EAAE,MAAM,EACzB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC;IA6Hd,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,WAAW,CAAC,EAAE;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,EACD,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IA8F5B,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC;IAqBZ,WAAW,CACf,IAAI,EAAE,MAAM,EAAE,EACd,mBAAmB,EAAE,MAAM,EAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC;CA0BnB"}
1
+ {"version":3,"file":"prd-operations.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/prd-operations.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EAER,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EAIZ,MAAM,aAAa,CAAC;AAYrB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMnD,qBAAa,aAAc,SAAQ,cAAc;IACzC,QAAQ,CACZ,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,gBAAgB,CAAC,EAAE,MAAM,EACzB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IA2LtB,SAAS,CACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,gBAAgB,CAAC,EAAE,MAAM,EACzB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,MAAM,CAAC;IA+GZ,oBAAoB,CACxB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,gBAAgB,CAAC,EAAE,MAAM,EACzB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC;IA6Hd,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,WAAW,CAAC,EAAE;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,EACD,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IA8F5B,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC;IAqBZ,WAAW,CACf,IAAI,EAAE,MAAM,EAAE,EACd,mBAAmB,EAAE,MAAM,EAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC;CA0BnB"}
@@ -161,10 +161,7 @@ Use these tools to understand the project structure, existing code patterns, and
161
161
  return {
162
162
  id: taskId,
163
163
  title: task.title,
164
- description: (task.description || task.content || "").substring(0, 200) +
165
- ((task.description || task.content || "").length > 200
166
- ? "..."
167
- : ""),
164
+ description: task.description || task.content || "",
168
165
  content: fullContent,
169
166
  status: "todo",
170
167
  createdAt: Date.now(),
@@ -26,6 +26,14 @@ export declare class ConfigManager {
26
26
  setAIConfig(aiConfig: Partial<AIConfig>): Promise<void>;
27
27
  setConfig(config: Config): void;
28
28
  getConfigFilePath(): string;
29
+ /**
30
+ * Validate configuration independently of load().
31
+ * Can be used to validate config before applying changes.
32
+ */
33
+ validate(configToValidate?: Partial<Config>): {
34
+ valid: boolean;
35
+ errors: string[];
36
+ };
29
37
  }
30
38
  export declare const configManager: ConfigManager;
31
39
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAA6C,MAAM,UAAU,CAAC;AAS/E,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,QAAQ,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC7C;AA4CD,wBAAgB,4BAA4B,CAC1C,UAAU,GAAE,MAAc,GACzB,eAAe,CA+BjB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,SAAS,CAAkB;gBAEvB,SAAS,CAAC,EAAE,eAAe,EAAE,gBAAgB,CAAC,EAAE,MAAM;IAiBlE,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQtC,YAAY,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI;IAK9C,mBAAmB,IAAI,MAAM;IAI7B,gBAAgB,IAAI,MAAM;IAI1B,OAAO,CAAC,aAAa;IAoBf,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IA6CvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB3B,SAAS,IAAI,MAAM;IAqBnB,WAAW,IAAI,QAAQ;IAIjB,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB7D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B,iBAAiB,IAAI,MAAM;CAG5B;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,aAA6B,GACrC,OAAO,CAAC,MAAM,CAAC,CAGjB"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAA6C,MAAM,UAAU,CAAC;AAS/E,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,QAAQ,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC7C;AAwBD,wBAAgB,4BAA4B,CAC1C,UAAU,GAAE,MAAc,GACzB,eAAe,CA+BjB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,SAAS,CAAkB;gBAEvB,SAAS,CAAC,EAAE,eAAe,EAAE,gBAAgB,CAAC,EAAE,MAAM;IAiBlE,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQtC,YAAY,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI;IAK9C,mBAAmB,IAAI,MAAM;IAI7B,gBAAgB,IAAI,MAAM;IAI1B,OAAO,CAAC,aAAa;IAoBf,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IA6CvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB3B,SAAS,IAAI,MAAM;IAqBnB,WAAW,IAAI,QAAQ;IAIjB,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB7D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B,iBAAiB,IAAI,MAAM;IAI3B;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG;QAC5C,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB;CAiEF;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,aAA6B,GACrC,OAAO,CAAC,MAAM,CAAC,CAGjB"}
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.configManager = exports.ConfigManager = void 0;
4
7
  exports.createDefaultConfigCallbacks = createDefaultConfigCallbacks;
@@ -10,28 +13,8 @@ const dotenv_1 = require("dotenv");
10
13
  const config_validation_1 = require("./config-validation");
11
14
  const task_o_matic_error_1 = require("../utils/task-o-matic-error");
12
15
  // Provider-specific sensible defaults for 2025
13
- const PROVIDER_DEFAULTS = {
14
- openrouter: {
15
- model: "z-ai/glm-4.6",
16
- maxTokens: 32768,
17
- temperature: 0.5,
18
- },
19
- anthropic: {
20
- model: "claude-sonnet-4.5",
21
- maxTokens: 32768,
22
- temperature: 0.5,
23
- },
24
- openai: {
25
- model: "gpt-5",
26
- maxTokens: 32768,
27
- temperature: 0.5,
28
- },
29
- custom: {
30
- model: "llama-3.3-70b",
31
- maxTokens: 32768,
32
- temperature: 0.5,
33
- },
34
- };
16
+ // Externalized to JSON for easy updates
17
+ const provider_defaults_json_1 = __importDefault(require("./provider-defaults.json"));
35
18
  function getApiKeyFromEnv(provider, getEnv) {
36
19
  switch (provider) {
37
20
  case "openrouter":
@@ -114,7 +97,7 @@ class ConfigManager {
114
97
  loadEnvConfig() {
115
98
  const provider = this.callbacks.getEnv("AI_PROVIDER")?.toLowerCase() ||
116
99
  "openrouter";
117
- const defaults = PROVIDER_DEFAULTS[provider] || PROVIDER_DEFAULTS.openrouter;
100
+ const defaults = provider_defaults_json_1.default[provider] || provider_defaults_json_1.default.openrouter;
118
101
  const maxTokensStr = this.callbacks.getEnv("AI_MAX_TOKENS");
119
102
  const tempStr = this.callbacks.getEnv("AI_TEMPERATURE");
120
103
  const modelStr = this.callbacks.getEnv("AI_MODEL");
@@ -221,6 +204,59 @@ class ConfigManager {
221
204
  getConfigFilePath() {
222
205
  return (0, path_1.join)(this.getTaskOMaticDir(), "config.json");
223
206
  }
207
+ /**
208
+ * Validate configuration independently of load().
209
+ * Can be used to validate config before applying changes.
210
+ */
211
+ validate(configToValidate) {
212
+ const errors = [];
213
+ const config = configToValidate || this.config;
214
+ if (!config) {
215
+ return {
216
+ valid: false,
217
+ errors: [
218
+ "No configuration to validate. Either provide a config or call load() first.",
219
+ ],
220
+ };
221
+ }
222
+ // Validate AI config
223
+ if (config.ai) {
224
+ const { provider, model, apiKey, maxTokens, temperature } = config.ai;
225
+ // Validate provider
226
+ if (provider &&
227
+ !["openrouter", "anthropic", "openai", "custom"].includes(provider)) {
228
+ errors.push(`Invalid provider: ${provider}. Must be one of: openrouter, anthropic, openai, custom`);
229
+ }
230
+ // Validate model
231
+ if (model !== undefined && typeof model !== "string") {
232
+ errors.push("Model must be a string");
233
+ }
234
+ // Validate maxTokens
235
+ if (maxTokens !== undefined) {
236
+ if (typeof maxTokens !== "number" ||
237
+ maxTokens < 1 ||
238
+ maxTokens > 200000) {
239
+ errors.push("maxTokens must be a number between 1 and 200000");
240
+ }
241
+ }
242
+ // Validate temperature
243
+ if (temperature !== undefined) {
244
+ if (typeof temperature !== "number" ||
245
+ temperature < 0 ||
246
+ temperature > 2) {
247
+ errors.push("temperature must be a number between 0 and 2");
248
+ }
249
+ }
250
+ // Warn about missing API key (not an error, just a warning)
251
+ if (!apiKey && provider !== "custom") {
252
+ // This is a soft validation - API key can be set via env vars
253
+ }
254
+ }
255
+ return {
256
+ valid: errors.length === 0,
257
+ errors,
258
+ };
259
+ }
224
260
  }
225
261
  exports.ConfigManager = ConfigManager;
226
262
  exports.configManager = new ConfigManager();
@@ -1 +1 @@
1
- {"version":3,"file":"git-utils.d.ts","sourceRoot":"","sources":["../../src/lib/git-utils.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAc5B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,QAAQ,EAClB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,EAC5D,KAAK,GAAE,GAAuB,GAC7B,OAAO,CAAC,UAAU,CAAC,CA6GrB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,UAAU,EACtB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,IAAI,CAAC,CAef"}
1
+ {"version":3,"file":"git-utils.d.ts","sourceRoot":"","sources":["../../src/lib/git-utils.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAc5B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,QAAQ,EAClB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,EAC5D,KAAK,GAAE,GAAuB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAuGrB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,UAAU,EACtB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.captureGitState = captureGitState;
7
4
  exports.extractCommitInfo = extractCommitInfo;
@@ -9,7 +6,7 @@ exports.autoCommit = autoCommit;
9
6
  exports.commitFile = commitFile;
10
7
  const child_process_1 = require("child_process");
11
8
  const util_1 = require("util");
12
- const chalk_1 = __importDefault(require("chalk"));
9
+ const logger_1 = require("./logger");
13
10
  const ai_service_factory_1 = require("../utils/ai-service-factory");
14
11
  const execAsync = (0, util_1.promisify)(child_process_1.exec);
15
12
  /**
@@ -38,7 +35,7 @@ async function extractCommitInfo(taskId, taskTitle, executionMessage, gitState,
38
35
  try {
39
36
  // Case 1: Executor created a commit
40
37
  if (gitState.beforeHead !== gitState.afterHead) {
41
- console.log(chalk_1.default.blue("📝 Executor created a commit, extracting info..."));
38
+ logger_1.logger.info("📝 Executor created a commit, extracting info...");
42
39
  const { stdout } = await execFn(`git show --stat --format="%s%n%b" ${gitState.afterHead}`);
43
40
  const lines = stdout.trim().split("\n");
44
41
  const message = lines[0].trim();
@@ -54,7 +51,7 @@ async function extractCommitInfo(taskId, taskTitle, executionMessage, gitState,
54
51
  }
55
52
  // Case 2: Executor left uncommitted changes
56
53
  if (gitState.hasUncommittedChanges) {
57
- console.log(chalk_1.default.blue("📝 Uncommitted changes detected, generating commit message..."));
54
+ logger_1.logger.info("📝 Uncommitted changes detected, generating commit message...");
58
55
  // Get the diff to send to AI
59
56
  const { stdout: diff } = await execFn("git diff HEAD");
60
57
  // Get list of changed files
@@ -109,7 +106,7 @@ The commit message should:
109
106
  };
110
107
  }
111
108
  catch (error) {
112
- console.warn(chalk_1.default.yellow(`⚠️ Failed to extract commit info: ${error instanceof Error ? error.message : "Unknown error"}`));
109
+ logger_1.logger.warn(`⚠️ Failed to extract commit info: ${error instanceof Error ? error.message : "Unknown error"}`);
113
110
  // Fallback commit info
114
111
  return {
115
112
  message: `feat: complete task ${taskTitle}`,
@@ -126,22 +123,22 @@ async function autoCommit(commitInfo, execFn = execAsync) {
126
123
  if (files.length > 0) {
127
124
  // Stage specific files
128
125
  const gitAdd = `git add ${files.join(" ")}`;
129
- console.log(chalk_1.default.blue(`📦 Staging files: ${gitAdd}`));
126
+ logger_1.logger.info(`📦 Staging files: ${gitAdd}`);
130
127
  await execFn(gitAdd);
131
128
  }
132
129
  else {
133
130
  // Stage all changes
134
- console.log(chalk_1.default.blue("📦 Staging all changes"));
131
+ logger_1.logger.info("📦 Staging all changes");
135
132
  await execFn("git add .");
136
133
  }
137
134
  // Commit
138
135
  const gitCommit = `git commit -m "${message}"`;
139
- console.log(chalk_1.default.blue(`💾 Committing: ${message}`));
136
+ logger_1.logger.info(`💾 Committing: ${message}`);
140
137
  await execFn(gitCommit);
141
- console.log(chalk_1.default.green("✅ Changes committed successfully\n"));
138
+ logger_1.logger.success("✅ Changes committed successfully\n");
142
139
  }
143
140
  catch (error) {
144
- console.warn(chalk_1.default.yellow(`⚠️ Auto-commit failed: ${error instanceof Error ? error.message : "Unknown error"}\n`));
141
+ logger_1.logger.warn(`⚠️ Auto-commit failed: ${error instanceof Error ? error.message : "Unknown error"}\n`);
145
142
  }
146
143
  }
147
144
  /**
@@ -149,12 +146,12 @@ async function autoCommit(commitInfo, execFn = execAsync) {
149
146
  */
150
147
  async function commitFile(filePath, message, execFn = execAsync) {
151
148
  try {
152
- console.log(chalk_1.default.blue(`📦 Staging file: ${filePath}`));
149
+ logger_1.logger.info(`📦 Staging file: ${filePath}`);
153
150
  await execFn(`git add ${filePath}`);
154
151
  await execFn(`git commit -m "${message}"`);
155
- console.log(chalk_1.default.green("✅ File committed successfully"));
152
+ logger_1.logger.success("✅ File committed successfully");
156
153
  }
157
154
  catch (e) {
158
- console.warn(chalk_1.default.yellow(`⚠️ Failed to commit file: ${e instanceof Error ? e.message : "Unknown error"}`));
155
+ logger_1.logger.warn(`⚠️ Failed to commit file: ${e instanceof Error ? e.message : "Unknown error"}`);
159
156
  }
160
157
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/lib/hooks/logger.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,SA8BlC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/lib/hooks/logger.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,SAmDlC"}
@@ -24,4 +24,20 @@ function registerLoggerHooks() {
24
24
  const status = success ? chalk_1.default.green("Success") : chalk_1.default.red("Failed");
25
25
  console.log(chalk_1.default.blue(`[Hook] Execution ended for ${taskId}: ${status}`));
26
26
  });
27
+ // Log event handlers - chalk-styled console output
28
+ hooks_1.hooks.on("log:info", ({ message }) => {
29
+ console.log(chalk_1.default.blue(message));
30
+ });
31
+ hooks_1.hooks.on("log:warn", ({ message }) => {
32
+ console.log(chalk_1.default.yellow(message));
33
+ });
34
+ hooks_1.hooks.on("log:error", ({ message }) => {
35
+ console.log(chalk_1.default.red(message));
36
+ });
37
+ hooks_1.hooks.on("log:success", ({ message }) => {
38
+ console.log(chalk_1.default.green(message));
39
+ });
40
+ hooks_1.hooks.on("log:progress", ({ message }) => {
41
+ console.log(chalk_1.default.cyan(message));
42
+ });
27
43
  }
@@ -1,5 +1,9 @@
1
1
  import { Task } from "../types";
2
- export type TaskEventType = "task:created" | "task:updated" | "task:deleted" | "task:status-changed" | "task:progress" | "execution:start" | "execution:end" | "execution:error";
2
+ export type TaskEventType = "task:created" | "task:updated" | "task:deleted" | "task:status-changed" | "task:progress" | "execution:start" | "execution:end" | "execution:error" | "log:info" | "log:warn" | "log:error" | "log:success" | "log:progress";
3
+ export interface LogEventPayload {
4
+ message: string;
5
+ context?: Record<string, unknown>;
6
+ }
3
7
  export interface TaskEventPayloads {
4
8
  "task:created": {
5
9
  task: Task;
@@ -33,6 +37,11 @@ export interface TaskEventPayloads {
33
37
  taskId: string;
34
38
  error: Error;
35
39
  };
40
+ "log:info": LogEventPayload;
41
+ "log:warn": LogEventPayload;
42
+ "log:error": LogEventPayload;
43
+ "log:success": LogEventPayload;
44
+ "log:progress": LogEventPayload;
36
45
  }
37
46
  export type TaskEventHandler<T extends TaskEventType> = (payload: TaskEventPayloads[T]) => Promise<void> | void;
38
47
  declare class HookRegistry {
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/lib/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGhC,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,cAAc,GACd,cAAc,GACd,qBAAqB,GACrB,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,iBAAiB,CAAC;AAGtB,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAC/B,cAAc,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IACvD,cAAc,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,qBAAqB,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,eAAe,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,iBAAiB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,eAAe,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACtD,iBAAiB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CACrD;AAGD,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,aAAa,IAAI,CACtD,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAe;IACtC,OAAO,CAAC,SAAS,CAAiD;IAElE,OAAO;WAIO,WAAW,IAAI,YAAY;IAOzC;;OAEG;IACI,EAAE,CAAC,CAAC,SAAS,aAAa,EAC/B,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,IAAI;IAOP;;OAEG;IACI,GAAG,CAAC,CAAC,SAAS,aAAa,EAChC,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,IAAI;IAOP;;;;OAIG;IACU,IAAI,CAAC,CAAC,SAAS,aAAa,EACvC,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;IAehB;;OAEG;IACI,KAAK,IAAI,IAAI;CAGrB;AAED,eAAO,MAAM,KAAK,cAA6B,CAAC"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/lib/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGhC,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,cAAc,GACd,cAAc,GACd,qBAAqB,GACrB,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,iBAAiB,GACjB,UAAU,GACV,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,CAAC;AAGnB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAGD,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAC/B,cAAc,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IACvD,cAAc,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,qBAAqB,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,eAAe,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,iBAAiB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,eAAe,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACtD,iBAAiB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IACpD,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,eAAe,CAAC;IAC5B,WAAW,EAAE,eAAe,CAAC;IAC7B,aAAa,EAAE,eAAe,CAAC;IAC/B,cAAc,EAAE,eAAe,CAAC;CACjC;AAGD,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,aAAa,IAAI,CACtD,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAe;IACtC,OAAO,CAAC,SAAS,CAAiD;IAElE,OAAO;WAIO,WAAW,IAAI,YAAY;IAOzC;;OAEG;IACI,EAAE,CAAC,CAAC,SAAS,aAAa,EAC/B,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,IAAI;IAOP;;OAEG;IACI,GAAG,CAAC,CAAC,SAAS,aAAa,EAChC,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,IAAI;IAOP;;;;OAIG;IACU,IAAI,CAAC,CAAC,SAAS,aAAa,EACvC,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;IAehB;;OAEG;IACI,KAAK,IAAI,IAAI;CAGrB;AAED,eAAO,MAAM,KAAK,cAA6B,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Logger - Thin wrapper that emits log events to the hooks system
3
+ *
4
+ * This decouples logging from direct console output, allowing:
5
+ * - CLI to render styled chalk output by subscribing to events
6
+ * - Web/TUI to handle logs differently
7
+ * - Testing without console pollution
8
+ */
9
+ export interface Logger {
10
+ info(message: string, context?: Record<string, unknown>): void;
11
+ warn(message: string, context?: Record<string, unknown>): void;
12
+ error(message: string, context?: Record<string, unknown>): void;
13
+ success(message: string, context?: Record<string, unknown>): void;
14
+ progress(message: string, context?: Record<string, unknown>): void;
15
+ }
16
+ /**
17
+ * Event-based logger that emits to the hooks system
18
+ */
19
+ export declare const logger: Logger;
20
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACpE;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,MAoBpB,CAAC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ /**
3
+ * Logger - Thin wrapper that emits log events to the hooks system
4
+ *
5
+ * This decouples logging from direct console output, allowing:
6
+ * - CLI to render styled chalk output by subscribing to events
7
+ * - Web/TUI to handle logs differently
8
+ * - Testing without console pollution
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.logger = void 0;
12
+ const hooks_1 = require("./hooks");
13
+ /**
14
+ * Event-based logger that emits to the hooks system
15
+ */
16
+ exports.logger = {
17
+ info(message, context) {
18
+ hooks_1.hooks.emit("log:info", { message, context });
19
+ },
20
+ warn(message, context) {
21
+ hooks_1.hooks.emit("log:warn", { message, context });
22
+ },
23
+ error(message, context) {
24
+ hooks_1.hooks.emit("log:error", { message, context });
25
+ },
26
+ success(message, context) {
27
+ hooks_1.hooks.emit("log:success", { message, context });
28
+ },
29
+ progress(message, context) {
30
+ hooks_1.hooks.emit("log:progress", { message, context });
31
+ },
32
+ };
@@ -0,0 +1,22 @@
1
+ {
2
+ "openrouter": {
3
+ "model": "z-ai/glm-4.6",
4
+ "maxTokens": 32768,
5
+ "temperature": 0.5
6
+ },
7
+ "anthropic": {
8
+ "model": "claude-sonnet-4.5",
9
+ "maxTokens": 32768,
10
+ "temperature": 0.5
11
+ },
12
+ "openai": {
13
+ "model": "gpt-5",
14
+ "maxTokens": 32768,
15
+ "temperature": 0.5
16
+ },
17
+ "custom": {
18
+ "model": "llama-3.3-70b",
19
+ "maxTokens": 32768,
20
+ "temperature": 0.5
21
+ }
22
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"task-execution-core.d.ts","sourceRoot":"","sources":["../../src/lib/task-execution-core.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EAKpB,MAAM,UAAU,CAAC;AAWlB;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CA+D9B"}
1
+ {"version":3,"file":"task-execution-core.d.ts","sourceRoot":"","sources":["../../src/lib/task-execution-core.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EAKpB,MAAM,UAAU,CAAC;AAgBlB;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAsE9B"}
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.executeTaskCore = executeTaskCore;
7
4
  const task_o_matic_error_1 = require("../utils/task-o-matic-error");
@@ -14,7 +11,7 @@ const prompt_builder_1 = require("./prompt-builder");
14
11
  const task_planning_1 = require("./task-planning");
15
12
  const task_review_1 = require("./task-review");
16
13
  const git_utils_1 = require("./git-utils");
17
- const chalk_1 = __importDefault(require("chalk"));
14
+ const logger_1 = require("./logger");
18
15
  /**
19
16
  * Execute a single task with all features (retry, planning, review, etc.)
20
17
  * This is the core unified execution logic used by both execute and execute-loop commands
@@ -66,25 +63,25 @@ async function executeTaskCore(taskId, config) {
66
63
  */
67
64
  async function executeTaskWithSubtasks(task, subtasks, config) {
68
65
  const { dry } = config;
69
- console.log(chalk_1.default.blue(`📋 Task has ${subtasks.length} subtasks, executing recursively...`));
66
+ logger_1.logger.info(`📋 Task has ${subtasks.length} subtasks, executing recursively...`);
70
67
  const subtaskResults = [];
71
68
  let allSuccess = true;
72
69
  // Execute subtasks one by one
73
70
  for (let i = 0; i < subtasks.length; i++) {
74
71
  const subtask = subtasks[i];
75
- console.log(chalk_1.default.cyan(`\n[${i + 1}/${subtasks.length}] Executing subtask: ${subtask.title} (${subtask.id})`));
72
+ logger_1.logger.progress(`\n[${i + 1}/${subtasks.length}] Executing subtask: ${subtask.title} (${subtask.id})`);
76
73
  try {
77
74
  const result = await executeTaskCore(subtask.id, config);
78
75
  subtaskResults.push(result);
79
76
  if (!result.success) {
80
77
  allSuccess = false;
81
- console.error(chalk_1.default.red(`❌ Failed to execute subtask ${subtask.id}: ${subtask.title}`));
78
+ logger_1.logger.error(`❌ Failed to execute subtask ${subtask.id}: ${subtask.title}`);
82
79
  break; // Stop on first failure
83
80
  }
84
81
  }
85
82
  catch (error) {
86
83
  allSuccess = false;
87
- console.error(chalk_1.default.red(`❌ Failed to execute subtask ${subtask.id}: ${error instanceof Error ? error.message : "Unknown error"}`));
84
+ logger_1.logger.error(`❌ Failed to execute subtask ${subtask.id}: ${error instanceof Error ? error.message : "Unknown error"}`);
88
85
  break;
89
86
  }
90
87
  }
@@ -92,11 +89,11 @@ async function executeTaskWithSubtasks(task, subtasks, config) {
92
89
  if (!dry) {
93
90
  if (allSuccess) {
94
91
  await tasks_1.taskService.setTaskStatus(task.id, "completed");
95
- console.log(chalk_1.default.green(`✅ Main task ${task.title} completed after all subtasks`));
92
+ logger_1.logger.success(`✅ Main task ${task.title} completed after all subtasks`);
96
93
  }
97
94
  else {
98
95
  await tasks_1.taskService.setTaskStatus(task.id, "todo");
99
- console.log(chalk_1.default.red(`❌ Main task ${task.title} failed due to subtask failure, status reset to todo`));
96
+ logger_1.logger.error(`❌ Main task ${task.title} failed due to subtask failure, status reset to todo`);
100
97
  }
101
98
  }
102
99
  return {
@@ -126,12 +123,12 @@ async function executeTaskWithRetry(task, config, attempts, planContent) {
126
123
  currentModel = modelConfig.model;
127
124
  }
128
125
  }
129
- console.log(chalk_1.default.blue(`\n🎯 Attempt ${currentAttempt}/${maxRetries} for task: ${task.title} (${task.id})`));
126
+ logger_1.logger.info(`\n🎯 Attempt ${currentAttempt}/${maxRetries} for task: ${task.title} (${task.id})`);
130
127
  if (currentModel) {
131
- console.log(chalk_1.default.cyan(` Using executor: ${currentExecutor} with model: ${currentModel}`));
128
+ logger_1.logger.progress(` Using executor: ${currentExecutor} with model: ${currentModel}`);
132
129
  }
133
130
  else {
134
- console.log(chalk_1.default.cyan(` Using executor: ${currentExecutor}`));
131
+ logger_1.logger.progress(` Using executor: ${currentExecutor}`);
135
132
  }
136
133
  // Build retry context if this is a retry attempt
137
134
  let retryContext = "";
@@ -164,11 +161,9 @@ async function executeTaskWithRetry(task, config, attempts, planContent) {
164
161
  try {
165
162
  const result = await executeSingleAttempt(task, attemptConfig, attempts, planContent, currentAttempt, maxRetries, retryContext);
166
163
  // Check if all verifications passed
167
- const allVerificationsPassed = result.attempts[result.attempts.length - 1]
168
- ?.verificationResults?.every((r) => r.success) ?? true;
164
+ const allVerificationsPassed = result.attempts[result.attempts.length - 1]?.verificationResults?.every((r) => r.success) ?? true;
169
165
  if (!allVerificationsPassed) {
170
- const failedVerification = result.attempts[result.attempts.length - 1]
171
- ?.verificationResults?.find((r) => !r.success);
166
+ const failedVerification = result.attempts[result.attempts.length - 1]?.verificationResults?.find((r) => !r.success);
172
167
  lastError = `Verification command "${failedVerification?.command}" failed:\n${failedVerification?.error}`;
173
168
  currentAttempt++;
174
169
  continue;
@@ -184,12 +179,12 @@ async function executeTaskWithRetry(task, config, attempts, planContent) {
184
179
  });
185
180
  if (!reviewResult.approved) {
186
181
  lastError = `AI Review Failed:\n${reviewResult.feedback}`;
187
- console.log(chalk_1.default.red(`❌ AI Review Rejected Changes: ${reviewResult.feedback}`));
182
+ logger_1.logger.error(`❌ AI Review Rejected Changes: ${reviewResult.feedback}`);
188
183
  currentAttempt++;
189
184
  continue;
190
185
  }
191
186
  else {
192
- console.log(chalk_1.default.green(`✅ AI Review Approved: ${reviewResult.feedback}`));
187
+ logger_1.logger.success(`✅ AI Review Approved: ${reviewResult.feedback}`);
193
188
  result.reviewFeedback = reviewResult.feedback;
194
189
  }
195
190
  }
@@ -198,10 +193,10 @@ async function executeTaskWithRetry(task, config, attempts, planContent) {
198
193
  }
199
194
  catch (error) {
200
195
  lastError = error instanceof Error ? error.message : String(error);
201
- console.log(chalk_1.default.red(`❌ Task execution failed on attempt ${currentAttempt}: ${lastError}`));
196
+ logger_1.logger.error(`❌ Task execution failed on attempt ${currentAttempt}: ${lastError}`);
202
197
  if (!dry && currentAttempt < maxRetries) {
203
198
  await tasks_1.taskService.setTaskStatus(task.id, "todo");
204
- console.log(chalk_1.default.yellow("⏸ Task status reset to todo for retry"));
199
+ logger_1.logger.warn("⏸ Task status reset to todo for retry");
205
200
  }
206
201
  currentAttempt++;
207
202
  }
@@ -209,7 +204,7 @@ async function executeTaskWithRetry(task, config, attempts, planContent) {
209
204
  // All retries exhausted
210
205
  if (!dry) {
211
206
  await tasks_1.taskService.setTaskStatus(task.id, "todo");
212
- console.log(chalk_1.default.red("❌ All retry attempts exhausted, task status reset to todo"));
207
+ logger_1.logger.error("❌ All retry attempts exhausted, task status reset to todo");
213
208
  }
214
209
  return {
215
210
  success: false,
@@ -222,7 +217,7 @@ async function executeTaskWithRetry(task, config, attempts, planContent) {
222
217
  async function executeSingleAttempt(task, config, attempts, planContent, attemptNumber, maxRetries, retryContext) {
223
218
  const { tool, executorConfig, customMessage, verificationCommands = [], autoCommit: enableAutoCommit = false, dry = false, } = config;
224
219
  const attemptStartTime = Date.now();
225
- console.log(chalk_1.default.blue(`🎯 ${dry ? "DRY RUN" : "Executing"} task: ${task.title} (${task.id})`));
220
+ logger_1.logger.info(`🎯 ${dry ? "DRY RUN" : "Executing"} task: ${task.title} (${task.id})`);
226
221
  // Capture git state before execution
227
222
  const gitStateBefore = await (0, git_utils_1.captureGitState)();
228
223
  // Build execution message
@@ -230,7 +225,7 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
230
225
  if (customMessage) {
231
226
  // Use custom message override
232
227
  executionMessage = customMessage;
233
- console.log(chalk_1.default.cyan("📝 Using custom execution message"));
228
+ logger_1.logger.progress("📝 Using custom execution message");
234
229
  }
235
230
  else {
236
231
  // Build comprehensive execution message with full context
@@ -262,7 +257,7 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
262
257
  // Update task status to in-progress
263
258
  if (!dry) {
264
259
  await tasks_1.taskService.setTaskStatus(task.id, "in-progress");
265
- console.log(chalk_1.default.yellow("⏳ Task status updated to in-progress"));
260
+ logger_1.logger.warn("⏳ Task status updated to in-progress");
266
261
  }
267
262
  // Emit execution:start event
268
263
  await hooks_1.hooks.emit("execution:start", { taskId: task.id, tool });
@@ -271,7 +266,7 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
271
266
  const executor = executor_factory_1.ExecutorFactory.create(tool, executorConfig);
272
267
  // Log session resumption if applicable
273
268
  if (executorConfig?.continueLastSession && attemptNumber > 1) {
274
- console.log(chalk_1.default.cyan("🔄 Resuming previous session to provide error feedback to AI"));
269
+ logger_1.logger.progress("🔄 Resuming previous session to provide error feedback to AI");
275
270
  }
276
271
  await executor.execute(executionMessage, dry, executorConfig);
277
272
  // Run verification commands
@@ -289,13 +284,13 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
289
284
  verificationResults,
290
285
  timestamp: Date.now() - attemptStartTime,
291
286
  });
292
- console.log(chalk_1.default.red(`❌ Task execution failed verification on attempt ${attemptNumber}`));
287
+ logger_1.logger.error(`❌ Task execution failed verification on attempt ${attemptNumber}`);
293
288
  throw new Error(error);
294
289
  }
295
290
  // Extract commit info if enabled
296
291
  let commitInfo;
297
292
  if (enableAutoCommit && !dry) {
298
- console.log(chalk_1.default.blue("📝 Extracting commit information..."));
293
+ logger_1.logger.info("📝 Extracting commit information...");
299
294
  const gitStateAfter = await (0, git_utils_1.captureGitState)();
300
295
  const gitState = {
301
296
  beforeHead: gitStateBefore.beforeHead || "",
@@ -303,9 +298,9 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
303
298
  hasUncommittedChanges: gitStateAfter.hasUncommittedChanges || false,
304
299
  };
305
300
  commitInfo = await (0, git_utils_1.extractCommitInfo)(task.id, task.title, executionMessage, gitState);
306
- console.log(chalk_1.default.green(`✅ Commit message: ${commitInfo.message}`));
301
+ logger_1.logger.success(`✅ Commit message: ${commitInfo.message}`);
307
302
  if (commitInfo.files.length > 0) {
308
- console.log(chalk_1.default.green(`📁 Changed files: ${commitInfo.files.join(", ")}`));
303
+ logger_1.logger.success(`📁 Changed files: ${commitInfo.files.join(", ")}`);
309
304
  }
310
305
  // Auto-commit the changes
311
306
  await (0, git_utils_1.autoCommit)(commitInfo);
@@ -313,7 +308,7 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
313
308
  // Update task status to completed
314
309
  if (!dry) {
315
310
  await tasks_1.taskService.setTaskStatus(task.id, "completed");
316
- console.log(chalk_1.default.green("✅ Task execution completed successfully"));
311
+ logger_1.logger.success("✅ Task execution completed successfully");
317
312
  }
318
313
  // Record successful attempt
319
314
  attempts.push({
@@ -337,7 +332,8 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
337
332
  catch (error) {
338
333
  const errorMessage = error instanceof Error ? error.message : String(error);
339
334
  // Record failed attempt if not already recorded
340
- if (attempts.length === 0 || attempts[attempts.length - 1].attemptNumber !== attemptNumber) {
335
+ if (attempts.length === 0 ||
336
+ attempts[attempts.length - 1].attemptNumber !== attemptNumber) {
341
337
  attempts.push({
342
338
  attemptNumber,
343
339
  success: false,
@@ -354,7 +350,7 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
354
350
  });
355
351
  if (!dry) {
356
352
  await tasks_1.taskService.setTaskStatus(task.id, "todo");
357
- console.log(chalk_1.default.red("❌ Task execution failed, status reset to todo"));
353
+ logger_1.logger.error("❌ Task execution failed, status reset to todo");
358
354
  }
359
355
  throw error;
360
356
  }
@@ -1 +1 @@
1
- {"version":3,"file":"task-planning.d.ts","sourceRoot":"","sources":["../../src/lib/task-planning.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,YAAY,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAS9D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,YAAY,EACzB,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,cAAc,CAAC,CAgIzB"}
1
+ {"version":3,"file":"task-planning.d.ts","sourceRoot":"","sources":["../../src/lib/task-planning.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,YAAY,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAS9D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,YAAY,EACzB,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,cAAc,CAAC,CAqHzB"}
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.executePlanningPhase = executePlanningPhase;
7
- const chalk_1 = __importDefault(require("chalk"));
7
+ const logger_1 = require("./logger");
8
8
  const executor_factory_1 = require("./executors/executor-factory");
9
9
  const fs_1 = require("fs");
10
10
  const inquirer_1 = __importDefault(require("inquirer"));
@@ -18,7 +18,7 @@ const execAsync = (0, util_1.promisify)(child_process_1.exec);
18
18
  */
19
19
  async function executePlanningPhase(task, defaultTool, config, execFn = execAsync) {
20
20
  const { planModel, reviewPlan, autoCommit, dry } = config;
21
- console.log(chalk_1.default.blue.bold(`\n🧠 Starting Planning Phase for Task: ${task.title}`));
21
+ logger_1.logger.info(`\n🧠 Starting Planning Phase for Task: ${task.title}`);
22
22
  const planFileName = `task-${task.id}-plan.md`;
23
23
  // Parse executor and model from planModel string
24
24
  const planExecutor = planModel
@@ -38,7 +38,7 @@ Requirements:
38
38
  5. Do NOT implement the code yet, just create the plan file.
39
39
 
40
40
  Please create the "${planFileName}" file now.`;
41
- console.log(chalk_1.default.cyan(` Using executor for planning: ${planExecutor}${planModelName ? ` (${planModelName})` : ""}`));
41
+ logger_1.logger.progress(` Using executor for planning: ${planExecutor}${planModelName ? ` (${planModelName})` : ""}`);
42
42
  // Create executor for planning
43
43
  const planningConfig = {
44
44
  model: planModelName,
@@ -54,11 +54,11 @@ Please create the "${planFileName}" file now.`;
54
54
  // Verify plan file exists and read it
55
55
  if ((0, fs_1.existsSync)(planFileName)) {
56
56
  planContent = (0, fs_1.readFileSync)(planFileName, "utf-8");
57
- console.log(chalk_1.default.green(`✅ Plan created successfully: ${planFileName}`));
57
+ logger_1.logger.success(`✅ Plan created successfully: ${planFileName}`);
58
58
  // Human Review Loop
59
59
  if (reviewPlan) {
60
- console.log(chalk_1.default.yellow(`\n👀 Pausing for Human Review of the Plan: ${planFileName}`));
61
- console.log(chalk_1.default.cyan("You can edit the file now."));
60
+ logger_1.logger.warn(`\n👀 Pausing for Human Review of the Plan: ${planFileName}`);
61
+ logger_1.logger.progress("You can edit the file now.");
62
62
  const { feedback } = await inquirer_1.default.prompt([
63
63
  {
64
64
  type: "input",
@@ -67,7 +67,7 @@ Please create the "${planFileName}" file now.`;
67
67
  },
68
68
  ]);
69
69
  if (feedback && feedback.trim() !== "") {
70
- console.log(chalk_1.default.blue("🔄 Refining plan based on feedback..."));
70
+ logger_1.logger.info("🔄 Refining plan based on feedback...");
71
71
  planningPrompt = `The user provided the following feedback on the plan you just created:
72
72
 
73
73
  "${feedback}"
@@ -84,7 +84,7 @@ Please update the plan file "${planFileName}" to incorporate this feedback.`;
84
84
  planningComplete = true;
85
85
  }
86
86
  else {
87
- console.warn(chalk_1.default.yellow(`⚠️ Plan file ${planFileName} was not created by the executor.`));
87
+ logger_1.logger.warn(`⚠️ Plan file ${planFileName} was not created by the executor.`);
88
88
  planningComplete = true; // Exit loop to avoid infinite retry if file not created
89
89
  }
90
90
  }
@@ -100,7 +100,7 @@ Please update the plan file "${planFileName}" to incorporate this feedback.`;
100
100
  }
101
101
  catch (error) {
102
102
  const errorMessage = error instanceof Error ? error.message : String(error);
103
- console.error(chalk_1.default.red(`❌ Planning phase failed: ${errorMessage}`));
103
+ logger_1.logger.error(`❌ Planning phase failed: ${errorMessage}`);
104
104
  return {
105
105
  success: false,
106
106
  error: errorMessage,
@@ -1 +1 @@
1
- {"version":3,"file":"task-review.d.ts","sourceRoot":"","sources":["../../src/lib/task-review.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,IAAI,EAAE,MAAM,UAAU,CAAC;AAO9C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,YAAY,EACpB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,YAAY,CAAC,CA+GvB"}
1
+ {"version":3,"file":"task-review.d.ts","sourceRoot":"","sources":["../../src/lib/task-review.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,IAAI,EAAE,MAAM,UAAU,CAAC;AAO9C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,YAAY,EACpB,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,YAAY,CAAC,CAoGvB"}
@@ -1,10 +1,7 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.executeReviewPhase = executeReviewPhase;
7
- const chalk_1 = __importDefault(require("chalk"));
4
+ const logger_1 = require("./logger");
8
5
  const ai_service_factory_1 = require("../utils/ai-service-factory");
9
6
  const child_process_1 = require("child_process");
10
7
  const util_1 = require("util");
@@ -15,9 +12,9 @@ const execAsync = (0, util_1.promisify)(child_process_1.exec);
15
12
  */
16
13
  async function executeReviewPhase(task, config, execFn = execAsync) {
17
14
  const { reviewModel, planContent, dry } = config;
18
- console.log(chalk_1.default.blue.bold("\n🕵️ Starting AI Review Phase..."));
15
+ logger_1.logger.info("\n🕵️ Starting AI Review Phase...");
19
16
  if (dry) {
20
- console.log(chalk_1.default.yellow("🔍 DRY RUN - Review phase skipped"));
17
+ logger_1.logger.warn("🔍 DRY RUN - Review phase skipped");
21
18
  return {
22
19
  approved: true,
23
20
  feedback: "Dry run - review skipped",
@@ -28,7 +25,7 @@ async function executeReviewPhase(task, config, execFn = execAsync) {
28
25
  // Get git diff
29
26
  const { stdout: diff } = await execFn("git diff HEAD");
30
27
  if (!diff.trim()) {
31
- console.log(chalk_1.default.yellow("⚠️ No changes detected to review."));
28
+ logger_1.logger.warn("⚠️ No changes detected to review.");
32
29
  return {
33
30
  approved: true,
34
31
  feedback: "No changes to review",
@@ -41,10 +38,10 @@ async function executeReviewPhase(task, config, execFn = execAsync) {
41
38
  : undefined;
42
39
  const reviewModelName = reviewModel ? reviewModel.split(":")[1] : undefined;
43
40
  if (reviewExecutor && reviewModelName) {
44
- console.log(chalk_1.default.cyan(` Using executor for review: ${reviewExecutor} (${reviewModelName})`));
41
+ logger_1.logger.progress(` Using executor for review: ${reviewExecutor} (${reviewModelName})`);
45
42
  }
46
43
  else {
47
- console.log(chalk_1.default.cyan(" Using default AI provider for review"));
44
+ logger_1.logger.progress(" Using default AI provider for review");
48
45
  }
49
46
  const reviewPrompt = `You are a strict code reviewer. Review the following changes for the task.
50
47
 
@@ -72,10 +69,10 @@ Return a JSON object:
72
69
  if (jsonMatch) {
73
70
  const reviewResult = JSON.parse(jsonMatch[0]);
74
71
  if (!reviewResult.approved) {
75
- console.log(chalk_1.default.red(`❌ AI Review Rejected Changes: ${reviewResult.feedback}`));
72
+ logger_1.logger.error(`❌ AI Review Rejected Changes: ${reviewResult.feedback}`);
76
73
  }
77
74
  else {
78
- console.log(chalk_1.default.green(`✅ AI Review Approved: ${reviewResult.feedback}`));
75
+ logger_1.logger.success(`✅ AI Review Approved: ${reviewResult.feedback}`);
79
76
  }
80
77
  return {
81
78
  approved: reviewResult.approved,
@@ -84,7 +81,7 @@ Return a JSON object:
84
81
  };
85
82
  }
86
83
  else {
87
- console.warn(chalk_1.default.yellow("⚠️ Could not parse AI review response. Assuming approval."));
84
+ logger_1.logger.warn("⚠️ Could not parse AI review response. Assuming approval.");
88
85
  return {
89
86
  approved: true,
90
87
  feedback: "Could not parse review response, assuming approval",
@@ -94,7 +91,7 @@ Return a JSON object:
94
91
  }
95
92
  catch (error) {
96
93
  const errorMessage = error instanceof Error ? error.message : String(error);
97
- console.error(chalk_1.default.red(`❌ AI Review failed: ${errorMessage}`));
94
+ logger_1.logger.error(`❌ AI Review failed: ${errorMessage}`);
98
95
  // If review crashes, warn but don't fail the task
99
96
  return {
100
97
  approved: true,
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/lib/validation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAIpC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,GACf,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAE/C;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EAAE,EACrB,GAAG,EAAE,OAAO,EACZ,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6F7B"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/lib/validation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAIpC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,GACf,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAE/C;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EAAE,EACrB,GAAG,EAAE,OAAO,EACZ,MAAM,GAAE,CACN,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAa,GAC3D,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAqF7B"}
@@ -1,13 +1,10 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.isValidAIProvider = isValidAIProvider;
7
4
  exports.runValidations = runValidations;
8
5
  const child_process_1 = require("child_process");
9
6
  const util_1 = require("util");
10
- const chalk_1 = __importDefault(require("chalk"));
7
+ const logger_1 = require("./logger");
11
8
  const execAsync = (0, util_1.promisify)(child_process_1.exec);
12
9
  function isValidAIProvider(provider) {
13
10
  return ["openrouter", "openai", "anthropic", "custom"].includes(provider);
@@ -23,9 +20,9 @@ async function runValidations(validations, dry, execFn = execAsync) {
23
20
  return results;
24
21
  }
25
22
  if (dry) {
26
- console.log(chalk_1.default.yellow("🔍 DRY RUN - Validation/verification commands that would run:"));
23
+ logger_1.logger.warn("🔍 DRY RUN - Validation/verification commands that would run:");
27
24
  validations.forEach((cmd) => {
28
- console.log(chalk_1.default.cyan(` ${cmd}`));
25
+ logger_1.logger.progress(` ${cmd}`);
29
26
  results.push({
30
27
  command: cmd,
31
28
  success: true,
@@ -34,16 +31,16 @@ async function runValidations(validations, dry, execFn = execAsync) {
34
31
  });
35
32
  return results;
36
33
  }
37
- console.log(chalk_1.default.blue(`🧪 Running ${validations.length} validation/verification command${validations.length > 1 ? "s" : ""}...`));
34
+ logger_1.logger.info(`🧪 Running ${validations.length} validation/verification command${validations.length > 1 ? "s" : ""}...`);
38
35
  for (let i = 0; i < validations.length; i++) {
39
36
  const validation = validations[i];
40
- console.log(chalk_1.default.blue(`🧪 Running validation [${i + 1}/${validations.length}]: ${validation}`));
37
+ logger_1.logger.info(`🧪 Running validation [${i + 1}/${validations.length}]: ${validation}`);
41
38
  try {
42
39
  const { stdout, stderr } = await execFn(validation);
43
- console.log(chalk_1.default.green(`✅ Validation passed: ${validation}`));
40
+ logger_1.logger.success(`✅ Validation passed: ${validation}`);
44
41
  // Show stdout if there's any output
45
42
  if (stdout && stdout.trim()) {
46
- console.log(chalk_1.default.gray(` Output: ${stdout.trim()}`));
43
+ logger_1.logger.progress(` Output: ${stdout.trim()}`);
47
44
  }
48
45
  results.push({
49
46
  command: validation,
@@ -52,17 +49,17 @@ async function runValidations(validations, dry, execFn = execAsync) {
52
49
  });
53
50
  }
54
51
  catch (error) {
55
- console.error(chalk_1.default.red(`❌ Validation failed: ${validation}`));
52
+ logger_1.logger.error(`❌ Validation failed: ${validation}`);
56
53
  const errorOutput = error.stderr || error.stdout || error.message;
57
54
  // Show error details
58
55
  if (error.stdout && error.stdout.trim()) {
59
- console.error(chalk_1.default.yellow(` stdout: ${error.stdout.trim()}`));
56
+ logger_1.logger.warn(` stdout: ${error.stdout.trim()}`);
60
57
  }
61
58
  if (error.stderr && error.stderr.trim()) {
62
- console.error(chalk_1.default.red(` stderr: ${error.stderr.trim()}`));
59
+ logger_1.logger.error(` stderr: ${error.stderr.trim()}`);
63
60
  }
64
61
  if (error.message) {
65
- console.error(chalk_1.default.red(` Error: ${error.message}`));
62
+ logger_1.logger.error(` Error: ${error.message}`);
66
63
  }
67
64
  results.push({
68
65
  command: validation,
@@ -75,7 +72,7 @@ async function runValidations(validations, dry, execFn = execAsync) {
75
72
  }
76
73
  const allPassed = results.every((r) => r.success);
77
74
  if (allPassed) {
78
- console.log(chalk_1.default.green(`🎉 All ${validations.length} validation${validations.length > 1 ? "s" : ""} passed!`));
75
+ logger_1.logger.success(`🎉 All ${validations.length} validation${validations.length > 1 ? "s" : ""} passed!`);
79
76
  }
80
77
  return results;
81
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-o-matic",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "AI-powered task management CLI",
5
5
  "keywords": [
6
6
  "task-management",