test(auto-reply): guard message-tool-only reply privacy · openclaw/openclaw@6e2f394
steipete
·
2026-05-03
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -471,6 +471,31 @@ describe("tryDispatchAcpReply", () => {
|
471 | 471 | expect(dispatcher.sendBlockReply).not.toHaveBeenCalled(); |
472 | 472 | }); |
473 | 473 | |
| 474 | +it("keeps same-provider tool-only ACP final replies private when an origin route exists", async () => { |
| 475 | +setReadyAcpResolution(); |
| 476 | +mockVisibleTextTurn("hidden final"); |
| 477 | +const onReplyStart = vi.fn(); |
| 478 | +const { dispatcher } = createDispatcher(); |
| 479 | + |
| 480 | +const result = await runDispatch({ |
| 481 | +bodyForAgent: "reply via message tool if needed", |
| 482 | + dispatcher, |
| 483 | + onReplyStart, |
| 484 | +suppressUserDelivery: true, |
| 485 | +suppressReplyLifecycle: false, |
| 486 | +sourceReplyDeliveryMode: "message_tool_only", |
| 487 | +shouldRouteToOriginating: true, |
| 488 | +originatingChannel: "discord", |
| 489 | +originatingTo: "channel:C1", |
| 490 | +}); |
| 491 | + |
| 492 | +expect(result?.queuedFinal).toBe(false); |
| 493 | +expect(onReplyStart).toHaveBeenCalledTimes(1); |
| 494 | +expect(routeMocks.routeReply).not.toHaveBeenCalled(); |
| 495 | +expect(dispatcher.sendFinalReply).not.toHaveBeenCalled(); |
| 496 | +expect(dispatcher.sendBlockReply).not.toHaveBeenCalled(); |
| 497 | +}); |
| 498 | + |
474 | 499 | it("edits ACP tool lifecycle updates in place when supported", async () => { |
475 | 500 | setReadyAcpResolution(); |
476 | 501 | mockToolLifecycleTurn("call-1"); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -4502,6 +4502,35 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
|
4502 | 4502 | expect(dispatcher.sendFinalReply).not.toHaveBeenCalled(); |
4503 | 4503 | }); |
4504 | 4504 | |
| 4505 | +it("does not auto-route same-provider group/channel final replies in message-tool-only mode", async () => { |
| 4506 | +setNoAbort(); |
| 4507 | +mocks.routeReply.mockClear(); |
| 4508 | +const dispatcher = createDispatcher(); |
| 4509 | +const replyResolver = vi.fn(async (_ctx: MsgContext, opts?: GetReplyOptions) => { |
| 4510 | +expect(opts?.sourceReplyDeliveryMode).toBe("message_tool_only"); |
| 4511 | +return { text: "final reply" } satisfies ReplyPayload; |
| 4512 | +}); |
| 4513 | + |
| 4514 | +const result = await dispatchReplyFromConfig({ |
| 4515 | +ctx: buildTestCtx({ |
| 4516 | +ChatType: "channel", |
| 4517 | +Provider: "discord", |
| 4518 | +Surface: "discord", |
| 4519 | +OriginatingChannel: "discord", |
| 4520 | +OriginatingTo: "channel:C1", |
| 4521 | +SessionKey: "test:discord:channel:C1", |
| 4522 | +}), |
| 4523 | +cfg: emptyConfig, |
| 4524 | + dispatcher, |
| 4525 | + replyResolver, |
| 4526 | +}); |
| 4527 | + |
| 4528 | +expect(replyResolver).toHaveBeenCalledTimes(1); |
| 4529 | +expect(result.queuedFinal).toBe(false); |
| 4530 | +expect(dispatcher.sendFinalReply).not.toHaveBeenCalled(); |
| 4531 | +expect(mocks.routeReply).not.toHaveBeenCalled(); |
| 4532 | +}); |
| 4533 | + |
4505 | 4534 | it("uses harness defaults for direct source delivery when config is unset", async () => { |
4506 | 4535 | setNoAbort(); |
4507 | 4536 | registerAgentHarness({ |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。