Skip to content

Commit 6fd9ec9

Browse files
committed
fix(gateway): preserve turn-origin messageChannel in agent runs
1 parent 08e3357 commit 6fd9ec9

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

src/gateway/server-methods/agent.test.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ async function invokeAgent(
184184
respond?: ReturnType<typeof vi.fn>;
185185
reqId?: string;
186186
context?: GatewayRequestContext;
187+
client?: AgentHandlerArgs["client"];
188+
isWebchatConnect?: AgentHandlerArgs["isWebchatConnect"];
187189
},
188190
) {
189191
const respond = options?.respond ?? vi.fn();
@@ -192,8 +194,8 @@ async function invokeAgent(
192194
respond: respond as never,
193195
context: options?.context ?? makeContext(),
194196
req: { type: "req", id: options?.reqId ?? "agent-test-req", method: "agent" },
195-
client: null,
196-
isWebchatConnect: () => false,
197+
client: options?.client ?? null,
198+
isWebchatConnect: options?.isWebchatConnect ?? (() => false),
197199
});
198200
return respond;
199201
}
@@ -346,6 +348,56 @@ describe("gateway agent handler", () => {
346348
expect(callArgs.bestEffortDeliver).toBe(false);
347349
});
348350

351+
it("keeps origin messageChannel as webchat while delivery channel uses last session channel", async () => {
352+
mockMainSessionEntry({
353+
sessionId: "existing-session-id",
354+
lastChannel: "telegram",
355+
lastTo: "12345",
356+
});
357+
mocks.updateSessionStore.mockImplementation(async (_path, updater) => {
358+
const store: Record<string, unknown> = {
359+
"agent:main:main": {
360+
sessionId: "existing-session-id",
361+
updatedAt: Date.now(),
362+
lastChannel: "telegram",
363+
lastTo: "12345",
364+
},
365+
};
366+
return await updater(store);
367+
});
368+
mocks.agentCommand.mockResolvedValue({
369+
payloads: [{ text: "ok" }],
370+
meta: { durationMs: 100 },
371+
});
372+
373+
await invokeAgent(
374+
{
375+
message: "webchat turn",
376+
sessionKey: "agent:main:main",
377+
idempotencyKey: "test-webchat-origin-channel",
378+
},
379+
{
380+
reqId: "webchat-origin-1",
381+
client: {
382+
connect: {
383+
client: { id: "webchat-ui", mode: "webchat" },
384+
},
385+
} as AgentHandlerArgs["client"],
386+
isWebchatConnect: () => true,
387+
},
388+
);
389+
390+
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
391+
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
392+
channel?: string;
393+
messageChannel?: string;
394+
runContext?: { messageChannel?: string };
395+
};
396+
expect(callArgs.channel).toBe("telegram");
397+
expect(callArgs.messageChannel).toBe("webchat");
398+
expect(callArgs.runContext?.messageChannel).toBe("webchat");
399+
});
400+
349401
it("handles missing cliSessionIds gracefully", async () => {
350402
mockMainSessionEntry({});
351403

src/gateway/server-methods/agent.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,17 @@ export const agentHandlers: GatewayRequestHandlers = {
563563
return;
564564
}
565565

566+
const normalizedTurnSource = normalizeMessageChannel(turnSourceChannel);
567+
const turnSourceMessageChannel =
568+
normalizedTurnSource && isGatewayMessageChannel(normalizedTurnSource)
569+
? normalizedTurnSource
570+
: undefined;
571+
const originMessageChannel =
572+
turnSourceMessageChannel ??
573+
(client?.connect && isWebchatConnect(client.connect)
574+
? INTERNAL_MESSAGE_CHANNEL
575+
: resolvedChannel);
576+
566577
const deliver = request.deliver === true && resolvedChannel !== INTERNAL_MESSAGE_CHANNEL;
567578

568579
const accepted = {
@@ -594,7 +605,7 @@ export const agentHandlers: GatewayRequestHandlers = {
594605
accountId: resolvedAccountId,
595606
threadId: resolvedThreadId,
596607
runContext: {
597-
messageChannel: resolvedChannel,
608+
messageChannel: originMessageChannel,
598609
accountId: resolvedAccountId,
599610
groupId: resolvedGroupId,
600611
groupChannel: resolvedGroupChannel,
@@ -607,7 +618,7 @@ export const agentHandlers: GatewayRequestHandlers = {
607618
spawnedBy: spawnedByValue,
608619
timeout: request.timeout?.toString(),
609620
bestEffortDeliver,
610-
messageChannel: resolvedChannel,
621+
messageChannel: originMessageChannel,
611622
runId,
612623
lane: request.lane,
613624
extraSystemPrompt: request.extraSystemPrompt,

0 commit comments

Comments
 (0)