kcode-pi 0.1.9 → 0.1.13
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 +13 -1
- package/extensions/kingdee-harness.ts +48 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -276,6 +276,7 @@ kcode start --provider openai --model gpt-4o
|
|
|
276
276
|
/kd-status
|
|
277
277
|
/kd-runs
|
|
278
278
|
/kd-switch <run-id>
|
|
279
|
+
/kd-resume [补充说明]
|
|
279
280
|
/kd-finish
|
|
280
281
|
/kd-gate
|
|
281
282
|
/kd-advance [phase]
|
|
@@ -289,6 +290,17 @@ kcode start --provider openai --model gpt-4o
|
|
|
289
290
|
/kd-start --product flagship 实现采购订单插件
|
|
290
291
|
```
|
|
291
292
|
|
|
293
|
+
`/kd-start` 会创建新的功能点 run,并立即触发 Agent 进入 `discuss` 阶段。如果未识别出产品画像,例如显示 `(unknown/unknown)`,下一步应先确认产品、版本和技术栈,而不是直接写代码。
|
|
294
|
+
|
|
295
|
+
暂停后接续:
|
|
296
|
+
|
|
297
|
+
```text
|
|
298
|
+
/kd-resume
|
|
299
|
+
/kd-resume 继续确认采购入库单即时库存检查插件
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
重新 `kcode start` 时,如果当前项目存在未完成 active run,KCode 会提示当前功能点和阶段。`/kd-resume` 会读取项目常驻上下文、active run 状态和已落盘的阶段文档,再把完整工作流上下文交给 Agent 继续。
|
|
303
|
+
|
|
292
304
|
支持的产品画像:
|
|
293
305
|
|
|
294
306
|
```text
|
|
@@ -346,7 +358,7 @@ KCode 会把金蝶开发需求纳入 Harness 工作流。你可以直接输入
|
|
|
346
358
|
.pi/kd/runs/<run-id>/evidence/
|
|
347
359
|
```
|
|
348
360
|
|
|
349
|
-
下次重新 `kcode start` 时,KCode
|
|
361
|
+
下次重新 `kcode start` 时,KCode 会提示当前项目的 active run。执行 `/kd-resume` 后,KCode 会读取项目常驻上下文、active run 状态和已生成的阶段文档,再继续当前功能点的当前阶段。已完成或暂停的功能点仍保留在 `.pi/kd/runs/<run-id>/`,可用 `/kd-runs` 查看,用 `/kd-switch <run-id>` 切回。
|
|
350
362
|
|
|
351
363
|
阶段含义:
|
|
352
364
|
|
|
@@ -77,6 +77,16 @@ function shouldStartHarnessFromInput(text: string): boolean {
|
|
|
77
77
|
return KINGDEE_INTENT_PATTERN.test(text);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
function sendWorkflowPrompt(pi: ExtensionAPI, ctx: ExtensionContext, run: NonNullable<ReturnType<typeof readActiveRun>>, userText: string): void {
|
|
81
|
+
const prompt = workflowPromptForRun(ctx.cwd, run, userText);
|
|
82
|
+
if (ctx.isIdle()) {
|
|
83
|
+
pi.sendUserMessage(prompt);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
pi.sendUserMessage(prompt, { deliverAs: "followUp" });
|
|
87
|
+
if (ctx.hasUI) ctx.ui.notify("KCode harness message queued.", "info");
|
|
88
|
+
}
|
|
89
|
+
|
|
80
90
|
function workflowPromptForRun(cwd: string, run: NonNullable<ReturnType<typeof readActiveRun>>, userText: string): string {
|
|
81
91
|
const status = formatStatus(cwd, run);
|
|
82
92
|
const memory = workflowMemoryForRun(cwd, run);
|
|
@@ -243,7 +253,7 @@ const kdQuestionTool = defineTool({
|
|
|
243
253
|
"请先问第一个必须确认的问题,例如:",
|
|
244
254
|
"kd_question action=ask question=\"采购入库单 Form ID 是否为 pur_receivebill?\" choices=[\"是\", \"不是\"]",
|
|
245
255
|
"",
|
|
246
|
-
"
|
|
256
|
+
"注意:交互模式下会弹出选择/输入对话并自动记录;非交互模式下用户在对话中回答后再用 kd_question action=answer 记录。",
|
|
247
257
|
].join("\n"),
|
|
248
258
|
},
|
|
249
259
|
],
|
|
@@ -279,6 +289,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
279
289
|
pi.registerTool(kdPlanStatusTool);
|
|
280
290
|
pi.registerTool(kdQuestionTool);
|
|
281
291
|
|
|
292
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
293
|
+
const run = readActiveRun(ctx.cwd);
|
|
294
|
+
if (!run || !ctx.hasUI) return;
|
|
295
|
+
ctx.ui.notify(
|
|
296
|
+
[
|
|
297
|
+
`发现未完成 KCode run:${run.goal ?? run.id}`,
|
|
298
|
+
`阶段:${run.phase},产品:${run.profile?.product ?? run.product ?? "unknown"}`,
|
|
299
|
+
"输入 /kd-resume 可接续;输入 /kd-runs 查看其他功能点。",
|
|
300
|
+
].join("\n"),
|
|
301
|
+
"info",
|
|
302
|
+
);
|
|
303
|
+
});
|
|
304
|
+
|
|
282
305
|
pi.on("input", async (event, ctx) => {
|
|
283
306
|
if (event.source === "extension") return { action: "continue" };
|
|
284
307
|
|
|
@@ -357,6 +380,27 @@ export default function (pi: ExtensionAPI) {
|
|
|
357
380
|
|
|
358
381
|
const run = createActiveRun(ctx.cwd, goal, parsed.product, parsed.version);
|
|
359
382
|
ctx.ui.notify(`Started Kingdee harness run: ${run.id} (${run.profile?.product}/${run.profile?.techStack})`, "info");
|
|
383
|
+
sendWorkflowPrompt(pi, ctx, run, `继续 KCode Harness run ${run.id}:${goal}`);
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
pi.registerCommand("kd-resume", {
|
|
388
|
+
description: "Resume the active Kingdee harness run and inject persisted context",
|
|
389
|
+
handler: async (args, ctx) => {
|
|
390
|
+
const run = requireRun(ctx.cwd);
|
|
391
|
+
if (!run) {
|
|
392
|
+
ctx.ui.notify("No active Kingdee harness run. Use /kd-start <goal> or /kd-runs.", "error");
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const note = args.trim();
|
|
397
|
+
const message = [
|
|
398
|
+
`继续 KCode Harness run ${run.id}:${run.goal ?? "unknown goal"}`,
|
|
399
|
+
note ? `用户补充:${note}` : undefined,
|
|
400
|
+
]
|
|
401
|
+
.filter(Boolean)
|
|
402
|
+
.join("\n");
|
|
403
|
+
sendWorkflowPrompt(pi, ctx, run, message);
|
|
360
404
|
},
|
|
361
405
|
});
|
|
362
406
|
|
|
@@ -529,14 +573,14 @@ async function askQuestionInteractively(
|
|
|
529
573
|
const normalizedChoices = choices?.map((choice) => choice.trim()).filter(Boolean) ?? [];
|
|
530
574
|
try {
|
|
531
575
|
if (normalizedChoices.length === 0) {
|
|
532
|
-
return (await ctx.ui.input(
|
|
576
|
+
return (await ctx.ui.input(question, "请输入答案"))?.trim() || undefined;
|
|
533
577
|
}
|
|
534
578
|
|
|
535
579
|
const customChoice = "其他,自定义输入";
|
|
536
|
-
const selected = await ctx.ui.select(
|
|
580
|
+
const selected = await ctx.ui.select(question, [...normalizedChoices, customChoice]);
|
|
537
581
|
if (!selected) return undefined;
|
|
538
582
|
if (selected !== customChoice) return selected;
|
|
539
|
-
return (await ctx.ui.input(
|
|
583
|
+
return (await ctx.ui.input(question, "请输入答案"))?.trim() || undefined;
|
|
540
584
|
} catch {
|
|
541
585
|
return undefined;
|
|
542
586
|
}
|