Skip to content

Commit d34e6ee

Browse files
author
Eva (agent)
committed
fix: preserve webchat external-origin message delivery
1 parent 9246fa6 commit d34e6ee

2 files changed

Lines changed: 55 additions & 4 deletions

File tree

src/auto-reply/reply/dispatch-from-config.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4960,6 +4960,50 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
49604960
expect(firstFinalReplyPayload(dispatcher)?.text).toBe("visible webchat reply");
49614961
});
49624962

4963+
it("keeps harness message-tool delivery for explicit external WebChat origins", async () => {
4964+
setNoAbort();
4965+
registerAgentHarness({
4966+
id: "codex",
4967+
label: "Codex",
4968+
deliveryDefaults: { sourceVisibleReplies: "message_tool" },
4969+
supports: () => ({ supported: true, priority: 100 }),
4970+
runAttempt: vi.fn(async () => ({}) as never),
4971+
});
4972+
sessionStoreMocks.currentEntry = {
4973+
sessionId: "s1",
4974+
updatedAt: 0,
4975+
agentHarnessId: "codex",
4976+
sendPolicy: "allow",
4977+
};
4978+
const dispatcher = createDispatcher();
4979+
const replyResolver = vi.fn(async (_ctx: MsgContext, opts?: GetReplyOptions) => {
4980+
expect(opts?.sourceReplyDeliveryMode).toBe("message_tool_only");
4981+
return { text: "external reply should use message tool" } satisfies ReplyPayload;
4982+
});
4983+
4984+
const result = await dispatchReplyFromConfig({
4985+
ctx: buildTestCtx({
4986+
ChatType: "direct",
4987+
CommandSource: undefined,
4988+
From: "webchat:user",
4989+
To: "webchat:main",
4990+
Provider: "webchat",
4991+
Surface: "webchat",
4992+
OriginatingChannel: "imessage",
4993+
OriginatingTo: "imessage:+15550001111",
4994+
ExplicitDeliverRoute: true,
4995+
SessionKey: "agent:main:main",
4996+
}),
4997+
cfg: emptyConfig,
4998+
dispatcher,
4999+
replyResolver,
5000+
});
5001+
5002+
expect(replyResolver).toHaveBeenCalledTimes(1);
5003+
expect(result.queuedFinal).toBe(false);
5004+
expect(dispatcher.sendFinalReply).not.toHaveBeenCalled();
5005+
});
5006+
49635007
it("falls back to automatic group/channel delivery when the message tool is unavailable", async () => {
49645008
setNoAbort();
49655009
const dispatcher = createDispatcher();

src/auto-reply/reply/dispatch-from-config.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,17 @@ const createShouldEmitVerboseProgress = (params: {
296296
};
297297
};
298298

299-
const isInternalWebchatSourceContext = (ctx: FinalizedMsgContext): boolean =>
300-
normalizeMessageChannel(ctx.Provider) === INTERNAL_MESSAGE_CHANNEL ||
301-
normalizeMessageChannel(ctx.Surface) === INTERNAL_MESSAGE_CHANNEL ||
302-
normalizeMessageChannel(ctx.OriginatingChannel) === INTERNAL_MESSAGE_CHANNEL;
299+
const isInternalWebchatSourceContext = (ctx: FinalizedMsgContext): boolean => {
300+
const provider = normalizeMessageChannel(ctx.Provider);
301+
const surface = normalizeMessageChannel(ctx.Surface);
302+
const originatingChannel = normalizeMessageChannel(ctx.OriginatingChannel);
303+
const currentSurfaceIsWebchat =
304+
provider === INTERNAL_MESSAGE_CHANNEL || surface === INTERNAL_MESSAGE_CHANNEL;
305+
if (!currentSurfaceIsWebchat) {
306+
return false;
307+
}
308+
return !originatingChannel || originatingChannel === INTERNAL_MESSAGE_CHANNEL;
309+
};
303310

304311
const resolveHarnessSourceVisibleRepliesDefault = (params: {
305312
cfg: OpenClawConfig;

0 commit comments

Comments
 (0)