task-o-matic 0.0.13 → 0.0.15
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/progress.d.ts +15 -2
- package/dist/cli/display/progress.d.ts.map +1 -1
- package/dist/cli/display/progress.js +72 -4
- package/dist/commands/benchmark.d.ts.map +1 -1
- package/dist/commands/benchmark.js +11 -3
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +60 -12
- package/dist/commands/prd.js +7 -1
- package/dist/commands/tasks/delete.d.ts.map +1 -1
- package/dist/commands/tasks/delete.js +2 -1
- package/dist/commands/tasks/document/add.d.ts.map +1 -1
- package/dist/commands/tasks/document/add.js +5 -4
- package/dist/commands/tasks/document/get.d.ts.map +1 -1
- package/dist/commands/tasks/document/get.js +2 -1
- package/dist/commands/tasks/list.js +2 -2
- package/dist/commands/tasks/next.js +4 -4
- package/dist/commands/tasks/plan/set.d.ts.map +1 -1
- package/dist/commands/tasks/plan/set.js +11 -3
- package/dist/commands/tasks/show.d.ts.map +1 -1
- package/dist/commands/tasks/show.js +2 -1
- package/dist/commands/tasks/status.d.ts.map +1 -1
- package/dist/commands/tasks/status.js +4 -3
- package/dist/commands/tasks/update.d.ts.map +1 -1
- package/dist/commands/tasks/update.js +7 -1
- package/dist/lib/ai-service/ai-operations.d.ts +1 -1
- package/dist/lib/ai-service/ai-operations.d.ts.map +1 -1
- package/dist/lib/ai-service/base-operations.d.ts +22 -0
- package/dist/lib/ai-service/base-operations.d.ts.map +1 -1
- package/dist/lib/ai-service/base-operations.js +29 -1
- package/dist/lib/ai-service/model-provider.d.ts.map +1 -1
- package/dist/lib/ai-service/model-provider.js +37 -6
- package/dist/lib/ai-service/task-operations.d.ts +2 -1
- package/dist/lib/ai-service/task-operations.d.ts.map +1 -1
- package/dist/lib/ai-service/task-operations.js +135 -173
- package/dist/lib/benchmark/registry.d.ts.map +1 -1
- package/dist/lib/benchmark/registry.js +6 -10
- package/dist/lib/better-t-stack-cli.d.ts +36 -21
- package/dist/lib/better-t-stack-cli.d.ts.map +1 -1
- package/dist/lib/better-t-stack-cli.js +212 -33
- package/dist/lib/bootstrap/cli-bootstrap.d.ts +14 -0
- package/dist/lib/bootstrap/cli-bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap/cli-bootstrap.js +325 -0
- package/dist/lib/bootstrap/index.d.ts +4 -0
- package/dist/lib/bootstrap/index.d.ts.map +1 -0
- package/dist/lib/bootstrap/index.js +19 -0
- package/dist/lib/bootstrap/medusa-bootstrap.d.ts +14 -0
- package/dist/lib/bootstrap/medusa-bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap/medusa-bootstrap.js +218 -0
- package/dist/lib/bootstrap/opentui-bootstrap.d.ts +11 -0
- package/dist/lib/bootstrap/opentui-bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap/opentui-bootstrap.js +342 -0
- package/dist/lib/config-validation.d.ts +215 -0
- package/dist/lib/config-validation.d.ts.map +1 -0
- package/dist/lib/config-validation.js +246 -0
- package/dist/lib/config.d.ts +14 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +37 -5
- package/dist/lib/storage/file-system.d.ts.map +1 -1
- package/dist/lib/storage/file-system.js +81 -21
- package/dist/lib/task-execution-core.d.ts.map +1 -1
- package/dist/lib/task-execution-core.js +3 -2
- package/dist/services/prd.d.ts +17 -0
- package/dist/services/prd.d.ts.map +1 -1
- package/dist/services/prd.js +67 -60
- package/dist/services/tasks.d.ts +317 -3
- package/dist/services/tasks.d.ts.map +1 -1
- package/dist/services/tasks.js +531 -185
- package/dist/services/workflow-ai-assistant.d.ts.map +1 -1
- package/dist/services/workflow-ai-assistant.js +19 -6
- package/dist/test/lib/ai-service/task-operations.test.d.ts +2 -0
- package/dist/test/lib/ai-service/task-operations.test.d.ts.map +1 -0
- package/dist/test/lib/ai-service/task-operations.test.js +362 -0
- package/dist/test/mocks/mock-ai-operations.d.ts +15 -0
- package/dist/test/mocks/mock-ai-operations.d.ts.map +1 -0
- package/dist/test/mocks/mock-ai-operations.js +107 -0
- package/dist/test/mocks/mock-context-builder.d.ts +10 -0
- package/dist/test/mocks/mock-context-builder.d.ts.map +1 -0
- package/dist/test/mocks/mock-context-builder.js +81 -0
- package/dist/test/mocks/mock-model-provider.d.ts +7 -0
- package/dist/test/mocks/mock-model-provider.d.ts.map +1 -0
- package/dist/test/mocks/mock-model-provider.js +21 -0
- package/dist/test/mocks/mock-service-factory.d.ts +11 -0
- package/dist/test/mocks/mock-service-factory.d.ts.map +1 -0
- package/dist/test/mocks/mock-service-factory.js +61 -0
- package/dist/test/mocks/mock-storage.d.ts +50 -0
- package/dist/test/mocks/mock-storage.d.ts.map +1 -0
- package/dist/test/mocks/mock-storage.js +145 -0
- package/dist/test/services/task-service.test.d.ts +2 -0
- package/dist/test/services/task-service.test.d.ts.map +1 -0
- package/dist/test/services/task-service.test.js +352 -0
- package/dist/test/test-mock-setup.d.ts +26 -0
- package/dist/test/test-mock-setup.d.ts.map +1 -0
- package/dist/test/test-mock-setup.js +41 -0
- package/dist/test/test-setup.d.ts +9 -0
- package/dist/test/test-setup.d.ts.map +1 -0
- package/dist/test/test-setup.js +44 -0
- package/dist/test/test-utils.d.ts +22 -0
- package/dist/test/test-utils.d.ts.map +1 -0
- package/dist/test/test-utils.js +37 -0
- package/dist/test/utils/ai-operation-utility.test.d.ts +2 -0
- package/dist/test/utils/ai-operation-utility.test.d.ts.map +1 -0
- package/dist/test/utils/ai-operation-utility.test.js +290 -0
- package/dist/test/utils/error-handling.test.d.ts +2 -0
- package/dist/test/utils/error-handling.test.d.ts.map +1 -0
- package/dist/test/utils/error-handling.test.js +231 -0
- package/dist/types/index.d.ts +36 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/results.d.ts +60 -6
- package/dist/types/results.d.ts.map +1 -1
- package/dist/utils/ai-operation-utility.d.ts +142 -0
- package/dist/utils/ai-operation-utility.d.ts.map +1 -0
- package/dist/utils/ai-operation-utility.js +288 -0
- package/dist/utils/ai-service-factory.d.ts +10 -0
- package/dist/utils/ai-service-factory.d.ts.map +1 -1
- package/dist/utils/ai-service-factory.js +19 -1
- package/dist/utils/cli-validators.d.ts +2 -2
- package/dist/utils/cli-validators.d.ts.map +1 -1
- package/dist/utils/cli-validators.js +7 -6
- package/dist/utils/error-utils.d.ts +70 -0
- package/dist/utils/error-utils.d.ts.map +1 -0
- package/dist/utils/error-utils.js +104 -0
- package/dist/utils/file-utils.d.ts +49 -0
- package/dist/utils/file-utils.d.ts.map +1 -0
- package/dist/utils/file-utils.js +82 -0
- package/dist/utils/id-generator.d.ts +92 -0
- package/dist/utils/id-generator.d.ts.map +1 -0
- package/dist/utils/id-generator.js +146 -0
- package/dist/utils/model-executor-parser.d.ts +1 -1
- package/dist/utils/model-executor-parser.d.ts.map +1 -1
- package/dist/utils/model-executor-parser.js +3 -2
- package/dist/utils/stack-formatter.d.ts +2 -1
- package/dist/utils/stack-formatter.d.ts.map +1 -1
- package/dist/utils/stack-formatter.js +8 -2
- package/dist/utils/storage-utils.d.ts +49 -0
- package/dist/utils/storage-utils.d.ts.map +1 -0
- package/dist/utils/storage-utils.js +80 -0
- package/dist/utils/streaming-utils.d.ts +38 -0
- package/dist/utils/streaming-utils.d.ts.map +1 -0
- package/dist/utils/streaming-utils.js +56 -0
- package/dist/utils/task-o-matic-error.d.ts +206 -0
- package/dist/utils/task-o-matic-error.d.ts.map +1 -0
- package/dist/utils/task-o-matic-error.js +304 -0
- package/docs/agents/cli.md +58 -149
- package/package.json +2 -2
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FileSystemStorage = void 0;
|
|
4
4
|
const config_1 = require("../config");
|
|
5
5
|
const storage_callbacks_1 = require("./storage-callbacks");
|
|
6
|
+
const task_o_matic_error_1 = require("../../utils/task-o-matic-error");
|
|
6
7
|
class FileSystemStorage {
|
|
7
8
|
callbacks;
|
|
8
9
|
constructor(callbacks) {
|
|
@@ -16,30 +17,54 @@ class FileSystemStorage {
|
|
|
16
17
|
}
|
|
17
18
|
validateTaskId(taskId) {
|
|
18
19
|
if (!taskId || typeof taskId !== "string" || taskId.trim() === "") {
|
|
19
|
-
throw
|
|
20
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Task ID must be a non-empty string", {
|
|
21
|
+
context: "validateTaskId",
|
|
22
|
+
suggestions: ["Provide a valid task ID string"],
|
|
23
|
+
metadata: { taskId },
|
|
24
|
+
});
|
|
20
25
|
}
|
|
21
26
|
}
|
|
22
27
|
validateTaskRequest(task) {
|
|
23
28
|
if (!task || typeof task !== "object") {
|
|
24
|
-
throw
|
|
29
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Task request must be a valid object", {
|
|
30
|
+
context: "validateTaskRequest",
|
|
31
|
+
suggestions: ["Provide a valid task request object"],
|
|
32
|
+
});
|
|
25
33
|
}
|
|
26
34
|
if (!task.title ||
|
|
27
35
|
typeof task.title !== "string" ||
|
|
28
36
|
task.title.trim() === "") {
|
|
29
|
-
throw
|
|
37
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Task title is required and must be a non-empty string", {
|
|
38
|
+
context: "validateTaskRequest - title validation",
|
|
39
|
+
suggestions: ["Provide a non-empty title for the task"],
|
|
40
|
+
});
|
|
30
41
|
}
|
|
31
42
|
if (task.parentId && typeof task.parentId !== "string") {
|
|
32
|
-
throw
|
|
43
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Parent ID must be a string if provided", {
|
|
44
|
+
context: "validateTaskRequest - parentId validation",
|
|
45
|
+
suggestions: ["Provide a valid parent ID string or omit the field"],
|
|
46
|
+
metadata: { parentId: task.parentId },
|
|
47
|
+
});
|
|
33
48
|
}
|
|
34
49
|
if (task.estimatedEffort &&
|
|
35
50
|
!["small", "medium", "large"].includes(task.estimatedEffort)) {
|
|
36
|
-
throw
|
|
51
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Estimated effort must be 'small', 'medium', or 'large'", {
|
|
52
|
+
context: "validateTaskRequest - estimatedEffort validation",
|
|
53
|
+
suggestions: ["Use 'small', 'medium', or 'large' for estimatedEffort"],
|
|
54
|
+
metadata: { estimatedEffort: task.estimatedEffort },
|
|
55
|
+
});
|
|
37
56
|
}
|
|
38
57
|
if (task.dependencies && !Array.isArray(task.dependencies)) {
|
|
39
|
-
throw
|
|
58
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Dependencies must be an array if provided", {
|
|
59
|
+
context: "validateTaskRequest - dependencies validation",
|
|
60
|
+
suggestions: ["Provide dependencies as an array of task IDs"],
|
|
61
|
+
});
|
|
40
62
|
}
|
|
41
63
|
if (task.tags && !Array.isArray(task.tags)) {
|
|
42
|
-
throw
|
|
64
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Tags must be an array if provided", {
|
|
65
|
+
context: "validateTaskRequest - tags validation",
|
|
66
|
+
suggestions: ["Provide tags as an array of strings"],
|
|
67
|
+
});
|
|
43
68
|
}
|
|
44
69
|
}
|
|
45
70
|
async loadTasksData() {
|
|
@@ -60,7 +85,7 @@ class FileSystemStorage {
|
|
|
60
85
|
await this.callbacks.write("tasks.json", JSON.stringify(data, null, 2));
|
|
61
86
|
}
|
|
62
87
|
catch (error) {
|
|
63
|
-
throw
|
|
88
|
+
throw (0, task_o_matic_error_1.formatStorageError)("write tasks.json", error instanceof Error ? error : undefined);
|
|
64
89
|
}
|
|
65
90
|
}
|
|
66
91
|
findTaskInHierarchy(tasks, id) {
|
|
@@ -111,7 +136,15 @@ class FileSystemStorage {
|
|
|
111
136
|
if (task.parentId) {
|
|
112
137
|
const parentResult = this.findTaskInHierarchy(data.tasks, task.parentId);
|
|
113
138
|
if (!parentResult.task) {
|
|
114
|
-
throw
|
|
139
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.TASK_NOT_FOUND, `Parent task with ID ${task.parentId} not found`, {
|
|
140
|
+
context: "createTask - parent validation",
|
|
141
|
+
suggestions: [
|
|
142
|
+
"Create the parent task first",
|
|
143
|
+
"Check that the parent ID is correct",
|
|
144
|
+
"List all tasks to see available parent IDs",
|
|
145
|
+
],
|
|
146
|
+
metadata: { parentId: task.parentId },
|
|
147
|
+
});
|
|
115
148
|
}
|
|
116
149
|
const siblingCount = (parentResult.task.subtasks?.length || 0) + 1;
|
|
117
150
|
id = `${task.parentId}.${siblingCount}`;
|
|
@@ -129,11 +162,26 @@ class FileSystemStorage {
|
|
|
129
162
|
for (const depId of task.dependencies) {
|
|
130
163
|
const depExists = this.taskExists(data.tasks, depId);
|
|
131
164
|
if (!depExists) {
|
|
132
|
-
throw
|
|
165
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.TASK_NOT_FOUND, `Dependency task not found: ${depId}`, {
|
|
166
|
+
context: "createTask - dependency validation",
|
|
167
|
+
suggestions: [
|
|
168
|
+
"Create the dependency task first",
|
|
169
|
+
"Check that the dependency ID is correct",
|
|
170
|
+
"Remove the dependency from the task",
|
|
171
|
+
],
|
|
172
|
+
metadata: { dependencyId: depId, taskDependencies: task.dependencies },
|
|
173
|
+
});
|
|
133
174
|
}
|
|
134
175
|
}
|
|
135
176
|
if (this.wouldCreateCircularDependency(data.tasks, id, task.dependencies)) {
|
|
136
|
-
throw
|
|
177
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.STORAGE_INTEGRITY_ERROR, `Circular dependency detected for task ${id}`, {
|
|
178
|
+
context: "createTask - circular dependency check",
|
|
179
|
+
suggestions: [
|
|
180
|
+
"Remove circular dependencies from the task",
|
|
181
|
+
"Review the dependency chain",
|
|
182
|
+
],
|
|
183
|
+
metadata: { taskId: id, dependencies: task.dependencies },
|
|
184
|
+
});
|
|
137
185
|
}
|
|
138
186
|
}
|
|
139
187
|
let contentFile;
|
|
@@ -184,7 +232,10 @@ class FileSystemStorage {
|
|
|
184
232
|
async updateTask(id, updates) {
|
|
185
233
|
this.validateTaskId(id);
|
|
186
234
|
if (!updates || typeof updates !== "object") {
|
|
187
|
-
throw
|
|
235
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Updates must be a valid object", {
|
|
236
|
+
context: "updateTask - updates validation",
|
|
237
|
+
suggestions: ["Provide a valid updates object with task properties"],
|
|
238
|
+
});
|
|
188
239
|
}
|
|
189
240
|
const data = await this.loadTasksData();
|
|
190
241
|
const result = this.findTaskInHierarchy(data.tasks, id);
|
|
@@ -314,28 +365,34 @@ class FileSystemStorage {
|
|
|
314
365
|
async saveTaskContent(taskId, content) {
|
|
315
366
|
this.validateTaskId(taskId);
|
|
316
367
|
if (typeof content !== "string") {
|
|
317
|
-
throw
|
|
368
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Content must be a string", {
|
|
369
|
+
context: "Content validation",
|
|
370
|
+
suggestions: ["Provide content as a string"],
|
|
371
|
+
});
|
|
318
372
|
}
|
|
319
373
|
const contentFileName = `tasks/${taskId}.md`;
|
|
320
374
|
try {
|
|
321
375
|
await this.callbacks.write(contentFileName, content);
|
|
322
376
|
}
|
|
323
377
|
catch (error) {
|
|
324
|
-
throw
|
|
378
|
+
throw (0, task_o_matic_error_1.formatStorageError)("write task content", error instanceof Error ? error : undefined);
|
|
325
379
|
}
|
|
326
380
|
return contentFileName;
|
|
327
381
|
}
|
|
328
382
|
async saveEnhancedTaskContent(taskId, content) {
|
|
329
383
|
this.validateTaskId(taskId);
|
|
330
384
|
if (typeof content !== "string") {
|
|
331
|
-
throw
|
|
385
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Content must be a string", {
|
|
386
|
+
context: "Content validation",
|
|
387
|
+
suggestions: ["Provide content as a string"],
|
|
388
|
+
});
|
|
332
389
|
}
|
|
333
390
|
const contentFileName = `tasks/enhanced/${taskId}.md`;
|
|
334
391
|
try {
|
|
335
392
|
await this.callbacks.write(contentFileName, content);
|
|
336
393
|
}
|
|
337
394
|
catch (error) {
|
|
338
|
-
throw
|
|
395
|
+
throw (0, task_o_matic_error_1.formatStorageError)("write enhanced task content", error instanceof Error ? error : undefined);
|
|
339
396
|
}
|
|
340
397
|
return contentFileName;
|
|
341
398
|
}
|
|
@@ -496,7 +553,7 @@ class FileSystemStorage {
|
|
|
496
553
|
await this.callbacks.write(planFile, JSON.stringify(planData, null, 2));
|
|
497
554
|
}
|
|
498
555
|
catch (error) {
|
|
499
|
-
throw
|
|
556
|
+
throw (0, task_o_matic_error_1.formatStorageError)(`write plan for task ${taskId}`, error instanceof Error ? error : undefined);
|
|
500
557
|
}
|
|
501
558
|
}
|
|
502
559
|
async getPlan(taskId) {
|
|
@@ -509,7 +566,7 @@ class FileSystemStorage {
|
|
|
509
566
|
return JSON.parse(content);
|
|
510
567
|
}
|
|
511
568
|
catch (error) {
|
|
512
|
-
throw
|
|
569
|
+
throw (0, task_o_matic_error_1.formatStorageError)(`read plan for task ${taskId}`, error instanceof Error ? error : undefined);
|
|
513
570
|
}
|
|
514
571
|
}
|
|
515
572
|
async listPlans() {
|
|
@@ -534,7 +591,7 @@ class FileSystemStorage {
|
|
|
534
591
|
return plans.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
535
592
|
}
|
|
536
593
|
catch (error) {
|
|
537
|
-
throw
|
|
594
|
+
throw (0, task_o_matic_error_1.formatStorageError)("list plans", error instanceof Error ? error : undefined);
|
|
538
595
|
}
|
|
539
596
|
}
|
|
540
597
|
async deletePlan(taskId) {
|
|
@@ -551,14 +608,17 @@ class FileSystemStorage {
|
|
|
551
608
|
async saveTaskDocumentation(taskId, documentation) {
|
|
552
609
|
this.validateTaskId(taskId);
|
|
553
610
|
if (typeof documentation !== "string") {
|
|
554
|
-
throw
|
|
611
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Documentation must be a string", {
|
|
612
|
+
context: "Documentation validation",
|
|
613
|
+
suggestions: ["Provide documentation as a string"],
|
|
614
|
+
});
|
|
555
615
|
}
|
|
556
616
|
const documentationFileName = `docs/tasks/${taskId}.md`;
|
|
557
617
|
try {
|
|
558
618
|
await this.callbacks.write(documentationFileName, documentation);
|
|
559
619
|
}
|
|
560
620
|
catch (error) {
|
|
561
|
-
throw
|
|
621
|
+
throw (0, task_o_matic_error_1.formatStorageError)("write task documentation", error instanceof Error ? error : undefined);
|
|
562
622
|
}
|
|
563
623
|
return documentationFileName;
|
|
564
624
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-execution-core.d.ts","sourceRoot":"","sources":["../../src/lib/task-execution-core.ts"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.executeTaskCore = executeTaskCore;
|
|
7
|
+
const task_o_matic_error_1 = require("../utils/task-o-matic-error");
|
|
7
8
|
const tasks_1 = require("../services/tasks");
|
|
8
9
|
const executor_factory_1 = require("./executors/executor-factory");
|
|
9
10
|
const validation_1 = require("./validation");
|
|
@@ -23,7 +24,7 @@ async function executeTaskCore(taskId, config) {
|
|
|
23
24
|
// Load task
|
|
24
25
|
const task = await tasks_1.taskService.getTask(taskId);
|
|
25
26
|
if (!task) {
|
|
26
|
-
throw
|
|
27
|
+
throw (0, task_o_matic_error_1.formatTaskNotFoundError)(taskId);
|
|
27
28
|
}
|
|
28
29
|
// Check if task has subtasks and should execute them recursively
|
|
29
30
|
if (executeSubtasks && !customMessage) {
|
|
@@ -254,7 +255,7 @@ async function executeSingleAttempt(task, config, attempts, planContent, attempt
|
|
|
254
255
|
retryContext,
|
|
255
256
|
});
|
|
256
257
|
if (!promptResult.success) {
|
|
257
|
-
throw
|
|
258
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.CONFIGURATION_ERROR, `Failed to build execution prompt: ${promptResult.error}`);
|
|
258
259
|
}
|
|
259
260
|
executionMessage = promptResult.prompt;
|
|
260
261
|
}
|
package/dist/services/prd.d.ts
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
+
import { getAIOperations, getStorage } from "../utils/ai-service-factory";
|
|
1
2
|
import { AIOptions } from "../utils/ai-config-builder";
|
|
2
3
|
import { StreamingOptions } from "../types";
|
|
3
4
|
import { PRDParseResult } from "../types/results";
|
|
4
5
|
import { ProgressCallback } from "../types/callbacks";
|
|
6
|
+
/**
|
|
7
|
+
* Dependencies for PRDService
|
|
8
|
+
*/
|
|
9
|
+
export interface PRDServiceDependencies {
|
|
10
|
+
storage?: ReturnType<typeof getStorage>;
|
|
11
|
+
aiOperations?: ReturnType<typeof getAIOperations>;
|
|
12
|
+
}
|
|
5
13
|
/**
|
|
6
14
|
* PRDService - Business logic for PRD operations
|
|
7
15
|
* Handles PRD parsing, task extraction, and PRD improvement
|
|
8
16
|
*/
|
|
9
17
|
export declare class PRDService {
|
|
18
|
+
private storage;
|
|
19
|
+
private aiOperations;
|
|
20
|
+
/**
|
|
21
|
+
* Create a new PRDService
|
|
22
|
+
*
|
|
23
|
+
* @param dependencies - Optional dependencies to inject (for testing)
|
|
24
|
+
*/
|
|
25
|
+
constructor(dependencies?: PRDServiceDependencies);
|
|
10
26
|
parsePRD(input: {
|
|
11
27
|
file: string;
|
|
12
28
|
workingDirectory?: string;
|
|
@@ -98,5 +114,6 @@ export declare class PRDService {
|
|
|
98
114
|
};
|
|
99
115
|
}>;
|
|
100
116
|
}
|
|
117
|
+
export declare function getPRDService(): PRDService;
|
|
101
118
|
export declare const prdService: PRDService;
|
|
102
119
|
//# sourceMappingURL=prd.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prd.d.ts","sourceRoot":"","sources":["../../src/services/prd.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prd.d.ts","sourceRoot":"","sources":["../../src/services/prd.ts"],"names":[],"mappings":"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"}
|
package/dist/services/prd.js
CHANGED
|
@@ -34,17 +34,33 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.prdService = exports.PRDService = void 0;
|
|
37
|
+
exports.getPRDService = getPRDService;
|
|
38
|
+
const task_o_matic_error_1 = require("../utils/task-o-matic-error");
|
|
37
39
|
const fs_1 = require("fs");
|
|
38
40
|
const path_1 = require("path");
|
|
39
41
|
const ai_service_factory_1 = require("../utils/ai-service-factory");
|
|
40
42
|
const ai_config_builder_1 = require("../utils/ai-config-builder");
|
|
41
43
|
const config_1 = require("../lib/config");
|
|
42
44
|
const validation_1 = require("../lib/validation");
|
|
45
|
+
const streaming_utils_1 = require("../utils/streaming-utils");
|
|
46
|
+
const file_utils_1 = require("../utils/file-utils");
|
|
43
47
|
/**
|
|
44
48
|
* PRDService - Business logic for PRD operations
|
|
45
49
|
* Handles PRD parsing, task extraction, and PRD improvement
|
|
46
50
|
*/
|
|
47
51
|
class PRDService {
|
|
52
|
+
storage;
|
|
53
|
+
aiOperations;
|
|
54
|
+
/**
|
|
55
|
+
* Create a new PRDService
|
|
56
|
+
*
|
|
57
|
+
* @param dependencies - Optional dependencies to inject (for testing)
|
|
58
|
+
*/
|
|
59
|
+
constructor(dependencies = {}) {
|
|
60
|
+
// Use injected dependencies or fall back to singletons
|
|
61
|
+
this.storage = dependencies.storage ?? (0, ai_service_factory_1.getStorage)();
|
|
62
|
+
this.aiOperations = dependencies.aiOperations ?? (0, ai_service_factory_1.getAIOperations)();
|
|
63
|
+
}
|
|
48
64
|
async parsePRD(input) {
|
|
49
65
|
const startTime = Date.now();
|
|
50
66
|
const steps = [];
|
|
@@ -52,20 +68,18 @@ class PRDService {
|
|
|
52
68
|
type: "started",
|
|
53
69
|
message: "Starting PRD parsing...",
|
|
54
70
|
});
|
|
55
|
-
// Validate file exists
|
|
56
|
-
|
|
57
|
-
throw new Error(`PRD file not found: ${input.file}`);
|
|
58
|
-
}
|
|
71
|
+
// Validate file exists (DRY fix 1.2)
|
|
72
|
+
(0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
|
|
59
73
|
// Ensure we're in a task-o-matic project
|
|
60
74
|
const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
|
|
61
75
|
if (!(0, fs_1.existsSync)(taskOMaticDir)) {
|
|
62
|
-
throw
|
|
76
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.CONFIGURATION_ERROR, "Not a task-o-matic project. Run 'task-o-matic init init' first.", {
|
|
77
|
+
suggestions: ["Run `task-o-matic init init` in your project root."],
|
|
78
|
+
});
|
|
63
79
|
}
|
|
64
|
-
// Set working directory
|
|
80
|
+
// Set working directory and reload config (DRY fix 1.4)
|
|
65
81
|
const workingDir = input.workingDirectory || process.cwd();
|
|
66
|
-
config_1.
|
|
67
|
-
// Reload config after changing working directory
|
|
68
|
-
await config_1.configManager.load();
|
|
82
|
+
await (0, config_1.setupWorkingDirectory)(workingDir);
|
|
69
83
|
input.callbacks?.onProgress?.({
|
|
70
84
|
type: "progress",
|
|
71
85
|
message: "Reading PRD file...",
|
|
@@ -96,7 +110,9 @@ class PRDService {
|
|
|
96
110
|
// Validate AI provider if specified
|
|
97
111
|
if (input.aiOptions?.aiProvider &&
|
|
98
112
|
!(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
|
|
99
|
-
throw
|
|
113
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
|
|
114
|
+
suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
|
|
115
|
+
});
|
|
100
116
|
}
|
|
101
117
|
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
102
118
|
input.callbacks?.onProgress?.({
|
|
@@ -104,34 +120,13 @@ class PRDService {
|
|
|
104
120
|
message: "Parsing PRD with AI...",
|
|
105
121
|
});
|
|
106
122
|
const stepStart2 = Date.now();
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
// Wrap streaming options to capture metrics
|
|
111
|
-
const metricsStreamingOptions = {
|
|
112
|
-
...input.streamingOptions,
|
|
113
|
-
onFinish: async (result) => {
|
|
114
|
-
if (result.usage) {
|
|
115
|
-
tokenUsage = {
|
|
116
|
-
prompt: result.usage.inputTokens || result.usage.promptTokens || 0,
|
|
117
|
-
completion: result.usage.outputTokens || result.usage.completionTokens || 0,
|
|
118
|
-
total: result.usage.totalTokens || 0,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
// Call original onFinish if provided
|
|
122
|
-
await input.streamingOptions?.onFinish?.(result);
|
|
123
|
-
},
|
|
124
|
-
onChunk: (chunk) => {
|
|
125
|
-
if (chunk && !timeToFirstToken) {
|
|
126
|
-
timeToFirstToken = Date.now() - stepStart2;
|
|
127
|
-
}
|
|
128
|
-
// Call original onChunk if provided
|
|
129
|
-
input.streamingOptions?.onChunk?.(chunk);
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
const result = await (0, ai_service_factory_1.getAIOperations)().parsePRD(prdContent, aiConfig, input.promptOverride, input.messageOverride, metricsStreamingOptions, undefined, // retryConfig
|
|
123
|
+
// Use utility to wrap streaming options and capture metrics (DRY fix 1.1)
|
|
124
|
+
const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, stepStart2);
|
|
125
|
+
const result = await this.aiOperations.parsePRD(prdContent, aiConfig, input.promptOverride, input.messageOverride, metricsStreamingOptions, undefined, // retryConfig
|
|
133
126
|
workingDir, // Pass working directory to AI operations
|
|
134
127
|
input.enableFilesystemTools);
|
|
128
|
+
// Extract metrics after AI call
|
|
129
|
+
const { tokenUsage, timeToFirstToken } = getMetrics();
|
|
135
130
|
steps.push({
|
|
136
131
|
step: "AI Parsing",
|
|
137
132
|
status: "completed",
|
|
@@ -153,7 +148,7 @@ class PRDService {
|
|
|
153
148
|
current: i + 1,
|
|
154
149
|
total: result.tasks.length,
|
|
155
150
|
});
|
|
156
|
-
const createdTask = await
|
|
151
|
+
const createdTask = await this.storage.createTask({
|
|
157
152
|
id: task.id, // Preserve AI-generated ID for dependencies
|
|
158
153
|
title: task.title,
|
|
159
154
|
description: task.description,
|
|
@@ -175,7 +170,7 @@ class PRDService {
|
|
|
175
170
|
aiModel: input.aiOptions?.aiModel,
|
|
176
171
|
generatedAt: Date.now(),
|
|
177
172
|
};
|
|
178
|
-
await
|
|
173
|
+
await this.storage.saveTaskAIMetadata(aiMetadata);
|
|
179
174
|
}
|
|
180
175
|
steps.push({
|
|
181
176
|
step: "Create Tasks",
|
|
@@ -220,12 +215,11 @@ class PRDService {
|
|
|
220
215
|
type: "started",
|
|
221
216
|
message: "Generating clarifying questions...",
|
|
222
217
|
});
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
218
|
+
// Validate file exists (DRY fix 1.2)
|
|
219
|
+
(0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
|
|
220
|
+
// Set working directory and reload config (DRY fix 1.4)
|
|
226
221
|
const workingDir = input.workingDirectory || process.cwd();
|
|
227
|
-
config_1.
|
|
228
|
-
await config_1.configManager.load();
|
|
222
|
+
await (0, config_1.setupWorkingDirectory)(workingDir);
|
|
229
223
|
input.callbacks?.onProgress?.({
|
|
230
224
|
type: "progress",
|
|
231
225
|
message: "Reading PRD file...",
|
|
@@ -233,14 +227,16 @@ class PRDService {
|
|
|
233
227
|
const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
|
|
234
228
|
if (input.aiOptions?.aiProvider &&
|
|
235
229
|
!(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
|
|
236
|
-
throw
|
|
230
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
|
|
231
|
+
suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
|
|
232
|
+
});
|
|
237
233
|
}
|
|
238
234
|
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
239
235
|
input.callbacks?.onProgress?.({
|
|
240
236
|
type: "progress",
|
|
241
237
|
message: "Analyzing PRD with AI...",
|
|
242
238
|
});
|
|
243
|
-
const questions = await
|
|
239
|
+
const questions = await this.aiOperations.generatePRDQuestions(prdContent, aiConfig, input.promptOverride, input.messageOverride, input.streamingOptions, undefined, workingDir, input.enableFilesystemTools);
|
|
244
240
|
input.callbacks?.onProgress?.({
|
|
245
241
|
type: "completed",
|
|
246
242
|
message: `Generated ${questions.length} questions`,
|
|
@@ -252,14 +248,11 @@ class PRDService {
|
|
|
252
248
|
type: "started",
|
|
253
249
|
message: "Starting PRD improvement...",
|
|
254
250
|
});
|
|
255
|
-
// Validate file exists
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
// Set working directory from CLI layer (defaults to process.cwd() for backward compatibility)
|
|
251
|
+
// Validate file exists (DRY fix 1.2)
|
|
252
|
+
(0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
|
|
253
|
+
// Set working directory and reload config (DRY fix 1.4)
|
|
260
254
|
const workingDir = input.workingDirectory || process.cwd();
|
|
261
|
-
config_1.
|
|
262
|
-
await config_1.configManager.load();
|
|
255
|
+
await (0, config_1.setupWorkingDirectory)(workingDir);
|
|
263
256
|
input.callbacks?.onProgress?.({
|
|
264
257
|
type: "progress",
|
|
265
258
|
message: "Reading PRD file...",
|
|
@@ -268,14 +261,16 @@ class PRDService {
|
|
|
268
261
|
// Validate AI provider if specified
|
|
269
262
|
if (input.aiOptions?.aiProvider &&
|
|
270
263
|
!(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
|
|
271
|
-
throw
|
|
264
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
|
|
265
|
+
suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
|
|
266
|
+
});
|
|
272
267
|
}
|
|
273
268
|
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
274
269
|
input.callbacks?.onProgress?.({
|
|
275
270
|
type: "progress",
|
|
276
271
|
message: "Calling AI to improve PRD...",
|
|
277
272
|
});
|
|
278
|
-
const improvedPRD = await
|
|
273
|
+
const improvedPRD = await this.aiOperations.reworkPRD(prdContent, input.feedback, aiConfig, input.promptOverride, input.messageOverride, input.streamingOptions, undefined, // retryConfig
|
|
279
274
|
workingDir, // Pass working directory to AI operations
|
|
280
275
|
input.enableFilesystemTools);
|
|
281
276
|
input.callbacks?.onProgress?.({
|
|
@@ -338,7 +333,7 @@ class PRDService {
|
|
|
338
333
|
// User mode: return questions for CLI to prompt user
|
|
339
334
|
// Answers should be provided in input.answers
|
|
340
335
|
if (!input.answers || Object.keys(input.answers).length === 0) {
|
|
341
|
-
throw
|
|
336
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "User mode selected but no answers provided. CLI layer should collect answers.");
|
|
342
337
|
}
|
|
343
338
|
answers = input.answers;
|
|
344
339
|
}
|
|
@@ -351,7 +346,7 @@ class PRDService {
|
|
|
351
346
|
const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
|
|
352
347
|
// Use questionAIOptions if provided, otherwise use main aiOptions
|
|
353
348
|
const answeringAIConfig = (0, ai_config_builder_1.buildAIConfig)(input.questionAIOptions || input.aiOptions);
|
|
354
|
-
answers = await
|
|
349
|
+
answers = await this.aiOperations.answerPRDQuestions(prdContent, questions, answeringAIConfig, {
|
|
355
350
|
stackInfo,
|
|
356
351
|
}, input.streamingOptions);
|
|
357
352
|
}
|
|
@@ -418,7 +413,7 @@ class PRDService {
|
|
|
418
413
|
},
|
|
419
414
|
};
|
|
420
415
|
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
421
|
-
const content = await
|
|
416
|
+
const content = await this.aiOperations.generatePRD(input.description, aiConfig, undefined, undefined, metricsStreamingOptions);
|
|
422
417
|
// Save file
|
|
423
418
|
const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
|
|
424
419
|
const prdDir = input.outputDir || (0, path_1.join)(taskOMaticDir, "prd");
|
|
@@ -476,7 +471,7 @@ class PRDService {
|
|
|
476
471
|
},
|
|
477
472
|
};
|
|
478
473
|
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
479
|
-
const content = await
|
|
474
|
+
const content = await this.aiOperations.combinePRDs(input.prds, input.originalDescription, aiConfig, undefined, undefined, metricsStreamingOptions);
|
|
480
475
|
// Save file
|
|
481
476
|
const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
|
|
482
477
|
const prdDir = input.outputDir || (0, path_1.join)(taskOMaticDir, "prd");
|
|
@@ -503,5 +498,17 @@ class PRDService {
|
|
|
503
498
|
}
|
|
504
499
|
}
|
|
505
500
|
exports.PRDService = PRDService;
|
|
506
|
-
//
|
|
507
|
-
|
|
501
|
+
// Lazy singleton instance - only created when first accessed
|
|
502
|
+
let prdServiceInstance;
|
|
503
|
+
function getPRDService() {
|
|
504
|
+
if (!prdServiceInstance) {
|
|
505
|
+
prdServiceInstance = new PRDService();
|
|
506
|
+
}
|
|
507
|
+
return prdServiceInstance;
|
|
508
|
+
}
|
|
509
|
+
// Backward compatibility: export as const but use getter
|
|
510
|
+
exports.prdService = new Proxy({}, {
|
|
511
|
+
get(target, prop) {
|
|
512
|
+
return getPRDService()[prop];
|
|
513
|
+
},
|
|
514
|
+
});
|