task-o-matic 0.0.9 → 0.0.11
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 +1 -1
- package/dist/cli/display/progress.d.ts.map +1 -1
- package/dist/cli/display/progress.js +16 -13
- package/dist/commands/benchmark.js +70 -2
- package/dist/commands/init.js +48 -27
- package/dist/commands/prd.d.ts.map +1 -1
- package/dist/commands/prd.js +201 -0
- package/dist/commands/tasks/execute-loop.d.ts.map +1 -1
- package/dist/commands/tasks/execute-loop.js +10 -0
- package/dist/commands/tasks/execute.d.ts.map +1 -1
- package/dist/commands/tasks/execute.js +4 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +56 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lib/ai-service/ai-operations.d.ts +13 -10
- package/dist/lib/ai-service/ai-operations.d.ts.map +1 -1
- package/dist/lib/ai-service/ai-operations.js +35 -995
- package/dist/lib/ai-service/base-operations.d.ts +13 -0
- package/dist/lib/ai-service/base-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/base-operations.js +79 -0
- package/dist/lib/ai-service/documentation-operations.d.ts +18 -0
- package/dist/lib/ai-service/documentation-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/documentation-operations.js +291 -0
- package/dist/lib/ai-service/prd-operations.d.ts +14 -0
- package/dist/lib/ai-service/prd-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/prd-operations.js +405 -0
- package/dist/lib/ai-service/task-operations.d.ts +12 -0
- package/dist/lib/ai-service/task-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/task-operations.js +225 -0
- package/dist/lib/benchmark/registry.d.ts.map +1 -1
- package/dist/lib/benchmark/registry.js +127 -0
- package/dist/lib/better-t-stack-cli.d.ts +4 -1
- package/dist/lib/better-t-stack-cli.d.ts.map +1 -1
- package/dist/lib/better-t-stack-cli.js +126 -5
- package/dist/lib/config.d.ts +13 -6
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +90 -48
- package/dist/lib/context-builder.d.ts +13 -1
- package/dist/lib/context-builder.d.ts.map +1 -1
- package/dist/lib/context-builder.js +68 -36
- package/dist/lib/executors/claude-code-executor.d.ts +5 -2
- package/dist/lib/executors/claude-code-executor.d.ts.map +1 -1
- package/dist/lib/executors/claude-code-executor.js +30 -3
- package/dist/lib/executors/codex-executor.d.ts +5 -2
- package/dist/lib/executors/codex-executor.d.ts.map +1 -1
- package/dist/lib/executors/codex-executor.js +30 -3
- package/dist/lib/executors/executor-factory.d.ts +2 -2
- package/dist/lib/executors/executor-factory.d.ts.map +1 -1
- package/dist/lib/executors/executor-factory.js +5 -5
- package/dist/lib/executors/gemini-executor.d.ts +5 -2
- package/dist/lib/executors/gemini-executor.d.ts.map +1 -1
- package/dist/lib/executors/gemini-executor.js +30 -3
- package/dist/lib/executors/opencode-executor.d.ts +5 -2
- package/dist/lib/executors/opencode-executor.d.ts.map +1 -1
- package/dist/lib/executors/opencode-executor.js +30 -7
- package/dist/lib/index.d.ts +5 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +7 -1
- package/dist/lib/prompt-builder.d.ts.map +1 -1
- package/dist/lib/prompt-builder.js +1 -0
- package/dist/lib/storage/file-system.d.ts +3 -7
- package/dist/lib/storage/file-system.d.ts.map +1 -1
- package/dist/lib/storage/file-system.js +50 -230
- package/dist/lib/storage/storage-callbacks.d.ts +17 -0
- package/dist/lib/storage/storage-callbacks.d.ts.map +1 -0
- package/dist/lib/storage/storage-callbacks.js +94 -0
- package/dist/lib/task-execution.d.ts.map +1 -1
- package/dist/lib/task-execution.js +16 -9
- package/dist/lib/task-loop-execution.d.ts.map +1 -1
- package/dist/lib/task-loop-execution.js +207 -8
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +2 -0
- package/dist/prompts/prd-combination.d.ts +2 -0
- package/dist/prompts/prd-combination.d.ts.map +1 -0
- package/dist/prompts/prd-combination.js +35 -0
- package/dist/prompts/prd-generation.d.ts +2 -0
- package/dist/prompts/prd-generation.d.ts.map +1 -0
- package/dist/prompts/prd-generation.js +49 -0
- package/dist/services/prd.d.ts +43 -0
- package/dist/services/prd.d.ts.map +1 -1
- package/dist/services/prd.js +121 -0
- package/dist/services/workflow-ai-assistant.d.ts.map +1 -1
- package/dist/services/workflow-ai-assistant.js +1 -40
- package/dist/services/workflow.d.ts +10 -0
- package/dist/services/workflow.d.ts.map +1 -1
- package/dist/services/workflow.js +118 -40
- package/dist/test/hooks.test.js +19 -10
- package/dist/test/integration/callbacks.test.d.ts +2 -0
- package/dist/test/integration/callbacks.test.d.ts.map +1 -0
- package/dist/test/integration/callbacks.test.js +64 -0
- package/dist/test/task-loop-git.test.js +33 -0
- package/dist/test/validation.test.d.ts +2 -0
- package/dist/test/validation.test.d.ts.map +1 -0
- package/dist/test/validation.test.js +22 -0
- package/dist/types/callbacks.d.ts +9 -6
- package/dist/types/callbacks.d.ts.map +1 -1
- package/dist/types/index.d.ts +17 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/workflow-options.d.ts +7 -0
- package/dist/types/workflow-options.d.ts.map +1 -1
- package/dist/utils/ai-service-factory.d.ts +15 -1
- package/dist/utils/ai-service-factory.d.ts.map +1 -1
- package/dist/utils/ai-service-factory.js +29 -1
- package/dist/utils/streaming-options.d.ts +1 -1
- package/dist/utils/streaming-options.d.ts.map +1 -1
- package/dist/utils/streaming-options.js +31 -18
- package/docs/agents/cli.md +191 -0
- package/package.json +3 -2
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PRDOperations = void 0;
|
|
37
|
+
const ai_1 = require("ai");
|
|
38
|
+
const prompt_builder_1 = require("../prompt-builder");
|
|
39
|
+
const prompts_1 = require("../../prompts");
|
|
40
|
+
const filesystem_tools_1 = require("./filesystem-tools");
|
|
41
|
+
const base_operations_1 = require("./base-operations");
|
|
42
|
+
class PRDOperations extends base_operations_1.BaseOperations {
|
|
43
|
+
async parsePRD(prdContent, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory, enableFilesystemTools) {
|
|
44
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
45
|
+
let stackInfo = "";
|
|
46
|
+
try {
|
|
47
|
+
stackInfo = await prompt_builder_1.PromptBuilder.detectStackInfo(workingDirectory);
|
|
48
|
+
if (stackInfo === "Not detected") {
|
|
49
|
+
stackInfo = "";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
// Stack info not available
|
|
54
|
+
}
|
|
55
|
+
let enhancedPrompt;
|
|
56
|
+
if (promptOverride) {
|
|
57
|
+
enhancedPrompt = promptOverride;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const variables = {
|
|
61
|
+
PRD_CONTENT: prdContent,
|
|
62
|
+
};
|
|
63
|
+
if (stackInfo) {
|
|
64
|
+
variables.STACK_INFO = stackInfo;
|
|
65
|
+
}
|
|
66
|
+
const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
|
|
67
|
+
name: "prd-parsing",
|
|
68
|
+
type: "user",
|
|
69
|
+
variables,
|
|
70
|
+
});
|
|
71
|
+
if (!promptResult.success) {
|
|
72
|
+
throw new Error(`Failed to build PRD parsing prompt: ${promptResult.error}`);
|
|
73
|
+
}
|
|
74
|
+
enhancedPrompt = promptResult.prompt;
|
|
75
|
+
}
|
|
76
|
+
let response;
|
|
77
|
+
if (enableFilesystemTools) {
|
|
78
|
+
const model = this.modelProvider.getModel({
|
|
79
|
+
...this.modelProvider.getAIConfig(),
|
|
80
|
+
...config,
|
|
81
|
+
});
|
|
82
|
+
const allTools = {
|
|
83
|
+
...filesystem_tools_1.filesystemTools,
|
|
84
|
+
};
|
|
85
|
+
const result = await (0, ai_1.streamText)({
|
|
86
|
+
model,
|
|
87
|
+
tools: allTools,
|
|
88
|
+
system: prompts_1.PRD_PARSING_SYSTEM_PROMPT +
|
|
89
|
+
`
|
|
90
|
+
|
|
91
|
+
You have access to filesystem tools that allow you to:
|
|
92
|
+
- readFile: Read the contents of any file in the project
|
|
93
|
+
- listDirectory: List contents of directories
|
|
94
|
+
|
|
95
|
+
Use these tools to understand the project structure, existing code patterns, and dependencies when parsing the PRD and creating tasks.`,
|
|
96
|
+
messages: [
|
|
97
|
+
{ role: "user", content: userMessage || enhancedPrompt },
|
|
98
|
+
],
|
|
99
|
+
maxRetries: 0,
|
|
100
|
+
onChunk: streamingOptions?.onChunk
|
|
101
|
+
? ({ chunk }) => {
|
|
102
|
+
if (chunk.type === "text-delta") {
|
|
103
|
+
streamingOptions.onChunk(chunk.text);
|
|
104
|
+
}
|
|
105
|
+
else if (chunk.type === "reasoning-delta") {
|
|
106
|
+
streamingOptions.onReasoning?.(chunk.text);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
: undefined,
|
|
110
|
+
onFinish: streamingOptions?.onFinish
|
|
111
|
+
? ({ text, finishReason, usage }) => {
|
|
112
|
+
streamingOptions.onFinish({
|
|
113
|
+
text,
|
|
114
|
+
finishReason,
|
|
115
|
+
usage,
|
|
116
|
+
isAborted: false,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
: undefined,
|
|
120
|
+
});
|
|
121
|
+
response = await result.text;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
response = await this.streamText("", config, prompts_1.PRD_PARSING_SYSTEM_PROMPT, userMessage || enhancedPrompt, streamingOptions, { maxAttempts: 1 });
|
|
125
|
+
}
|
|
126
|
+
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
127
|
+
if (!parseResult.success) {
|
|
128
|
+
throw new Error(parseResult.error || "Failed to parse PRD response");
|
|
129
|
+
}
|
|
130
|
+
const parsed = parseResult.data;
|
|
131
|
+
const tasks = (parsed?.tasks || []).map((task, index) => {
|
|
132
|
+
const taskId = task.id || (index + 1).toString();
|
|
133
|
+
const { title, description, content, effort, dependencies, ...extraData } = task;
|
|
134
|
+
let fullContent = "";
|
|
135
|
+
if (description || content) {
|
|
136
|
+
fullContent = description || content || "";
|
|
137
|
+
}
|
|
138
|
+
if (Object.keys(extraData).length > 0) {
|
|
139
|
+
fullContent += "\n\n## Additional AI-Generated Information\n";
|
|
140
|
+
for (const [key, value] of Object.entries(extraData)) {
|
|
141
|
+
fullContent += `\n**${key}:** ${JSON.stringify(value, null, 2)}`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
id: taskId,
|
|
146
|
+
title: task.title,
|
|
147
|
+
description: (task.description || task.content || "").substring(0, 200) +
|
|
148
|
+
((task.description || task.content || "").length > 200
|
|
149
|
+
? "..."
|
|
150
|
+
: ""),
|
|
151
|
+
content: fullContent,
|
|
152
|
+
status: "todo",
|
|
153
|
+
createdAt: Date.now(),
|
|
154
|
+
updatedAt: Date.now(),
|
|
155
|
+
estimatedEffort: task.effort,
|
|
156
|
+
dependencies: task.dependencies || [],
|
|
157
|
+
tags: task.tags || [],
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
tasks,
|
|
162
|
+
summary: parsed?.summary || "PRD parsed successfully",
|
|
163
|
+
estimatedDuration: parsed?.estimatedDuration || "Unknown",
|
|
164
|
+
confidence: parsed?.confidence || 0.7,
|
|
165
|
+
};
|
|
166
|
+
}, retryConfig, "PRD parsing");
|
|
167
|
+
}
|
|
168
|
+
async reworkPRD(prdContent, feedback, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory, enableFilesystemTools) {
|
|
169
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
170
|
+
let stackInfo = "";
|
|
171
|
+
try {
|
|
172
|
+
stackInfo = await prompt_builder_1.PromptBuilder.detectStackInfo(workingDirectory);
|
|
173
|
+
if (stackInfo === "Not detected") {
|
|
174
|
+
stackInfo = "";
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
// Stack info not available
|
|
179
|
+
}
|
|
180
|
+
let prompt;
|
|
181
|
+
if (promptOverride) {
|
|
182
|
+
prompt = promptOverride;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
const variables = {
|
|
186
|
+
PRD_CONTENT: prdContent,
|
|
187
|
+
USER_FEEDBACK: feedback,
|
|
188
|
+
};
|
|
189
|
+
if (stackInfo) {
|
|
190
|
+
variables.STACK_INFO = stackInfo;
|
|
191
|
+
}
|
|
192
|
+
const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
|
|
193
|
+
name: "prd-rework",
|
|
194
|
+
type: "user",
|
|
195
|
+
variables,
|
|
196
|
+
});
|
|
197
|
+
if (!promptResult.success) {
|
|
198
|
+
throw new Error(`Failed to build PRD rework prompt: ${promptResult.error}`);
|
|
199
|
+
}
|
|
200
|
+
prompt = promptResult.prompt;
|
|
201
|
+
}
|
|
202
|
+
if (enableFilesystemTools) {
|
|
203
|
+
const model = this.modelProvider.getModel({
|
|
204
|
+
...this.modelProvider.getAIConfig(),
|
|
205
|
+
...config,
|
|
206
|
+
});
|
|
207
|
+
const allTools = {
|
|
208
|
+
...filesystem_tools_1.filesystemTools,
|
|
209
|
+
};
|
|
210
|
+
const result = await (0, ai_1.streamText)({
|
|
211
|
+
model,
|
|
212
|
+
tools: allTools,
|
|
213
|
+
system: prompts_1.PRD_REWORK_SYSTEM_PROMPT +
|
|
214
|
+
`
|
|
215
|
+
|
|
216
|
+
You have access to filesystem tools that allow you to:
|
|
217
|
+
- readFile: Read the contents of any file in the project
|
|
218
|
+
- listDirectory: List contents of directories
|
|
219
|
+
|
|
220
|
+
Use these tools to understand the current project structure, existing code patterns, and dependencies when reworking the PRD based on feedback.`,
|
|
221
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
222
|
+
maxRetries: 0,
|
|
223
|
+
onChunk: streamingOptions?.onChunk
|
|
224
|
+
? ({ chunk }) => {
|
|
225
|
+
if (chunk.type === "text-delta") {
|
|
226
|
+
streamingOptions.onChunk(chunk.text);
|
|
227
|
+
}
|
|
228
|
+
else if (chunk.type === "reasoning-delta") {
|
|
229
|
+
streamingOptions.onReasoning?.(chunk.text);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
: undefined,
|
|
233
|
+
onFinish: streamingOptions?.onFinish
|
|
234
|
+
? ({ text, finishReason, usage }) => {
|
|
235
|
+
streamingOptions.onFinish({
|
|
236
|
+
text,
|
|
237
|
+
finishReason,
|
|
238
|
+
usage,
|
|
239
|
+
isAborted: false,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
: undefined,
|
|
243
|
+
});
|
|
244
|
+
return await result.text;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
return this.streamText("", config, prompts_1.PRD_REWORK_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
|
|
248
|
+
}
|
|
249
|
+
}, retryConfig, "PRD rework");
|
|
250
|
+
}
|
|
251
|
+
async generatePRDQuestions(prdContent, config, promptOverride, userMessage, streamingOptions, retryConfig, workingDirectory, enableFilesystemTools) {
|
|
252
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
253
|
+
let stackInfo = "";
|
|
254
|
+
try {
|
|
255
|
+
stackInfo = await prompt_builder_1.PromptBuilder.detectStackInfo(workingDirectory);
|
|
256
|
+
if (stackInfo === "Not detected") {
|
|
257
|
+
stackInfo = "";
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
// Stack info not available
|
|
262
|
+
}
|
|
263
|
+
let prompt;
|
|
264
|
+
if (promptOverride) {
|
|
265
|
+
prompt = promptOverride;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
const variables = {
|
|
269
|
+
PRD_CONTENT: prdContent,
|
|
270
|
+
};
|
|
271
|
+
if (stackInfo) {
|
|
272
|
+
variables.STACK_INFO = stackInfo;
|
|
273
|
+
}
|
|
274
|
+
const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
|
|
275
|
+
name: "prd-question",
|
|
276
|
+
type: "user",
|
|
277
|
+
variables,
|
|
278
|
+
});
|
|
279
|
+
if (!promptResult.success) {
|
|
280
|
+
throw new Error(`Failed to build PRD question prompt: ${promptResult.error}`);
|
|
281
|
+
}
|
|
282
|
+
prompt = promptResult.prompt;
|
|
283
|
+
}
|
|
284
|
+
const { PRD_QUESTION_SYSTEM_PROMPT } = await Promise.resolve().then(() => __importStar(require("../../prompts")));
|
|
285
|
+
let response;
|
|
286
|
+
if (enableFilesystemTools) {
|
|
287
|
+
const model = this.modelProvider.getModel({
|
|
288
|
+
...this.modelProvider.getAIConfig(),
|
|
289
|
+
...config,
|
|
290
|
+
});
|
|
291
|
+
const allTools = { ...filesystem_tools_1.filesystemTools };
|
|
292
|
+
const result = await (0, ai_1.streamText)({
|
|
293
|
+
model,
|
|
294
|
+
tools: allTools,
|
|
295
|
+
system: PRD_QUESTION_SYSTEM_PROMPT +
|
|
296
|
+
`\n\nYou have access to filesystem tools to check existing code/structure if needed.`,
|
|
297
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
298
|
+
maxRetries: 0,
|
|
299
|
+
onChunk: streamingOptions?.onChunk
|
|
300
|
+
? ({ chunk }) => {
|
|
301
|
+
if (chunk.type === "text-delta") {
|
|
302
|
+
streamingOptions.onChunk(chunk.text);
|
|
303
|
+
}
|
|
304
|
+
else if (chunk.type === "reasoning-delta") {
|
|
305
|
+
streamingOptions.onReasoning?.(chunk.text);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
: undefined,
|
|
309
|
+
onFinish: streamingOptions?.onFinish
|
|
310
|
+
? ({ text, finishReason, usage }) => {
|
|
311
|
+
streamingOptions.onFinish({
|
|
312
|
+
text,
|
|
313
|
+
finishReason,
|
|
314
|
+
usage,
|
|
315
|
+
isAborted: false,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
: undefined,
|
|
319
|
+
});
|
|
320
|
+
response = await result.text;
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
response = await this.streamText("", config, PRD_QUESTION_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
|
|
324
|
+
}
|
|
325
|
+
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
326
|
+
if (!parseResult.success) {
|
|
327
|
+
throw new Error(parseResult.error || "Failed to parse PRD questions");
|
|
328
|
+
}
|
|
329
|
+
return parseResult.data?.questions || [];
|
|
330
|
+
}, retryConfig, "PRD questioning");
|
|
331
|
+
}
|
|
332
|
+
async answerPRDQuestions(prdContent, questions, config, contextInfo, streamingOptions, retryConfig) {
|
|
333
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
334
|
+
const questionsText = questions
|
|
335
|
+
.map((q, i) => `${i + 1}. ${q}`)
|
|
336
|
+
.join("\n");
|
|
337
|
+
const contextText = contextInfo
|
|
338
|
+
? `\n\nProject Context:\n${contextInfo.stackInfo
|
|
339
|
+
? `Technology Stack: ${contextInfo.stackInfo}\n`
|
|
340
|
+
: ""}${contextInfo.projectDescription
|
|
341
|
+
? `Project Description: ${contextInfo.projectDescription}\n`
|
|
342
|
+
: ""}`
|
|
343
|
+
: "";
|
|
344
|
+
const prompt = `You are a product expert helping to clarify a PRD.
|
|
345
|
+
|
|
346
|
+
PRD Content:
|
|
347
|
+
${prdContent}${contextText}
|
|
348
|
+
|
|
349
|
+
Please answer the following questions based on the PRD and context:
|
|
350
|
+
|
|
351
|
+
${questionsText}
|
|
352
|
+
|
|
353
|
+
Provide thoughtful, specific answers that will help refine the PRD.
|
|
354
|
+
Format your response as JSON with the following structure:
|
|
355
|
+
{
|
|
356
|
+
"answers": {
|
|
357
|
+
"1": "answer to question 1",
|
|
358
|
+
"2": "answer to question 2",
|
|
359
|
+
...
|
|
360
|
+
}
|
|
361
|
+
}`;
|
|
362
|
+
const systemPrompt = `You are a product expert analyzing PRDs and answering clarifying questions.
|
|
363
|
+
Your answers should be:
|
|
364
|
+
- Specific and actionable
|
|
365
|
+
- Based on the PRD content and project context
|
|
366
|
+
- Helpful for refining the PRD
|
|
367
|
+
- Formatted as JSON`;
|
|
368
|
+
const response = await this.streamText("", config, systemPrompt, prompt, streamingOptions, { maxAttempts: 1 });
|
|
369
|
+
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
370
|
+
if (!parseResult.success) {
|
|
371
|
+
throw new Error(parseResult.error || "Failed to parse PRD answers response");
|
|
372
|
+
}
|
|
373
|
+
const answers = {};
|
|
374
|
+
const numberedAnswers = parseResult.data?.answers || {};
|
|
375
|
+
questions.forEach((question, index) => {
|
|
376
|
+
const key = String(index + 1);
|
|
377
|
+
if (numberedAnswers[key]) {
|
|
378
|
+
answers[question] = numberedAnswers[key];
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
return answers;
|
|
382
|
+
}, retryConfig, "PRD question answering");
|
|
383
|
+
}
|
|
384
|
+
async generatePRD(description, config, promptOverride, userMessage, streamingOptions, retryConfig) {
|
|
385
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
386
|
+
const systemPrompt = prompts_1.PRD_GENERATION_SYSTEM_PROMPT;
|
|
387
|
+
const userContent = userMessage || `Product Description:\n${description}`;
|
|
388
|
+
return this.streamText("", config, systemPrompt, userContent, streamingOptions, { maxAttempts: 1 });
|
|
389
|
+
}, retryConfig, "PRD generation");
|
|
390
|
+
}
|
|
391
|
+
async combinePRDs(prds, originalDescription, config, promptOverride, userMessage, streamingOptions, retryConfig) {
|
|
392
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
393
|
+
const systemPrompt = prompts_1.PRD_COMBINATION_SYSTEM_PROMPT;
|
|
394
|
+
let userContent = userMessage;
|
|
395
|
+
if (!userContent) {
|
|
396
|
+
userContent = `Original Description:\n${originalDescription}\n\n`;
|
|
397
|
+
prds.forEach((prd, index) => {
|
|
398
|
+
userContent += `--- PRD ${index + 1} ---\n${prd}\n\n`;
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
return this.streamText("", config, systemPrompt, userContent, streamingOptions, { maxAttempts: 1 });
|
|
402
|
+
}, retryConfig, "PRD combination");
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
exports.PRDOperations = PRDOperations;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AIConfig, Task, StreamingOptions, RetryConfig } from "../../types";
|
|
2
|
+
import { BaseOperations } from "./base-operations";
|
|
3
|
+
export declare class TaskOperations extends BaseOperations {
|
|
4
|
+
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<{
|
|
5
|
+
title: string;
|
|
6
|
+
content: string;
|
|
7
|
+
estimatedEffort?: string;
|
|
8
|
+
}>>;
|
|
9
|
+
enhanceTask(title: string, description?: string, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, taskId?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>): Promise<string>;
|
|
10
|
+
planTask(taskContext: string, taskDetails: string, config?: Partial<AIConfig>, promptOverride?: string, userMessage?: string, streamingOptions?: StreamingOptions, retryConfig?: Partial<RetryConfig>): Promise<any>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=task-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-operations.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/task-operations.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EACR,IAAI,EACJ,gBAAgB,EAChB,WAAW,EAEZ,MAAM,aAAa,CAAC;AAUrB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,qBAAa,cAAe,SAAQ,cAAc;IAC1C,aAAa,CACjB,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,WAAW,CAAC,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,gBAAgB,CAAC,EAAE,IAAI,EAAE,EACzB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CACR,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CACpE;IAgIK,WAAW,CACf,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC;IAyEZ,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC,GAAG,CAAC;CA6EhB"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TaskOperations = void 0;
|
|
4
|
+
const ai_1 = require("ai");
|
|
5
|
+
const prompt_builder_1 = require("../prompt-builder");
|
|
6
|
+
const stack_formatter_1 = require("../../utils/stack-formatter");
|
|
7
|
+
const prompts_1 = require("../../prompts");
|
|
8
|
+
const ai_service_factory_1 = require("../../utils/ai-service-factory");
|
|
9
|
+
const filesystem_tools_1 = require("./filesystem-tools");
|
|
10
|
+
const base_operations_1 = require("./base-operations");
|
|
11
|
+
class TaskOperations extends base_operations_1.BaseOperations {
|
|
12
|
+
async breakdownTask(task, config, promptOverride, userMessage, streamingOptions, retryConfig, fullContent, stackInfo, existingSubtasks, enableFilesystemTools) {
|
|
13
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
14
|
+
let prompt;
|
|
15
|
+
if (promptOverride) {
|
|
16
|
+
prompt = promptOverride;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const variables = {
|
|
20
|
+
TASK_TITLE: task.title,
|
|
21
|
+
TASK_DESCRIPTION: task.description || "No description",
|
|
22
|
+
};
|
|
23
|
+
if (fullContent) {
|
|
24
|
+
variables.TASK_CONTENT = fullContent;
|
|
25
|
+
}
|
|
26
|
+
if (existingSubtasks && existingSubtasks.length > 0) {
|
|
27
|
+
const existingSubtasksText = existingSubtasks
|
|
28
|
+
.map((subtask, index) => `${index + 1}. ${subtask.title}: ${subtask.description || "No description"}`)
|
|
29
|
+
.join("\n");
|
|
30
|
+
variables.EXISTING_SUBTASKS = existingSubtasksText;
|
|
31
|
+
}
|
|
32
|
+
if (stackInfo) {
|
|
33
|
+
variables.STACK_INFO = stackInfo;
|
|
34
|
+
}
|
|
35
|
+
const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
|
|
36
|
+
name: "task-breakdown",
|
|
37
|
+
type: "user",
|
|
38
|
+
variables,
|
|
39
|
+
});
|
|
40
|
+
if (!promptResult.success) {
|
|
41
|
+
throw new Error(`Failed to build task breakdown prompt: ${promptResult.error}`);
|
|
42
|
+
}
|
|
43
|
+
prompt = promptResult.prompt;
|
|
44
|
+
}
|
|
45
|
+
let response;
|
|
46
|
+
if (enableFilesystemTools) {
|
|
47
|
+
const model = this.modelProvider.getModel({
|
|
48
|
+
...this.modelProvider.getAIConfig(),
|
|
49
|
+
...config,
|
|
50
|
+
});
|
|
51
|
+
const allTools = {
|
|
52
|
+
...filesystem_tools_1.filesystemTools,
|
|
53
|
+
};
|
|
54
|
+
const result = await (0, ai_1.streamText)({
|
|
55
|
+
model,
|
|
56
|
+
tools: allTools,
|
|
57
|
+
system: prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT +
|
|
58
|
+
`
|
|
59
|
+
|
|
60
|
+
You have access to filesystem tools that allow you to:
|
|
61
|
+
- readFile: Read the contents of any file in the project
|
|
62
|
+
- listDirectory: List contents of directories
|
|
63
|
+
|
|
64
|
+
Use these tools to understand the project structure, existing code, and dependencies when breaking down tasks into subtasks.`,
|
|
65
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
66
|
+
maxRetries: 0,
|
|
67
|
+
onChunk: streamingOptions?.onChunk
|
|
68
|
+
? ({ chunk }) => {
|
|
69
|
+
if (chunk.type === "text-delta") {
|
|
70
|
+
streamingOptions.onChunk(chunk.text);
|
|
71
|
+
}
|
|
72
|
+
else if (chunk.type === "reasoning-delta") {
|
|
73
|
+
streamingOptions.onReasoning?.(chunk.text);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
: undefined,
|
|
77
|
+
onFinish: streamingOptions?.onFinish
|
|
78
|
+
? ({ text, finishReason, usage }) => {
|
|
79
|
+
streamingOptions.onFinish({
|
|
80
|
+
text,
|
|
81
|
+
finishReason,
|
|
82
|
+
usage,
|
|
83
|
+
isAborted: false,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
: undefined,
|
|
87
|
+
});
|
|
88
|
+
response = await result.text;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
response = await this.streamText("", config, prompts_1.TASK_BREAKDOWN_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
|
|
92
|
+
}
|
|
93
|
+
const parseResult = this.jsonParser.parseJSONFromResponse(response);
|
|
94
|
+
if (!parseResult.success) {
|
|
95
|
+
throw new Error(parseResult.error || "Failed to parse task breakdown response");
|
|
96
|
+
}
|
|
97
|
+
const parsed = parseResult.data;
|
|
98
|
+
return (parsed?.subtasks || []).map((subtask) => ({
|
|
99
|
+
title: subtask.title,
|
|
100
|
+
content: subtask.description || "",
|
|
101
|
+
estimatedEffort: subtask.effort,
|
|
102
|
+
}));
|
|
103
|
+
}, retryConfig, "Task breakdown");
|
|
104
|
+
}
|
|
105
|
+
async enhanceTask(title, description, config, promptOverride, userMessage, taskId, streamingOptions, retryConfig) {
|
|
106
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
107
|
+
let contextInfo = "";
|
|
108
|
+
let prdContent = "";
|
|
109
|
+
if (taskId) {
|
|
110
|
+
const contextBuilder = (0, ai_service_factory_1.getContextBuilder)();
|
|
111
|
+
try {
|
|
112
|
+
const context = await contextBuilder.buildContext(taskId);
|
|
113
|
+
if (context.documentation || context.stack || context.prdContent) {
|
|
114
|
+
contextInfo = "\n\nAvailable Context:\n";
|
|
115
|
+
if (context.stack) {
|
|
116
|
+
contextInfo += (0, stack_formatter_1.formatStackForContext)(context.stack) + "\n";
|
|
117
|
+
}
|
|
118
|
+
if (context.documentation) {
|
|
119
|
+
contextInfo += `Documentation Available: ${context.documentation.recap}\n`;
|
|
120
|
+
if (context.documentation.files.length > 0) {
|
|
121
|
+
contextInfo += `Documentation Files: ${context.documentation.files
|
|
122
|
+
.map((f) => f.path)
|
|
123
|
+
.join(", ")}\n`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (context.prdContent) {
|
|
127
|
+
prdContent = context.prdContent;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
let prompt;
|
|
136
|
+
if (promptOverride) {
|
|
137
|
+
prompt = promptOverride;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
|
|
141
|
+
name: "task-enhancement",
|
|
142
|
+
type: "user",
|
|
143
|
+
variables: {
|
|
144
|
+
TASK_TITLE: title,
|
|
145
|
+
TASK_DESCRIPTION: description || "None",
|
|
146
|
+
CONTEXT_INFO: contextInfo,
|
|
147
|
+
PRD_CONTENT: prdContent || "No PRD content available",
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
if (!promptResult.success) {
|
|
151
|
+
throw new Error(`Failed to build task enhancement prompt: ${promptResult.error}`);
|
|
152
|
+
}
|
|
153
|
+
prompt = promptResult.prompt;
|
|
154
|
+
}
|
|
155
|
+
return this.streamText("", config, prompts_1.TASK_ENHANCEMENT_SYSTEM_PROMPT, userMessage || prompt, streamingOptions, { maxAttempts: 1 });
|
|
156
|
+
}, retryConfig, "Task enhancement");
|
|
157
|
+
}
|
|
158
|
+
async planTask(taskContext, taskDetails, config, promptOverride, userMessage, streamingOptions, retryConfig) {
|
|
159
|
+
return this.retryHandler.executeWithRetry(async () => {
|
|
160
|
+
let prompt;
|
|
161
|
+
if (promptOverride) {
|
|
162
|
+
prompt = promptOverride;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const promptResult = prompt_builder_1.PromptBuilder.buildPrompt({
|
|
166
|
+
name: "task-planning",
|
|
167
|
+
type: "user",
|
|
168
|
+
variables: {
|
|
169
|
+
TASK_CONTEXT: taskContext,
|
|
170
|
+
TASK_DETAILS: taskDetails,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
if (!promptResult.success) {
|
|
174
|
+
throw new Error(`Failed to build task planning prompt: ${promptResult.error}`);
|
|
175
|
+
}
|
|
176
|
+
prompt = promptResult.prompt;
|
|
177
|
+
}
|
|
178
|
+
const model = this.modelProvider.getModel({
|
|
179
|
+
...this.modelProvider.getAIConfig(),
|
|
180
|
+
...config,
|
|
181
|
+
});
|
|
182
|
+
const mcpTools = await this.context7Client.getMCPTools();
|
|
183
|
+
const allTools = {
|
|
184
|
+
...mcpTools,
|
|
185
|
+
...filesystem_tools_1.filesystemTools,
|
|
186
|
+
};
|
|
187
|
+
const result = (0, ai_1.streamText)({
|
|
188
|
+
model,
|
|
189
|
+
tools: allTools,
|
|
190
|
+
system: prompts_1.TASK_PLANNING_SYSTEM_PROMPT +
|
|
191
|
+
`
|
|
192
|
+
|
|
193
|
+
You have access to filesystem tools that allow you to:
|
|
194
|
+
- readFile: Read the contents of any file in the project
|
|
195
|
+
- listDirectory: List contents of directories
|
|
196
|
+
|
|
197
|
+
Use these tools to understand the project structure, existing code, and dependencies when creating implementation plans.`,
|
|
198
|
+
messages: [{ role: "user", content: userMessage || prompt }],
|
|
199
|
+
maxRetries: 0,
|
|
200
|
+
onChunk: streamingOptions?.onChunk
|
|
201
|
+
? ({ chunk }) => {
|
|
202
|
+
if (chunk.type === "text-delta") {
|
|
203
|
+
streamingOptions.onChunk(chunk.text);
|
|
204
|
+
}
|
|
205
|
+
else if (chunk.type === "reasoning-delta") {
|
|
206
|
+
streamingOptions.onReasoning?.(chunk.text);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
: undefined,
|
|
210
|
+
onFinish: streamingOptions?.onFinish
|
|
211
|
+
? ({ text, finishReason, usage }) => {
|
|
212
|
+
streamingOptions.onFinish({
|
|
213
|
+
text,
|
|
214
|
+
finishReason,
|
|
215
|
+
usage,
|
|
216
|
+
isAborted: false,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
: undefined,
|
|
220
|
+
});
|
|
221
|
+
return (await result).text;
|
|
222
|
+
}, retryConfig, "Task planning");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.TaskOperations = TaskOperations;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/benchmark/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAA0B,MAAM,SAAS,CAAC;AAOzE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAkD;;IAMpE,QAAQ,CAAC,EAAE,EAAE,sBAAsB;IAInC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAInD,IAAI,IAAI,sBAAsB,EAAE;IAIhC,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/benchmark/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAA0B,MAAM,SAAS,CAAC;AAOzE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAkD;;IAMpE,QAAQ,CAAC,EAAE,EAAE,sBAAsB;IAInC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAInD,IAAI,IAAI,sBAAsB,EAAE;IAIhC,OAAO,CAAC,gBAAgB;CA2RzB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|