test(auto-reply): guard message-tool-only reply privacy

This commit is contained in:
Peter Steinberger
2026-05-03 13:02:43 +01:00
parent 869103684f
commit 6e2f394473
2 changed files with 54 additions and 0 deletions

View File

@@ -471,6 +471,31 @@ describe("tryDispatchAcpReply", () => {
expect(dispatcher.sendBlockReply).not.toHaveBeenCalled();
});
it("keeps same-provider tool-only ACP final replies private when an origin route exists", async () => {
setReadyAcpResolution();
mockVisibleTextTurn("hidden final");
const onReplyStart = vi.fn();
const { dispatcher } = createDispatcher();
const result = await runDispatch({
bodyForAgent: "reply via message tool if needed",
dispatcher,
onReplyStart,
suppressUserDelivery: true,
suppressReplyLifecycle: false,
sourceReplyDeliveryMode: "message_tool_only",
shouldRouteToOriginating: true,
originatingChannel: "discord",
originatingTo: "channel:C1",
});
expect(result?.queuedFinal).toBe(false);
expect(onReplyStart).toHaveBeenCalledTimes(1);
expect(routeMocks.routeReply).not.toHaveBeenCalled();
expect(dispatcher.sendFinalReply).not.toHaveBeenCalled();
expect(dispatcher.sendBlockReply).not.toHaveBeenCalled();
});
it("edits ACP tool lifecycle updates in place when supported", async () => {
setReadyAcpResolution();
mockToolLifecycleTurn("call-1");

View File

@@ -4502,6 +4502,35 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
expect(dispatcher.sendFinalReply).not.toHaveBeenCalled();
});
it("does not auto-route same-provider group/channel final replies in message-tool-only mode", async () => {
setNoAbort();
mocks.routeReply.mockClear();
const dispatcher = createDispatcher();
const replyResolver = vi.fn(async (_ctx: MsgContext, opts?: GetReplyOptions) => {
expect(opts?.sourceReplyDeliveryMode).toBe("message_tool_only");
return { text: "final reply" } satisfies ReplyPayload;
});
const result = await dispatchReplyFromConfig({
ctx: buildTestCtx({
ChatType: "channel",
Provider: "discord",
Surface: "discord",
OriginatingChannel: "discord",
OriginatingTo: "channel:C1",
SessionKey: "test:discord:channel:C1",
}),
cfg: emptyConfig,
dispatcher,
replyResolver,
});
expect(replyResolver).toHaveBeenCalledTimes(1);
expect(result.queuedFinal).toBe(false);
expect(dispatcher.sendFinalReply).not.toHaveBeenCalled();
expect(mocks.routeReply).not.toHaveBeenCalled();
});
it("uses harness defaults for direct source delivery when config is unset", async () => {
setNoAbort();
registerAgentHarness({