task-o-matic 0.0.2 → 0.0.3
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/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.js +93 -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 +189 -20
- 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/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/prompt-builder.d.ts +8 -0
- package/dist/lib/prompt-builder.d.ts.map +1 -1
- package/dist/lib/prompt-builder.js +98 -0
- package/dist/lib/task-execution.d.ts.map +1 -1
- package/dist/lib/task-execution.js +44 -14
- 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 +10 -1
- package/dist/services/tasks.d.ts.map +1 -1
- package/dist/services/tasks.js +97 -2
- package/package.json +1 -1
package/dist/commands/prd.js
CHANGED
|
@@ -24,6 +24,7 @@ exports.prdCommand
|
|
|
24
24
|
.option("--ai-provider-url <url>", "AI provider URL override")
|
|
25
25
|
.option("--ai-reasoning <tokens>", "Enable reasoning for OpenRouter models (max reasoning tokens)")
|
|
26
26
|
.option("--stream", "Show streaming AI output during parsing")
|
|
27
|
+
.option("--tools", "Enable filesystem tools for project analysis")
|
|
27
28
|
.action(async (options) => {
|
|
28
29
|
try {
|
|
29
30
|
// Determine working directory from current process location
|
|
@@ -33,6 +34,7 @@ exports.prdCommand
|
|
|
33
34
|
const result = await prd_1.prdService.parsePRD({
|
|
34
35
|
file: options.file,
|
|
35
36
|
workingDirectory, // Pass working directory explicitly to service
|
|
37
|
+
enableFilesystemTools: options.tools,
|
|
36
38
|
aiOptions: {
|
|
37
39
|
aiProvider: options.aiProvider,
|
|
38
40
|
aiModel: options.aiModel,
|
|
@@ -94,6 +96,7 @@ exports.prdCommand
|
|
|
94
96
|
.option("--ai-provider-url <url>", "AI provider URL override")
|
|
95
97
|
.option("--ai-reasoning <tokens>", "Enable reasoning for OpenRouter models (max reasoning tokens)")
|
|
96
98
|
.option("--stream", "Show streaming AI output during rework")
|
|
99
|
+
.option("--tools", "Enable filesystem tools for project analysis")
|
|
97
100
|
.action(async (options) => {
|
|
98
101
|
try {
|
|
99
102
|
// Determine working directory from current process location
|
|
@@ -105,6 +108,7 @@ exports.prdCommand
|
|
|
105
108
|
feedback: options.feedback,
|
|
106
109
|
output: options.output,
|
|
107
110
|
workingDirectory, // Pass working directory explicitly to service
|
|
111
|
+
enableFilesystemTools: options.tools,
|
|
108
112
|
aiOptions: {
|
|
109
113
|
aiProvider: options.aiProvider,
|
|
110
114
|
aiModel: options.aiModel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/commands/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/commands/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,eAAO,MAAM,aAAa,SAyPtB,CAAC"}
|
package/dist/commands/prompt.js
CHANGED
|
@@ -21,6 +21,8 @@ exports.promptCommand = new commander_1.Command("prompt")
|
|
|
21
21
|
.option("--var <key=value>", "Custom variable in format key=value (can be used multiple times)", (value, previous = []) => {
|
|
22
22
|
return [...previous, value];
|
|
23
23
|
}, [])
|
|
24
|
+
.option("--full-context", "Include comprehensive project context (file structure, dependencies, etc.)", false)
|
|
25
|
+
.option("--executor <type>", "Format output for specific executor: opencode, claude, gemini, codex")
|
|
24
26
|
.action(async (name, options) => {
|
|
25
27
|
try {
|
|
26
28
|
// Handle list option
|
|
@@ -55,91 +57,92 @@ exports.promptCommand = new commander_1.Command("prompt")
|
|
|
55
57
|
console.error('Error: --type must be either "system" or "user"');
|
|
56
58
|
(0, process_1.exit)(1);
|
|
57
59
|
}
|
|
58
|
-
// Build variables object
|
|
60
|
+
// Build variables object with AUTOMATIC DETECTION FIRST (like all other commands)
|
|
59
61
|
const variables = {};
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
//
|
|
72
|
-
|
|
62
|
+
// STEP 1: AUTO-DETECT EVERYTHING (default behavior)
|
|
63
|
+
// Auto-detect PRD content ALWAYS
|
|
64
|
+
const autoPrdContent = await prompt_builder_1.PromptBuilder.autoDetectPRDContent();
|
|
65
|
+
if (autoPrdContent) {
|
|
66
|
+
variables.PRD_CONTENT = autoPrdContent;
|
|
67
|
+
}
|
|
68
|
+
// Auto-detect stack info ALWAYS
|
|
69
|
+
const autoStackInfo = await prompt_builder_1.PromptBuilder.detectStackInfo(process.cwd());
|
|
70
|
+
if (autoStackInfo !== "Not detected") {
|
|
71
|
+
variables.STACK_INFO = autoStackInfo;
|
|
72
|
+
}
|
|
73
|
+
// STEP 2: OVERRIDE with explicit options if provided
|
|
74
|
+
// Override PRD if explicitly provided
|
|
73
75
|
if (options.prdFile) {
|
|
74
|
-
|
|
76
|
+
variables.PRD_CONTENT = prompt_builder_1.PromptBuilder.loadPRDContent(options.prdFile);
|
|
75
77
|
}
|
|
76
|
-
if (prdContent) {
|
|
77
|
-
variables.PRD_CONTENT = prdContent;
|
|
78
|
+
else if (options.prdContent) {
|
|
79
|
+
variables.PRD_CONTENT = options.prdContent;
|
|
78
80
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (prdContent) {
|
|
83
|
-
variables.PRD_CONTENT = prdContent;
|
|
84
|
-
}
|
|
81
|
+
// Override stack if explicitly provided
|
|
82
|
+
if (options.stackInfo) {
|
|
83
|
+
variables.STACK_INFO = options.stackInfo;
|
|
85
84
|
}
|
|
86
85
|
// Handle task information
|
|
87
|
-
let taskDescription = options.taskDescription;
|
|
88
|
-
if (options.taskFile) {
|
|
89
|
-
taskDescription = await prompt_builder_1.PromptBuilder.buildTaskContext("", "", options.taskFile);
|
|
90
|
-
}
|
|
91
86
|
if (options.taskTitle) {
|
|
92
87
|
variables.TASK_TITLE = options.taskTitle;
|
|
93
88
|
}
|
|
94
|
-
if (
|
|
95
|
-
variables.TASK_DESCRIPTION =
|
|
89
|
+
if (options.taskFile) {
|
|
90
|
+
variables.TASK_DESCRIPTION = await prompt_builder_1.PromptBuilder.buildTaskContext(options.taskTitle || "", "", options.taskFile);
|
|
91
|
+
}
|
|
92
|
+
else if (options.taskDescription) {
|
|
93
|
+
variables.TASK_DESCRIPTION = options.taskDescription;
|
|
96
94
|
}
|
|
97
|
-
//
|
|
95
|
+
// Build rich task context if we have title and description
|
|
98
96
|
if (options.taskTitle && (options.taskDescription || options.taskFile)) {
|
|
99
|
-
|
|
100
|
-
variables.TASK_CONTEXT = richContext;
|
|
97
|
+
variables.TASK_CONTEXT = await prompt_builder_1.PromptBuilder.buildTaskContext(options.taskTitle, options.taskDescription, options.taskFile);
|
|
101
98
|
}
|
|
102
|
-
// Handle
|
|
103
|
-
if (options.
|
|
104
|
-
variables.
|
|
99
|
+
// Handle user feedback
|
|
100
|
+
if (options.userFeedback) {
|
|
101
|
+
variables.USER_FEEDBACK = options.userFeedback;
|
|
105
102
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
// Build comprehensive CONTEXT_INFO (combining everything)
|
|
104
|
+
const contextParts = [];
|
|
105
|
+
// Add stack info if available
|
|
106
|
+
if (variables.STACK_INFO) {
|
|
107
|
+
contextParts.push(`**Technology Stack:** ${variables.STACK_INFO}`);
|
|
108
|
+
}
|
|
109
|
+
// Add PRD content if available
|
|
110
|
+
if (variables.PRD_CONTENT) {
|
|
111
|
+
contextParts.push(`**Product Requirements:**\n${variables.PRD_CONTENT}`);
|
|
112
|
+
}
|
|
113
|
+
// Add full context if requested
|
|
114
|
+
if (options.fullContext) {
|
|
115
|
+
const fullContext = await prompt_builder_1.PromptBuilder.buildFullProjectContext(process.cwd());
|
|
116
|
+
if (fullContext) {
|
|
117
|
+
contextParts.push(fullContext);
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
|
-
//
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
// Add stack info if available
|
|
117
|
-
if (variables.STACK_INFO) {
|
|
118
|
-
contextParts.push(`**Technology Stack:** ${variables.STACK_INFO}`);
|
|
119
|
-
}
|
|
120
|
-
// Add PRD content if available
|
|
121
|
-
if (variables.PRD_CONTENT) {
|
|
122
|
-
contextParts.push(`**Product Requirements:**\n${variables.PRD_CONTENT}`);
|
|
123
|
-
}
|
|
124
|
-
// Set combined context info
|
|
125
|
-
if (contextParts.length > 0) {
|
|
126
|
-
variables.CONTEXT_INFO = contextParts.join('\n\n');
|
|
127
|
-
}
|
|
120
|
+
// Set combined context info
|
|
121
|
+
if (contextParts.length > 0) {
|
|
122
|
+
variables.CONTEXT_INFO = contextParts.join('\n\n');
|
|
128
123
|
}
|
|
129
|
-
//
|
|
124
|
+
// Override context info if explicitly provided
|
|
130
125
|
if (options.contextInfo) {
|
|
131
126
|
variables.CONTEXT_INFO = options.contextInfo;
|
|
132
127
|
}
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
// STEP 3: FINAL OVERRIDE with custom --var variables (highest priority)
|
|
129
|
+
if (options.var) {
|
|
130
|
+
for (const varPair of options.var) {
|
|
131
|
+
const [key, ...valueParts] = varPair.split("=");
|
|
132
|
+
if (!key || valueParts.length === 0) {
|
|
133
|
+
console.error(`Error: Invalid variable format: ${varPair}. Expected format: key=value`);
|
|
134
|
+
(0, process_1.exit)(1);
|
|
135
|
+
}
|
|
136
|
+
variables[key] = valueParts.join("=");
|
|
137
|
+
}
|
|
135
138
|
}
|
|
136
139
|
// Build the prompt
|
|
137
140
|
const result = prompt_builder_1.PromptBuilder.buildPrompt({
|
|
138
|
-
name,
|
|
141
|
+
name: name, // name is checked above, will not be undefined here
|
|
139
142
|
type: options.type,
|
|
140
143
|
variables,
|
|
141
144
|
});
|
|
142
|
-
if (!result.success) {
|
|
145
|
+
if (!result.success || !result.prompt) {
|
|
143
146
|
console.error(`Error: ${result.error}`);
|
|
144
147
|
if (result.missingVariables && result.missingVariables.length > 0) {
|
|
145
148
|
console.error("\nMissing required variables:");
|
|
@@ -159,8 +162,13 @@ exports.promptCommand = new commander_1.Command("prompt")
|
|
|
159
162
|
}
|
|
160
163
|
(0, process_1.exit)(1);
|
|
161
164
|
}
|
|
165
|
+
// Format output based on executor if specified
|
|
166
|
+
let outputPrompt = result.prompt;
|
|
167
|
+
if (options.executor) {
|
|
168
|
+
outputPrompt = prompt_builder_1.PromptBuilder.formatForExecutor(result.prompt, options.executor);
|
|
169
|
+
}
|
|
162
170
|
// Output the built prompt
|
|
163
|
-
console.log(
|
|
171
|
+
console.log(outputPrompt);
|
|
164
172
|
}
|
|
165
173
|
catch (error) {
|
|
166
174
|
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
package/dist/commands/tasks.js
CHANGED
|
@@ -225,6 +225,7 @@ exports.tasksCommand
|
|
|
225
225
|
.option("--ai-key <key>", "AI API key override")
|
|
226
226
|
.option("--ai-provider-url <url>", "AI provider URL override")
|
|
227
227
|
.option("--reasoning <tokens>", "Enable reasoning for OpenRouter models (max reasoning tokens)")
|
|
228
|
+
.option("--tools", "Enable filesystem tools for project analysis")
|
|
228
229
|
.action(async (options) => {
|
|
229
230
|
try {
|
|
230
231
|
if (!options.taskId && !options.all) {
|
|
@@ -245,7 +246,7 @@ exports.tasksCommand
|
|
|
245
246
|
}, undefined, undefined, streamingOptions, {
|
|
246
247
|
onProgress: progress_1.displayProgress,
|
|
247
248
|
onError: progress_1.displayError,
|
|
248
|
-
});
|
|
249
|
+
}, options.tools);
|
|
249
250
|
(0, task_1.displaySubtaskCreation)(result.subtasks);
|
|
250
251
|
// Display AI metadata
|
|
251
252
|
console.log(chalk_1.default.gray(`\n📊 AI Splitting Details:`));
|
|
@@ -597,3 +598,94 @@ exports.tasksCommand
|
|
|
597
598
|
process.exit(1);
|
|
598
599
|
}
|
|
599
600
|
});
|
|
601
|
+
// Get task documentation
|
|
602
|
+
exports.tasksCommand
|
|
603
|
+
.command("get-documentation")
|
|
604
|
+
.description("Get existing documentation for a task")
|
|
605
|
+
.requiredOption("--id <id>", "Task ID")
|
|
606
|
+
.action(async (options) => {
|
|
607
|
+
try {
|
|
608
|
+
const task = await tasks_1.taskService.getTask(options.id);
|
|
609
|
+
if (!task) {
|
|
610
|
+
throw new Error(`Task with ID ${options.id} not found`);
|
|
611
|
+
}
|
|
612
|
+
const documentation = await tasks_1.taskService.getTaskDocumentation(options.id);
|
|
613
|
+
if (!documentation) {
|
|
614
|
+
console.log(chalk_1.default.yellow(`⚠️ No documentation found for task ${options.id}`));
|
|
615
|
+
console.log(chalk_1.default.gray(` Task: ${task.title}`));
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
console.log(chalk_1.default.blue(`\n📖 Documentation for Task: ${task.title} (${options.id})`));
|
|
619
|
+
console.log(chalk_1.default.gray(` File: .task-o-matic/docs/tasks/${options.id}.md`));
|
|
620
|
+
console.log("");
|
|
621
|
+
console.log(documentation);
|
|
622
|
+
}
|
|
623
|
+
catch (error) {
|
|
624
|
+
(0, progress_1.displayError)(error);
|
|
625
|
+
process.exit(1);
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
// Add documentation from file
|
|
629
|
+
exports.tasksCommand
|
|
630
|
+
.command("add-documentation")
|
|
631
|
+
.description("Add documentation to a task from a file")
|
|
632
|
+
.requiredOption("--id <id>", "Task ID")
|
|
633
|
+
.requiredOption("--doc-file <path>", "Path to documentation file")
|
|
634
|
+
.option("--overwrite", "Overwrite existing documentation")
|
|
635
|
+
.action(async (options) => {
|
|
636
|
+
try {
|
|
637
|
+
const task = await tasks_1.taskService.getTask(options.id);
|
|
638
|
+
if (!task) {
|
|
639
|
+
throw new Error(`Task with ID ${options.id} not found`);
|
|
640
|
+
}
|
|
641
|
+
// Check if documentation already exists
|
|
642
|
+
const existingDoc = await tasks_1.taskService.getTaskDocumentation(options.id);
|
|
643
|
+
if (existingDoc && !options.overwrite) {
|
|
644
|
+
console.log(chalk_1.default.yellow(`⚠️ Documentation already exists for task ${options.id}`));
|
|
645
|
+
console.log(chalk_1.default.gray(` Use --overwrite to replace existing documentation`));
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
const result = await tasks_1.taskService.addTaskDocumentationFromFile(options.id, options.docFile);
|
|
649
|
+
console.log(chalk_1.default.green(`✓ Documentation added to task: ${task.title} (${options.id})`));
|
|
650
|
+
console.log(chalk_1.default.gray(` Source file: ${options.docFile}`));
|
|
651
|
+
console.log(chalk_1.default.gray(` Saved to: ${result.filePath}`));
|
|
652
|
+
if (options.overwrite) {
|
|
653
|
+
console.log(chalk_1.default.cyan(` Previous documentation was overwritten`));
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
catch (error) {
|
|
657
|
+
(0, progress_1.displayError)(error);
|
|
658
|
+
process.exit(1);
|
|
659
|
+
}
|
|
660
|
+
});
|
|
661
|
+
// Set task plan
|
|
662
|
+
exports.tasksCommand
|
|
663
|
+
.command("set-plan")
|
|
664
|
+
.description("Set implementation plan for a task")
|
|
665
|
+
.requiredOption("--id <id>", "Task ID")
|
|
666
|
+
.option("--plan <text>", "Plan text (use quotes for multi-line)")
|
|
667
|
+
.option("--plan-file <path>", "Path to file containing the plan")
|
|
668
|
+
.action(async (options) => {
|
|
669
|
+
try {
|
|
670
|
+
const task = await tasks_1.taskService.getTask(options.id);
|
|
671
|
+
if (!task) {
|
|
672
|
+
throw new Error(`Task with ID ${options.id} not found`);
|
|
673
|
+
}
|
|
674
|
+
if (!options.plan && !options.planFile) {
|
|
675
|
+
throw new Error("Either --plan or --plan-file must be specified");
|
|
676
|
+
}
|
|
677
|
+
if (options.plan && options.planFile) {
|
|
678
|
+
throw new Error("Cannot specify both --plan and --plan-file");
|
|
679
|
+
}
|
|
680
|
+
const result = await tasks_1.taskService.setTaskPlan(options.id, options.plan || undefined, options.planFile || undefined);
|
|
681
|
+
console.log(chalk_1.default.green(`✓ Plan set for task: ${task.title} (${options.id})`));
|
|
682
|
+
console.log(chalk_1.default.gray(` Plan file: ${result.planFile}`));
|
|
683
|
+
if (options.planFile) {
|
|
684
|
+
console.log(chalk_1.default.gray(` Source file: ${options.planFile}`));
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
catch (error) {
|
|
688
|
+
(0, progress_1.displayError)(error);
|
|
689
|
+
process.exit(1);
|
|
690
|
+
}
|
|
691
|
+
});
|
|
@@ -5,14 +5,16 @@ export declare class AIOperations {
|
|
|
5
5
|
private retryHandler;
|
|
6
6
|
private modelProvider;
|
|
7
7
|
streamText(prompt: string, config?: Partial<AIConfig>, systemPrompt?: string, userMessage?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>): Promise<string>;
|
|
8
|
-
parsePRD(prdContent: string, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>, workingDirectory?: string
|
|
9
|
-
|
|
8
|
+
parsePRD(prdContent: string, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>, workingDirectory?: string, // Working directory passed from service layer
|
|
9
|
+
enableFilesystemTools?: boolean): Promise<AIPRDParseResult>;
|
|
10
|
+
breakdownTask(task: Task, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>, fullContent?: string, stackInfo?: string, existingSubtasks?: Task[], enableFilesystemTools?: boolean): Promise<Array<{
|
|
10
11
|
title: string;
|
|
11
12
|
content: string;
|
|
12
13
|
estimatedEffort?: string;
|
|
13
14
|
}>>;
|
|
14
15
|
enhanceTask(title: string, description?: string, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, taskId?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>): Promise<string>;
|
|
15
|
-
reworkPRD(prdContent: string, feedback: string, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>, workingDirectory?: string
|
|
16
|
+
reworkPRD(prdContent: string, feedback: string, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>, workingDirectory?: string, // Working directory passed from service layer
|
|
17
|
+
enableFilesystemTools?: boolean): Promise<string>;
|
|
16
18
|
enhanceTaskWithDocumentation(taskId: string, taskTitle: string, taskDescription: string, stackInfo?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>, config?: Partial<AIConfig>, existingResearch?: Record<string, Array<{
|
|
17
19
|
query: string;
|
|
18
20
|
doc: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-operations.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/ai-operations.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,QAAQ,EACR,IAAI,EACJ,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,EAGX,iBAAiB,EAClB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ai-operations.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/ai-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ const json_parser_1 = require("./json-parser");
|
|
|
11
11
|
const mcp_client_1 = require("./mcp-client");
|
|
12
12
|
const retry_handler_1 = require("./retry-handler");
|
|
13
13
|
const model_provider_1 = require("./model-provider");
|
|
14
|
+
const filesystem_tools_1 = require("./filesystem-tools");
|
|
14
15
|
class AIOperations {
|
|
15
16
|
jsonParser = new json_parser_1.JSONParser();
|
|
16
17
|
context7Client = new mcp_client_1.Context7Client();
|
|
@@ -81,7 +82,8 @@ class AIOperations {
|
|
|
81
82
|
return fullText;
|
|
82
83
|
}, retryConfig, "AI streaming");
|
|
83
84
|
}
|
|
84
|
-
async parsePRD(prdContent, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory
|
|
85
|
+
async parsePRD(prdContent, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory, // Working directory passed from service layer
|
|
86
|
+
enableFilesystemTools) {
|
|
85
87
|
return this.retryHandler.executeWithRetry(async () => {
|
|
86
88
|
// Get stack context for better PRD parsing using PromptBuilder
|
|
87
89
|
// Pass working directory explicitly to avoid process.cwd() issues
|
|
@@ -118,8 +120,50 @@ class AIOperations {
|
|
|
118
120
|
}
|
|
119
121
|
enhancedPrompt = promptResult.prompt; // TypeScript: prompt is guaranteed when success is true
|
|
120
122
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
let response;
|
|
124
|
+
if (enableFilesystemTools) {
|
|
125
|
+
// Use filesystem tools when enabled
|
|
126
|
+
const model = this.modelProvider.getModel({ ...this.modelProvider.getAIConfig(), ...config });
|
|
127
|
+
const allTools = {
|
|
128
|
+
...filesystem_tools_1.filesystemTools,
|
|
129
|
+
};
|
|
130
|
+
const result = await (0, ai_1.streamText)({
|
|
131
|
+
model,
|
|
132
|
+
tools: allTools, // Filesystem tools for project analysis
|
|
133
|
+
system: prompts_1.PRD_PARSING_SYSTEM_PROMPT + `
|
|
134
|
+
|
|
135
|
+
You have access to filesystem tools that allow you to:
|
|
136
|
+
- readFile: Read the contents of any file in the project
|
|
137
|
+
- listDirectory: List contents of directories
|
|
138
|
+
|
|
139
|
+
Use these tools to understand the project structure, existing code patterns, and dependencies when parsing the PRD and creating tasks.`,
|
|
140
|
+
messages: [{ role: "user", content: userMessage || enhancedPrompt }],
|
|
141
|
+
maxRetries: 0,
|
|
142
|
+
onChunk: streamingOptions?.onChunk
|
|
143
|
+
? ({ chunk }) => {
|
|
144
|
+
if (chunk.type === "text-delta") {
|
|
145
|
+
streamingOptions.onChunk(chunk.text);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
: undefined,
|
|
149
|
+
onFinish: streamingOptions?.onFinish
|
|
150
|
+
? ({ text, finishReason, usage }) => {
|
|
151
|
+
streamingOptions.onFinish({
|
|
152
|
+
text,
|
|
153
|
+
finishReason,
|
|
154
|
+
usage,
|
|
155
|
+
isAborted: false,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
: undefined,
|
|
159
|
+
});
|
|
160
|
+
response = await result.text;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Use standard streamText without tools
|
|
164
|
+
response = await this.streamText("", // empty prompt since we use messages
|
|
165
|
+
config, prompts_1.PRD_PARSING_SYSTEM_PROMPT, userMessage || enhancedPrompt, streamingOptions, { maxAttempts: 1 });
|
|
166
|
+
}
|
|
123
167
|
// Parse JSON from response using proper typing
|
|
124
168
|
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
125
169
|
if (!parseResult.success) {
|
|
@@ -167,7 +211,7 @@ class AIOperations {
|
|
|
167
211
|
};
|
|
168
212
|
}, retryConfig, "PRD parsing");
|
|
169
213
|
}
|
|
170
|
-
async breakdownTask(task, config, promptOverride, userMessage, streamingOptions, retryConfig, fullContent, stackInfo, existingSubtasks) {
|
|
214
|
+
async breakdownTask(task, config, promptOverride, userMessage, streamingOptions, retryConfig, fullContent, stackInfo, existingSubtasks, enableFilesystemTools) {
|
|
171
215
|
return this.retryHandler.executeWithRetry(async () => {
|
|
172
216
|
// Use PromptBuilder if no prompt override provided
|
|
173
217
|
let prompt;
|
|
@@ -205,8 +249,50 @@ class AIOperations {
|
|
|
205
249
|
}
|
|
206
250
|
prompt = promptResult.prompt;
|
|
207
251
|
}
|
|
208
|
-
|
|
209
|
-
|
|
252
|
+
let response;
|
|
253
|
+
if (enableFilesystemTools) {
|
|
254
|
+
// Use filesystem tools when enabled
|
|
255
|
+
const model = this.modelProvider.getModel({ ...this.modelProvider.getAIConfig(), ...config });
|
|
256
|
+
const allTools = {
|
|
257
|
+
...filesystem_tools_1.filesystemTools,
|
|
258
|
+
};
|
|
259
|
+
const result = await (0, ai_1.streamText)({
|
|
260
|
+
model,
|
|
261
|
+
tools: allTools, // Filesystem tools for project analysis
|
|
262
|
+
system: prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT + `
|
|
263
|
+
|
|
264
|
+
You have access to filesystem tools that allow you to:
|
|
265
|
+
- readFile: Read the contents of any file in the project
|
|
266
|
+
- listDirectory: List contents of directories
|
|
267
|
+
|
|
268
|
+
Use these tools to understand the project structure, existing code, and dependencies when breaking down tasks into subtasks.`,
|
|
269
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
270
|
+
maxRetries: 0,
|
|
271
|
+
onChunk: streamingOptions?.onChunk
|
|
272
|
+
? ({ chunk }) => {
|
|
273
|
+
if (chunk.type === "text-delta") {
|
|
274
|
+
streamingOptions.onChunk(chunk.text);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
: undefined,
|
|
278
|
+
onFinish: streamingOptions?.onFinish
|
|
279
|
+
? ({ text, finishReason, usage }) => {
|
|
280
|
+
streamingOptions.onFinish({
|
|
281
|
+
text,
|
|
282
|
+
finishReason,
|
|
283
|
+
usage,
|
|
284
|
+
isAborted: false,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
: undefined,
|
|
288
|
+
});
|
|
289
|
+
response = await result.text;
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
// Use standard streamText without tools
|
|
293
|
+
response = await this.streamText("", // empty prompt since we use messages
|
|
294
|
+
config, prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
|
|
295
|
+
}
|
|
210
296
|
// Parse JSON from response using proper typing
|
|
211
297
|
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
212
298
|
if (!parseResult.success) {
|
|
@@ -275,7 +361,8 @@ class AIOperations {
|
|
|
275
361
|
config, prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
|
|
276
362
|
}, retryConfig, "Task enhancement");
|
|
277
363
|
}
|
|
278
|
-
async reworkPRD(prdContent, feedback, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory
|
|
364
|
+
async reworkPRD(prdContent, feedback, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory, // Working directory passed from service layer
|
|
365
|
+
enableFilesystemTools) {
|
|
279
366
|
return this.retryHandler.executeWithRetry(async () => {
|
|
280
367
|
// Get stack context for better PRD rework using PromptBuilder
|
|
281
368
|
// Pass working directory explicitly to avoid process.cwd() issues
|
|
@@ -313,8 +400,49 @@ class AIOperations {
|
|
|
313
400
|
}
|
|
314
401
|
prompt = promptResult.prompt;
|
|
315
402
|
}
|
|
316
|
-
|
|
317
|
-
|
|
403
|
+
if (enableFilesystemTools) {
|
|
404
|
+
// Use filesystem tools when enabled
|
|
405
|
+
const model = this.modelProvider.getModel({ ...this.modelProvider.getAIConfig(), ...config });
|
|
406
|
+
const allTools = {
|
|
407
|
+
...filesystem_tools_1.filesystemTools,
|
|
408
|
+
};
|
|
409
|
+
const result = await (0, ai_1.streamText)({
|
|
410
|
+
model,
|
|
411
|
+
tools: allTools, // Filesystem tools for project analysis
|
|
412
|
+
system: prompts_1.PRD_REWORK_SYSTEM_PROMPT + `
|
|
413
|
+
|
|
414
|
+
You have access to filesystem tools that allow you to:
|
|
415
|
+
- readFile: Read the contents of any file in the project
|
|
416
|
+
- listDirectory: List contents of directories
|
|
417
|
+
|
|
418
|
+
Use these tools to understand the current project structure, existing code patterns, and dependencies when reworking the PRD based on feedback.`,
|
|
419
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
420
|
+
maxRetries: 0,
|
|
421
|
+
onChunk: streamingOptions?.onChunk
|
|
422
|
+
? ({ chunk }) => {
|
|
423
|
+
if (chunk.type === "text-delta") {
|
|
424
|
+
streamingOptions.onChunk(chunk.text);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
: undefined,
|
|
428
|
+
onFinish: streamingOptions?.onFinish
|
|
429
|
+
? ({ text, finishReason, usage }) => {
|
|
430
|
+
streamingOptions.onFinish({
|
|
431
|
+
text,
|
|
432
|
+
finishReason,
|
|
433
|
+
usage,
|
|
434
|
+
isAborted: false,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
: undefined,
|
|
438
|
+
});
|
|
439
|
+
return await result.text;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
// Use standard streamText without tools
|
|
443
|
+
return this.streamText("", // empty prompt since we use messages
|
|
444
|
+
config, prompts_1.PRD_REWORK_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
|
|
445
|
+
}
|
|
318
446
|
}, retryConfig, "PRD rework");
|
|
319
447
|
}
|
|
320
448
|
// Context7 Integration Methods
|
|
@@ -365,22 +493,28 @@ class AIOperations {
|
|
|
365
493
|
throw new Error(`Failed to build task enhancement prompt: ${promptResult.error}`);
|
|
366
494
|
}
|
|
367
495
|
const prompt = promptResult.prompt;
|
|
368
|
-
// Merge Context7 MCP tools with
|
|
496
|
+
// Merge Context7 MCP tools with filesystem tools
|
|
369
497
|
const allTools = {
|
|
370
498
|
...mcpTools,
|
|
371
|
-
|
|
499
|
+
...filesystem_tools_1.filesystemTools,
|
|
372
500
|
};
|
|
373
|
-
const result = (0, ai_1.streamText)({
|
|
501
|
+
const result = await (0, ai_1.streamText)({
|
|
374
502
|
model,
|
|
375
|
-
tools: allTools, // Context7 MCP tools +
|
|
503
|
+
tools: allTools, // Context7 MCP tools + filesystem tools
|
|
376
504
|
system: prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT +
|
|
377
505
|
`
|
|
378
506
|
|
|
379
|
-
You have access to Context7 documentation tools.
|
|
507
|
+
You have access to Context7 documentation tools and filesystem tools.
|
|
508
|
+
|
|
509
|
+
## Available Tools:
|
|
510
|
+
- Context7 MCP tools (context7_resolve_library_id, context7_get_library_docs) for library documentation
|
|
511
|
+
- readFile: Read the contents of any file in the project
|
|
512
|
+
- listDirectory: List contents of directories
|
|
380
513
|
|
|
381
514
|
## Research Strategy:
|
|
382
|
-
1. Use Context7 MCP tools
|
|
383
|
-
2.
|
|
515
|
+
1. Use Context7 MCP tools for library documentation research
|
|
516
|
+
2. Use filesystem tools to understand project structure, existing code, and dependencies
|
|
517
|
+
3. Synthesize information from all sources to enhance the task
|
|
384
518
|
|
|
385
519
|
Technology stack context: ${stackInfo || "Not specified"}
|
|
386
520
|
|
|
@@ -484,7 +618,7 @@ ${existingResearchContext}`,
|
|
|
484
618
|
const allTools = {
|
|
485
619
|
...mcpTools,
|
|
486
620
|
};
|
|
487
|
-
const result = (0, ai_1.streamText)({
|
|
621
|
+
const result = await (0, ai_1.streamText)({
|
|
488
622
|
model,
|
|
489
623
|
tools: allTools,
|
|
490
624
|
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.`,
|
|
@@ -638,10 +772,45 @@ Please provide a 2-3 sentence summary of what documentation is available and how
|
|
|
638
772
|
}
|
|
639
773
|
prompt = promptResult.prompt;
|
|
640
774
|
}
|
|
641
|
-
const
|
|
642
|
-
|
|
775
|
+
const model = this.modelProvider.getModel({ ...this.modelProvider.getAIConfig(), ...config });
|
|
776
|
+
// Get MCP tools and merge with filesystem tools
|
|
777
|
+
const mcpTools = await this.context7Client.getMCPTools();
|
|
778
|
+
const allTools = {
|
|
779
|
+
...mcpTools,
|
|
780
|
+
...filesystem_tools_1.filesystemTools,
|
|
781
|
+
};
|
|
782
|
+
const result = (0, ai_1.streamText)({
|
|
783
|
+
model,
|
|
784
|
+
tools: allTools, // Context7 MCP tools + filesystem tools
|
|
785
|
+
system: prompts_1.TASK_PLANNING_SYSTEM_PROMPT + `
|
|
786
|
+
|
|
787
|
+
You have access to filesystem tools that allow you to:
|
|
788
|
+
- readFile: Read the contents of any file in the project
|
|
789
|
+
- listDirectory: List contents of directories
|
|
790
|
+
|
|
791
|
+
Use these tools to understand the project structure, existing code, and dependencies when creating implementation plans.`,
|
|
792
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
793
|
+
maxRetries: 0,
|
|
794
|
+
onChunk: streamingOptions?.onChunk
|
|
795
|
+
? ({ chunk }) => {
|
|
796
|
+
if (chunk.type === "text-delta") {
|
|
797
|
+
streamingOptions.onChunk(chunk.text);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
: undefined,
|
|
801
|
+
onFinish: streamingOptions?.onFinish
|
|
802
|
+
? ({ text, finishReason, usage }) => {
|
|
803
|
+
streamingOptions.onFinish({
|
|
804
|
+
text,
|
|
805
|
+
finishReason,
|
|
806
|
+
usage,
|
|
807
|
+
isAborted: false,
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
: undefined,
|
|
811
|
+
});
|
|
643
812
|
// Return the plan text directly - no JSON parsing needed
|
|
644
|
-
return
|
|
813
|
+
return (await result).text;
|
|
645
814
|
}, retryConfig, "Task planning");
|
|
646
815
|
}
|
|
647
816
|
}
|