diff --git a/CHANGELOG.md b/CHANGELOG.md index c9a2af12556..b79c297b700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Agents/session status: keep semantic `session_status({ sessionKey: "current" })` on the live run session even before that run has a persisted session-store entry, instead of falling back to the sandbox policy key. Thanks @vincentkoc. - Codex: pass the live run session key into app-server dynamic tools when sandbox policy uses a separate session key, so `session_status({ sessionKey: "current" })` reports the active run instead of the sandbox policy key. Thanks @vincentkoc. - Plugins/tools: mark manifest-optional sibling tools as optional even when they come from a shared non-optional factory, so cached/status/MCP metadata keeps opt-in tool policy accurate. Thanks @vincentkoc. - Matrix: keep `streaming.progress.toolProgress` scoped to progress draft mode, so partial and quiet Matrix previews do not lose tool progress unless `streaming.preview.toolProgress` is disabled. Thanks @vincentkoc. diff --git a/src/agents/openclaw-tools.session-status.test.ts b/src/agents/openclaw-tools.session-status.test.ts index ea08a4c59b4..aaabe3594f4 100644 --- a/src/agents/openclaw-tools.session-status.test.ts +++ b/src/agents/openclaw-tools.session-status.test.ts @@ -521,6 +521,28 @@ describe("session_status tool", () => { expect(details.sessionKey).toBe("agent:main:main"); }); + it("synthesizes semantic current from runSessionKey when the live run is not persisted yet", async () => { + resetSessionStore({ + "agent:main:telegram:default:direct:1234": { + sessionId: "s-tg-direct", + updatedAt: 5, + status: "done", + }, + }); + + const tool = createSessionStatusTool({ + agentSessionKey: "agent:main:telegram:default:direct:1234", + runSessionKey: "agent:main:main", + config: mockConfig as never, + }); + + const result = await tool.execute("call-current-unpersisted-run", { sessionKey: "current" }); + const details = result.details as { ok?: boolean; sessionKey?: string; statusText?: string }; + expect(details.ok).toBe(true); + expect(details.sessionKey).toBe("agent:main:main"); + expect(details.statusText).toContain("OpenClaw"); + }); + it("rejects explicit cross-session key under tree visibility even when it equals runSessionKey (#76708)", async () => { resetSessionStore({ "agent:main:telegram:default:direct:1234": { diff --git a/src/agents/tools/session-status-tool.ts b/src/agents/tools/session-status-tool.ts index 6dba9a402bb..2d823a22b5a 100644 --- a/src/agents/tools/session-status-tool.ts +++ b/src/agents/tools/session-status-tool.ts @@ -147,14 +147,14 @@ function synthesizeImplicitCurrentSessionEntry(): SessionEntry { function resolveImplicitCurrentSessionFallback(params: { allowFallback: boolean; - storeScopedRequesterKey: string; + fallbackKey: string; }): { key: string; entry: SessionEntry } | null { - const requesterKey = params.storeScopedRequesterKey.trim(); - if (!params.allowFallback || !requesterKey) { + const fallbackKey = params.fallbackKey.trim(); + if (!params.allowFallback || !fallbackKey) { return null; } return { - key: requesterKey, + key: fallbackKey, entry: synthesizeImplicitCurrentSessionEntry(), }; } @@ -511,7 +511,10 @@ export function createSessionStatusTool(opts?: { if (!resolved) { const fallback = resolveImplicitCurrentSessionFallback({ allowFallback: isSemanticCurrentRequest || requestedKeyParam === undefined, - storeScopedRequesterKey, + fallbackKey: + isSemanticCurrentRequest && opts?.runSessionKey + ? opts.runSessionKey + : storeScopedRequesterKey, }); if (fallback) { resolved = fallback;