From d708ddb222abda2c8d5396bbf4ce9ee5c4549fe3 Mon Sep 17 00:00:00 2001 From: Josh Lehman Date: Fri, 20 Mar 2026 07:41:03 -0700 Subject: [PATCH] Agents: cover model-aware context engine assembly --- CHANGELOG.md | 1 + .../run/attempt.spawn-workspace.test.ts | 40 +++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a0f3618bc7..b95fe247361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ Docs: https://docs.openclaw.ai - Web tools/Tavily: add Tavily as a bundled web-search provider with dedicated `tavily_search` and `tavily_extract` tools, using canonical plugin-owned config under `plugins.entries.tavily.config.webSearch.*`. (#49200) thanks @lakshyaag-tavily. - Docs/plugins: add the community DingTalk plugin listing to the docs catalog. (#29913) Thanks @sliverp. - Docs/plugins: add the community QQbot plugin listing to the docs catalog. (#29898) Thanks @sliverp. +- Plugins/context engines: pass the embedded runner `modelId` into context-engine `assemble()` so plugins can adapt context formatting per model. (#47437) thanks @jscianna. ### Fixes diff --git a/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test.ts b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test.ts index fa2bb58fbbc..082442045d3 100644 --- a/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test.ts +++ b/src/agents/pi-embedded-runner/run/attempt.spawn-workspace.test.ts @@ -39,6 +39,7 @@ const hoisted = vi.hoisted(() => { contextFiles: [], })); const getGlobalHookRunnerMock = vi.fn<() => unknown>(() => undefined); + const initializeGlobalHookRunnerMock = vi.fn(); const sessionManager = { getLeafEntry: vi.fn(() => null), branch: vi.fn(), @@ -55,6 +56,7 @@ const hoisted = vi.hoisted(() => { acquireSessionWriteLockMock, resolveBootstrapContextForRunMock, getGlobalHookRunnerMock, + initializeGlobalHookRunnerMock, sessionManager, }; }); @@ -94,6 +96,7 @@ vi.mock("../../pi-embedded-subscribe.js", () => ({ vi.mock("../../../plugins/hook-runner-global.js", () => ({ getGlobalHookRunner: hoisted.getGlobalHookRunnerMock, + initializeGlobalHookRunner: hoisted.initializeGlobalHookRunnerMock, })); vi.mock("../../../infra/machine-name.js", () => ({ @@ -216,6 +219,16 @@ vi.mock("../../cache-trace.js", () => ({ createCacheTrace: () => undefined, })); +vi.mock("../../pi-tools.js", () => ({ + createOpenClawCodingTools: () => [], + resolveToolLoopDetectionConfig: () => undefined, +})); + +vi.mock("../../../image-generation/runtime.js", () => ({ + generateImage: vi.fn(), + listRuntimeImageGenerationProviders: () => [], +})); + vi.mock("../../model-selection.js", async (importOriginal) => { const actual = await importOriginal(); @@ -346,10 +359,12 @@ function createDefaultEmbeddedSession(params?: { function createContextEngineBootstrapAndAssemble() { return { bootstrap: vi.fn(async (_params: { sessionKey?: string }) => ({ bootstrapped: true })), - assemble: vi.fn(async ({ messages }: { messages: AgentMessage[]; sessionKey?: string }) => ({ - messages, - estimatedTokens: 1, - })), + assemble: vi.fn( + async ({ messages }: { messages: AgentMessage[]; sessionKey?: string; model?: string }) => ({ + messages, + estimatedTokens: 1, + }), + ), }; } @@ -677,6 +692,7 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => { sessionKey?: string; messages: AgentMessage[]; tokenBudget?: number; + model?: string; }) => Promise; afterTurn?: (params: { sessionId: string; @@ -783,6 +799,22 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => { expectCalledWithSessionKey(afterTurn, sessionKey); }); + it("forwards modelId to assemble", async () => { + const { bootstrap, assemble } = createContextEngineBootstrapAndAssemble(); + + const result = await runAttemptWithContextEngine({ + bootstrap, + assemble, + }); + + expect(result.promptError).toBeNull(); + expect(assemble).toHaveBeenCalledWith( + expect.objectContaining({ + model: "gpt-test", + }), + ); + }); + it("forwards sessionKey to ingestBatch when afterTurn is absent", async () => { const { bootstrap, assemble } = createContextEngineBootstrapAndAssemble(); const ingestBatch = vi.fn(