claude-coder 1.8.4 → 1.9.1
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 +214 -167
- package/bin/cli.js +155 -172
- package/package.json +55 -53
- package/recipes/_shared/roles/developer.md +11 -11
- package/recipes/_shared/roles/product.md +12 -12
- package/recipes/_shared/roles/tester.md +12 -12
- package/recipes/_shared/test/report-format.md +86 -86
- package/recipes/backend/base.md +27 -27
- package/recipes/backend/components/auth.md +18 -18
- package/recipes/backend/components/crud-api.md +18 -18
- package/recipes/backend/components/file-service.md +15 -15
- package/recipes/backend/manifest.json +20 -20
- package/recipes/backend/test/api-test.md +25 -25
- package/recipes/console/base.md +37 -37
- package/recipes/console/components/modal-form.md +20 -20
- package/recipes/console/components/pagination.md +17 -17
- package/recipes/console/components/search.md +17 -17
- package/recipes/console/components/table-list.md +18 -18
- package/recipes/console/components/tabs.md +14 -14
- package/recipes/console/components/tree.md +15 -15
- package/recipes/console/components/upload.md +15 -15
- package/recipes/console/manifest.json +24 -24
- package/recipes/console/test/crud-e2e.md +47 -47
- package/recipes/h5/base.md +26 -26
- package/recipes/h5/components/animation.md +11 -11
- package/recipes/h5/components/countdown.md +11 -11
- package/recipes/h5/components/share.md +11 -11
- package/recipes/h5/components/swiper.md +11 -11
- package/recipes/h5/manifest.json +21 -21
- package/recipes/h5/test/h5-e2e.md +20 -20
- package/src/commands/auth.js +362 -290
- package/src/commands/setup-modules/helpers.js +100 -99
- package/src/commands/setup-modules/index.js +25 -25
- package/src/commands/setup-modules/mcp.js +115 -95
- package/src/commands/setup-modules/provider.js +260 -260
- package/src/commands/setup-modules/safety.js +47 -61
- package/src/commands/setup-modules/simplify.js +52 -52
- package/src/commands/setup.js +172 -172
- package/src/common/assets.js +245 -236
- package/src/common/config.js +125 -125
- package/src/common/constants.js +55 -55
- package/src/common/indicator.js +260 -222
- package/src/common/interaction.js +170 -170
- package/src/common/logging.js +77 -77
- package/src/common/sdk.js +50 -50
- package/src/common/tasks.js +88 -88
- package/src/common/utils.js +213 -161
- package/src/core/coding.js +33 -55
- package/src/core/go.js +264 -310
- package/src/core/hooks.js +500 -533
- package/src/core/init.js +166 -171
- package/src/core/plan.js +188 -325
- package/src/core/prompts.js +247 -227
- package/src/core/repair.js +36 -46
- package/src/core/runner.js +458 -195
- package/src/core/scan.js +93 -89
- package/src/core/session.js +271 -57
- package/src/core/simplify.js +74 -53
- package/src/core/state.js +105 -0
- package/src/index.js +76 -0
- package/templates/bash-process.md +12 -12
- package/templates/codingSystem.md +65 -65
- package/templates/codingUser.md +17 -17
- package/templates/coreProtocol.md +29 -29
- package/templates/goSystem.md +130 -130
- package/templates/guidance.json +72 -53
- package/templates/planSystem.md +78 -78
- package/templates/planUser.md +8 -8
- package/templates/requirements.example.md +57 -57
- package/templates/scanSystem.md +120 -120
- package/templates/scanUser.md +10 -10
- package/templates/test_rule.md +194 -194
- package/templates/web-testing.md +17 -0
- package/types/index.d.ts +217 -0
- package/src/core/context.js +0 -117
- package/src/core/harness.js +0 -484
- package/src/core/query.js +0 -50
- package/templates/playwright.md +0 -17
package/src/core/plan.js
CHANGED
|
@@ -1,325 +1,188 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const readline = require('readline');
|
|
7
|
-
const {
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
10
|
-
const {
|
|
11
|
-
const {
|
|
12
|
-
const {
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const planPath = extractPlanPathFromCollected(collected, startTime);
|
|
192
|
-
|
|
193
|
-
if (planPath) {
|
|
194
|
-
const targetPath = copyPlanToProject(planPath);
|
|
195
|
-
return { success: true, targetPath, generatedPath: planPath };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
log('warn', '无法从输出中提取计划路径');
|
|
199
|
-
log('info', `请手动查看: ${PLANS_DIR}`);
|
|
200
|
-
return { success: false, reason: 'no_path', targetPath: null };
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
async function runPlanSession(instruction, opts = {}) {
|
|
204
|
-
const planOnly = opts.planOnly || false;
|
|
205
|
-
const interactive = opts.interactive || false;
|
|
206
|
-
const ts = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 12);
|
|
207
|
-
const label = planOnly ? 'plan_only' : 'plan_tasks';
|
|
208
|
-
const hookType = interactive ? 'plan_interactive' : 'plan';
|
|
209
|
-
|
|
210
|
-
return runSession(hookType, {
|
|
211
|
-
opts,
|
|
212
|
-
sessionNum: 0,
|
|
213
|
-
logFileName: `plan_${ts}.log`,
|
|
214
|
-
label,
|
|
215
|
-
|
|
216
|
-
async execute(sdk, ctx) {
|
|
217
|
-
log('info', '正在生成计划方案...');
|
|
218
|
-
|
|
219
|
-
const planResult = await _executePlanGen(sdk, ctx, instruction, opts);
|
|
220
|
-
|
|
221
|
-
if (!planResult.success) {
|
|
222
|
-
log('error', `\n计划生成失败: ${planResult.reason || planResult.error}`);
|
|
223
|
-
return { success: false, reason: planResult.reason };
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
log('ok', `\n计划已生成: ${planResult.targetPath}`);
|
|
227
|
-
|
|
228
|
-
if (planOnly) {
|
|
229
|
-
return { success: true, planPath: planResult.targetPath };
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
log('info', '正在生成任务列表...');
|
|
233
|
-
|
|
234
|
-
const tasksPrompt = buildPlanPrompt(planResult.targetPath);
|
|
235
|
-
const queryOpts = buildQueryOptions(ctx.config, opts);
|
|
236
|
-
queryOpts.systemPrompt = buildSystemPrompt('plan');
|
|
237
|
-
queryOpts.hooks = ctx.hooks;
|
|
238
|
-
queryOpts.abortController = ctx.abortController;
|
|
239
|
-
|
|
240
|
-
await ctx.runQuery(sdk, tasksPrompt, queryOpts);
|
|
241
|
-
|
|
242
|
-
syncAfterPlan();
|
|
243
|
-
log('ok', '任务追加完成');
|
|
244
|
-
return { success: true, planPath: planResult.targetPath };
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
async function promptAutoRun() {
|
|
250
|
-
if (!process.stdin.isTTY) return false;
|
|
251
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
252
|
-
return new Promise(resolve => {
|
|
253
|
-
rl.question('任务分解完成后是否自动开始执行?(y/n) ', answer => {
|
|
254
|
-
rl.close();
|
|
255
|
-
resolve(/^[Yy]/.test(answer.trim()));
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
async function run(input, opts = {}) {
|
|
261
|
-
const instruction = input || '';
|
|
262
|
-
|
|
263
|
-
assets.ensureDirs();
|
|
264
|
-
const projectRoot = assets.projectRoot;
|
|
265
|
-
|
|
266
|
-
if (opts.readFile) {
|
|
267
|
-
const reqPath = path.resolve(projectRoot, opts.readFile);
|
|
268
|
-
if (!fs.existsSync(reqPath)) {
|
|
269
|
-
log('error', `文件不存在: ${reqPath}`);
|
|
270
|
-
process.exit(1);
|
|
271
|
-
}
|
|
272
|
-
opts.reqFile = reqPath;
|
|
273
|
-
if (instruction) {
|
|
274
|
-
log('info', `-r 模式下忽略文本输入,使用需求文件: ${reqPath}`);
|
|
275
|
-
} else {
|
|
276
|
-
console.log(`需求文件: ${reqPath}`);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (!instruction && !opts.reqFile) {
|
|
281
|
-
log('error', '用法: claude-coder plan "需求内容" 或 claude-coder plan -r [requirements.md]');
|
|
282
|
-
process.exit(1);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const config = loadConfig();
|
|
286
|
-
// if opts.model is not set, use the default opus model or default model, make sure the model is set.
|
|
287
|
-
if (!opts.model) {
|
|
288
|
-
if (config.defaultOpus) {
|
|
289
|
-
opts.model = config.defaultOpus;
|
|
290
|
-
} else if (config.model) {
|
|
291
|
-
opts.model = config.model;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const displayModel = opts.model || config.model || '(default)';
|
|
296
|
-
log('ok', `模型配置已加载: ${config.provider || 'claude'} (plan 使用: ${displayModel})`);
|
|
297
|
-
if (opts.interactive) {
|
|
298
|
-
log('info', '交互模式已启用,模型可能会向您提问');
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
if (!assets.exists('profile')) {
|
|
302
|
-
log('error', 'profile 不存在,请先运行 claude-coder init 初始化项目');
|
|
303
|
-
process.exit(1);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
let shouldAutoRun = false;
|
|
307
|
-
if (!opts.planOnly) {
|
|
308
|
-
shouldAutoRun = await promptAutoRun();
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const result = await runPlanSession(instruction, { projectRoot, ...opts });
|
|
312
|
-
|
|
313
|
-
if (result.success) {
|
|
314
|
-
printStats();
|
|
315
|
-
|
|
316
|
-
if (shouldAutoRun) {
|
|
317
|
-
console.log('');
|
|
318
|
-
log('info', '开始自动执行任务...');
|
|
319
|
-
const { run: runCoding } = require('./runner');
|
|
320
|
-
await runCoding(opts);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
module.exports = { runPlanSession, run };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const readline = require('readline');
|
|
7
|
+
const { buildSystemPrompt, buildPlanPrompt } = require('./prompts');
|
|
8
|
+
const { log } = require('../common/config');
|
|
9
|
+
const { assets } = require('../common/assets');
|
|
10
|
+
const { printStats } = require('../common/tasks');
|
|
11
|
+
const { syncAfterPlan } = require('./state');
|
|
12
|
+
const { Session } = require('./session');
|
|
13
|
+
|
|
14
|
+
const PLANS_DIR = path.join(os.homedir(), '.claude', 'plans');
|
|
15
|
+
|
|
16
|
+
function buildPlanOnlySystem(opts = {}) {
|
|
17
|
+
const interactive = opts.interactive || false;
|
|
18
|
+
const interactionRule = interactive
|
|
19
|
+
? '如有不确定的关键决策点,使用 AskUserQuestion 工具向用户提问,对话确认方案。'
|
|
20
|
+
: '不要提问,默认使用最佳推荐方案。';
|
|
21
|
+
|
|
22
|
+
return `你是一个资深技术架构师。根据用户需求,探索项目代码库后输出完整的技术方案文档。
|
|
23
|
+
|
|
24
|
+
【流程】
|
|
25
|
+
1. 探索项目代码库,理解结构和技术栈
|
|
26
|
+
2. ${interactionRule}
|
|
27
|
+
3. 使用 Write 工具将完整计划写入 ~/.claude/plans/ 目录(.md 格式)
|
|
28
|
+
4. 写入后输出标记(独占一行):PLAN_FILE_PATH: <计划文件绝对路径>
|
|
29
|
+
5. 简要总结计划要点`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function buildPlanOnlyPrompt(instruction, opts = {}) {
|
|
33
|
+
const reqFile = opts.reqFile || null;
|
|
34
|
+
return reqFile
|
|
35
|
+
? `需求文件路径: ${reqFile}\n先读取该文件,理解用户需求和约束。`
|
|
36
|
+
: instruction;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function copyPlanToProject(generatedPath) {
|
|
40
|
+
const filename = path.basename(generatedPath);
|
|
41
|
+
const targetDir = path.join(assets.projectRoot, '.claude-coder', 'plan');
|
|
42
|
+
const targetPath = path.join(targetDir, filename);
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
if (!fs.existsSync(targetDir)) {
|
|
46
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
fs.copyFileSync(generatedPath, targetPath);
|
|
49
|
+
return targetPath;
|
|
50
|
+
} catch {
|
|
51
|
+
return generatedPath;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function _executePlanGen(session, instruction, opts = {}) {
|
|
56
|
+
const interactive = opts.interactive || false;
|
|
57
|
+
const prompt = buildPlanOnlyPrompt(instruction, opts);
|
|
58
|
+
const queryOpts = {
|
|
59
|
+
permissionMode: 'plan',
|
|
60
|
+
systemPrompt: buildPlanOnlySystem(opts),
|
|
61
|
+
cwd: opts.projectRoot || assets.projectRoot,
|
|
62
|
+
hooks: session.hooks,
|
|
63
|
+
};
|
|
64
|
+
if (!interactive) {
|
|
65
|
+
queryOpts.disallowedTools = ['askUserQuestion'];
|
|
66
|
+
}
|
|
67
|
+
if (opts.model) queryOpts.model = opts.model;
|
|
68
|
+
|
|
69
|
+
let capturedPlanPath = null;
|
|
70
|
+
|
|
71
|
+
const { success } = await session.runQuery(prompt, queryOpts, {
|
|
72
|
+
onMessage(message) {
|
|
73
|
+
if (message.type !== 'assistant' || !message.message?.content) return;
|
|
74
|
+
for (const block of message.message.content) {
|
|
75
|
+
if (block.type === 'tool_use' && block.name === 'Write') {
|
|
76
|
+
const target = block.input?.file_path || block.input?.path || '';
|
|
77
|
+
const normalized = target.replace(/\\/g, '/');
|
|
78
|
+
if (normalized.includes('.claude/plans/') && normalized.endsWith('.md')) {
|
|
79
|
+
capturedPlanPath = target;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (!success) {
|
|
87
|
+
log('warn', '计划生成查询未正常结束');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (capturedPlanPath && fs.existsSync(capturedPlanPath)) {
|
|
91
|
+
const targetPath = copyPlanToProject(capturedPlanPath);
|
|
92
|
+
return { success: true, targetPath, generatedPath: capturedPlanPath };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
log('warn', '无法从输出中提取计划路径');
|
|
96
|
+
log('info', `请手动查看: ${PLANS_DIR}`);
|
|
97
|
+
return { success: false, reason: 'no_path', targetPath: null };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function promptAutoRun() {
|
|
101
|
+
if (!process.stdin.isTTY) return false;
|
|
102
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
103
|
+
return new Promise(resolve => {
|
|
104
|
+
rl.question('任务分解完成后是否自动开始执行?(y/n) ', answer => {
|
|
105
|
+
rl.close();
|
|
106
|
+
resolve(/^[Yy]/.test(answer.trim()));
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ─── Main Entry ──────────────────────────────────────────
|
|
112
|
+
|
|
113
|
+
async function executePlan(config, input, opts = {}) {
|
|
114
|
+
const instruction = input || '';
|
|
115
|
+
|
|
116
|
+
if (opts.reqFile && instruction) {
|
|
117
|
+
log('info', `-r 模式下忽略文本输入,使用需求文件: ${opts.reqFile}`);
|
|
118
|
+
} else if (opts.reqFile) {
|
|
119
|
+
console.log(`需求文件: ${opts.reqFile}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!instruction && !opts.reqFile) {
|
|
123
|
+
throw new Error('用法: claude-coder plan "需求内容" 或 claude-coder plan -r [requirements.md]');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (opts.interactive) {
|
|
127
|
+
log('info', '交互模式已启用,模型可能会向您提问');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let shouldAutoRun = false;
|
|
131
|
+
if (!opts.planOnly) {
|
|
132
|
+
shouldAutoRun = await promptAutoRun();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const hookType = opts.interactive ? 'plan_interactive' : 'plan';
|
|
136
|
+
const ts = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 12);
|
|
137
|
+
const label = opts.planOnly ? 'plan_only' : 'plan_tasks';
|
|
138
|
+
|
|
139
|
+
const result = await Session.run(hookType, config, {
|
|
140
|
+
logFileName: `plan_${ts}.log`,
|
|
141
|
+
label,
|
|
142
|
+
|
|
143
|
+
async execute(session) {
|
|
144
|
+
log('info', '正在生成计划方案...');
|
|
145
|
+
|
|
146
|
+
const planResult = await _executePlanGen(session, instruction, opts);
|
|
147
|
+
|
|
148
|
+
if (!planResult.success) {
|
|
149
|
+
log('error', `\n计划生成失败: ${planResult.reason || planResult.error}`);
|
|
150
|
+
return { success: false, reason: planResult.reason };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
log('ok', `\n计划已生成: ${planResult.targetPath}`);
|
|
154
|
+
|
|
155
|
+
if (opts.planOnly) {
|
|
156
|
+
return { success: true, planPath: planResult.targetPath };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
log('info', '正在生成任务列表...');
|
|
160
|
+
|
|
161
|
+
const tasksPrompt = buildPlanPrompt(planResult.targetPath);
|
|
162
|
+
const queryOpts = session.buildQueryOptions(opts);
|
|
163
|
+
queryOpts.systemPrompt = buildSystemPrompt('plan');
|
|
164
|
+
|
|
165
|
+
const { success } = await session.runQuery(tasksPrompt, queryOpts);
|
|
166
|
+
if (!success) {
|
|
167
|
+
log('warn', '任务分解查询未正常结束');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
syncAfterPlan();
|
|
171
|
+
log('ok', '任务追加完成');
|
|
172
|
+
return { success: true, planPath: planResult.targetPath };
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (result.success) {
|
|
177
|
+
printStats();
|
|
178
|
+
|
|
179
|
+
if (shouldAutoRun) {
|
|
180
|
+
console.log('');
|
|
181
|
+
log('info', '开始自动执行任务...');
|
|
182
|
+
const { executeRun } = require('./runner');
|
|
183
|
+
await executeRun(config, opts);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
module.exports = { executePlan };
|