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.
- 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 +19 -4
- 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 +2 -1
- package/dist/commands/tasks/document/get.d.ts.map +1 -1
- package/dist/commands/tasks/document/get.js +2 -1
- 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 +2 -1
- package/dist/commands/tasks/update.d.ts.map +1 -1
- package/dist/commands/tasks/update.js +7 -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 +1 -0
- 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/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.map +1 -1
- package/dist/lib/config.js +19 -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 +49 -15
- package/dist/services/tasks.d.ts +315 -1
- package/dist/services/tasks.d.ts.map +1 -1
- package/dist/services/tasks.js +483 -107
- 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/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 +3 -3
- package/dist/utils/error-utils.d.ts.map +1 -1
- package/dist/utils/error-utils.js +5 -4
- package/dist/utils/file-utils.d.ts +4 -4
- package/dist/utils/file-utils.d.ts.map +1 -1
- package/dist/utils/file-utils.js +11 -6
- package/dist/utils/id-generator.d.ts +1 -1
- package/dist/utils/id-generator.d.ts.map +1 -1
- package/dist/utils/id-generator.js +8 -2
- 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/storage-utils.d.ts +3 -3
- package/dist/utils/storage-utils.d.ts.map +1 -1
- package/dist/utils/storage-utils.js +7 -6
- 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/package.json +2 -2
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AIOperationUtility = void 0;
|
|
4
|
+
const ai_1 = require("ai");
|
|
5
|
+
const base_operations_1 = require("../lib/ai-service/base-operations");
|
|
6
|
+
const task_o_matic_error_1 = require("./task-o-matic-error");
|
|
7
|
+
/**
|
|
8
|
+
* AIOperationUtility - Centralized utility for AI operations with metrics and error handling
|
|
9
|
+
*
|
|
10
|
+
* Extends BaseOperations to inherit core AI functionality (streamText, model provider, etc.)
|
|
11
|
+
* and adds standardized metrics collection, error handling, and retry logic.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const utility = new AIOperationUtility();
|
|
16
|
+
*
|
|
17
|
+
* // Execute operation with metrics
|
|
18
|
+
* const result = await utility.executeAIOperation(
|
|
19
|
+
* "Task breakdown",
|
|
20
|
+
* async () => performBreakdown(task),
|
|
21
|
+
* {
|
|
22
|
+
* maxRetries: 3,
|
|
23
|
+
* streamingOptions: { onChunk: console.log }
|
|
24
|
+
* }
|
|
25
|
+
* );
|
|
26
|
+
*
|
|
27
|
+
* console.log(result.metrics.duration);
|
|
28
|
+
* console.log(result.metrics.timeToFirstToken);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
class AIOperationUtility extends base_operations_1.BaseOperations {
|
|
32
|
+
/**
|
|
33
|
+
* Execute an AI operation with standardized metrics, error handling, and streaming support
|
|
34
|
+
*
|
|
35
|
+
* This method wraps AI operations to provide:
|
|
36
|
+
* - Automatic retry logic with configurable attempts
|
|
37
|
+
* - Metrics collection (duration, token usage, time to first token)
|
|
38
|
+
* - Error handling with TaskOMaticError wrapping
|
|
39
|
+
* - Streaming support with metrics capture
|
|
40
|
+
*
|
|
41
|
+
* @param operationName - Human-readable name for the operation (used in errors)
|
|
42
|
+
* @param operation - The async operation to execute
|
|
43
|
+
* @param options - Configuration options for retry, streaming, and AI config
|
|
44
|
+
* @returns Promise resolving to AIOperationResult with result and metrics
|
|
45
|
+
* @throws {TaskOMaticError} If operation fails after all retry attempts
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* try {
|
|
50
|
+
* const result = await utility.executeAIOperation(
|
|
51
|
+
* "Task enhancement",
|
|
52
|
+
* async () => enhanceTask(task),
|
|
53
|
+
* { maxRetries: 2 }
|
|
54
|
+
* );
|
|
55
|
+
* console.log(`Operation took ${result.metrics.duration}ms`);
|
|
56
|
+
* } catch (error) {
|
|
57
|
+
* if (error instanceof TaskOMaticError) {
|
|
58
|
+
* console.error(error.getDetails());
|
|
59
|
+
* }
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
async executeAIOperation(operationName, operation, options = {}) {
|
|
64
|
+
const startTime = Date.now();
|
|
65
|
+
let timeToFirstToken;
|
|
66
|
+
// Create wrapped streaming options to capture metrics
|
|
67
|
+
const wrappedStreamingOptions = this.wrapStreamingOptions(options.streamingOptions, startTime, (time) => {
|
|
68
|
+
timeToFirstToken = time;
|
|
69
|
+
});
|
|
70
|
+
try {
|
|
71
|
+
// Execute with retry logic
|
|
72
|
+
const result = await this.retryHandler.executeWithRetry(async () => {
|
|
73
|
+
// Execute operation - note: operations should use the streaming options
|
|
74
|
+
// passed through the closure, not directly from options
|
|
75
|
+
return await operation();
|
|
76
|
+
}, {
|
|
77
|
+
maxAttempts: options.maxRetries || options.retryConfig?.maxAttempts || 2,
|
|
78
|
+
...options.retryConfig,
|
|
79
|
+
}, operationName);
|
|
80
|
+
const duration = Date.now() - startTime;
|
|
81
|
+
return {
|
|
82
|
+
result,
|
|
83
|
+
metrics: {
|
|
84
|
+
duration,
|
|
85
|
+
timeToFirstToken,
|
|
86
|
+
tokenUsage: this.extractTokenUsageFromResult(result),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
const duration = Date.now() - startTime;
|
|
92
|
+
const typedError = error instanceof Error ? error : new Error(String(error));
|
|
93
|
+
// THROW error instead of returning it
|
|
94
|
+
throw new task_o_matic_error_1.TaskOMaticError(`AI operation failed: ${operationName}`, {
|
|
95
|
+
code: "AI_OPERATION_FAILED",
|
|
96
|
+
context: JSON.stringify({
|
|
97
|
+
operation: operationName,
|
|
98
|
+
duration,
|
|
99
|
+
error: this.getErrorMessage(typedError),
|
|
100
|
+
}),
|
|
101
|
+
cause: typedError,
|
|
102
|
+
suggestions: [
|
|
103
|
+
"Check AI configuration",
|
|
104
|
+
"Verify network connectivity",
|
|
105
|
+
"Review operation parameters",
|
|
106
|
+
"Check API keys and endpoints",
|
|
107
|
+
],
|
|
108
|
+
metadata: {
|
|
109
|
+
operationName,
|
|
110
|
+
duration,
|
|
111
|
+
attemptedRetries: options.maxRetries || 2,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Standardized streaming text operation with tool support
|
|
118
|
+
*
|
|
119
|
+
* This method provides a unified interface for AI text generation with:
|
|
120
|
+
* - Optional tool integration (filesystem, MCP, etc.)
|
|
121
|
+
* - Streaming support with callbacks
|
|
122
|
+
* - Context7 documentation caching
|
|
123
|
+
* - Metrics collection
|
|
124
|
+
* - Error handling
|
|
125
|
+
*
|
|
126
|
+
* @param systemPrompt - System prompt for the AI
|
|
127
|
+
* @param userMessage - User message/prompt
|
|
128
|
+
* @param config - Optional AI configuration overrides
|
|
129
|
+
* @param streamingOptions - Optional streaming callbacks
|
|
130
|
+
* @param tools - Optional tool set to provide to the AI
|
|
131
|
+
* @returns Promise resolving to the generated text
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const result = await utility.streamTextWithTools(
|
|
136
|
+
* "You are a helpful assistant",
|
|
137
|
+
* "Explain quantum computing",
|
|
138
|
+
* undefined,
|
|
139
|
+
* { onChunk: (chunk) => console.log(chunk) },
|
|
140
|
+
* filesystemTools
|
|
141
|
+
* );
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
async streamTextWithTools(systemPrompt, userMessage, config, streamingOptions, tools) {
|
|
145
|
+
const aiConfig = this.mergeAIConfig(config);
|
|
146
|
+
const model = this.modelProvider.getModel(aiConfig);
|
|
147
|
+
// Create streaming configuration with Context7 handling and callbacks
|
|
148
|
+
const streamConfig = this.createStreamingConfig(streamingOptions);
|
|
149
|
+
const result = await (0, ai_1.streamText)({
|
|
150
|
+
model,
|
|
151
|
+
tools: tools || {},
|
|
152
|
+
system: systemPrompt,
|
|
153
|
+
messages: [{ role: "user", content: userMessage }],
|
|
154
|
+
maxRetries: 0,
|
|
155
|
+
...streamConfig,
|
|
156
|
+
...(aiConfig.provider === "openrouter" &&
|
|
157
|
+
aiConfig.reasoning &&
|
|
158
|
+
aiConfig.reasoning.maxTokens
|
|
159
|
+
? {
|
|
160
|
+
providerOptions: {
|
|
161
|
+
openrouter: {
|
|
162
|
+
reasoning: {
|
|
163
|
+
max_tokens: aiConfig.reasoning.maxTokens,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
: {}),
|
|
169
|
+
});
|
|
170
|
+
return await result.text;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Wrap streaming options to capture metrics
|
|
174
|
+
*
|
|
175
|
+
* @private
|
|
176
|
+
*/
|
|
177
|
+
wrapStreamingOptions(streamingOptions, startTime, onFirstToken) {
|
|
178
|
+
if (!streamingOptions) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
let firstTokenCaptured = false;
|
|
182
|
+
return {
|
|
183
|
+
...streamingOptions,
|
|
184
|
+
onChunk: (chunk) => {
|
|
185
|
+
if (!firstTokenCaptured && chunk.trim()) {
|
|
186
|
+
onFirstToken(Date.now() - startTime);
|
|
187
|
+
firstTokenCaptured = true;
|
|
188
|
+
}
|
|
189
|
+
streamingOptions.onChunk?.(chunk);
|
|
190
|
+
},
|
|
191
|
+
onFinish: (result) => {
|
|
192
|
+
streamingOptions.onFinish?.(result);
|
|
193
|
+
},
|
|
194
|
+
onReasoning: (reasoning) => {
|
|
195
|
+
streamingOptions.onReasoning?.(reasoning);
|
|
196
|
+
},
|
|
197
|
+
onError: (error) => {
|
|
198
|
+
streamingOptions.onError?.(error);
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Create streaming configuration with Context7 handling and callbacks
|
|
204
|
+
*
|
|
205
|
+
* This method creates a unified streaming configuration that:
|
|
206
|
+
* - Always handles Context7 tool-result events (even without streaming UI)
|
|
207
|
+
* - Forwards text-delta events to onChunk callback
|
|
208
|
+
* - Forwards reasoning-delta events to onReasoning callback
|
|
209
|
+
* - Handles errors with onError callback
|
|
210
|
+
* - Provides onFinish callback with completion data
|
|
211
|
+
*
|
|
212
|
+
* @private
|
|
213
|
+
*/
|
|
214
|
+
createStreamingConfig(streamingOptions) {
|
|
215
|
+
return {
|
|
216
|
+
onChunk: streamingOptions?.onChunk || streamingOptions?.onReasoning
|
|
217
|
+
? (event) => {
|
|
218
|
+
// Handle Context7 tool results ALWAYS (critical for caching)
|
|
219
|
+
if (event.chunk?.type === "tool-result" &&
|
|
220
|
+
event.chunk?.toolName === "get-library-docs") {
|
|
221
|
+
const docs = event.chunk.output;
|
|
222
|
+
if (docs && typeof docs === "object" && "content" in docs) {
|
|
223
|
+
this.context7Client.saveContext7Documentation(event.chunk.input?.context7CompatibleLibraryID || "unknown", docs.content, event.chunk.input?.topic || "general");
|
|
224
|
+
}
|
|
225
|
+
else if (docs && typeof docs === "string") {
|
|
226
|
+
this.context7Client.saveContext7Documentation(event.chunk.input?.context7CompatibleLibraryID || "unknown", docs, event.chunk.input?.topic || "general");
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Forward text deltas to user callback
|
|
230
|
+
if (event.chunk?.type === "text-delta") {
|
|
231
|
+
streamingOptions?.onChunk?.(event.chunk.text);
|
|
232
|
+
}
|
|
233
|
+
// Forward reasoning deltas to user callback
|
|
234
|
+
if (event.chunk?.type === "reasoning-delta") {
|
|
235
|
+
streamingOptions?.onReasoning?.(event.chunk.text);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
: undefined,
|
|
239
|
+
onFinish: streamingOptions?.onFinish
|
|
240
|
+
? (event) => {
|
|
241
|
+
streamingOptions.onFinish({
|
|
242
|
+
text: event.text,
|
|
243
|
+
finishReason: event.finishReason,
|
|
244
|
+
usage: event.usage,
|
|
245
|
+
isAborted: false,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
: undefined,
|
|
249
|
+
onError: streamingOptions?.onError
|
|
250
|
+
? (event) => {
|
|
251
|
+
streamingOptions.onError(event.error);
|
|
252
|
+
}
|
|
253
|
+
: undefined,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Extract token usage from AI result
|
|
258
|
+
*
|
|
259
|
+
* @private
|
|
260
|
+
*/
|
|
261
|
+
extractTokenUsageFromResult(result) {
|
|
262
|
+
if (result && result.usage) {
|
|
263
|
+
return {
|
|
264
|
+
prompt: result.usage.prompt_tokens || 0,
|
|
265
|
+
completion: result.usage.completion_tokens || 0,
|
|
266
|
+
total: result.usage.total_tokens || 0,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Get error message from any error type
|
|
273
|
+
*
|
|
274
|
+
* @private
|
|
275
|
+
*/
|
|
276
|
+
getErrorMessage(error) {
|
|
277
|
+
if (error instanceof Error) {
|
|
278
|
+
return error.message;
|
|
279
|
+
}
|
|
280
|
+
else if (typeof error === "string") {
|
|
281
|
+
return error;
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
return "Unknown error";
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
exports.AIOperationUtility = AIOperationUtility;
|
|
@@ -21,4 +21,14 @@ export declare function getModelProvider(): ModelProvider;
|
|
|
21
21
|
export declare function getStorage(): TaskRepository;
|
|
22
22
|
export declare function getContextBuilder(): ContextBuilder;
|
|
23
23
|
export declare function resetServiceInstances(): void;
|
|
24
|
+
/**
|
|
25
|
+
* FOR TESTING ONLY: Inject mock instances
|
|
26
|
+
* This allows tests to provide mock implementations without complex module mocking
|
|
27
|
+
*/
|
|
28
|
+
export declare function injectTestInstances(instances: {
|
|
29
|
+
storage?: TaskRepository;
|
|
30
|
+
aiOperations?: AIOperations;
|
|
31
|
+
modelProvider?: ModelProvider;
|
|
32
|
+
contextBuilder?: ContextBuilder;
|
|
33
|
+
}): void;
|
|
24
34
|
//# sourceMappingURL=ai-service-factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-service-factory.d.ts","sourceRoot":"","sources":["../../src/utils/ai-service-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,EAAiB,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"ai-service-factory.d.ts","sourceRoot":"","sources":["../../src/utils/ai-service-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,EAAiB,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAMpE,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAOD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED,wBAAgB,UAAU,IAAI,cAAc,CAsB3C;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAMlD;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE;IAC7C,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,GAAG,IAAI,CAKP"}
|
|
@@ -6,12 +6,14 @@ exports.getModelProvider = getModelProvider;
|
|
|
6
6
|
exports.getStorage = getStorage;
|
|
7
7
|
exports.getContextBuilder = getContextBuilder;
|
|
8
8
|
exports.resetServiceInstances = resetServiceInstances;
|
|
9
|
+
exports.injectTestInstances = injectTestInstances;
|
|
9
10
|
const file_system_1 = require("../lib/storage/file-system");
|
|
10
11
|
const context_builder_1 = require("../lib/context-builder");
|
|
11
12
|
const fs_1 = require("fs");
|
|
12
13
|
const config_1 = require("../lib/config");
|
|
13
14
|
const ai_operations_1 = require("../lib/ai-service/ai-operations");
|
|
14
15
|
const model_provider_1 = require("../lib/ai-service/model-provider");
|
|
16
|
+
const task_o_matic_error_1 = require("./task-o-matic-error");
|
|
15
17
|
let aiOperations = null;
|
|
16
18
|
let modelProvider = null;
|
|
17
19
|
let storage = null;
|
|
@@ -60,7 +62,9 @@ function getStorage() {
|
|
|
60
62
|
const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
|
|
61
63
|
// Note: This check relies on FS. Web apps should call initializeServices first.
|
|
62
64
|
if (!(0, fs_1.existsSync)(taskOMaticDir)) {
|
|
63
|
-
throw
|
|
65
|
+
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' first.", {
|
|
66
|
+
suggestions: ["Run `task-o-matic init` in your project root."],
|
|
67
|
+
});
|
|
64
68
|
}
|
|
65
69
|
storage = new file_system_1.FileSystemStorage();
|
|
66
70
|
}
|
|
@@ -79,3 +83,17 @@ function resetServiceInstances() {
|
|
|
79
83
|
storage = null;
|
|
80
84
|
contextBuilder = null;
|
|
81
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* FOR TESTING ONLY: Inject mock instances
|
|
88
|
+
* This allows tests to provide mock implementations without complex module mocking
|
|
89
|
+
*/
|
|
90
|
+
function injectTestInstances(instances) {
|
|
91
|
+
if (instances.storage)
|
|
92
|
+
storage = instances.storage;
|
|
93
|
+
if (instances.aiOperations)
|
|
94
|
+
aiOperations = instances.aiOperations;
|
|
95
|
+
if (instances.modelProvider)
|
|
96
|
+
modelProvider = instances.modelProvider;
|
|
97
|
+
if (instances.contextBuilder)
|
|
98
|
+
contextBuilder = instances.contextBuilder;
|
|
99
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param field2 - Second field name in options
|
|
7
7
|
* @param field1Label - Display label for first field (defaults to field1)
|
|
8
8
|
* @param field2Label - Display label for second field (defaults to field2)
|
|
9
|
-
* @throws
|
|
9
|
+
* @throws TaskOMaticError if neither or both fields are provided
|
|
10
10
|
*
|
|
11
11
|
* @example
|
|
12
12
|
* ```typescript
|
|
@@ -26,7 +26,7 @@ export interface FieldSpec {
|
|
|
26
26
|
*
|
|
27
27
|
* @param options - The command options object
|
|
28
28
|
* @param fields - Array of field specifications
|
|
29
|
-
* @throws
|
|
29
|
+
* @throws TaskOMaticError if none or multiple fields are provided
|
|
30
30
|
*
|
|
31
31
|
* @example
|
|
32
32
|
* ```typescript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-validators.d.ts","sourceRoot":"","sources":["../../src/utils/cli-validators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli-validators.d.ts","sourceRoot":"","sources":["../../src/utils/cli-validators.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,WAAW,GAAE,MAAe,EAC5B,WAAW,GAAE,MAAe,GAC3B,IAAI,CAgBN;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,GAAG,EACZ,GAAG,MAAM,EAAE,SAAS,EAAE,GACrB,IAAI,CAiBN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKtD"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.validateMutuallyExclusive = validateMutuallyExclusive;
|
|
4
4
|
exports.validateOneRequired = validateOneRequired;
|
|
5
5
|
exports.parseCsvOption = parseCsvOption;
|
|
6
|
+
const task_o_matic_error_1 = require("./task-o-matic-error");
|
|
6
7
|
/**
|
|
7
8
|
* Validate that exactly one of two mutually exclusive options is provided
|
|
8
9
|
*
|
|
@@ -11,7 +12,7 @@ exports.parseCsvOption = parseCsvOption;
|
|
|
11
12
|
* @param field2 - Second field name in options
|
|
12
13
|
* @param field1Label - Display label for first field (defaults to field1)
|
|
13
14
|
* @param field2Label - Display label for second field (defaults to field2)
|
|
14
|
-
* @throws
|
|
15
|
+
* @throws TaskOMaticError if neither or both fields are provided
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
* ```typescript
|
|
@@ -22,10 +23,10 @@ function validateMutuallyExclusive(options, field1, field2, field1Label = field1
|
|
|
22
23
|
const has1 = Boolean(options[field1]);
|
|
23
24
|
const has2 = Boolean(options[field2]);
|
|
24
25
|
if (!has1 && !has2) {
|
|
25
|
-
throw
|
|
26
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, `Either --${field1Label} or --${field2Label} must be specified`);
|
|
26
27
|
}
|
|
27
28
|
if (has1 && has2) {
|
|
28
|
-
throw
|
|
29
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, `Cannot specify both --${field1Label} and --${field2Label}`);
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
@@ -33,7 +34,7 @@ function validateMutuallyExclusive(options, field1, field2, field1Label = field1
|
|
|
33
34
|
*
|
|
34
35
|
* @param options - The command options object
|
|
35
36
|
* @param fields - Array of field specifications
|
|
36
|
-
* @throws
|
|
37
|
+
* @throws TaskOMaticError if none or multiple fields are provided
|
|
37
38
|
*
|
|
38
39
|
* @example
|
|
39
40
|
* ```typescript
|
|
@@ -48,11 +49,11 @@ function validateOneRequired(options, ...fields) {
|
|
|
48
49
|
const provided = fields.filter((f) => Boolean(options[f.name]));
|
|
49
50
|
if (provided.length === 0) {
|
|
50
51
|
const labels = fields.map((f) => `--${f.label}`).join(", ");
|
|
51
|
-
throw
|
|
52
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, `One of ${labels} must be specified`);
|
|
52
53
|
}
|
|
53
54
|
if (provided.length > 1) {
|
|
54
55
|
const labels = provided.map((f) => `--${f.label}`).join(", ");
|
|
55
|
-
throw
|
|
56
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, `Cannot specify multiple options: ${labels}`);
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
@@ -39,7 +39,7 @@ export declare function formatError(error: unknown, context?: string): string;
|
|
|
39
39
|
*
|
|
40
40
|
* @param error - The original error
|
|
41
41
|
* @param context - Context to add to the error
|
|
42
|
-
* @returns A new
|
|
42
|
+
* @returns A new TaskOMaticError instance with formatted message
|
|
43
43
|
*
|
|
44
44
|
* @example
|
|
45
45
|
* ```typescript
|
|
@@ -50,7 +50,7 @@ export declare function formatError(error: unknown, context?: string): string;
|
|
|
50
50
|
* }
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
|
-
export declare function createContextError(error: unknown, context: string):
|
|
53
|
+
export declare function createContextError(error: unknown, context: string): import("./task-o-matic-error").TaskOMaticError;
|
|
54
54
|
/**
|
|
55
55
|
* Type guard to check if an error is an Error instance.
|
|
56
56
|
*
|
|
@@ -66,5 +66,5 @@ export declare function isError(error: unknown): error is Error;
|
|
|
66
66
|
* @param error - Value to convert
|
|
67
67
|
* @returns An Error instance
|
|
68
68
|
*/
|
|
69
|
-
export declare function toError(error: unknown):
|
|
69
|
+
export declare function toError(error: unknown): import("./task-o-matic-error").TaskOMaticError;
|
|
70
70
|
//# sourceMappingURL=error-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-utils.d.ts","sourceRoot":"","sources":["../../src/utils/error-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error-utils.d.ts","sourceRoot":"","sources":["../../src/utils/error-utils.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAkBtD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,GACd,OAAO,sBAAsB,EAAE,eAAe,CAMhD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAEtD;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CACrB,KAAK,EAAE,OAAO,GACb,OAAO,sBAAsB,EAAE,eAAe,CAYhD"}
|
|
@@ -5,6 +5,7 @@ exports.formatError = formatError;
|
|
|
5
5
|
exports.createContextError = createContextError;
|
|
6
6
|
exports.isError = isError;
|
|
7
7
|
exports.toError = toError;
|
|
8
|
+
const task_o_matic_error_1 = require("./task-o-matic-error");
|
|
8
9
|
/**
|
|
9
10
|
* Extracts a readable error message from an unknown error value.
|
|
10
11
|
* Handles Error objects, strings, objects with message property, and unknown types.
|
|
@@ -64,7 +65,7 @@ function formatError(error, context) {
|
|
|
64
65
|
*
|
|
65
66
|
* @param error - The original error
|
|
66
67
|
* @param context - Context to add to the error
|
|
67
|
-
* @returns A new
|
|
68
|
+
* @returns A new TaskOMaticError instance with formatted message
|
|
68
69
|
*
|
|
69
70
|
* @example
|
|
70
71
|
* ```typescript
|
|
@@ -76,7 +77,7 @@ function formatError(error, context) {
|
|
|
76
77
|
* ```
|
|
77
78
|
*/
|
|
78
79
|
function createContextError(error, context) {
|
|
79
|
-
return
|
|
80
|
+
return (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.UNEXPECTED_ERROR, formatError(error, context), { cause: error instanceof Error ? error : undefined });
|
|
80
81
|
}
|
|
81
82
|
/**
|
|
82
83
|
* Type guard to check if an error is an Error instance.
|
|
@@ -97,7 +98,7 @@ function isError(error) {
|
|
|
97
98
|
*/
|
|
98
99
|
function toError(error) {
|
|
99
100
|
if (error instanceof Error) {
|
|
100
|
-
return error;
|
|
101
|
+
return (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.UNEXPECTED_ERROR, error.message, { cause: error });
|
|
101
102
|
}
|
|
102
|
-
return
|
|
103
|
+
return (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.UNEXPECTED_ERROR, getErrorMessage(error));
|
|
103
104
|
}
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @param filePath - Path to the file to validate
|
|
6
6
|
* @param customMessage - Optional custom error message
|
|
7
|
-
* @throws
|
|
7
|
+
* @throws TaskOMaticError if file doesn't exist
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```typescript
|
|
11
11
|
* validateFileExists("./config.json", "Configuration file not found");
|
|
12
|
-
* // Throws:
|
|
12
|
+
* // Throws: TaskOMaticError with code INVALID_INPUT if file doesn't exist
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
15
|
export declare function validateFileExists(filePath: string, customMessage?: string): void;
|
|
@@ -19,12 +19,12 @@ export declare function validateFileExists(filePath: string, customMessage?: str
|
|
|
19
19
|
*
|
|
20
20
|
* @param filePath - Path to the file to validate
|
|
21
21
|
* @param customMessage - Optional custom error message
|
|
22
|
-
* @throws
|
|
22
|
+
* @throws TaskOMaticError if file doesn't exist
|
|
23
23
|
*
|
|
24
24
|
* @example
|
|
25
25
|
* ```typescript
|
|
26
26
|
* await validateFileExistsAsync("./data.json");
|
|
27
|
-
* // Throws:
|
|
27
|
+
* // Throws: TaskOMaticError with code INVALID_INPUT if file doesn't exist
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
30
|
export declare function validateFileExistsAsync(filePath: string, customMessage?: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI,CAUN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxE"}
|
package/dist/utils/file-utils.js
CHANGED
|
@@ -6,23 +6,26 @@ exports.fileExists = fileExists;
|
|
|
6
6
|
exports.fileExistsAsync = fileExistsAsync;
|
|
7
7
|
const fs_1 = require("fs");
|
|
8
8
|
const promises_1 = require("fs/promises");
|
|
9
|
+
const task_o_matic_error_1 = require("./task-o-matic-error");
|
|
9
10
|
/**
|
|
10
11
|
* Validates that a file exists at the given path (synchronous).
|
|
11
12
|
* Throws an error with a custom message if the file doesn't exist.
|
|
12
13
|
*
|
|
13
14
|
* @param filePath - Path to the file to validate
|
|
14
15
|
* @param customMessage - Optional custom error message
|
|
15
|
-
* @throws
|
|
16
|
+
* @throws TaskOMaticError if file doesn't exist
|
|
16
17
|
*
|
|
17
18
|
* @example
|
|
18
19
|
* ```typescript
|
|
19
20
|
* validateFileExists("./config.json", "Configuration file not found");
|
|
20
|
-
* // Throws:
|
|
21
|
+
* // Throws: TaskOMaticError with code INVALID_INPUT if file doesn't exist
|
|
21
22
|
* ```
|
|
22
23
|
*/
|
|
23
24
|
function validateFileExists(filePath, customMessage) {
|
|
24
25
|
if (!(0, fs_1.existsSync)(filePath)) {
|
|
25
|
-
throw
|
|
26
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, customMessage || `File not found: ${filePath}`, {
|
|
27
|
+
suggestions: ["Verify the file path is correct."],
|
|
28
|
+
});
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
/**
|
|
@@ -31,12 +34,12 @@ function validateFileExists(filePath, customMessage) {
|
|
|
31
34
|
*
|
|
32
35
|
* @param filePath - Path to the file to validate
|
|
33
36
|
* @param customMessage - Optional custom error message
|
|
34
|
-
* @throws
|
|
37
|
+
* @throws TaskOMaticError if file doesn't exist
|
|
35
38
|
*
|
|
36
39
|
* @example
|
|
37
40
|
* ```typescript
|
|
38
41
|
* await validateFileExistsAsync("./data.json");
|
|
39
|
-
* // Throws:
|
|
42
|
+
* // Throws: TaskOMaticError with code INVALID_INPUT if file doesn't exist
|
|
40
43
|
* ```
|
|
41
44
|
*/
|
|
42
45
|
async function validateFileExistsAsync(filePath, customMessage) {
|
|
@@ -44,7 +47,9 @@ async function validateFileExistsAsync(filePath, customMessage) {
|
|
|
44
47
|
await (0, promises_1.access)(filePath, promises_1.constants.F_OK);
|
|
45
48
|
}
|
|
46
49
|
catch {
|
|
47
|
-
throw
|
|
50
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, customMessage || `File not found: ${filePath}`, {
|
|
51
|
+
suggestions: ["Verify the file path is correct."],
|
|
52
|
+
});
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
/**
|
|
@@ -54,7 +54,7 @@ export declare class TaskIDGenerator {
|
|
|
54
54
|
* @param prefix - Prefix for the ID
|
|
55
55
|
* @param maxAttempts - Maximum number of generation attempts
|
|
56
56
|
* @returns Unique task ID
|
|
57
|
-
* @throws
|
|
57
|
+
* @throws TaskOMaticError if unable to generate unique ID after maxAttempts
|
|
58
58
|
*/
|
|
59
59
|
static generateUnique(existingIds: Set<string>, prefix?: string, maxAttempts?: number): string;
|
|
60
60
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-generator.d.ts","sourceRoot":"","sources":["../../src/utils/id-generator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"id-generator.d.ts","sourceRoot":"","sources":["../../src/utils/id-generator.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,qBAAa,eAAe;IAC1B;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAE,MAAe,GAAG,MAAM;IAMhD;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IA0BpC;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO;IAI9D;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAc,CACnB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,MAAM,GAAE,MAAe,EACvB,WAAW,GAAE,MAAW,GACvB,MAAM;IAoBT;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAIpE;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,mBAAmB,CACxB,EAAE,EAAE,MAAM,GACT;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAcnD"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TaskIDGenerator = void 0;
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
|
+
const task_o_matic_error_1 = require("./task-o-matic-error");
|
|
5
6
|
/**
|
|
6
7
|
* Generates unique task IDs with consistent format.
|
|
7
8
|
* Uses timestamp + random hex for uniqueness.
|
|
@@ -84,7 +85,7 @@ class TaskIDGenerator {
|
|
|
84
85
|
* @param prefix - Prefix for the ID
|
|
85
86
|
* @param maxAttempts - Maximum number of generation attempts
|
|
86
87
|
* @returns Unique task ID
|
|
87
|
-
* @throws
|
|
88
|
+
* @throws TaskOMaticError if unable to generate unique ID after maxAttempts
|
|
88
89
|
*/
|
|
89
90
|
static generateUnique(existingIds, prefix = "task", maxAttempts = 10) {
|
|
90
91
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
@@ -93,7 +94,12 @@ class TaskIDGenerator {
|
|
|
93
94
|
return id;
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
|
-
throw
|
|
97
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.UNEXPECTED_ERROR, `Failed to generate unique ID after ${maxAttempts} attempts`, {
|
|
98
|
+
context: `Could not find a unique ID with prefix '${prefix}' after ${maxAttempts} attempts.`,
|
|
99
|
+
suggestions: [
|
|
100
|
+
"Increase maxAttempts if you have a very large number of tasks.",
|
|
101
|
+
],
|
|
102
|
+
});
|
|
97
103
|
}
|
|
98
104
|
/**
|
|
99
105
|
* Generates a hierarchical child ID from a parent ID.
|
|
@@ -12,7 +12,7 @@ export declare const VALID_EXECUTORS: ExecutorTool[];
|
|
|
12
12
|
*
|
|
13
13
|
* @param value - Comma-separated model/executor specifications
|
|
14
14
|
* @returns Array of model attempt configurations
|
|
15
|
-
* @throws
|
|
15
|
+
* @throws TaskOMaticError if an invalid executor is specified
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```typescript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-executor-parser.d.ts","sourceRoot":"","sources":["../../src/utils/model-executor-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"model-executor-parser.d.ts","sourceRoot":"","sources":["../../src/utils/model-executor-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAM5D;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,YAAY,EAKzC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAAE,CA4BlE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,IAAI,YAAY,CAE3E"}
|