task-o-matic 0.0.2 → 0.0.4
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/README.md +96 -40
- package/dist/commands/prd.js +4 -0
- package/dist/commands/prompt.d.ts.map +1 -1
- package/dist/commands/prompt.js +69 -61
- package/dist/commands/tasks/create.d.ts +3 -0
- package/dist/commands/tasks/create.d.ts.map +1 -0
- package/dist/commands/tasks/create.js +58 -0
- package/dist/commands/tasks/delete.d.ts +3 -0
- package/dist/commands/tasks/delete.d.ts.map +1 -0
- package/dist/commands/tasks/delete.js +40 -0
- package/dist/commands/tasks/document.d.ts +5 -0
- package/dist/commands/tasks/document.d.ts.map +1 -0
- package/dist/commands/tasks/document.js +118 -0
- package/dist/commands/tasks/enhance.d.ts +3 -0
- package/dist/commands/tasks/enhance.d.ts.map +1 -0
- package/dist/commands/tasks/enhance.js +86 -0
- package/dist/commands/tasks/execute.d.ts +3 -0
- package/dist/commands/tasks/execute.d.ts.map +1 -0
- package/dist/commands/tasks/execute.js +33 -0
- package/dist/commands/tasks/index.d.ts +16 -0
- package/dist/commands/tasks/index.d.ts.map +1 -0
- package/dist/commands/tasks/index.js +31 -0
- package/dist/commands/tasks/list.d.ts +3 -0
- package/dist/commands/tasks/list.d.ts.map +1 -0
- package/dist/commands/tasks/list.js +27 -0
- package/dist/commands/tasks/next.d.ts +3 -0
- package/dist/commands/tasks/next.d.ts.map +1 -0
- package/dist/commands/tasks/next.js +44 -0
- package/dist/commands/tasks/plan.d.ts +7 -0
- package/dist/commands/tasks/plan.d.ts.map +1 -0
- package/dist/commands/tasks/plan.js +131 -0
- package/dist/commands/tasks/show.d.ts +3 -0
- package/dist/commands/tasks/show.d.ts.map +1 -0
- package/dist/commands/tasks/show.js +23 -0
- package/dist/commands/tasks/split.d.ts +3 -0
- package/dist/commands/tasks/split.d.ts.map +1 -0
- package/dist/commands/tasks/split.js +95 -0
- package/dist/commands/tasks/status.d.ts +3 -0
- package/dist/commands/tasks/status.d.ts.map +1 -0
- package/dist/commands/tasks/status.js +26 -0
- package/dist/commands/tasks/subtasks.d.ts +3 -0
- package/dist/commands/tasks/subtasks.d.ts.map +1 -0
- package/dist/commands/tasks/subtasks.js +35 -0
- package/dist/commands/tasks/tags.d.ts +4 -0
- package/dist/commands/tasks/tags.d.ts.map +1 -0
- package/dist/commands/tasks/tags.js +37 -0
- package/dist/commands/tasks/tree.d.ts +3 -0
- package/dist/commands/tasks/tree.d.ts.map +1 -0
- package/dist/commands/tasks/tree.js +20 -0
- package/dist/commands/tasks/update.d.ts +3 -0
- package/dist/commands/tasks/update.d.ts.map +1 -0
- package/dist/commands/tasks/update.js +35 -0
- package/dist/commands/tasks.d.ts.map +1 -1
- package/dist/commands/tasks.js +23 -594
- package/dist/commands/workflow.d.ts +4 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +434 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/lib/ai-service/ai-operations.d.ts +5 -3
- package/dist/lib/ai-service/ai-operations.d.ts.map +1 -1
- package/dist/lib/ai-service/ai-operations.js +231 -30
- package/dist/lib/ai-service/filesystem-tools.d.ts +69 -0
- package/dist/lib/ai-service/filesystem-tools.d.ts.map +1 -0
- package/dist/lib/ai-service/filesystem-tools.js +70 -0
- package/dist/lib/ai-service/research-tools.d.ts.map +1 -1
- package/dist/lib/ai-service/research-tools.js +2 -2
- package/dist/lib/context-builder.d.ts +2 -1
- package/dist/lib/context-builder.d.ts.map +1 -1
- package/dist/lib/context-builder.js +3 -8
- package/dist/lib/executors/claude-code-executor.d.ts +6 -0
- package/dist/lib/executors/claude-code-executor.d.ts.map +1 -0
- package/dist/lib/executors/claude-code-executor.js +41 -0
- package/dist/lib/executors/codex-executor.d.ts +6 -0
- package/dist/lib/executors/codex-executor.d.ts.map +1 -0
- package/dist/lib/executors/codex-executor.js +41 -0
- package/dist/lib/executors/executor-factory.d.ts.map +1 -1
- package/dist/lib/executors/executor-factory.js +6 -3
- package/dist/lib/executors/gemini-executor.d.ts +6 -0
- package/dist/lib/executors/gemini-executor.d.ts.map +1 -0
- package/dist/lib/executors/gemini-executor.js +41 -0
- package/dist/lib/executors/opencode-executor.d.ts.map +1 -1
- package/dist/lib/executors/opencode-executor.js +2 -3
- package/dist/lib/hooks/logger.d.ts +2 -0
- package/dist/lib/hooks/logger.d.ts.map +1 -0
- package/dist/lib/hooks/logger.js +27 -0
- package/dist/lib/hooks.d.ts +64 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/lib/hooks.js +60 -0
- package/dist/lib/index.d.ts +18 -17
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +3 -3
- package/dist/lib/prompt-builder.d.ts +8 -0
- package/dist/lib/prompt-builder.d.ts.map +1 -1
- package/dist/lib/prompt-builder.js +110 -4
- package/dist/lib/{storage.d.ts → storage/file-system.d.ts} +4 -3
- package/dist/lib/storage/file-system.d.ts.map +1 -0
- package/dist/lib/{storage.js → storage/file-system.js} +141 -152
- package/dist/lib/storage/types.d.ts +43 -0
- package/dist/lib/storage/types.d.ts.map +1 -0
- package/dist/lib/storage/types.js +2 -0
- package/dist/lib/task-execution.d.ts.map +1 -1
- package/dist/lib/task-execution.js +63 -14
- package/dist/prompts/workflow-assistance.d.ts +32 -0
- package/dist/prompts/workflow-assistance.d.ts.map +1 -0
- package/dist/prompts/workflow-assistance.js +130 -0
- package/dist/services/prd.d.ts +2 -0
- package/dist/services/prd.d.ts.map +1 -1
- package/dist/services/prd.js +4 -4
- package/dist/services/tasks.d.ts +13 -6
- package/dist/services/tasks.d.ts.map +1 -1
- package/dist/services/tasks.js +202 -88
- package/dist/services/workflow-ai-assistant.d.ts +74 -0
- package/dist/services/workflow-ai-assistant.d.ts.map +1 -0
- package/dist/services/workflow-ai-assistant.js +223 -0
- package/dist/test/hooks.test.d.ts +2 -0
- package/dist/test/hooks.test.d.ts.map +1 -0
- package/dist/test/hooks.test.js +58 -0
- package/dist/test/storage.test.js +16 -16
- package/dist/types/options.d.ts +35 -0
- package/dist/types/options.d.ts.map +1 -1
- package/dist/utils/ai-service-factory.d.ts +5 -5
- package/dist/utils/ai-service-factory.d.ts.map +1 -1
- package/dist/utils/ai-service-factory.js +4 -3
- package/dist/utils/workflow-prompts.d.ts +17 -0
- package/dist/utils/workflow-prompts.d.ts.map +1 -0
- package/dist/utils/workflow-prompts.js +88 -0
- package/package.json +2 -2
- package/dist/lib/storage.d.ts.map +0 -1
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AIOperations = void 0;
|
|
4
4
|
const ai_1 = require("ai");
|
|
5
|
-
const context_builder_1 = require("../context-builder");
|
|
6
5
|
const prompt_builder_1 = require("../prompt-builder");
|
|
7
6
|
const stack_formatter_1 = require("../../utils/stack-formatter");
|
|
8
7
|
const prompts_1 = require("../../prompts");
|
|
@@ -11,6 +10,7 @@ const json_parser_1 = require("./json-parser");
|
|
|
11
10
|
const mcp_client_1 = require("./mcp-client");
|
|
12
11
|
const retry_handler_1 = require("./retry-handler");
|
|
13
12
|
const model_provider_1 = require("./model-provider");
|
|
13
|
+
const filesystem_tools_1 = require("./filesystem-tools");
|
|
14
14
|
class AIOperations {
|
|
15
15
|
jsonParser = new json_parser_1.JSONParser();
|
|
16
16
|
context7Client = new mcp_client_1.Context7Client();
|
|
@@ -81,7 +81,8 @@ class AIOperations {
|
|
|
81
81
|
return fullText;
|
|
82
82
|
}, retryConfig, "AI streaming");
|
|
83
83
|
}
|
|
84
|
-
async parsePRD(prdContent, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory
|
|
84
|
+
async parsePRD(prdContent, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory, // Working directory passed from service layer
|
|
85
|
+
enableFilesystemTools) {
|
|
85
86
|
return this.retryHandler.executeWithRetry(async () => {
|
|
86
87
|
// Get stack context for better PRD parsing using PromptBuilder
|
|
87
88
|
// Pass working directory explicitly to avoid process.cwd() issues
|
|
@@ -118,8 +119,57 @@ class AIOperations {
|
|
|
118
119
|
}
|
|
119
120
|
enhancedPrompt = promptResult.prompt; // TypeScript: prompt is guaranteed when success is true
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
let response;
|
|
123
|
+
if (enableFilesystemTools) {
|
|
124
|
+
// Use filesystem tools when enabled
|
|
125
|
+
const model = this.modelProvider.getModel({
|
|
126
|
+
...this.modelProvider.getAIConfig(),
|
|
127
|
+
...config,
|
|
128
|
+
});
|
|
129
|
+
const allTools = {
|
|
130
|
+
...filesystem_tools_1.filesystemTools,
|
|
131
|
+
};
|
|
132
|
+
const result = await (0, ai_1.streamText)({
|
|
133
|
+
model,
|
|
134
|
+
tools: allTools, // Filesystem tools for project analysis
|
|
135
|
+
system: prompts_1.PRD_PARSING_SYSTEM_PROMPT +
|
|
136
|
+
`
|
|
137
|
+
|
|
138
|
+
You have access to filesystem tools that allow you to:
|
|
139
|
+
- readFile: Read the contents of any file in the project
|
|
140
|
+
- listDirectory: List contents of directories
|
|
141
|
+
|
|
142
|
+
Use these tools to understand the project structure, existing code patterns, and dependencies when parsing the PRD and creating tasks.`,
|
|
143
|
+
messages: [
|
|
144
|
+
{ role: "user", content: userMessage || enhancedPrompt },
|
|
145
|
+
],
|
|
146
|
+
maxRetries: 0,
|
|
147
|
+
onChunk: streamingOptions?.onChunk
|
|
148
|
+
? ({ chunk }) => {
|
|
149
|
+
if (chunk.type === "text-delta") {
|
|
150
|
+
streamingOptions.onChunk(chunk.text);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
: undefined,
|
|
154
|
+
onFinish: streamingOptions?.onFinish
|
|
155
|
+
? ({ text, finishReason, usage }) => {
|
|
156
|
+
streamingOptions.onFinish({
|
|
157
|
+
text,
|
|
158
|
+
finishReason,
|
|
159
|
+
usage,
|
|
160
|
+
isAborted: false,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
: undefined,
|
|
164
|
+
});
|
|
165
|
+
response = await result.text;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Use standard streamText without tools
|
|
169
|
+
response = await this.streamText("", // empty prompt since we use messages
|
|
170
|
+
config, prompts_1.PRD_PARSING_SYSTEM_PROMPT, userMessage || enhancedPrompt, streamingOptions, { maxAttempts: 1 } // Disable retries here since we're handling them at the outer level
|
|
171
|
+
);
|
|
172
|
+
}
|
|
123
173
|
// Parse JSON from response using proper typing
|
|
124
174
|
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
125
175
|
if (!parseResult.success) {
|
|
@@ -167,7 +217,7 @@ class AIOperations {
|
|
|
167
217
|
};
|
|
168
218
|
}, retryConfig, "PRD parsing");
|
|
169
219
|
}
|
|
170
|
-
async breakdownTask(task, config, promptOverride, userMessage, streamingOptions, retryConfig, fullContent, stackInfo, existingSubtasks) {
|
|
220
|
+
async breakdownTask(task, config, promptOverride, userMessage, streamingOptions, retryConfig, fullContent, stackInfo, existingSubtasks, enableFilesystemTools) {
|
|
171
221
|
return this.retryHandler.executeWithRetry(async () => {
|
|
172
222
|
// Use PromptBuilder if no prompt override provided
|
|
173
223
|
let prompt;
|
|
@@ -205,8 +255,55 @@ class AIOperations {
|
|
|
205
255
|
}
|
|
206
256
|
prompt = promptResult.prompt;
|
|
207
257
|
}
|
|
208
|
-
|
|
209
|
-
|
|
258
|
+
let response;
|
|
259
|
+
if (enableFilesystemTools) {
|
|
260
|
+
// Use filesystem tools when enabled
|
|
261
|
+
const model = this.modelProvider.getModel({
|
|
262
|
+
...this.modelProvider.getAIConfig(),
|
|
263
|
+
...config,
|
|
264
|
+
});
|
|
265
|
+
const allTools = {
|
|
266
|
+
...filesystem_tools_1.filesystemTools,
|
|
267
|
+
};
|
|
268
|
+
const result = await (0, ai_1.streamText)({
|
|
269
|
+
model,
|
|
270
|
+
tools: allTools, // Filesystem tools for project analysis
|
|
271
|
+
system: prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT +
|
|
272
|
+
`
|
|
273
|
+
|
|
274
|
+
You have access to filesystem tools that allow you to:
|
|
275
|
+
- readFile: Read the contents of any file in the project
|
|
276
|
+
- listDirectory: List contents of directories
|
|
277
|
+
|
|
278
|
+
Use these tools to understand the project structure, existing code, and dependencies when breaking down tasks into subtasks.`,
|
|
279
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
280
|
+
maxRetries: 0,
|
|
281
|
+
onChunk: streamingOptions?.onChunk
|
|
282
|
+
? ({ chunk }) => {
|
|
283
|
+
if (chunk.type === "text-delta") {
|
|
284
|
+
streamingOptions.onChunk(chunk.text);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
: undefined,
|
|
288
|
+
onFinish: streamingOptions?.onFinish
|
|
289
|
+
? ({ text, finishReason, usage }) => {
|
|
290
|
+
streamingOptions.onFinish({
|
|
291
|
+
text,
|
|
292
|
+
finishReason,
|
|
293
|
+
usage,
|
|
294
|
+
isAborted: false,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
: undefined,
|
|
298
|
+
});
|
|
299
|
+
response = await result.text;
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// Use standard streamText without tools
|
|
303
|
+
response = await this.streamText("", // empty prompt since we use messages
|
|
304
|
+
config, prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 } // Disable retries here since we're handling them at the outer level
|
|
305
|
+
);
|
|
306
|
+
}
|
|
210
307
|
// Parse JSON from response using proper typing
|
|
211
308
|
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
212
309
|
if (!parseResult.success) {
|
|
@@ -227,7 +324,7 @@ class AIOperations {
|
|
|
227
324
|
let prdContent = "";
|
|
228
325
|
// If taskId is provided, include existing documentation context
|
|
229
326
|
if (taskId) {
|
|
230
|
-
const contextBuilder =
|
|
327
|
+
const contextBuilder = (0, ai_service_factory_1.getContextBuilder)();
|
|
231
328
|
try {
|
|
232
329
|
const context = await contextBuilder.buildContext(taskId);
|
|
233
330
|
if (context.documentation || context.stack || context.prdContent) {
|
|
@@ -238,7 +335,9 @@ class AIOperations {
|
|
|
238
335
|
if (context.documentation) {
|
|
239
336
|
contextInfo += `Documentation Available: ${context.documentation.recap}\n`;
|
|
240
337
|
if (context.documentation.files.length > 0) {
|
|
241
|
-
contextInfo += `Documentation Files: ${context.documentation.files
|
|
338
|
+
contextInfo += `Documentation Files: ${context.documentation.files
|
|
339
|
+
.map((f) => f.path)
|
|
340
|
+
.join(", ")}\n`;
|
|
242
341
|
}
|
|
243
342
|
}
|
|
244
343
|
if (context.prdContent) {
|
|
@@ -272,10 +371,12 @@ class AIOperations {
|
|
|
272
371
|
prompt = promptResult.prompt;
|
|
273
372
|
}
|
|
274
373
|
return this.streamText("", // empty prompt since we use messages
|
|
275
|
-
config, prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 }
|
|
374
|
+
config, prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 } // Disable retries here since we're handling them at the outer level
|
|
375
|
+
);
|
|
276
376
|
}, retryConfig, "Task enhancement");
|
|
277
377
|
}
|
|
278
|
-
async reworkPRD(prdContent, feedback, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory
|
|
378
|
+
async reworkPRD(prdContent, feedback, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory, // Working directory passed from service layer
|
|
379
|
+
enableFilesystemTools) {
|
|
279
380
|
return this.retryHandler.executeWithRetry(async () => {
|
|
280
381
|
// Get stack context for better PRD rework using PromptBuilder
|
|
281
382
|
// Pass working directory explicitly to avoid process.cwd() issues
|
|
@@ -313,12 +414,60 @@ class AIOperations {
|
|
|
313
414
|
}
|
|
314
415
|
prompt = promptResult.prompt;
|
|
315
416
|
}
|
|
316
|
-
|
|
317
|
-
|
|
417
|
+
if (enableFilesystemTools) {
|
|
418
|
+
// Use filesystem tools when enabled
|
|
419
|
+
const model = this.modelProvider.getModel({
|
|
420
|
+
...this.modelProvider.getAIConfig(),
|
|
421
|
+
...config,
|
|
422
|
+
});
|
|
423
|
+
const allTools = {
|
|
424
|
+
...filesystem_tools_1.filesystemTools,
|
|
425
|
+
};
|
|
426
|
+
const result = await (0, ai_1.streamText)({
|
|
427
|
+
model,
|
|
428
|
+
tools: allTools, // Filesystem tools for project analysis
|
|
429
|
+
system: prompts_1.PRD_REWORK_SYSTEM_PROMPT +
|
|
430
|
+
`
|
|
431
|
+
|
|
432
|
+
You have access to filesystem tools that allow you to:
|
|
433
|
+
- readFile: Read the contents of any file in the project
|
|
434
|
+
- listDirectory: List contents of directories
|
|
435
|
+
|
|
436
|
+
Use these tools to understand the current project structure, existing code patterns, and dependencies when reworking the PRD based on feedback.`,
|
|
437
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
438
|
+
maxRetries: 0,
|
|
439
|
+
onChunk: streamingOptions?.onChunk
|
|
440
|
+
? ({ chunk }) => {
|
|
441
|
+
if (chunk.type === "text-delta") {
|
|
442
|
+
streamingOptions.onChunk(chunk.text);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
: undefined,
|
|
446
|
+
onFinish: streamingOptions?.onFinish
|
|
447
|
+
? ({ text, finishReason, usage }) => {
|
|
448
|
+
streamingOptions.onFinish({
|
|
449
|
+
text,
|
|
450
|
+
finishReason,
|
|
451
|
+
usage,
|
|
452
|
+
isAborted: false,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
: undefined,
|
|
456
|
+
});
|
|
457
|
+
return await result.text;
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
// Use standard streamText without tools
|
|
461
|
+
return this.streamText("", // empty prompt since we use messages
|
|
462
|
+
config, prompts_1.PRD_REWORK_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 } // Disable retries here since we're handling them at the outer level
|
|
463
|
+
);
|
|
464
|
+
}
|
|
318
465
|
}, retryConfig, "PRD rework");
|
|
319
466
|
}
|
|
320
467
|
// Context7 Integration Methods
|
|
321
|
-
async enhanceTaskWithDocumentation(taskId, taskTitle, taskDescription, stackInfo, streamingOptions, retryConfig, config, existingResearch
|
|
468
|
+
async enhanceTaskWithDocumentation(taskId, taskTitle, taskDescription, stackInfo, streamingOptions, retryConfig, config, existingResearch
|
|
469
|
+
// existingResearch?: (TaskDocumentation | undefined)[],
|
|
470
|
+
) {
|
|
322
471
|
return this.retryHandler
|
|
323
472
|
.executeWithRetry(async () => {
|
|
324
473
|
// Context7 integration via HTTP calls
|
|
@@ -331,12 +480,14 @@ class AIOperations {
|
|
|
331
480
|
// Get custom research tools
|
|
332
481
|
// const customResearchTools = this.researchTools.getResearchTools();
|
|
333
482
|
// Build context for this operation using the actual task ID
|
|
334
|
-
const contextBuilder =
|
|
483
|
+
const contextBuilder = (0, ai_service_factory_1.getContextBuilder)();
|
|
335
484
|
const builtContext = await contextBuilder.buildContext("1.1");
|
|
336
485
|
// Build existing research context
|
|
337
486
|
const existingResearchContext = existingResearch
|
|
338
487
|
? Object.entries(existingResearch)
|
|
339
|
-
.map(([lib, entries]) => `### ${lib}\n${entries
|
|
488
|
+
.map(([lib, entries]) => `### ${lib}\n${entries
|
|
489
|
+
.map((e) => `- Query: "${e.query}"`)
|
|
490
|
+
.join("\n")}`)
|
|
340
491
|
.join("\n\n")
|
|
341
492
|
: "No existing research available.";
|
|
342
493
|
// const existingResearchContext = existingResearch
|
|
@@ -365,22 +516,28 @@ class AIOperations {
|
|
|
365
516
|
throw new Error(`Failed to build task enhancement prompt: ${promptResult.error}`);
|
|
366
517
|
}
|
|
367
518
|
const prompt = promptResult.prompt;
|
|
368
|
-
// Merge Context7 MCP tools with
|
|
519
|
+
// Merge Context7 MCP tools with filesystem tools
|
|
369
520
|
const allTools = {
|
|
370
521
|
...mcpTools,
|
|
371
|
-
|
|
522
|
+
...filesystem_tools_1.filesystemTools,
|
|
372
523
|
};
|
|
373
|
-
const result = (0, ai_1.streamText)({
|
|
524
|
+
const result = await (0, ai_1.streamText)({
|
|
374
525
|
model,
|
|
375
|
-
tools: allTools, // Context7 MCP tools +
|
|
526
|
+
tools: allTools, // Context7 MCP tools + filesystem tools
|
|
376
527
|
system: prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT +
|
|
377
528
|
`
|
|
378
529
|
|
|
379
|
-
You have access to Context7 documentation tools.
|
|
530
|
+
You have access to Context7 documentation tools and filesystem tools.
|
|
531
|
+
|
|
532
|
+
## Available Tools:
|
|
533
|
+
- Context7 MCP tools (context7_resolve_library_id, context7_get_library_docs) for library documentation
|
|
534
|
+
- readFile: Read the contents of any file in the project
|
|
535
|
+
- listDirectory: List contents of directories
|
|
380
536
|
|
|
381
537
|
## Research Strategy:
|
|
382
|
-
1. Use Context7 MCP tools
|
|
383
|
-
2.
|
|
538
|
+
1. Use Context7 MCP tools for library documentation research
|
|
539
|
+
2. Use filesystem tools to understand project structure, existing code, and dependencies
|
|
540
|
+
3. Synthesize information from all sources to enhance the task
|
|
384
541
|
|
|
385
542
|
Technology stack context: ${stackInfo || "Not specified"}
|
|
386
543
|
|
|
@@ -484,7 +641,7 @@ ${existingResearchContext}`,
|
|
|
484
641
|
const allTools = {
|
|
485
642
|
...mcpTools,
|
|
486
643
|
};
|
|
487
|
-
const result = (0, ai_1.streamText)({
|
|
644
|
+
const result = await (0, ai_1.streamText)({
|
|
488
645
|
model,
|
|
489
646
|
tools: allTools,
|
|
490
647
|
system: `You are an expert developer.\nYou have access to Context7 MCP tools for documentation research.\nFetch documentation relevant to the task in the project context and create a document giving that knowledge to the AI assistant that will implement the task.`,
|
|
@@ -607,14 +764,19 @@ ${existingResearchContext}`,
|
|
|
607
764
|
const prompt = `Create a concise recap of the documentation fetched for these libraries:
|
|
608
765
|
|
|
609
766
|
Libraries:
|
|
610
|
-
${libraries
|
|
767
|
+
${libraries
|
|
768
|
+
.map((lib) => `- ${lib.name} (${lib.context7Id}): ${lib.reason}`)
|
|
769
|
+
.join("\n")}
|
|
611
770
|
|
|
612
771
|
Documentation Contents:
|
|
613
|
-
${documentContents
|
|
772
|
+
${documentContents
|
|
773
|
+
.map((doc) => `## ${doc.library}\n${doc.content.substring(0, 500)}...`)
|
|
774
|
+
.join("\n\n")}
|
|
614
775
|
|
|
615
776
|
Please provide a 2-3 sentence summary of what documentation is available and how it relates to the task.`;
|
|
616
777
|
return this.retryHandler.executeWithRetry(async () => {
|
|
617
|
-
return this.streamText(prompt, undefined, "You are a technical writer who creates concise summaries of documentation collections.", undefined, streamingOptions, { maxAttempts: 1 }
|
|
778
|
+
return this.streamText(prompt, undefined, "You are a technical writer who creates concise summaries of documentation collections.", undefined, streamingOptions, { maxAttempts: 1 } // Disable retries here since we're handling them at the outer level
|
|
779
|
+
);
|
|
618
780
|
}, retryConfig, "Documentation recap generation");
|
|
619
781
|
}
|
|
620
782
|
async planTask(taskContext, taskDetails, config, promptOverride, userMessage, streamingOptions, retryConfig) {
|
|
@@ -638,10 +800,49 @@ Please provide a 2-3 sentence summary of what documentation is available and how
|
|
|
638
800
|
}
|
|
639
801
|
prompt = promptResult.prompt;
|
|
640
802
|
}
|
|
641
|
-
const
|
|
642
|
-
|
|
803
|
+
const model = this.modelProvider.getModel({
|
|
804
|
+
...this.modelProvider.getAIConfig(),
|
|
805
|
+
...config,
|
|
806
|
+
});
|
|
807
|
+
// Get MCP tools and merge with filesystem tools
|
|
808
|
+
const mcpTools = await this.context7Client.getMCPTools();
|
|
809
|
+
const allTools = {
|
|
810
|
+
...mcpTools,
|
|
811
|
+
...filesystem_tools_1.filesystemTools,
|
|
812
|
+
};
|
|
813
|
+
const result = (0, ai_1.streamText)({
|
|
814
|
+
model,
|
|
815
|
+
tools: allTools, // Context7 MCP tools + filesystem tools
|
|
816
|
+
system: prompts_1.TASK_PLANNING_SYSTEM_PROMPT +
|
|
817
|
+
`
|
|
818
|
+
|
|
819
|
+
You have access to filesystem tools that allow you to:
|
|
820
|
+
- readFile: Read the contents of any file in the project
|
|
821
|
+
- listDirectory: List contents of directories
|
|
822
|
+
|
|
823
|
+
Use these tools to understand the project structure, existing code, and dependencies when creating implementation plans.`,
|
|
824
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
825
|
+
maxRetries: 0,
|
|
826
|
+
onChunk: streamingOptions?.onChunk
|
|
827
|
+
? ({ chunk }) => {
|
|
828
|
+
if (chunk.type === "text-delta") {
|
|
829
|
+
streamingOptions.onChunk(chunk.text);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
: undefined,
|
|
833
|
+
onFinish: streamingOptions?.onFinish
|
|
834
|
+
? ({ text, finishReason, usage }) => {
|
|
835
|
+
streamingOptions.onFinish({
|
|
836
|
+
text,
|
|
837
|
+
finishReason,
|
|
838
|
+
usage,
|
|
839
|
+
isAborted: false,
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
: undefined,
|
|
843
|
+
});
|
|
643
844
|
// Return the plan text directly - no JSON parsing needed
|
|
644
|
-
return
|
|
845
|
+
return (await result).text;
|
|
645
846
|
}, retryConfig, "Task planning");
|
|
646
847
|
}
|
|
647
848
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export declare const readFileTool: import("ai").Tool<{
|
|
2
|
+
filePath: string;
|
|
3
|
+
}, {
|
|
4
|
+
success: boolean;
|
|
5
|
+
content: string;
|
|
6
|
+
path: string;
|
|
7
|
+
size: number;
|
|
8
|
+
error?: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
success: boolean;
|
|
11
|
+
error: string;
|
|
12
|
+
content?: undefined;
|
|
13
|
+
path?: undefined;
|
|
14
|
+
size?: undefined;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const listDirectoryTool: import("ai").Tool<{
|
|
17
|
+
dirPath: string;
|
|
18
|
+
}, {
|
|
19
|
+
success: boolean;
|
|
20
|
+
contents: {
|
|
21
|
+
name: string;
|
|
22
|
+
type: string;
|
|
23
|
+
path: string;
|
|
24
|
+
size: number | undefined;
|
|
25
|
+
}[];
|
|
26
|
+
directory: string;
|
|
27
|
+
error?: undefined;
|
|
28
|
+
} | {
|
|
29
|
+
success: boolean;
|
|
30
|
+
error: string;
|
|
31
|
+
contents: never[];
|
|
32
|
+
directory?: undefined;
|
|
33
|
+
}>;
|
|
34
|
+
export declare const filesystemTools: {
|
|
35
|
+
readFile: import("ai").Tool<{
|
|
36
|
+
filePath: string;
|
|
37
|
+
}, {
|
|
38
|
+
success: boolean;
|
|
39
|
+
content: string;
|
|
40
|
+
path: string;
|
|
41
|
+
size: number;
|
|
42
|
+
error?: undefined;
|
|
43
|
+
} | {
|
|
44
|
+
success: boolean;
|
|
45
|
+
error: string;
|
|
46
|
+
content?: undefined;
|
|
47
|
+
path?: undefined;
|
|
48
|
+
size?: undefined;
|
|
49
|
+
}>;
|
|
50
|
+
listDirectory: import("ai").Tool<{
|
|
51
|
+
dirPath: string;
|
|
52
|
+
}, {
|
|
53
|
+
success: boolean;
|
|
54
|
+
contents: {
|
|
55
|
+
name: string;
|
|
56
|
+
type: string;
|
|
57
|
+
path: string;
|
|
58
|
+
size: number | undefined;
|
|
59
|
+
}[];
|
|
60
|
+
directory: string;
|
|
61
|
+
error?: undefined;
|
|
62
|
+
} | {
|
|
63
|
+
success: boolean;
|
|
64
|
+
error: string;
|
|
65
|
+
contents: never[];
|
|
66
|
+
directory?: undefined;
|
|
67
|
+
}>;
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=filesystem-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/filesystem-tools.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;EAwBvB,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;EAoC5B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG3B,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.filesystemTools = exports.listDirectoryTool = exports.readFileTool = void 0;
|
|
4
|
+
const ai_1 = require("ai");
|
|
5
|
+
const v3_1 = require("zod/v3");
|
|
6
|
+
const promises_1 = require("fs/promises");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
exports.readFileTool = (0, ai_1.tool)({
|
|
9
|
+
description: "Read the contents of a file",
|
|
10
|
+
inputSchema: v3_1.z.object({
|
|
11
|
+
filePath: v3_1.z.string().describe("Path to the file to read"),
|
|
12
|
+
}),
|
|
13
|
+
execute: async ({ filePath }) => {
|
|
14
|
+
try {
|
|
15
|
+
const resolvedPath = (0, path_1.resolve)(filePath);
|
|
16
|
+
const content = await (0, promises_1.readFile)(resolvedPath, 'utf-8');
|
|
17
|
+
const stats = await (0, promises_1.stat)(resolvedPath);
|
|
18
|
+
return {
|
|
19
|
+
success: true,
|
|
20
|
+
content,
|
|
21
|
+
path: (0, path_1.relative)(process.cwd(), resolvedPath),
|
|
22
|
+
size: stats.size,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return {
|
|
27
|
+
success: false,
|
|
28
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
exports.listDirectoryTool = (0, ai_1.tool)({
|
|
34
|
+
description: "List contents of a directory",
|
|
35
|
+
inputSchema: v3_1.z.object({
|
|
36
|
+
dirPath: v3_1.z.string().describe("Directory path to list"),
|
|
37
|
+
}),
|
|
38
|
+
execute: async ({ dirPath }) => {
|
|
39
|
+
try {
|
|
40
|
+
const resolvedPath = (0, path_1.resolve)(dirPath);
|
|
41
|
+
const entries = await (0, promises_1.readdir)(resolvedPath, { withFileTypes: true });
|
|
42
|
+
const contents = await Promise.all(entries.map(async (entry) => {
|
|
43
|
+
const fullPath = (0, path_1.join)(resolvedPath, entry.name);
|
|
44
|
+
const stats = await (0, promises_1.stat)(fullPath);
|
|
45
|
+
return {
|
|
46
|
+
name: entry.name,
|
|
47
|
+
type: entry.isDirectory() ? "directory" : "file",
|
|
48
|
+
path: (0, path_1.relative)(process.cwd(), fullPath),
|
|
49
|
+
size: entry.isFile() ? stats.size : undefined,
|
|
50
|
+
};
|
|
51
|
+
}));
|
|
52
|
+
return {
|
|
53
|
+
success: true,
|
|
54
|
+
contents,
|
|
55
|
+
directory: (0, path_1.relative)(process.cwd(), resolvedPath),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return {
|
|
60
|
+
success: false,
|
|
61
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
62
|
+
contents: [],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
exports.filesystemTools = {
|
|
68
|
+
readFile: exports.readFileTool,
|
|
69
|
+
listDirectory: exports.listDirectoryTool,
|
|
70
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"research-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/research-tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"research-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/research-tools.ts"],"names":[],"mappings":"AAKA,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAgC;CAwMhD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ResearchTools = void 0;
|
|
4
|
-
const
|
|
4
|
+
const ai_service_factory_1 = require("../../utils/ai-service-factory");
|
|
5
5
|
class ResearchTools {
|
|
6
|
-
storage =
|
|
6
|
+
storage = (0, ai_service_factory_1.getStorage)();
|
|
7
7
|
}
|
|
8
8
|
exports.ResearchTools = ResearchTools;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { TaskContext, TaskDocumentation } from "../types";
|
|
2
|
+
import { TaskRepository } from "./storage/types";
|
|
2
3
|
export declare class ContextBuilder {
|
|
3
4
|
private storage;
|
|
4
5
|
private taskOMatic;
|
|
5
6
|
private initialized;
|
|
6
|
-
constructor();
|
|
7
|
+
constructor(storage: TaskRepository);
|
|
7
8
|
private ensureInitialized;
|
|
8
9
|
/**
|
|
9
10
|
* Build comprehensive context for AI operations
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../src/lib/context-builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,WAAW,EAAa,iBAAiB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../src/lib/context-builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,WAAW,EAAa,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,cAAc;IAInC,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAuCxD;;OAEG;IACG,sBAAsB,CAC1B,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC;IAsBvB;;OAEG;IACH,OAAO,CAAC,cAAc;IA6CtB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkB7B;;OAEG;IACH,oBAAoB,CAAC,aAAa,EAAE,iBAAiB,GAAG,OAAO;IAK/D;;OAEG;IACH,oBAAoB,CAAC,aAAa,EAAE,iBAAiB,GAAG,OAAO;IAK/D;;OAEG;IACH,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0C7B;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;CAmDjD"}
|
|
@@ -3,20 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ContextBuilder = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
-
const storage_1 = require("./storage");
|
|
7
6
|
const config_1 = require("./config");
|
|
8
7
|
class ContextBuilder {
|
|
9
|
-
storage
|
|
8
|
+
storage;
|
|
10
9
|
taskOMatic = null;
|
|
11
10
|
initialized = false;
|
|
12
|
-
constructor() {
|
|
13
|
-
|
|
11
|
+
constructor(storage) {
|
|
12
|
+
this.storage = storage;
|
|
14
13
|
}
|
|
15
14
|
ensureInitialized() {
|
|
16
15
|
if (this.initialized) {
|
|
17
16
|
return;
|
|
18
17
|
}
|
|
19
|
-
this.storage = new storage_1.LocalStorage();
|
|
20
18
|
this.taskOMatic = config_1.configManager.getTaskOMaticDir();
|
|
21
19
|
this.initialized = true;
|
|
22
20
|
}
|
|
@@ -25,9 +23,6 @@ class ContextBuilder {
|
|
|
25
23
|
*/
|
|
26
24
|
async buildContext(taskId) {
|
|
27
25
|
this.ensureInitialized();
|
|
28
|
-
if (!this.storage) {
|
|
29
|
-
throw new Error("ContextBuilder not initialized");
|
|
30
|
-
}
|
|
31
26
|
const task = await this.storage.getTask(taskId);
|
|
32
27
|
if (!task) {
|
|
33
28
|
throw new Error(`Task with ID ${taskId} not found`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-executor.d.ts","sourceRoot":"","sources":["../../../src/lib/executors/claude-code-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAI/C,qBAAa,kBAAmB,YAAW,gBAAgB;IACzD,IAAI,SAAY;IAEV,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CA+BpE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ClaudeCodeExecutor = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
class ClaudeCodeExecutor {
|
|
10
|
+
name = "claude";
|
|
11
|
+
async execute(message, dry = false) {
|
|
12
|
+
if (dry) {
|
|
13
|
+
console.log(chalk_1.default.cyan(`🔧 Using executor: ${this.name}`));
|
|
14
|
+
console.log(chalk_1.default.cyan(`claude -p "${message}"`));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
// Launch claude and wait for it to complete
|
|
18
|
+
const child = (0, child_process_1.spawn)("claude", ["-p", message], {
|
|
19
|
+
stdio: "inherit", // Give tool full terminal control
|
|
20
|
+
});
|
|
21
|
+
// Wait for completion (blocking)
|
|
22
|
+
await new Promise((resolve, reject) => {
|
|
23
|
+
child.on("close", (code) => {
|
|
24
|
+
if (code === 0) {
|
|
25
|
+
console.log("✅ Claude Code execution completed successfully");
|
|
26
|
+
resolve();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const error = new Error(`Claude Code exited with code ${code}`);
|
|
30
|
+
console.error(`❌ ${error.message}`);
|
|
31
|
+
reject(error);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
child.on("error", (error) => {
|
|
35
|
+
console.error(`❌ Failed to launch Claude Code: ${error.message}`);
|
|
36
|
+
reject(error);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.ClaudeCodeExecutor = ClaudeCodeExecutor;
|