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 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 会读取当前项目的 active run、项目常驻上下文和已生成的阶段文档,再继续当前功能点的当前阶段。已完成或暂停的功能点仍保留在 `.pi/kd/runs/<run-id>/`,可用 `/kd-runs` 查看,用 `/kd-switch <run-id>` 切回。
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
- "注意:Pi 当前不会弹出表单;问题会显示在对话里,用户在对话中回答后再用 kd_question action=answer 记录。",
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("KCode Question", question))?.trim() || undefined;
576
+ return (await ctx.ui.input(question, "请输入答案"))?.trim() || undefined;
533
577
  }
534
578
 
535
579
  const customChoice = "其他,自定义输入";
536
- const selected = await ctx.ui.select("KCode Question", [...normalizedChoices, customChoice]);
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("KCode Question", question))?.trim() || undefined;
583
+ return (await ctx.ui.input(question, "请输入答案"))?.trim() || undefined;
540
584
  } catch {
541
585
  return undefined;
542
586
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kcode-pi",
3
- "version": "0.1.9",
3
+ "version": "0.1.13",
4
4
  "description": "Kingdee-specific package and harness for Pi Coding Agent",
5
5
  "type": "module",
6
6
  "private": false,