mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:40:49 +00:00
fix: scope session id routing to requested agent
This commit is contained in:
@@ -41,6 +41,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Plugins/onboarding: record local plugin install source metadata without duplicating raw absolute local paths in persisted `plugins.installs`, while preserving linked load-path cleanup. (#70970) Thanks @vincentkoc.
|
||||
- Browser/tool: tell agents not to pass per-call `timeoutMs` on existing-session type, evaluate, and other Chrome MCP actions that reject timeout overrides.
|
||||
- Codex/GPT-5.4: harden fallback, auth-profile, tool-schema, and replay edge cases across native and embedded runtime paths. (#70743) Thanks @100yenadmin.
|
||||
- Agents/CLI: keep `--agent` plus `--session-id` lookup scoped to the requested agent store, so explicit agent resumes cannot select another agent's session. (#70985) Thanks @frankekn.
|
||||
- Voice-call/Telnyx: preserve inbound/outbound callback metadata and read transcription text from Telnyx's current `transcription_data` payload.
|
||||
- Codex harness: send verbose tool progress to chat channels for native app-server runs, matching the Pi harness `/verbose on` and `/verbose full` behavior. (#70966) Thanks @jalehman.
|
||||
- Codex models: fetch paginated Codex app-server model catalogs, mark truncated `/codex models` output, and keep ChatGPT OAuth defaults on the `openai-codex/gpt-5.5` route instead of the OpenAI API-key route.
|
||||
|
||||
@@ -58,6 +58,7 @@ function collectSessionIdMatchesForRequest(opts: {
|
||||
storePath: string;
|
||||
storeAgentId?: string;
|
||||
sessionId: string;
|
||||
searchOtherAgentStores: boolean;
|
||||
}): SessionIdMatchSet {
|
||||
const matches: Array<[string, SessionEntry]> = [];
|
||||
const primaryStoreMatches: Array<[string, SessionEntry]> = [];
|
||||
@@ -85,6 +86,10 @@ function collectSessionIdMatchesForRequest(opts: {
|
||||
};
|
||||
|
||||
addMatches(opts.sessionStore, opts.storePath, { primary: true });
|
||||
if (!opts.searchOtherAgentStores) {
|
||||
return { matches, primaryStoreMatches, storeByKey };
|
||||
}
|
||||
|
||||
for (const agentId of listAgentIds(opts.cfg)) {
|
||||
if (agentId === opts.storeAgentId) {
|
||||
continue;
|
||||
@@ -146,7 +151,9 @@ export function resolveSessionKeyForRequest(opts: {
|
||||
agentId: requestedAgentId,
|
||||
})
|
||||
: undefined);
|
||||
const storeAgentId = resolveAgentIdFromSessionKey(explicitSessionKey) ?? requestedAgentId;
|
||||
const storeAgentId = explicitSessionKey
|
||||
? resolveAgentIdFromSessionKey(explicitSessionKey)
|
||||
: (requestedAgentId ?? normalizeAgentId(undefined));
|
||||
const storePath = resolveStorePath(sessionCfg?.store, {
|
||||
agentId: storeAgentId,
|
||||
});
|
||||
@@ -171,6 +178,7 @@ export function resolveSessionKeyForRequest(opts: {
|
||||
storePath,
|
||||
storeAgentId,
|
||||
sessionId: opts.sessionId,
|
||||
searchOtherAgentStores: requestedAgentId === undefined,
|
||||
});
|
||||
const preferredSelection = resolveSessionIdMatchSelection(matches, opts.sessionId);
|
||||
const currentStoreSelection =
|
||||
|
||||
@@ -126,6 +126,30 @@ describe("resolveSessionKeyForRequest", () => {
|
||||
expect(result.storePath).toBe(MYBOT_STORE_PATH);
|
||||
});
|
||||
|
||||
it("does not search other agent stores when --agent scopes --session-id", async () => {
|
||||
setupMainAndMybotStorePaths();
|
||||
mockStoresByPath({
|
||||
[MAIN_STORE_PATH]: {
|
||||
"agent:main:whatsapp:direct:+15550000000": {
|
||||
sessionId: "target-session-id",
|
||||
updatedAt: 10,
|
||||
},
|
||||
},
|
||||
[MYBOT_STORE_PATH]: {},
|
||||
});
|
||||
|
||||
const result = resolveSessionKeyForRequest({
|
||||
cfg: baseCfg,
|
||||
agentId: "mybot",
|
||||
sessionId: "target-session-id",
|
||||
});
|
||||
|
||||
expect(result.sessionKey).toBe("agent:mybot:explicit:target-session-id");
|
||||
expect(result.storePath).toBe(MYBOT_STORE_PATH);
|
||||
expect(mocks.loadSessionStore).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.loadSessionStore).toHaveBeenCalledWith(MYBOT_STORE_PATH);
|
||||
});
|
||||
|
||||
it("returns correct sessionStore when session found in non-primary agent store", async () => {
|
||||
const mybotStore = {
|
||||
"agent:mybot:main": { sessionId: "target-session-id", updatedAt: 0 },
|
||||
|
||||
@@ -1018,9 +1018,11 @@ describe("gateway agent handler", () => {
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
|
||||
agentId?: string;
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
};
|
||||
expect(call?.agentId).toBe("main");
|
||||
expect(call?.sessionId).toBe("resume-whatsapp-session");
|
||||
expect(call?.sessionKey).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -921,6 +921,7 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
message,
|
||||
images,
|
||||
imageOrder,
|
||||
agentId,
|
||||
provider: providerOverride,
|
||||
model: modelOverride,
|
||||
to: resolvedTo,
|
||||
|
||||
Reference in New Issue
Block a user