diff --git a/packages/adapters/openclaw-gateway/src/server/execute.test.ts b/packages/adapters/openclaw-gateway/src/server/execute.test.ts new file mode 100644 index 00000000..0b18108c --- /dev/null +++ b/packages/adapters/openclaw-gateway/src/server/execute.test.ts @@ -0,0 +1,52 @@ +import { describe, expect, it } from "vitest"; +import { resolveSessionKey } from "./execute.js"; + +describe("resolveSessionKey", () => { + it("prefixes run-scoped session keys with the configured agent", () => { + expect( + resolveSessionKey({ + strategy: "run", + configuredSessionKey: null, + agentId: "meridian", + runId: "run-123", + issueId: null, + }), + ).toBe("agent:meridian:paperclip:run:run-123"); + }); + + it("prefixes issue-scoped session keys with the configured agent", () => { + expect( + resolveSessionKey({ + strategy: "issue", + configuredSessionKey: null, + agentId: "meridian", + runId: "run-123", + issueId: "issue-456", + }), + ).toBe("agent:meridian:paperclip:issue:issue-456"); + }); + + it("prefixes fixed session keys with the configured agent", () => { + expect( + resolveSessionKey({ + strategy: "fixed", + configuredSessionKey: "paperclip", + agentId: "meridian", + runId: "run-123", + issueId: null, + }), + ).toBe("agent:meridian:paperclip"); + }); + + it("does not double-prefix an already-routed session key", () => { + expect( + resolveSessionKey({ + strategy: "fixed", + configuredSessionKey: "agent:meridian:paperclip", + agentId: "meridian", + runId: "run-123", + issueId: null, + }), + ).toBe("agent:meridian:paperclip"); + }); +}); diff --git a/packages/adapters/openclaw-gateway/src/server/execute.ts b/packages/adapters/openclaw-gateway/src/server/execute.ts index bcb4e06b..02235f39 100644 --- a/packages/adapters/openclaw-gateway/src/server/execute.ts +++ b/packages/adapters/openclaw-gateway/src/server/execute.ts @@ -133,16 +133,26 @@ function normalizeSessionKeyStrategy(value: unknown): SessionKeyStrategy { return "issue"; } -function resolveSessionKey(input: { +function prefixSessionKeyForAgent(sessionKey: string, agentId: string | null): string { + if (!agentId || sessionKey.startsWith("agent:")) return sessionKey; + return `agent:${agentId}:${sessionKey}`; +} + +export function resolveSessionKey(input: { strategy: SessionKeyStrategy; configuredSessionKey: string | null; + agentId: string | null; runId: string; issueId: string | null; }): string { const fallback = input.configuredSessionKey ?? "paperclip"; - if (input.strategy === "run") return `paperclip:run:${input.runId}`; - if (input.strategy === "issue" && input.issueId) return `paperclip:issue:${input.issueId}`; - return fallback; + if (input.strategy === "run") { + return prefixSessionKeyForAgent(`paperclip:run:${input.runId}`, input.agentId); + } + if (input.strategy === "issue" && input.issueId) { + return prefixSessionKeyForAgent(`paperclip:issue:${input.issueId}`, input.agentId); + } + return prefixSessionKeyForAgent(fallback, input.agentId); } function isLoopbackHost(hostname: string): boolean { @@ -1106,6 +1116,7 @@ export async function execute(ctx: AdapterExecutionContext): Promise