diff --git a/src/main/services/ai/human/prompts/brain.ts b/src/main/services/ai/human/prompts/brain.ts
index 1b425383..d04677f6 100644
--- a/src/main/services/ai/human/prompts/brain.ts
+++ b/src/main/services/ai/human/prompts/brain.ts
@@ -171,32 +171,22 @@ ${renderRoundResult(record)}
`.trim()
const renderRoundSection = (input: {
- intro: string
records: HumanRoundRecord[]
detail: 'focus' | 'chain' | 'loaded'
}): string =>
- `
-${input.intro}
-
-${
input.records.length > 0
? input.records.map((record) => renderRoundRecord(record, input.detail)).join('\n\n')
: 'none'
-}
-`.trim()
-const renderLoadedHistorySection = (
+const renderLoadedHistoryText = (
loadedHistoryContext: HumanLoadedHistoryContext | undefined
-): string => {
- const intro = loadedHistoryContext
- ? `这是你主动加载的更详细历史。只有在你明确调用 history-recall 后才会出现。
-本次过滤条件:roundIds=${renderInlineList(
- (loadedHistoryContext.filters.roundIds || []).map(String),
- {
- separator: '、',
- fallback: 'none'
- }
- )};executionKinds=${renderInlineList(loadedHistoryContext.filters.executionKinds || [], {
+): string =>
+ loadedHistoryContext
+ ? `
+过滤条件:roundIds=${renderInlineList((loadedHistoryContext.filters.roundIds || []).map(String), {
+ separator: '、',
+ fallback: 'none'
+ })};executionKinds=${renderInlineList(loadedHistoryContext.filters.executionKinds || [], {
separator: '、',
fallback: 'none'
})};toolNames=${renderInlineList(loadedHistoryContext.filters.toolNames || [], {
@@ -205,15 +195,15 @@ const renderLoadedHistorySection = (
})};watchHintCodes=${renderInlineList(loadedHistoryContext.filters.watchHintCodes || [], {
separator: '、',
fallback: 'none'
- })};limit=${String(loadedHistoryContext.filters.limit || loadedHistoryContext.rounds.length)}。`
- : '这是你主动回看后加载的历史细节。只有在明确回看历史后这里才会出现内容。'
+ })};limit=${String(loadedHistoryContext.filters.limit || loadedHistoryContext.rounds.length)}
- return renderRoundSection({
- intro,
- records: loadedHistoryContext?.rounds || [],
- detail: 'loaded'
- })
-}
+${renderRoundSection({
+ records: loadedHistoryContext.rounds,
+ detail: 'loaded'
+})}
+`
+ .trim()
+ : 'none'
const renderAvailableSkillsSection = (state: HumanState): string => {
const effectiveSkillIds = getEffectiveLearnedSkillIds(state.skills.learnedSkillIds)
@@ -235,8 +225,6 @@ const renderAvailableSkillsSection = (state: HumanState): string => {
.map(renderLearnedToolSpecLine)
return `
-这是你当前已经可直接依赖、或仍可补充学习的技能与工具信息。
-
始终可用的技能:
${
listBuiltinSkillDefinitions()
@@ -283,7 +271,7 @@ export const buildBrainPrompt = (input: { state: HumanState; ctx: AiRunContext }
- 你会收到任务、记忆、技能、历史和提示等不同类型的信息。
- 这些信息是提供给你判断当前局面的参考材料,不是固定流程。
- 你需要自行判断哪些信息重要、哪些信息只是背景,以及下一步最合适的动作。
- - 除了明确写出的职责边界、输出规则和硬约束,不要把上下文说明理解成固定操作指令。
+ - 除了明确写出的职责边界、输出契约和硬约束,不要把上下文说明理解成固定操作指令。
@@ -298,39 +286,54 @@ export const buildBrainPrompt = (input: { state: HumanState; ctx: AiRunContext }
- 选择 mouth 时,readyToDeliver 必须为 true。
-
- 你必须只输出 JSON,不要输出任何额外说明。
+
+ - task_goal:用户原始诉求与限制。
+ - reference_scope:当前工作区、默认知识范围、显式缩圈范围和可用边界。
+ - your_notes:稳定任务笔记,按“已确认 / 关键依据 / 未决问题”组织。
+ - recent_progress:最近一轮完整过程记录,用于判断刚做了什么、得到什么。
+ - earlier_attempts:更早轮次过程链,用于识别重复路径、失败模式和已经验证过的动作。
+ - recalled_history:主动回看的详细历史;只有明确回看后才会出现,并可能附带过滤条件。
+ - available_skills:当前已生效或仍可学习的 skills,以及当前可直接调用的工具说明。
+ - correction_hint:当前额外的收敛或纠偏提示;若无则为 none。
+
- 输出结构固定为:
- {
- "updatedStableMemory": {
- "confirmedFacts": "string",
- "keyEvidence": "string",
- "openQuestions": "string"
- },
- "decision": {
- "summary": "string",
- "reason": "string",
- "expectedOutcome": "string"
- },
- "readyToDeliver": false,
- "nextAction":
- | { "action": "learning", "wantLearnSkillIds": ["skill-id"] }
- | { "action": "hand", "toolUsePlan": { "mode": "parallel", "calls": [{ "toolName": "tool_name", "args": {} }] } }
- | { "action": "mouth" }
- }
-
- 字段解释:
- - updatedStableMemory:可选对象。表示本轮对任务笔记的局部更新。
- - updatedStableMemory 缺失:表示本轮不更新任务笔记。
- - updatedStableMemory 出现但某个字段缺失:表示该字段保持原值。
- - updatedStableMemory 的字段值是字符串:表示用该字符串覆盖对应字段。
- - updatedStableMemory 的字段值是空字符串:表示显式清空对应字段。
- - decision:对象。表示你本轮的正式判断。
- - readyToDeliver:布尔值。只有当当前已经具备最终交付所需的信息、证据和产物时,才为 true。
- - nextAction:对象。表示下一跳动作,且只能输出 learning、hand、mouth 三种结构之一。
- - 不要输出 markdown。
-
+
+ - 你必须只输出 JSON,不要输出任何额外说明,也不要输出 markdown。
+ - 输出顶层结构固定为:
+ {
+ "updatedStableMemory"?: {
+ "confirmedFacts"?: "string",
+ "keyEvidence"?: "string",
+ "openQuestions"?: "string"
+ },
+ "decision": {
+ "summary": "string",
+ "reason": "string",
+ "expectedOutcome": "string"
+ },
+ "readyToDeliver": "boolean",
+ "nextAction":
+ | { "action": "learning", "wantLearnSkillIds": ["skill-id"] }
+ | { "action": "hand", "toolUsePlan": { "mode": "parallel|serial", "calls": [{ "toolName": "tool_name", "args": {} }] } }
+ | { "action": "mouth" }
+ }
+ - updatedStableMemory 是可选的 partial patch;缺失表示本轮不更新任务笔记。
+ - updatedStableMemory 中某个字段缺失:表示该字段保持原值。
+ - updatedStableMemory 中某个字段为空字符串:表示显式清空该字段。
+ - updatedStableMemory.confirmedFacts:只写当前已经确认、可以直接成立的事实。
+ - updatedStableMemory.keyEvidence:只写支撑事实的关键依据、证据来源或命中摘要。
+ - updatedStableMemory.openQuestions:只写仍阻碍收敛的未知点、限制或待确认项。
+ - decision.summary:一句话概括你本轮的判断或下一步意图。
+ - decision.reason:说明你为什么这样判断,必须基于已给上下文、记忆或真实结果。
+ - decision.expectedOutcome:说明你希望下一跳拿到什么结果,帮助后续节点收敛。
+ - readyToDeliver=true 只表示当前已经具备最终交付所需的信息、证据和产物。
+ - nextAction=learning:当你已经知道缺少哪类能力说明,且补齐后能明显降低不确定性时选择。
+ - nextAction=hand:当下一步已经明确成一批工具调用,且你能给出完整合法的 toolUsePlan 时选择。
+ - hand.toolUsePlan.mode:parallel 只用于只读且彼此独立、并行安全的调用;其余情况必须用 serial。
+ - hand.toolUsePlan.calls[*].toolName:必须严格使用当前工具说明里的精确名称。
+ - hand.toolUsePlan.calls[*].args:必须是对象,字段名、必填参数和参数层级都必须与工具说明一致。
+ - nextAction=mouth:只在 readyToDeliver=true 且当前已经足够形成最终交付时选择。
+
@@ -348,6 +351,31 @@ export const buildBrainPrompt = (input: { state: HumanState; ctx: AiRunContext }
}
+
+ {
+ "decision": {
+ "summary": "下一步已经明确,准备执行真实工具调用。",
+ "reason": "当前已具备所需能力,且已经能写出完整合法的工具参数。",
+ "expectedOutcome": "拿到当前工作区路径,供后续判断继续使用。"
+ },
+ "readyToDeliver": false,
+ "nextAction": {
+ "action": "hand",
+ "toolUsePlan": {
+ "mode": "serial",
+ "calls": [
+ {
+ "toolName": "terminal_run_command",
+ "args": {
+ "command": "pwd"
+ }
+ }
+ ]
+ }
+ }
+ }
+
+
{
"updatedStableMemory": {
@@ -376,23 +404,16 @@ ${input.state.task.userInput}
-这是当前任务的资料范围、工作区边界与默认可检索范围说明。
-它描述当前任务默认可以接触的资料范围,以及用户是否已经显式缩圈。
-
${renderReferenceScopeText(input.ctx.referenceScope)}
-这是你之前沉淀下来的任务笔记。
-它记录当前任务中已经确认的事实、关键依据和仍未解决的问题。
-
${renderHumanStableNotes(input.state, 'brain_prompt')}
${renderRoundSection({
- intro: '这是最近一轮过程记录。',
records: getLastRoundFocus(input.state) ? [getLastRoundFocus(input.state)!] : [],
detail: 'focus'
})}
@@ -400,14 +421,13 @@ ${renderRoundSection({
${renderRoundSection({
- intro: '这是更早几轮过程记录。',
records: getHistoryChainRounds(input.state),
detail: 'chain'
})}
-${renderLoadedHistorySection(getLoadedHistoryContext(input.state))}
+${renderLoadedHistoryText(getLoadedHistoryContext(input.state))}
@@ -416,8 +436,6 @@ ${renderAvailableSkillsSection(input.state)}
-这是当前的收敛或纠偏提示。
-
${input.state.execution.watchHint ? renderWatchHintForBrain(input.state.execution.watchHint) : 'none'}
diff --git a/src/main/services/ai/human/prompts/mouth.ts b/src/main/services/ai/human/prompts/mouth.ts
index c8ca3e28..487b4fe6 100644
--- a/src/main/services/ai/human/prompts/mouth.ts
+++ b/src/main/services/ai/human/prompts/mouth.ts
@@ -11,11 +11,7 @@ import { renderWatchHintForMouth } from './watchHints'
const renderRecentProgressSection = (record: HumanRoundRecord | undefined): string => {
if (!record) {
- return `
-这是最近一轮过程记录。
-
-none
-`.trim()
+ return 'none'
}
const progressText =
@@ -55,8 +51,6 @@ ${record.execution.toolResults.map((result) => `- \`${result.toolName}\`:${res
: `- mouth 输出摘要:${record.execution.summary}`
return `
-这是最近一轮过程记录。
-
- 第 ${record.roundId} 轮判断:${record.decision.decision.summary}
- 原因:${record.decision.decision.reason}
- 预期结果:${record.decision.decision.expectedOutcome}
@@ -83,6 +77,24 @@ export const buildMouthPrompt = (input: { state: HumanState; deliveryMode: Human
只把已经确认的信息组织成最终交付。
+
+ - final_decision 是 brain 已经确认的最终判断;你负责表达,不负责重新推翻或改写它。
+ - your_notes 是当前任务的稳定事实来源,包括已确认事实、关键依据和未决问题;正文中的事实与依据优先从这里取。
+ - recent_progress 只用于补充最近完成到哪里、最近结果如何,不必把内部过程完整复述出来。
+ - runtime_artifacts 只允许准确引用已经给出的路径、文件名、状态和摘要,不要补编额外元数据。
+ - correction_hint 只用于如实说明限制、阻断或未完成点,不要把它扩写成新的事实。
+
+
+
+ - delivery_mode:当前交付模式,决定结果面向谁,以及结果应该如何组织。
+ - task_goal:用户原始诉求与限制。
+ - final_decision:brain 已经确认的最终判断与收口方向。
+ - your_notes:稳定任务笔记,按“已确认 / 关键依据 / 未决问题”组织。
+ - recent_progress:最近一轮过程记录,用于补充当前完成到哪里。
+ - runtime_artifacts:运行中已经产生的真实产物列表。
+ - correction_hint:当前额外的收敛或纠偏提醒;若无则为 none。
+
+
1. 如果任务已经完成,先直接给出结论,再给关键依据,再给结果或产物说明。
2. 如果当前结果有限,先说明已经完成到哪里,再说明限制和继续需要什么。
@@ -96,17 +108,14 @@ export const buildMouthPrompt = (input: { state: HumanState; deliveryMode: Human
${DELIVERY_MODE_PROMPT_RULES[input.deliveryMode]}
-
- 你必须只输出最终 markdown 正文,不要输出任何额外说明,不要包 JSON,不要包代码块。
-
-
-
+
+ - 你必须只输出最终 markdown 正文,不要输出任何额外说明、JSON 或代码块。
- 不要引入新的事实、依据、步骤或承诺。
- 不要暴露内部字段名、节点名或系统术语。
- 如果依据不足,就保持保守表达,不要写成确定结论。
- 不要把未来可能执行的工具动作写成“后续会自动完成”或“已经在进行中”。
- 输出必须是完整结果,而不是零散句子或局部片段。
-
+
${DELIVERY_MODE_PROMPT_EXAMPLES[input.deliveryMode]}
diff --git a/tests/unit/ai/human-brain-history-prompt.test.ts b/tests/unit/ai/human-brain-history-prompt.test.ts
index 4c79fe77..2d45b1d3 100644
--- a/tests/unit/ai/human-brain-history-prompt.test.ts
+++ b/tests/unit/ai/human-brain-history-prompt.test.ts
@@ -204,14 +204,19 @@ describe('ai unit brain prompt history blocks', () => {
expect(prompt.user).toContain('优先参考资料:')
expect(prompt.system).toContain('')
expect(prompt.system).toContain('')
- expect(prompt.system).toContain('')
+ expect(prompt.system).toContain('')
+ expect(prompt.system).toContain('')
expect(prompt.system).not.toContain('')
expect(prompt.system).not.toContain('')
expect(prompt.system).not.toContain('human graph')
expect(prompt.system).not.toContain('')
- expect(prompt.user).toContain('这是你之前沉淀下来的任务笔记。')
- expect(prompt.user).toContain('这是最近一轮过程记录。')
- expect(prompt.user).toContain('这是更早几轮过程记录。')
+ expect(prompt.system).toContain('task_goal:用户原始诉求与限制。')
+ expect(prompt.system).toContain('recalled_history:主动回看的详细历史')
+ expect(prompt.user).not.toContain('这是用户这次直接提出的自然语言任务目标与限制。')
+ expect(prompt.user).not.toContain('这是你之前沉淀下来的任务笔记。')
+ expect(prompt.user).not.toContain('这是最近一轮最值得优先看的完整过程记录。')
+ expect(prompt.user).not.toContain('这是更早几轮的过程链。')
+ expect(prompt.user).not.toContain('这是当前的收敛或纠偏提示。')
expect(prompt.user).toContain('history-recall')
expect(prompt.user).toContain('决策了什么:')
expect(prompt.user).toContain('做了什么:')
diff --git a/tests/unit/ai/learning-tool-budget.test.ts b/tests/unit/ai/learning-tool-budget.test.ts
index 9514c09c..2635424b 100644
--- a/tests/unit/ai/learning-tool-budget.test.ts
+++ b/tests/unit/ai/learning-tool-budget.test.ts
@@ -133,8 +133,11 @@ describe('ai unit learning tool budget', () => {
expect(prompt).toContain('')
expect(prompt).toContain('你只负责判断下一步')
expect(prompt).toContain('learning 只负责补齐当前真正缺失的技能说明')
- expect(prompt).toContain('')
+ expect(prompt).toContain('')
+ expect(prompt).toContain('')
expect(prompt).toContain('updatedStableMemory')
+ expect(prompt).toContain('updatedStableMemory 是可选的 partial patch')
+ expect(prompt).toContain('hand.toolUsePlan.calls[*].args')
expect(prompt).toContain('mouth 只负责整理最终结果,不新增事实,不继续执行工具')
expect(prompt).not.toContain('')
expect(prompt).not.toContain('')
diff --git a/tests/unit/ai/mouth-ready-to-deliver.test.ts b/tests/unit/ai/mouth-ready-to-deliver.test.ts
index 883cd6ba..6a7b327e 100644
--- a/tests/unit/ai/mouth-ready-to-deliver.test.ts
+++ b/tests/unit/ai/mouth-ready-to-deliver.test.ts
@@ -72,10 +72,35 @@ describe('ai unit mouth readyToDeliver guard', () => {
deliveryMode: 'user_answer'
}).system
+ expect(prompt).toContain('')
+ expect(prompt).toContain('')
+ expect(prompt).toContain('')
+ expect(prompt).toContain('final_decision 是 brain 已经确认的最终判断')
+ expect(prompt).toContain('runtime_artifacts 只允许准确引用已经给出的路径')
expect(prompt).toContain('你不会调用工具,也不会继续推进未完成步骤')
expect(prompt).toContain('不要把未来可能执行的工具动作写成“后续会自动完成”')
expect(prompt).toContain('你必须只输出最终 markdown 正文')
expect(prompt).not.toContain('"deliveryMarkdown"')
expect(prompt).not.toContain('"summary"')
})
+
+ it('keeps mouth user-context blocks data-only and moves explanations into system', () => {
+ const result = buildMouthPrompt({
+ state: createInitialHumanState({
+ taskId: 'task-2',
+ userInput: '请根据当前信息给我一个最终答复'
+ }),
+ deliveryMode: 'user_answer'
+ })
+
+ expect(result.system).toContain('delivery_mode:当前交付模式')
+ expect(result.system).toContain('final_decision:brain 已经确认的最终判断')
+ expect(result.user).not.toContain('这是当前交付模式。')
+ expect(result.user).not.toContain('这是用户这次原始诉求与限制。')
+ expect(result.user).not.toContain('这是 brain 已经做出的最终决定。')
+ expect(result.user).not.toContain('这是任务的稳定笔记')
+ expect(result.user).not.toContain('这是最近一轮最相关的过程记录。')
+ expect(result.user).not.toContain('这是运行中已经产生的真实产物列表。')
+ expect(result.user).not.toContain('这是当前额外的收敛或纠偏提醒。')
+ })
})