diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java index b92c6999..69f31c16 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java @@ -509,6 +509,8 @@ public class ReasoningNode implements NodeAction { String workspaceBasePath = state.value(vip.mate.agent.graph.state.MateClawStateKeys.WORKSPACE_BASE_PATH, ""); String agentIdStr = state.value(MateClawStateKeys.AGENT_ID, ""); String userMsg = state.value(MateClawStateKeys.USER_MESSAGE, ""); + String runtimeModelName = state.value(MateClawStateKeys.RUNTIME_MODEL_NAME, ""); + String runtimeProviderId = state.value(MateClawStateKeys.RUNTIME_PROVIDER_ID, ""); // Build the non-history prefix ONCE. The PTL retry branch below // reuses this list verbatim so the retried prompt has exactly the @@ -517,7 +519,7 @@ public class ReasoningNode implements NodeAction { // segment which led to "answer regressed after compaction" // complaints on long sessions. List nonHistoryPrefix = buildNonHistoryPrefix(systemPrompt, workspaceBasePath, agentIdStr, userMsg, - accessor.chatOrigin()); + accessor.chatOrigin(), runtimeModelName, runtimeProviderId); // Append the runtime-rendered skill catalog as a SEPARATE SystemMessage // right after the skeleton system prompt. Keeping it out of the baked @@ -967,10 +969,13 @@ public class ReasoningNode implements NodeAction { String workspaceBasePath, String agentIdStr, String userMsg, - vip.mate.agent.context.ChatOrigin chatOrigin) { + vip.mate.agent.context.ChatOrigin chatOrigin, + String runtimeModelName, + String runtimeProviderId) { List prefix = new ArrayList<>(); prefix.add(new SystemMessage(systemPrompt)); - prefix.add(new UserMessage(RuntimeContextInjector.buildContextMessage(workspaceBasePath, null, chatOrigin))); + prefix.add(new UserMessage(RuntimeContextInjector.buildContextMessage( + workspaceBasePath, null, chatOrigin, runtimeModelName, runtimeProviderId))); // When this turn already recalled the user's own current project from // structured memory, skip auto-injecting knowledge-base reference context. // Otherwise the KB pages (reference material, possibly about unrelated diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/PlanGenerationNode.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/PlanGenerationNode.java index 7d4ed73e..a3f1fb74 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/PlanGenerationNode.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/PlanGenerationNode.java @@ -169,8 +169,11 @@ public class PlanGenerationNode implements NodeAction { vip.mate.agent.context.ChatOrigin chatOrigin = state.value(MateClawStateKeys.CHAT_ORIGIN) .orElse(vip.mate.agent.context.ChatOrigin.EMPTY); + String runtimeModelName = state.value(MateClawStateKeys.RUNTIME_MODEL_NAME, ""); + String runtimeProviderId = state.value(MateClawStateKeys.RUNTIME_PROVIDER_ID, ""); promptMessages.add(new UserMessage( - RuntimeContextInjector.buildContextMessage(workspaceBasePath, null, chatOrigin))); + RuntimeContextInjector.buildContextMessage( + workspaceBasePath, null, chatOrigin, runtimeModelName, runtimeProviderId))); // Advertise available tools so the LLM can recognize when an action is possible, // but do NOT force "any tool usage implies multi-step" — single-hop tool use diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/StepExecutionNode.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/StepExecutionNode.java index f43729de..5097e880 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/StepExecutionNode.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/plan/node/StepExecutionNode.java @@ -166,6 +166,8 @@ public class StepExecutionNode implements NodeAction { vip.mate.agent.context.ChatOrigin chatOrigin = state.value(MateClawStateKeys.CHAT_ORIGIN) .orElse(vip.mate.agent.context.ChatOrigin.EMPTY); + String runtimeModelName = state.value(MateClawStateKeys.RUNTIME_MODEL_NAME, ""); + String runtimeProviderId = state.value(MateClawStateKeys.RUNTIME_PROVIDER_ID, ""); if (stepIndex >= steps.size()) { log.warn("[StepExecution] stepIndex {} >= steps.size() {}, skipping", stepIndex, steps.size()); @@ -195,7 +197,8 @@ public class StepExecutionNode implements NodeAction { planningService.updateSubPlanStatus(planId, stepIndex, "running"); // 构建消息列表 - List messages = buildStepMessages(accessor, step, systemPrompt, workspaceBasePath); + List messages = buildStepMessages(accessor, step, systemPrompt, workspaceBasePath, + runtimeModelName, runtimeProviderId); // 显式工具执行循环 String finalResult = null; @@ -509,7 +512,8 @@ public class StepExecutionNode implements NodeAction { return sb.toString(); } - private List buildStepMessages(PlanStateAccessor accessor, String step, String systemPrompt, String workspaceBasePath) { + private List buildStepMessages(PlanStateAccessor accessor, String step, String systemPrompt, + String workspaceBasePath, String runtimeModelName, String runtimeProviderId) { List messages = new ArrayList<>(); // Layer 1: System prompt(增强指令) @@ -537,9 +541,10 @@ public class StepExecutionNode implements NodeAction { messages.add(new SystemMessage(skillCatalog)); } } - // 注入运行时上下文(当前时间 + 工作目录 + 发起者上下文) + // 注入运行时上下文(当前时间 + 工作目录 + 发起者上下文 + 模型身份) messages.add(new UserMessage( - RuntimeContextInjector.buildContextMessage(workspaceBasePath, null, accessor.chatOrigin()))); + RuntimeContextInjector.buildContextMessage( + workspaceBasePath, null, accessor.chatOrigin(), runtimeModelName, runtimeProviderId))); // Layer 2: Working context(对话历史 + 步骤结果的受控长度摘要) String workingContext = accessor.workingContext(); diff --git a/mateclaw-server/src/test/java/vip/mate/agent/graph/node/ReasoningNodePtlPromptTest.java b/mateclaw-server/src/test/java/vip/mate/agent/graph/node/ReasoningNodePtlPromptTest.java index 34679910..3c0d4851 100644 --- a/mateclaw-server/src/test/java/vip/mate/agent/graph/node/ReasoningNodePtlPromptTest.java +++ b/mateclaw-server/src/test/java/vip/mate/agent/graph/node/ReasoningNodePtlPromptTest.java @@ -48,7 +48,7 @@ class ReasoningNodePtlPromptTest { "/workspace/active", "42", "investigate the bug in module X", - vip.mate.agent.context.ChatOrigin.EMPTY); + vip.mate.agent.context.ChatOrigin.EMPTY, "", ""); // Three layers: System, runtime-context UserMessage, wiki UserMessage. assertThat(prefix).hasSize(3); @@ -74,10 +74,10 @@ class ReasoningNodePtlPromptTest { List a = node.buildNonHistoryPrefix( "sys", "/workspace", "42", "goal", - vip.mate.agent.context.ChatOrigin.EMPTY); + vip.mate.agent.context.ChatOrigin.EMPTY, "", ""); List b = node.buildNonHistoryPrefix( "sys", "/workspace", "42", "goal", - vip.mate.agent.context.ChatOrigin.EMPTY); + vip.mate.agent.context.ChatOrigin.EMPTY, "", ""); assertThat(a).hasSameSizeAs(b); for (int i = 0; i < a.size(); i++) { @@ -98,7 +98,7 @@ class ReasoningNodePtlPromptTest { "/workspace/active", "42", "investigate the bug in module X", - vip.mate.agent.context.ChatOrigin.EMPTY); + vip.mate.agent.context.ChatOrigin.EMPTY, "", ""); assertThat(prefix).hasSize(2); assertThat(prefix.get(0)).isInstanceOf(SystemMessage.class); @@ -112,7 +112,7 @@ class ReasoningNodePtlPromptTest { List prefix = node.buildNonHistoryPrefix( "sys", "/workspace", "not-a-number", "goal", - vip.mate.agent.context.ChatOrigin.EMPTY); + vip.mate.agent.context.ChatOrigin.EMPTY, "", ""); // Non-numeric agentId is the contract carried over from the // pre-refactor codebase — skip wiki injection rather than throwing. @@ -132,7 +132,7 @@ class ReasoningNodePtlPromptTest { List prefix = node.buildNonHistoryPrefix( "sys", "/workspace", "42", "goal", - vip.mate.agent.context.ChatOrigin.EMPTY); + vip.mate.agent.context.ChatOrigin.EMPTY, "", ""); assertThat(prefix).hasSize(2); }