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.
- package/dist/cli/display/task.d.ts +28 -2
- package/dist/cli/display/task.d.ts.map +1 -1
- package/dist/cli/display/task.js +27 -21
- package/dist/commands/tasks/show.d.ts.map +1 -1
- package/dist/commands/tasks/show.js +21 -1
- package/dist/commands/tasks/tree.d.ts.map +1 -1
- package/dist/commands/tasks/tree.js +21 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/lib/ai-service/model-provider.d.ts +4 -0
- package/dist/lib/ai-service/model-provider.d.ts.map +1 -1
- package/dist/lib/ai-service/model-provider.js +21 -5
- package/dist/lib/ai-service/prd-operations.d.ts.map +1 -1
- package/dist/lib/ai-service/prd-operations.js +1 -4
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +59 -23
- package/dist/lib/git-utils.d.ts.map +1 -1
- package/dist/lib/git-utils.js +12 -15
- package/dist/lib/hooks/logger.d.ts.map +1 -1
- package/dist/lib/hooks/logger.js +16 -0
- package/dist/lib/hooks.d.ts +10 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/logger.d.ts +20 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +32 -0
- package/dist/lib/provider-defaults.json +22 -0
- package/dist/lib/task-execution-core.d.ts.map +1 -1
- package/dist/lib/task-execution-core.js +29 -33
- package/dist/lib/task-planning.d.ts.map +1 -1
- package/dist/lib/task-planning.js +9 -9
- package/dist/lib/task-review.d.ts.map +1 -1
- package/dist/lib/task-review.js +10 -13
- package/dist/lib/validation.d.ts.map +1 -1
- package/dist/lib/validation.js +12 -15
- 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
|
-
|
|
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
|
-
|
|
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":"
|
|
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"}
|
package/dist/cli/display/task.js
CHANGED
|
@@ -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
|
-
|
|
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 (
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
97
|
-
if (
|
|
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"
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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;
|
|
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
|
-
|
|
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);
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
|
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:
|
|
40
|
+
apiKey: getEnv("OPENAI_API_KEY"),
|
|
25
41
|
},
|
|
26
42
|
anthropic: {
|
|
27
|
-
apiKey:
|
|
43
|
+
apiKey: getEnv("ANTHROPIC_API_KEY"),
|
|
28
44
|
},
|
|
29
45
|
openrouter: {
|
|
30
|
-
apiKey:
|
|
46
|
+
apiKey: getEnv("OPENROUTER_API_KEY"),
|
|
31
47
|
baseURL: "https://openrouter.ai/api/v1",
|
|
32
48
|
},
|
|
33
49
|
custom: {
|
|
34
|
-
apiKey:
|
|
35
|
-
baseURL:
|
|
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;
|
|
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:
|
|
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(),
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -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
|
/**
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/lib/config.js
CHANGED
|
@@ -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
|
-
|
|
14
|
-
|
|
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 =
|
|
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,
|
|
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"}
|
package/dist/lib/git-utils.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
126
|
+
logger_1.logger.info(`📦 Staging files: ${gitAdd}`);
|
|
130
127
|
await execFn(gitAdd);
|
|
131
128
|
}
|
|
132
129
|
else {
|
|
133
130
|
// Stage all changes
|
|
134
|
-
|
|
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
|
-
|
|
136
|
+
logger_1.logger.info(`💾 Committing: ${message}`);
|
|
140
137
|
await execFn(gitCommit);
|
|
141
|
-
|
|
138
|
+
logger_1.logger.success("✅ Changes committed successfully\n");
|
|
142
139
|
}
|
|
143
140
|
catch (error) {
|
|
144
|
-
|
|
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
|
-
|
|
149
|
+
logger_1.logger.info(`📦 Staging file: ${filePath}`);
|
|
153
150
|
await execFn(`git add ${filePath}`);
|
|
154
151
|
await execFn(`git commit -m "${message}"`);
|
|
155
|
-
|
|
152
|
+
logger_1.logger.success("✅ File committed successfully");
|
|
156
153
|
}
|
|
157
154
|
catch (e) {
|
|
158
|
-
|
|
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,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/lib/hooks/logger.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,SAmDlC"}
|
package/dist/lib/hooks/logger.js
CHANGED
|
@@ -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
|
}
|
package/dist/lib/hooks.d.ts
CHANGED
|
@@ -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 {
|
package/dist/lib/hooks.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
126
|
+
logger_1.logger.info(`\n🎯 Attempt ${currentAttempt}/${maxRetries} for task: ${task.title} (${task.id})`);
|
|
130
127
|
if (currentModel) {
|
|
131
|
-
|
|
128
|
+
logger_1.logger.progress(` Using executor: ${currentExecutor} with model: ${currentModel}`);
|
|
132
129
|
}
|
|
133
130
|
else {
|
|
134
|
-
|
|
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
|
-
|
|
182
|
+
logger_1.logger.error(`❌ AI Review Rejected Changes: ${reviewResult.feedback}`);
|
|
188
183
|
currentAttempt++;
|
|
189
184
|
continue;
|
|
190
185
|
}
|
|
191
186
|
else {
|
|
192
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
301
|
+
logger_1.logger.success(`✅ Commit message: ${commitInfo.message}`);
|
|
307
302
|
if (commitInfo.files.length > 0) {
|
|
308
|
-
|
|
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
|
-
|
|
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 ||
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
57
|
+
logger_1.logger.success(`✅ Plan created successfully: ${planFileName}`);
|
|
58
58
|
// Human Review Loop
|
|
59
59
|
if (reviewPlan) {
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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"}
|
package/dist/lib/task-review.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
15
|
+
logger_1.logger.info("\n🕵️ Starting AI Review Phase...");
|
|
19
16
|
if (dry) {
|
|
20
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
+
logger_1.logger.progress(` Using executor for review: ${reviewExecutor} (${reviewModelName})`);
|
|
45
42
|
}
|
|
46
43
|
else {
|
|
47
|
-
|
|
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
|
-
|
|
72
|
+
logger_1.logger.error(`❌ AI Review Rejected Changes: ${reviewResult.feedback}`);
|
|
76
73
|
}
|
|
77
74
|
else {
|
|
78
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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"}
|
package/dist/lib/validation.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
23
|
+
logger_1.logger.warn("🔍 DRY RUN - Validation/verification commands that would run:");
|
|
27
24
|
validations.forEach((cmd) => {
|
|
28
|
-
|
|
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
|
-
|
|
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
|
-
|
|
37
|
+
logger_1.logger.info(`🧪 Running validation [${i + 1}/${validations.length}]: ${validation}`);
|
|
41
38
|
try {
|
|
42
39
|
const { stdout, stderr } = await execFn(validation);
|
|
43
|
-
|
|
40
|
+
logger_1.logger.success(`✅ Validation passed: ${validation}`);
|
|
44
41
|
// Show stdout if there's any output
|
|
45
42
|
if (stdout && stdout.trim()) {
|
|
46
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56
|
+
logger_1.logger.warn(` stdout: ${error.stdout.trim()}`);
|
|
60
57
|
}
|
|
61
58
|
if (error.stderr && error.stderr.trim()) {
|
|
62
|
-
|
|
59
|
+
logger_1.logger.error(` stderr: ${error.stderr.trim()}`);
|
|
63
60
|
}
|
|
64
61
|
if (error.message) {
|
|
65
|
-
|
|
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
|
-
|
|
75
|
+
logger_1.logger.success(`🎉 All ${validations.length} validation${validations.length > 1 ? "s" : ""} passed!`);
|
|
79
76
|
}
|
|
80
77
|
return results;
|
|
81
78
|
}
|