mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 19:35:28 -06:00
fix(sessions): preserve thread on internal turns (#121321)
This commit is contained in:
committed by
GitHub
parent
7d1958bf61
commit
93ba11138f
@@ -5095,6 +5095,75 @@ describe("initSessionState stale threadId fallback", () => {
|
||||
expect(result.sessionEntry.deliveryContext?.threadId).toBe("650.000");
|
||||
});
|
||||
|
||||
it("preserves external thread routing for internal turns and clears it for external non-thread turns", async () => {
|
||||
const storePath = await createStorePath("internal-thread-route-");
|
||||
const cfg = { session: { store: storePath } } as OpenClawConfig;
|
||||
const sessionKey = "agent:main:main";
|
||||
|
||||
await writeSessionStoreFast(storePath, {
|
||||
[sessionKey]: {
|
||||
sessionId: "session-internal-thread-route",
|
||||
updatedAt: Date.now(),
|
||||
delivery: {
|
||||
kind: "external",
|
||||
route: {
|
||||
channel: "imessage",
|
||||
accountId: "imessage-default",
|
||||
target: { to: "+15551234567", chatType: "direct" },
|
||||
thread: { id: "thread-42", kind: "thread", source: "session" },
|
||||
},
|
||||
context: {
|
||||
channel: "imessage",
|
||||
to: "+15551234567",
|
||||
accountId: "imessage-default",
|
||||
threadId: "thread-42",
|
||||
},
|
||||
origin: {
|
||||
provider: "webchat",
|
||||
to: "+15551234567",
|
||||
accountId: "imessage-default",
|
||||
threadId: "thread-42",
|
||||
chatType: "direct",
|
||||
surface: "webchat",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const internal = await initSessionState({
|
||||
ctx: {
|
||||
Body: "internal control-ui turn",
|
||||
SessionKey: sessionKey,
|
||||
OriginatingChannel: "webchat",
|
||||
},
|
||||
cfg,
|
||||
});
|
||||
expect(internal.sessionEntry.lastThreadId).toBe("thread-42");
|
||||
expect(internal.sessionEntry.deliveryContext).toEqual({
|
||||
channel: "imessage",
|
||||
to: "+15551234567",
|
||||
accountId: "imessage-default",
|
||||
threadId: "thread-42",
|
||||
});
|
||||
|
||||
const plainExternal = await initSessionState({
|
||||
ctx: {
|
||||
Body: "plain external turn",
|
||||
SessionKey: sessionKey,
|
||||
OriginatingChannel: "imessage",
|
||||
OriginatingTo: "+15551234567",
|
||||
AccountId: "imessage-default",
|
||||
},
|
||||
cfg,
|
||||
});
|
||||
expect(plainExternal.sessionEntry.lastThreadId).toBeUndefined();
|
||||
expect(plainExternal.sessionEntry.deliveryContext).toEqual({
|
||||
channel: "imessage",
|
||||
to: "+15551234567",
|
||||
accountId: "imessage-default",
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves lastThreadId within the same thread session", async () => {
|
||||
const storePath = await createStorePath("preserve-thread-");
|
||||
const cfg = { session: { store: storePath } } as OpenClawConfig;
|
||||
|
||||
@@ -91,6 +91,7 @@ import {
|
||||
sessionDeliveryOrigin,
|
||||
sessionDeliveryRoute,
|
||||
} from "../../utils/delivery-context.shared.js";
|
||||
import { isInternalMessageChannel } from "../../utils/message-channel.js";
|
||||
import { resolveCommandTurnTargetSessionKey } from "../command-turn-context.js";
|
||||
import type {
|
||||
FinalizedRuntimeMsgContext,
|
||||
@@ -839,14 +840,14 @@ async function initSessionStateAttemptLocked(
|
||||
accountIdRaw: ctx.AccountId,
|
||||
persistedLastAccountId: baseDeliveryContext?.accountId,
|
||||
});
|
||||
// Only fall back to persisted threadId for thread sessions. Non-thread
|
||||
// sessions (e.g. DM without topics) must not inherit a stale threadId from a
|
||||
// previous interaction that happened inside a topic/thread.
|
||||
// Internal turns share the established external route and must not erase its
|
||||
// thread. External non-thread turns still clear stale thread routing.
|
||||
const preservePersistedThread = isThread || isInternalMessageChannel(originatingChannelRaw);
|
||||
const lastThreadIdRaw = isSystemEvent
|
||||
? baseDeliveryContext?.threadId
|
||||
: (ctx.MessageThreadId ??
|
||||
ctx.TransportThreadId ??
|
||||
(isThread ? baseDeliveryContext?.threadId : undefined));
|
||||
(preservePersistedThread ? baseDeliveryContext?.threadId : undefined));
|
||||
const delivery = isSystemEvent
|
||||
? normalizeSessionDeliveryState({
|
||||
route: isThread ? baseDeliveryRoute : stripThreadFromSessionRoute(baseDeliveryRoute),
|
||||
|
||||
Reference in New Issue
Block a user