task-o-matic 0.0.14 → 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.
Files changed (110) hide show
  1. package/dist/cli/display/progress.d.ts +15 -2
  2. package/dist/cli/display/progress.d.ts.map +1 -1
  3. package/dist/cli/display/progress.js +72 -4
  4. package/dist/commands/benchmark.d.ts.map +1 -1
  5. package/dist/commands/benchmark.js +11 -3
  6. package/dist/commands/init.d.ts.map +1 -1
  7. package/dist/commands/init.js +19 -4
  8. package/dist/commands/prd.js +7 -1
  9. package/dist/commands/tasks/delete.d.ts.map +1 -1
  10. package/dist/commands/tasks/delete.js +2 -1
  11. package/dist/commands/tasks/document/add.d.ts.map +1 -1
  12. package/dist/commands/tasks/document/add.js +2 -1
  13. package/dist/commands/tasks/document/get.d.ts.map +1 -1
  14. package/dist/commands/tasks/document/get.js +2 -1
  15. package/dist/commands/tasks/plan/set.d.ts.map +1 -1
  16. package/dist/commands/tasks/plan/set.js +11 -3
  17. package/dist/commands/tasks/show.d.ts.map +1 -1
  18. package/dist/commands/tasks/show.js +2 -1
  19. package/dist/commands/tasks/status.d.ts.map +1 -1
  20. package/dist/commands/tasks/status.js +2 -1
  21. package/dist/commands/tasks/update.d.ts.map +1 -1
  22. package/dist/commands/tasks/update.js +7 -1
  23. package/dist/lib/ai-service/model-provider.d.ts.map +1 -1
  24. package/dist/lib/ai-service/model-provider.js +37 -6
  25. package/dist/lib/ai-service/task-operations.d.ts +1 -0
  26. package/dist/lib/ai-service/task-operations.d.ts.map +1 -1
  27. package/dist/lib/ai-service/task-operations.js +135 -173
  28. package/dist/lib/benchmark/registry.d.ts.map +1 -1
  29. package/dist/lib/benchmark/registry.js +6 -10
  30. package/dist/lib/config-validation.d.ts +215 -0
  31. package/dist/lib/config-validation.d.ts.map +1 -0
  32. package/dist/lib/config-validation.js +246 -0
  33. package/dist/lib/config.d.ts.map +1 -1
  34. package/dist/lib/config.js +19 -5
  35. package/dist/lib/storage/file-system.d.ts.map +1 -1
  36. package/dist/lib/storage/file-system.js +81 -21
  37. package/dist/lib/task-execution-core.d.ts.map +1 -1
  38. package/dist/lib/task-execution-core.js +3 -2
  39. package/dist/services/prd.d.ts +17 -0
  40. package/dist/services/prd.d.ts.map +1 -1
  41. package/dist/services/prd.js +49 -15
  42. package/dist/services/tasks.d.ts +315 -1
  43. package/dist/services/tasks.d.ts.map +1 -1
  44. package/dist/services/tasks.js +483 -107
  45. package/dist/services/workflow-ai-assistant.d.ts.map +1 -1
  46. package/dist/services/workflow-ai-assistant.js +19 -6
  47. package/dist/test/lib/ai-service/task-operations.test.d.ts +2 -0
  48. package/dist/test/lib/ai-service/task-operations.test.d.ts.map +1 -0
  49. package/dist/test/lib/ai-service/task-operations.test.js +362 -0
  50. package/dist/test/mocks/mock-ai-operations.d.ts +15 -0
  51. package/dist/test/mocks/mock-ai-operations.d.ts.map +1 -0
  52. package/dist/test/mocks/mock-ai-operations.js +107 -0
  53. package/dist/test/mocks/mock-context-builder.d.ts +10 -0
  54. package/dist/test/mocks/mock-context-builder.d.ts.map +1 -0
  55. package/dist/test/mocks/mock-context-builder.js +81 -0
  56. package/dist/test/mocks/mock-model-provider.d.ts +7 -0
  57. package/dist/test/mocks/mock-model-provider.d.ts.map +1 -0
  58. package/dist/test/mocks/mock-model-provider.js +21 -0
  59. package/dist/test/mocks/mock-service-factory.d.ts +11 -0
  60. package/dist/test/mocks/mock-service-factory.d.ts.map +1 -0
  61. package/dist/test/mocks/mock-service-factory.js +61 -0
  62. package/dist/test/mocks/mock-storage.d.ts +50 -0
  63. package/dist/test/mocks/mock-storage.d.ts.map +1 -0
  64. package/dist/test/mocks/mock-storage.js +145 -0
  65. package/dist/test/services/task-service.test.d.ts +2 -0
  66. package/dist/test/services/task-service.test.d.ts.map +1 -0
  67. package/dist/test/services/task-service.test.js +352 -0
  68. package/dist/test/test-mock-setup.d.ts +26 -0
  69. package/dist/test/test-mock-setup.d.ts.map +1 -0
  70. package/dist/test/test-mock-setup.js +41 -0
  71. package/dist/test/test-setup.d.ts +9 -0
  72. package/dist/test/test-setup.d.ts.map +1 -0
  73. package/dist/test/test-setup.js +44 -0
  74. package/dist/test/test-utils.d.ts +22 -0
  75. package/dist/test/test-utils.d.ts.map +1 -0
  76. package/dist/test/test-utils.js +37 -0
  77. package/dist/test/utils/ai-operation-utility.test.d.ts +2 -0
  78. package/dist/test/utils/ai-operation-utility.test.d.ts.map +1 -0
  79. package/dist/test/utils/ai-operation-utility.test.js +290 -0
  80. package/dist/test/utils/error-handling.test.d.ts +2 -0
  81. package/dist/test/utils/error-handling.test.d.ts.map +1 -0
  82. package/dist/test/utils/error-handling.test.js +231 -0
  83. package/dist/utils/ai-operation-utility.d.ts +142 -0
  84. package/dist/utils/ai-operation-utility.d.ts.map +1 -0
  85. package/dist/utils/ai-operation-utility.js +288 -0
  86. package/dist/utils/ai-service-factory.d.ts +10 -0
  87. package/dist/utils/ai-service-factory.d.ts.map +1 -1
  88. package/dist/utils/ai-service-factory.js +19 -1
  89. package/dist/utils/cli-validators.d.ts +2 -2
  90. package/dist/utils/cli-validators.d.ts.map +1 -1
  91. package/dist/utils/cli-validators.js +7 -6
  92. package/dist/utils/error-utils.d.ts +3 -3
  93. package/dist/utils/error-utils.d.ts.map +1 -1
  94. package/dist/utils/error-utils.js +5 -4
  95. package/dist/utils/file-utils.d.ts +4 -4
  96. package/dist/utils/file-utils.d.ts.map +1 -1
  97. package/dist/utils/file-utils.js +11 -6
  98. package/dist/utils/id-generator.d.ts +1 -1
  99. package/dist/utils/id-generator.d.ts.map +1 -1
  100. package/dist/utils/id-generator.js +8 -2
  101. package/dist/utils/model-executor-parser.d.ts +1 -1
  102. package/dist/utils/model-executor-parser.d.ts.map +1 -1
  103. package/dist/utils/model-executor-parser.js +3 -2
  104. package/dist/utils/storage-utils.d.ts +3 -3
  105. package/dist/utils/storage-utils.d.ts.map +1 -1
  106. package/dist/utils/storage-utils.js +7 -6
  107. package/dist/utils/task-o-matic-error.d.ts +206 -0
  108. package/dist/utils/task-o-matic-error.d.ts.map +1 -0
  109. package/dist/utils/task-o-matic-error.js +304 -0
  110. package/package.json +2 -2
@@ -1,95 +1,62 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TaskOperations = void 0;
4
- const ai_1 = require("ai");
5
4
  const prompt_builder_1 = require("../prompt-builder");
6
5
  const stack_formatter_1 = require("../../utils/stack-formatter");
7
6
  const prompts_1 = require("../../prompts");
8
7
  const ai_service_factory_1 = require("../../utils/ai-service-factory");
9
8
  const filesystem_tools_1 = require("./filesystem-tools");
10
9
  const base_operations_1 = require("./base-operations");
10
+ const ai_operation_utility_1 = require("../../utils/ai-operation-utility");
11
11
  class TaskOperations extends base_operations_1.BaseOperations {
12
+ aiOperationUtility = new ai_operation_utility_1.AIOperationUtility();
12
13
  async breakdownTask(task, config, promptOverride, userMessage, streamingOptions, retryConfig, fullContent, stackInfo, existingSubtasks, enableFilesystemTools) {
13
- return this.retryHandler.executeWithRetry(async () => {
14
- let prompt;
15
- if (promptOverride) {
16
- prompt = promptOverride;
14
+ // Build prompt
15
+ let prompt;
16
+ if (promptOverride) {
17
+ prompt = promptOverride;
18
+ }
19
+ else {
20
+ const variables = {
21
+ TASK_TITLE: task.title,
22
+ TASK_DESCRIPTION: task.description || "No description",
23
+ };
24
+ if (fullContent) {
25
+ variables.TASK_CONTENT = fullContent;
17
26
  }
18
- else {
19
- const variables = {
20
- TASK_TITLE: task.title,
21
- TASK_DESCRIPTION: task.description || "No description",
22
- };
23
- if (fullContent) {
24
- variables.TASK_CONTENT = fullContent;
25
- }
26
- if (existingSubtasks && existingSubtasks.length > 0) {
27
- const existingSubtasksText = existingSubtasks
28
- .map((subtask, index) => `${index + 1}. ${subtask.title}: ${subtask.description || "No description"}`)
29
- .join("\n");
30
- variables.EXISTING_SUBTASKS = existingSubtasksText;
31
- }
32
- if (stackInfo) {
33
- variables.STACK_INFO = stackInfo;
34
- }
35
- const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
36
- name: "task-breakdown",
37
- type: "user",
38
- variables,
39
- });
40
- if (!promptResult.success) {
41
- throw new Error(`Failed to build task breakdown prompt: ${promptResult.error}`);
42
- }
43
- prompt = promptResult.prompt;
27
+ if (existingSubtasks && existingSubtasks.length > 0) {
28
+ const existingSubtasksText = existingSubtasks
29
+ .map((subtask, index) => `${index + 1}. ${subtask.title}: ${subtask.description || "No description"}`)
30
+ .join("\n");
31
+ variables.EXISTING_SUBTASKS = existingSubtasksText;
32
+ }
33
+ if (stackInfo) {
34
+ variables.STACK_INFO = stackInfo;
35
+ }
36
+ const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
37
+ name: "task-breakdown",
38
+ type: "user",
39
+ variables,
40
+ });
41
+ if (!promptResult.success) {
42
+ throw new Error(`Failed to build task breakdown prompt: ${promptResult.error}`);
44
43
  }
45
- let response;
46
- if (enableFilesystemTools) {
47
- const model = this.modelProvider.getModel({
48
- ...this.modelProvider.getAIConfig(),
49
- ...config,
50
- });
51
- const allTools = {
52
- ...filesystem_tools_1.filesystemTools,
53
- };
54
- const result = await (0, ai_1.streamText)({
55
- model,
56
- tools: allTools,
57
- system: prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT +
58
- `
44
+ prompt = promptResult.prompt;
45
+ }
46
+ // Execute AI operation with proper error handling
47
+ const result = await this.aiOperationUtility.executeAIOperation("Task breakdown", async () => {
48
+ // Prepare tools if filesystem tools are enabled
49
+ const tools = enableFilesystemTools ? filesystem_tools_1.filesystemTools : undefined;
50
+ const response = await this.aiOperationUtility.streamTextWithTools(prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT +
51
+ (enableFilesystemTools
52
+ ? `
59
53
 
60
54
  You have access to filesystem tools that allow you to:
61
55
  - readFile: Read the contents of any file in the project
62
56
  - listDirectory: List contents of directories
63
57
 
64
- Use these tools to understand the project structure, existing code, and dependencies when breaking down tasks into subtasks.`,
65
- messages: [{ role: "user", content: userMessage || prompt }],
66
- maxRetries: 0,
67
- onChunk: streamingOptions?.onChunk
68
- ? ({ chunk }) => {
69
- if (chunk.type === "text-delta") {
70
- streamingOptions.onChunk(chunk.text);
71
- }
72
- else if (chunk.type === "reasoning-delta") {
73
- streamingOptions.onReasoning?.(chunk.text);
74
- }
75
- }
76
- : undefined,
77
- onFinish: streamingOptions?.onFinish
78
- ? ({ text, finishReason, usage }) => {
79
- streamingOptions.onFinish({
80
- text,
81
- finishReason,
82
- usage,
83
- isAborted: false,
84
- });
85
- }
86
- : undefined,
87
- });
88
- response = await result.text;
89
- }
90
- else {
91
- response = await this.streamText("", config, prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
92
- }
58
+ Use these tools to understand the project structure, existing code, and dependencies when breaking down tasks into subtasks.`
59
+ : ""), userMessage || prompt, config, streamingOptions, tools);
93
60
  const parseResult = this.jsonParser.parseJSONFromResponse(response);
94
61
  if (!parseResult.success) {
95
62
  throw new Error(parseResult.error || "Failed to parse task breakdown response");
@@ -100,126 +67,121 @@ Use these tools to understand the project structure, existing code, and dependen
100
67
  content: subtask.description || "",
101
68
  estimatedEffort: subtask.effort,
102
69
  }));
103
- }, retryConfig, "Task breakdown");
70
+ }, {
71
+ streamingOptions,
72
+ retryConfig,
73
+ aiConfig: config,
74
+ maxRetries: retryConfig?.maxAttempts || 2,
75
+ });
76
+ // Return the result directly (errors are thrown, not returned)
77
+ return result.result;
104
78
  }
105
79
  async enhanceTask(title, description, config, promptOverride, userMessage, taskId, streamingOptions, retryConfig) {
106
- return this.retryHandler.executeWithRetry(async () => {
107
- let contextInfo = "";
108
- let prdContent = "";
109
- if (taskId) {
110
- const contextBuilder = (0, ai_service_factory_1.getContextBuilder)();
111
- try {
112
- const context = await contextBuilder.buildContext(taskId);
113
- if (context.documentation || context.stack || context.prdContent) {
114
- contextInfo = "\n\nAvailable Context:\n";
115
- if (context.stack) {
116
- contextInfo += (0, stack_formatter_1.formatStackForContext)(context.stack) + "\n";
117
- }
118
- if (context.documentation) {
119
- contextInfo += `Documentation Available: ${context.documentation.recap}\n`;
120
- if (context.documentation.files.length > 0) {
121
- contextInfo += `Documentation Files: ${context.documentation.files
122
- .map((f) => f.path)
123
- .join(", ")}\n`;
124
- }
125
- }
126
- if (context.prdContent) {
127
- prdContent = context.prdContent;
80
+ // Build context
81
+ let contextInfo = "";
82
+ let prdContent = "";
83
+ if (taskId) {
84
+ const contextBuilder = (0, ai_service_factory_1.getContextBuilder)();
85
+ try {
86
+ const context = await contextBuilder.buildContext(taskId);
87
+ if (context.documentation || context.stack || context.prdContent) {
88
+ contextInfo = "\n\nAvailable Context:\n";
89
+ if (context.stack) {
90
+ contextInfo += (0, stack_formatter_1.formatStackForContext)(context.stack) + "\n";
91
+ }
92
+ if (context.documentation) {
93
+ contextInfo += `Documentation Available: ${context.documentation.recap}\n`;
94
+ if (context.documentation.files.length > 0) {
95
+ contextInfo += `Documentation Files: ${context.documentation.files
96
+ .map((f) => f.path)
97
+ .join(", ")}\n`;
128
98
  }
129
99
  }
130
- }
131
- catch (error) {
132
- throw error;
100
+ if (context.prdContent) {
101
+ prdContent = context.prdContent;
102
+ }
133
103
  }
134
104
  }
135
- let prompt;
136
- if (promptOverride) {
137
- prompt = promptOverride;
105
+ catch (error) {
106
+ throw error;
138
107
  }
139
- else {
140
- const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
141
- name: "task-enhancement",
142
- type: "user",
143
- variables: {
144
- TASK_TITLE: title,
145
- TASK_DESCRIPTION: description || "None",
146
- CONTEXT_INFO: contextInfo,
147
- PRD_CONTENT: prdContent || "No PRD content available",
148
- },
149
- });
150
- if (!promptResult.success) {
151
- throw new Error(`Failed to build task enhancement prompt: ${promptResult.error}`);
152
- }
153
- prompt = promptResult.prompt;
108
+ }
109
+ // Build prompt
110
+ let prompt;
111
+ if (promptOverride) {
112
+ prompt = promptOverride;
113
+ }
114
+ else {
115
+ const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
116
+ name: "task-enhancement",
117
+ type: "user",
118
+ variables: {
119
+ TASK_TITLE: title,
120
+ TASK_DESCRIPTION: description || "None",
121
+ CONTEXT_INFO: contextInfo,
122
+ PRD_CONTENT: prdContent || "No PRD content available",
123
+ },
124
+ });
125
+ if (!promptResult.success) {
126
+ throw new Error(`Failed to build task enhancement prompt: ${promptResult.error}`);
154
127
  }
155
- return this.streamText("", config, prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
156
- }, retryConfig, "Task enhancement");
128
+ prompt = promptResult.prompt;
129
+ }
130
+ // Execute AI operation with proper error handling
131
+ const result = await this.aiOperationUtility.executeAIOperation("Task enhancement", async () => {
132
+ return await this.aiOperationUtility.streamText("", config, prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
133
+ }, {
134
+ streamingOptions,
135
+ retryConfig,
136
+ aiConfig: config,
137
+ maxRetries: retryConfig?.maxAttempts || 2,
138
+ });
139
+ // Return the result directly (errors are thrown, not returned)
140
+ return result.result;
157
141
  }
158
142
  async planTask(taskContext, taskDetails, config, promptOverride, userMessage, streamingOptions, retryConfig) {
159
- return this.retryHandler.executeWithRetry(async () => {
160
- let prompt;
161
- if (promptOverride) {
162
- prompt = promptOverride;
163
- }
164
- else {
165
- const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
166
- name: "task-planning",
167
- type: "user",
168
- variables: {
169
- TASK_CONTEXT: taskContext,
170
- TASK_DETAILS: taskDetails,
171
- },
172
- });
173
- if (!promptResult.success) {
174
- throw new Error(`Failed to build task planning prompt: ${promptResult.error}`);
175
- }
176
- prompt = promptResult.prompt;
177
- }
178
- const model = this.modelProvider.getModel({
179
- ...this.modelProvider.getAIConfig(),
180
- ...config,
143
+ // Build prompt
144
+ let prompt;
145
+ if (promptOverride) {
146
+ prompt = promptOverride;
147
+ }
148
+ else {
149
+ const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
150
+ name: "task-planning",
151
+ type: "user",
152
+ variables: {
153
+ TASK_CONTEXT: taskContext,
154
+ TASK_DETAILS: taskDetails,
155
+ },
181
156
  });
157
+ if (!promptResult.success) {
158
+ throw new Error(`Failed to build task planning prompt: ${promptResult.error}`);
159
+ }
160
+ prompt = promptResult.prompt;
161
+ }
162
+ // Execute AI operation with proper error handling
163
+ const result = await this.aiOperationUtility.executeAIOperation("Task planning", async () => {
182
164
  const mcpTools = await this.context7Client.getMCPTools();
183
165
  const allTools = {
184
166
  ...mcpTools,
185
167
  ...filesystem_tools_1.filesystemTools,
186
168
  };
187
- const result = (0, ai_1.streamText)({
188
- model,
189
- tools: allTools,
190
- system: prompts_1.TASK_PLANNING_SYSTEM_PROMPT +
191
- `
169
+ return await this.aiOperationUtility.streamTextWithTools(prompts_1.TASK_PLANNING_SYSTEM_PROMPT +
170
+ `
192
171
 
193
172
  You have access to filesystem tools that allow you to:
194
173
  - readFile: Read the contents of any file in the project
195
174
  - listDirectory: List contents of directories
196
175
 
197
- Use these tools to understand the project structure, existing code, and dependencies when creating implementation plans.`,
198
- messages: [{ role: "user", content: userMessage || prompt }],
199
- maxRetries: 0,
200
- onChunk: streamingOptions?.onChunk
201
- ? ({ chunk }) => {
202
- if (chunk.type === "text-delta") {
203
- streamingOptions.onChunk(chunk.text);
204
- }
205
- else if (chunk.type === "reasoning-delta") {
206
- streamingOptions.onReasoning?.(chunk.text);
207
- }
208
- }
209
- : undefined,
210
- onFinish: streamingOptions?.onFinish
211
- ? ({ text, finishReason, usage }) => {
212
- streamingOptions.onFinish({
213
- text,
214
- finishReason,
215
- usage,
216
- isAborted: false,
217
- });
218
- }
219
- : undefined,
220
- });
221
- return (await result).text;
222
- }, retryConfig, "Task planning");
176
+ Use these tools to understand the project structure, existing code, and dependencies when creating implementation plans.`, userMessage || prompt, config, streamingOptions, allTools);
177
+ }, {
178
+ streamingOptions,
179
+ retryConfig,
180
+ aiConfig: config,
181
+ maxRetries: retryConfig?.maxAttempts || 2,
182
+ });
183
+ // Return the result directly (errors are thrown, not returned)
184
+ return result.result;
223
185
  }
224
186
  }
225
187
  exports.TaskOperations = TaskOperations;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/benchmark/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAA0B,MAAM,SAAS,CAAC;AAOzE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAkD;;IAMpE,QAAQ,CAAC,EAAE,EAAE,sBAAsB;IAInC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAInD,IAAI,IAAI,sBAAsB,EAAE;IAIhC,OAAO,CAAC,gBAAgB;CA2RzB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/benchmark/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAA0B,MAAM,SAAS,CAAC;AAOzE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAkD;;IAMpE,QAAQ,CAAC,EAAE,EAAE,sBAAsB;IAInC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAInD,IAAI,IAAI,sBAAsB,EAAE;IAIhC,OAAO,CAAC,gBAAgB;CAsRzB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.benchmarkRegistry = exports.BenchmarkRegistry = void 0;
4
4
  const prd_1 = require("../../services/prd");
5
- const tasks_1 = require("../../services/tasks"); // We'll need to instantiate this or use a singleton if available
5
+ const tasks_1 = require("../../services/tasks");
6
6
  const workflow_benchmark_1 = require("../../services/workflow-benchmark");
7
7
  class BenchmarkRegistry {
8
8
  operations = new Map();
@@ -59,17 +59,13 @@ class BenchmarkRegistry {
59
59
  },
60
60
  });
61
61
  // Task Breakdown Adapter
62
- // Note: TaskService is a class, we need an instance.
63
- // In a real app we should use dependency injection or a singleton.
64
- // For now, we'll create a new instance or assume one is available.
65
- const taskService = new tasks_1.TaskService();
66
62
  this.register({
67
63
  id: "task-breakdown",
68
64
  name: "Task Breakdown",
69
65
  description: "Break down a task into subtasks",
70
66
  validateInput: (input) => typeof input.taskId === "string",
71
67
  execute: async (input, aiOptions, streamingOptions) => {
72
- return await taskService.splitTask(input.taskId, aiOptions, input.prompt, input.message, streamingOptions, // streaming options
68
+ return await tasks_1.taskService.splitTask(input.taskId, aiOptions, input.prompt, input.message, streamingOptions, // streaming options
73
69
  input.tools);
74
70
  },
75
71
  });
@@ -90,7 +86,7 @@ class BenchmarkRegistry {
90
86
  description: "Create a new task with AI enhancement using Context7 documentation",
91
87
  validateInput: (input) => typeof input.title === "string" && input.title.length > 0,
92
88
  execute: async (input, aiOptions, streamingOptions) => {
93
- return await taskService.createTask({
89
+ return await tasks_1.taskService.createTask({
94
90
  title: input.title,
95
91
  content: input.content,
96
92
  parentId: input.parentId,
@@ -108,7 +104,7 @@ class BenchmarkRegistry {
108
104
  description: "Enhance an existing task with AI using Context7 documentation",
109
105
  validateInput: (input) => typeof input.taskId === "string",
110
106
  execute: async (input, aiOptions, streamingOptions) => {
111
- return await taskService.enhanceTask(input.taskId, aiOptions, streamingOptions);
107
+ return await tasks_1.taskService.enhanceTask(input.taskId, aiOptions, streamingOptions);
112
108
  },
113
109
  });
114
110
  // Task Planning
@@ -118,7 +114,7 @@ class BenchmarkRegistry {
118
114
  description: "Create a detailed implementation plan for a task",
119
115
  validateInput: (input) => typeof input.taskId === "string",
120
116
  execute: async (input, aiOptions, streamingOptions) => {
121
- return await taskService.planTask(input.taskId, aiOptions, streamingOptions);
117
+ return await tasks_1.taskService.planTask(input.taskId, aiOptions, streamingOptions);
122
118
  },
123
119
  });
124
120
  // Task Documentation
@@ -128,7 +124,7 @@ class BenchmarkRegistry {
128
124
  description: "Analyze and generate documentation for a task",
129
125
  validateInput: (input) => typeof input.taskId === "string",
130
126
  execute: async (input, aiOptions, streamingOptions) => {
131
- return await taskService.documentTask(input.taskId, input.force || false, aiOptions, streamingOptions);
127
+ return await tasks_1.taskService.documentTask(input.taskId, input.force || false, aiOptions, streamingOptions);
132
128
  },
133
129
  });
134
130
  // PRD Creation
@@ -0,0 +1,215 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Zod schema for AI Provider
4
+ */
5
+ export declare const AIProviderSchema: z.ZodEnum<["openai", "anthropic", "openrouter", "custom"]>;
6
+ /**
7
+ * Zod schema for AI Configuration
8
+ */
9
+ export declare const AIConfigSchema: z.ZodObject<{
10
+ provider: z.ZodEnum<["openai", "anthropic", "openrouter", "custom"]>;
11
+ model: z.ZodString;
12
+ apiKey: z.ZodOptional<z.ZodString>;
13
+ baseURL: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
14
+ maxTokens: z.ZodOptional<z.ZodNumber>;
15
+ temperature: z.ZodOptional<z.ZodNumber>;
16
+ context7Enabled: z.ZodOptional<z.ZodBoolean>;
17
+ reasoning: z.ZodOptional<z.ZodObject<{
18
+ maxTokens: z.ZodOptional<z.ZodNumber>;
19
+ }, "strip", z.ZodTypeAny, {
20
+ maxTokens?: number | undefined;
21
+ }, {
22
+ maxTokens?: number | undefined;
23
+ }>>;
24
+ }, "strip", z.ZodTypeAny, {
25
+ provider: "openai" | "anthropic" | "openrouter" | "custom";
26
+ model: string;
27
+ apiKey?: string | undefined;
28
+ baseURL?: string | undefined;
29
+ maxTokens?: number | undefined;
30
+ temperature?: number | undefined;
31
+ context7Enabled?: boolean | undefined;
32
+ reasoning?: {
33
+ maxTokens?: number | undefined;
34
+ } | undefined;
35
+ }, {
36
+ provider: "openai" | "anthropic" | "openrouter" | "custom";
37
+ model: string;
38
+ apiKey?: string | undefined;
39
+ baseURL?: string | undefined;
40
+ maxTokens?: number | undefined;
41
+ temperature?: number | undefined;
42
+ context7Enabled?: boolean | undefined;
43
+ reasoning?: {
44
+ maxTokens?: number | undefined;
45
+ } | undefined;
46
+ }>;
47
+ /**
48
+ * Zod schema for full Config object
49
+ */
50
+ export declare const ConfigSchema: z.ZodObject<{
51
+ ai: z.ZodObject<{
52
+ provider: z.ZodEnum<["openai", "anthropic", "openrouter", "custom"]>;
53
+ model: z.ZodString;
54
+ apiKey: z.ZodOptional<z.ZodString>;
55
+ baseURL: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
56
+ maxTokens: z.ZodOptional<z.ZodNumber>;
57
+ temperature: z.ZodOptional<z.ZodNumber>;
58
+ context7Enabled: z.ZodOptional<z.ZodBoolean>;
59
+ reasoning: z.ZodOptional<z.ZodObject<{
60
+ maxTokens: z.ZodOptional<z.ZodNumber>;
61
+ }, "strip", z.ZodTypeAny, {
62
+ maxTokens?: number | undefined;
63
+ }, {
64
+ maxTokens?: number | undefined;
65
+ }>>;
66
+ }, "strip", z.ZodTypeAny, {
67
+ provider: "openai" | "anthropic" | "openrouter" | "custom";
68
+ model: string;
69
+ apiKey?: string | undefined;
70
+ baseURL?: string | undefined;
71
+ maxTokens?: number | undefined;
72
+ temperature?: number | undefined;
73
+ context7Enabled?: boolean | undefined;
74
+ reasoning?: {
75
+ maxTokens?: number | undefined;
76
+ } | undefined;
77
+ }, {
78
+ provider: "openai" | "anthropic" | "openrouter" | "custom";
79
+ model: string;
80
+ apiKey?: string | undefined;
81
+ baseURL?: string | undefined;
82
+ maxTokens?: number | undefined;
83
+ temperature?: number | undefined;
84
+ context7Enabled?: boolean | undefined;
85
+ reasoning?: {
86
+ maxTokens?: number | undefined;
87
+ } | undefined;
88
+ }>;
89
+ workingDirectory: z.ZodOptional<z.ZodString>;
90
+ }, "strip", z.ZodTypeAny, {
91
+ ai: {
92
+ provider: "openai" | "anthropic" | "openrouter" | "custom";
93
+ model: string;
94
+ apiKey?: string | undefined;
95
+ baseURL?: string | undefined;
96
+ maxTokens?: number | undefined;
97
+ temperature?: number | undefined;
98
+ context7Enabled?: boolean | undefined;
99
+ reasoning?: {
100
+ maxTokens?: number | undefined;
101
+ } | undefined;
102
+ };
103
+ workingDirectory?: string | undefined;
104
+ }, {
105
+ ai: {
106
+ provider: "openai" | "anthropic" | "openrouter" | "custom";
107
+ model: string;
108
+ apiKey?: string | undefined;
109
+ baseURL?: string | undefined;
110
+ maxTokens?: number | undefined;
111
+ temperature?: number | undefined;
112
+ context7Enabled?: boolean | undefined;
113
+ reasoning?: {
114
+ maxTokens?: number | undefined;
115
+ } | undefined;
116
+ };
117
+ workingDirectory?: string | undefined;
118
+ }>;
119
+ /**
120
+ * Validation result type
121
+ */
122
+ export interface ValidationResult<T> {
123
+ success: boolean;
124
+ data?: T;
125
+ errors?: Array<{
126
+ path: string;
127
+ message: string;
128
+ }>;
129
+ }
130
+ /**
131
+ * Validate AI configuration
132
+ *
133
+ * @param config - AI configuration to validate
134
+ * @returns Validated and typed configuration
135
+ * @throws {TaskOMaticError} If validation fails
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * const aiConfig = {
140
+ * provider: "openai",
141
+ * model: "gpt-4",
142
+ * temperature: 0.7,
143
+ * maxTokens: 4000
144
+ * };
145
+ *
146
+ * const validated = validateAIConfig(aiConfig);
147
+ * // validated is now type-safe and guaranteed valid
148
+ * ```
149
+ */
150
+ export declare function validateAIConfig(config: unknown): z.infer<typeof AIConfigSchema>;
151
+ /**
152
+ * Validate full configuration object
153
+ *
154
+ * @param config - Configuration object to validate
155
+ * @returns Validated and typed configuration
156
+ * @throws {TaskOMaticError} If validation fails
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * const config = {
161
+ * ai: {
162
+ * provider: "anthropic",
163
+ * model: "claude-sonnet-4.5",
164
+ * temperature: 0.5
165
+ * },
166
+ * workingDirectory: "/path/to/project"
167
+ * };
168
+ *
169
+ * const validated = validateConfig(config);
170
+ * ```
171
+ */
172
+ export declare function validateConfig(config: unknown): z.infer<typeof ConfigSchema>;
173
+ /**
174
+ * Safe validation that returns a result object instead of throwing
175
+ *
176
+ * @param config - Configuration to validate
177
+ * @returns Validation result with success flag and data or errors
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const result = safeValidateConfig(userInput);
182
+ * if (result.success) {
183
+ * console.log("Valid config:", result.data);
184
+ * } else {
185
+ * console.error("Validation errors:", result.errors);
186
+ * }
187
+ * ```
188
+ */
189
+ export declare function safeValidateConfig(config: unknown): ValidationResult<z.infer<typeof ConfigSchema>>;
190
+ /**
191
+ * Safe AI config validation
192
+ *
193
+ * @param config - AI configuration to validate
194
+ * @returns Validation result with success flag and data or errors
195
+ */
196
+ export declare function safeValidateAIConfig(config: unknown): ValidationResult<z.infer<typeof AIConfigSchema>>;
197
+ /**
198
+ * Validate partial AI config (for updates)
199
+ *
200
+ * @param config - Partial AI configuration to validate
201
+ * @returns Validated partial configuration
202
+ * @throws {TaskOMaticError} If validation fails
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * // Only validating fields that are present
207
+ * const updates = {
208
+ * temperature: 0.8
209
+ * };
210
+ *
211
+ * const validated = validatePartialAIConfig(updates);
212
+ * ```
213
+ */
214
+ export declare function validatePartialAIConfig(config: unknown): Partial<z.infer<typeof AIConfigSchema>>;
215
+ //# sourceMappingURL=config-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-validation.d.ts","sourceRoot":"","sources":["../../src/lib/config-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;GAEG;AACH,eAAO,MAAM,gBAAgB,4DAI3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGvB,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CA0BhF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAuB5E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC,CAiBlG;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC,CAiBtG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC,CAsBzC"}