From 7951d9a82bf302d199c454757a7912ba8628c61c Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Thu, 11 Jun 2026 16:39:14 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20discuss=20=E5=92=8C=20plan=20?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E6=94=B9=E7=94=A8=20PromptBuilder=20?= =?UTF-8?q?=E7=BB=84=E8=A3=85=E6=8F=90=E7=A4=BA=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/assembler.ts | 38 +++++++++++++++++----------------- tests/core/assembler.test.ts | 3 ++- tests/integration/flow.test.ts | 3 ++- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/core/assembler.ts b/src/core/assembler.ts index 348da25..50e8152 100644 --- a/src/core/assembler.ts +++ b/src/core/assembler.ts @@ -6,6 +6,7 @@ import { CommandError } from "../cli/errors.ts"; import { getChangeDir } from "./config.ts"; import { parseTasks, validateTaskFormat, TaskFormatError } from "./task-parser.ts"; import { applyCommandPrefix, getPmPrefix } from "./pm.ts"; +import { PromptBuilder } from "./prompt-builder"; export function assembleDiscussPrompt(config: RuneConfig): string { const discuss = config.stages.discuss; @@ -13,7 +14,10 @@ export function assembleDiscussPrompt(config: RuneConfig): string { throw new CommandError("讨论阶段未配置", { hint: "请在 .rune/config.yaml 中配置 stages.discuss", }); - return applyCommandPrefix(discuss.prompt, config); + + const raw = new PromptBuilder().head("# 讨论阶段").prompt(discuss.prompt).build(); + + return applyCommandPrefix(raw, config); } export async function assemblePlanPrompt( @@ -36,39 +40,35 @@ export async function assemblePlanPrompt( } const changeDir = getChangeDir(projectRoot, changeName); - const parts: string[] = []; + const builder = new PromptBuilder(); - parts.push(`# 规划阶段:${changeName}`); - parts.push(""); - parts.push(`## 文档:${doc.name}.md`); - parts.push(doc.prompt); + builder.head(`# 规划阶段:${changeName}\n\n## 文档:${doc.name}.md`); + builder.prompt(doc.prompt); const docPath = join(changeDir, `${doc.name}.md`); if (existsSync(docPath)) { - parts.push(`\n文档已存在,请先读取 ${docPath} 查看已有内容,在此基础上修订。`); + builder.context(`文档已存在,请先读取 ${docPath} 查看已有内容,在此基础上修订。`); } if (doc.template) { - parts.push(`\n### 格式模板:\n${doc.template}`); + builder.context(`### 格式模板:\n${doc.template}`); } if (doc.depend && doc.depend.length > 0) { - parts.push("\n---\n"); - parts.push("## 依赖说明\n"); - parts.push("本文档依赖以下前置文档:"); - - for (const dep of doc.depend) { + const depLines = doc.depend.map((dep) => { const depPath = join(changeDir, `${dep}.md`); const depCompleted = existsSync(depPath); const status = depCompleted ? "已完成" : "未完成"; - parts.push(`- ${dep}.md(${status})`); - } - - parts.push("\n请先阅读已完成的前置文档,确保内容一致。"); + return `- ${dep}.md(${status})`; + }); + builder.context( + `## 依赖说明\n\n本文档依赖以下前置文档:\n${depLines.join("\n")}\n\n请先阅读已完成的前置文档,确保内容一致。`, + ); } - parts.push(`\n请将文档写入目录:${changeDir}`); - return applyCommandPrefix(parts.join("\n"), config); + builder.guide(`请将文档写入目录:${changeDir}`); + + return applyCommandPrefix(builder.build(), config); } export async function assembleTaskPrompt( diff --git a/tests/core/assembler.test.ts b/tests/core/assembler.test.ts index 1ab1823..79b73de 100644 --- a/tests/core/assembler.test.ts +++ b/tests/core/assembler.test.ts @@ -35,7 +35,8 @@ describe("assembleDiscussPrompt", () => { stages: { discuss: { prompt: "自定义讨论" } }, }; const prompt = assembleDiscussPrompt(config); - expect(prompt).toBe("自定义讨论"); + expect(prompt).toContain("自定义讨论"); + expect(prompt).toContain("# 讨论阶段"); }); }); diff --git a/tests/integration/flow.test.ts b/tests/integration/flow.test.ts index 016eac1..2f1084b 100644 --- a/tests/integration/flow.test.ts +++ b/tests/integration/flow.test.ts @@ -118,7 +118,8 @@ describe("完整 SDD 流程", () => { const config = await loadConfig(TMP_DIR); const discussPrompt = assembleDiscussPrompt(config); - expect(discussPrompt).toBe("自定义讨论"); + expect(discussPrompt).toContain("自定义讨论"); + expect(discussPrompt).toContain("# 讨论阶段"); await mkdir(getChangeDir(TMP_DIR, "test"), { recursive: true }); const planPrompt = await assemblePlanPrompt(config, TMP_DIR, "test", "spec");