diff --git a/vscode/src/cc/prompts.ts b/vscode/src/cc/prompts.ts index 7a47184..7e97294 100644 --- a/vscode/src/cc/prompts.ts +++ b/vscode/src/cc/prompts.ts @@ -31,25 +31,37 @@ export function getBrainstormPrompt( export function getBrainstormContinuePrompt( ctx: ExtensionContext, - vars: { issueNumber: number, issueRef?: string, prototypeFile?: string }, + vars: { issueNumber: number, issueRef?: string, prototypeFile?: string, prototypeSessionId?: string }, ): string { const tpl = getSettings(ctx).brainstormContinuePrompt // For youtrack cards the board number is synthetic; substitute the readable // id (e.g. LXF-12) so the cc agent references the real issue (readable via // `opencli yt issues show `), not a non-existent gitea number. const out = tpl.split('{issueNumber}').join(vars.issueRef ?? String(vars.issueNumber)) - return fillPrototypeRef(out, vars.prototypeFile) + return fillPrototypeRef(out, vars.prototypeFile, { + issueNumber: vars.issueRef ?? String(vars.issueNumber), + prototypeSessionId: vars.prototypeSessionId, + }) } /** * `{prototypeRef}` 在模板里独占一段:有原型插件就填一段「先读它」的交代, * 没有就连同前后空行一起抹掉——否则模板里会留下一个空洞段落。 */ -function fillPrototypeRef(tpl: string, prototypeFile: string | undefined): string { +function fillPrototypeRef( + tpl: string, + prototypeFile: string | undefined, + ctx: { issueNumber: string, prototypeSessionId: string | undefined }, +): string { if (!prototypeFile) return tpl.replace(/\n*\{prototypeRef\}\n*/g, '\n\n').trimEnd() - const para = `工单已有原型插件 ${prototypeFile},先读它了解已经定下来的界面和交互,在此基础上只对齐还不明确的地方,不要从零重画。` - return tpl.split('{prototypeRef}').join(para) + const lines = [ + `工单已有原型插件 ${prototypeFile},先读它了解已经定下来的界面和交互,在此基础上只对齐还不明确的地方,不要从零重画。`, + // 讨论里冒出来的原型改动要回到原型会话去做:那边有画图上下文,这边动插件 + // 代码会和它打架。定位靠会话 id——transcript 文件名就是它。 + `讨论中发现原型要改时,不要自己动插件代码,也不要去翻 git log 猜:用 ecc 的 \`spawning-peer-sessions\` 技能,ListAgents 找到本工单的原型会话(终端名 issue-${ctx.issueNumber}-原型${ctx.prototypeSessionId ? `,会话 id ${ctx.prototypeSessionId},它的 transcript 文件名就是这个 id` : ''}),SendMessage 说清要改哪块、为什么改、改完怎么算对。找不到活会话就停下告诉我去工单面板的「原型会话id」行点 ▶ 起一个。`, + ] + return tpl.split('{prototypeRef}').join(lines.join('\n\n')) } export function getImplementPlanPrompt(ctx: ExtensionContext, vars: { planFile: string, issueNumber: number, issueRef?: string }): string { diff --git a/vscode/src/panel/handlers/sessions.ts b/vscode/src/panel/handlers/sessions.ts index dff6048..11057cc 100644 --- a/vscode/src/panel/handlers/sessions.ts +++ b/vscode/src/panel/handlers/sessions.ts @@ -947,8 +947,10 @@ export async function handleContinueBrainstorm(panel: KanbanWebviewPanel, issueN // 头脑风暴只用 brainstormProfilePath;空 = DEFAULT,不回退实施 profile。 let brainstormProfilePath: string | undefined let sessionId: string | undefined - // 工单已有原型插件时,续聊提示词里让 cc 先读它,别把已经画定的界面又讨论一遍。 + // 工单已有原型插件时,续聊提示词里让 cc 先读它,别把已经画定的界面又讨论一遍; + // 会话 id 一并带上,讨论里要改原型时直接 SendMessage 给原型会话。 let prototypeFile: string | undefined + let prototypeSessionId: string | undefined try { const stateObj = await panel.readIssueState(issueNumber) if (stateObj && typeof stateObj.brainstormProfilePath === 'string' && stateObj.brainstormProfilePath.length > 0) @@ -957,6 +959,8 @@ export async function handleContinueBrainstorm(panel: KanbanWebviewPanel, issueN sessionId = stateObj.sessionId if (stateObj && typeof stateObj.prototypeFile === 'string' && stateObj.prototypeFile.length > 0) prototypeFile = stateObj.prototypeFile + if (stateObj && typeof stateObj.prototypeSessionId === 'string' && stateObj.prototypeSessionId.length > 0) + prototypeSessionId = stateObj.prototypeSessionId } catch (err) { logger.add({ @@ -971,6 +975,7 @@ export async function handleContinueBrainstorm(panel: KanbanWebviewPanel, issueN issueNumber, issueRef: panel.refFor(issueNumber).externalId, prototypeFile, + prototypeSessionId, }) const terminalName = `issue-${issueNumber}-规划` // 新建工单流程的 tab 叫 issue-new-{nonce}-规划,只能靠 newIssueTerminals 反查。