diff --git a/examples/openclaw-plugin/README.md b/examples/openclaw-plugin/README.md index 46007e0cb..bc97ea306 100644 --- a/examples/openclaw-plugin/README.md +++ b/examples/openclaw-plugin/README.md @@ -55,7 +55,7 @@ This matters because the plugin is built to support multi-agent and multi-sessio ![Automatic recall flow before prompt build](./images/openclaw-plugin-recall-flow.png) -Today the main recall path still lives in `before_prompt_build`: +Today there are two recall-related paths: legacy hook injection in `before_prompt_build`, and context reconstruction in `assemble()`. They should not both inject prompt context for the same run: 1. Extract the latest user text from `messages` or `prompt`. 2. Resolve the agent routing for the current `sessionId/sessionKey`. @@ -182,7 +182,7 @@ The repo also contains a more future-looking design draft at `docs/design/opencl - this README describes current implemented behavior - the older draft discusses a stronger future move into context-engine-owned lifecycle control -- in the current version, the main automatic recall path still lives in `before_prompt_build`, not fully in `assemble()` +- in the current version, hook-based auto-recall still exists in `before_prompt_build`, but when the context-engine path is active it should not run alongside `assemble()` - in the current version, `afterTurn()` already appends to the OpenViking session, but commit remains threshold-triggered and asynchronous on that path - in the current version, `compact()` already uses `commit(wait=true)`, but it is still focused on synchronous commit plus readback rather than owning every orchestration concern diff --git a/examples/openclaw-plugin/index.ts b/examples/openclaw-plugin/index.ts index 849501402..b325ae3c7 100644 --- a/examples/openclaw-plugin/index.ts +++ b/examples/openclaw-plugin/index.ts @@ -903,6 +903,12 @@ const contextEnginePlugin = { ); return; } + if (contextEngineRef) { + verboseRoutingInfo( + `openviking: skipping before_prompt_build auto-recall because context-engine is active (sessionKey=${ctx?.sessionKey ?? "none"}, sessionId=${ctx?.sessionId ?? "none"})`, + ); + return; + } const agentId = resolveAgentId(ctx?.sessionId, ctx?.sessionKey); let client: OpenVikingClient; try { diff --git a/examples/openclaw-plugin/tests/ut/plugin-bypass-session-patterns.test.ts b/examples/openclaw-plugin/tests/ut/plugin-bypass-session-patterns.test.ts index 88e2e61d3..48226992d 100644 --- a/examples/openclaw-plugin/tests/ut/plugin-bypass-session-patterns.test.ts +++ b/examples/openclaw-plugin/tests/ut/plugin-bypass-session-patterns.test.ts @@ -65,6 +65,33 @@ describe("plugin bypass session patterns", () => { ); }); + it("skips before_prompt_build auto-recall once context-engine is active", async () => { + const { handlers, logger, registerContextEngine } = setupPlugin(); + + const factory = registerContextEngine.mock.calls[0]?.[1] as (() => unknown) | undefined; + expect(factory).toBeTruthy(); + factory!(); + + const hook = handlers.get("before_prompt_build"); + expect(hook).toBeTruthy(); + + const result = await hook!( + { + messages: [{ role: "user", content: "remember the launch checklist" }], + prompt: "remember the launch checklist", + }, + { + sessionId: "runtime-session", + sessionKey: "agent:main:test:1", + }, + ); + + expect(result).toBeUndefined(); + expect(logger.warn).not.toHaveBeenCalledWith( + expect.stringContaining("failed to get client"), + ); + }); + it("bypasses before_reset without calling commitOVSession", async () => { const { handlers, registerContextEngine } = setupPlugin({ bypassSessionPatterns: ["agent:*:cron:**"],