fix(auto-reply): tighten silent token semantics and prefix streaming

This commit is contained in:
Ayaan Zaidi
2026-02-26 15:51:52 +05:30
committed by Ayaan Zaidi
parent 2f2110a32c
commit e64d72299e
7 changed files with 56 additions and 14 deletions

View File

@@ -1099,18 +1099,20 @@ describe("followup queue collect routing", () => {
const emptyCfg = {} as OpenClawConfig;
describe("createReplyDispatcher", () => {
it("drops empty payloads and silent tokens without media", async () => {
it("drops empty payloads and exact silent tokens without media", async () => {
const deliver = vi.fn().mockResolvedValue(undefined);
const dispatcher = createReplyDispatcher({ deliver });
expect(dispatcher.sendFinalReply({})).toBe(false);
expect(dispatcher.sendFinalReply({ text: " " })).toBe(false);
expect(dispatcher.sendFinalReply({ text: SILENT_REPLY_TOKEN })).toBe(false);
expect(dispatcher.sendFinalReply({ text: `${SILENT_REPLY_TOKEN} -- nope` })).toBe(false);
expect(dispatcher.sendFinalReply({ text: `interject.${SILENT_REPLY_TOKEN}` })).toBe(false);
expect(dispatcher.sendFinalReply({ text: `${SILENT_REPLY_TOKEN} -- nope` })).toBe(true);
expect(dispatcher.sendFinalReply({ text: `interject.${SILENT_REPLY_TOKEN}` })).toBe(true);
await dispatcher.waitForIdle();
expect(deliver).not.toHaveBeenCalled();
expect(deliver).toHaveBeenCalledTimes(2);
expect(deliver.mock.calls[0]?.[0]?.text).toBe(`${SILENT_REPLY_TOKEN} -- nope`);
expect(deliver.mock.calls[1]?.[0]?.text).toBe(`interject.${SILENT_REPLY_TOKEN}`);
});
it("strips heartbeat tokens and applies responsePrefix", async () => {
@@ -1162,7 +1164,7 @@ describe("createReplyDispatcher", () => {
expect(deliver).toHaveBeenCalledTimes(3);
expect(deliver.mock.calls[0][0].text).toBe("PFX already");
expect(deliver.mock.calls[1][0].text).toBe("");
expect(deliver.mock.calls[2][0].text).toBe("");
expect(deliver.mock.calls[2][0].text).toBe(`PFX ${SILENT_REPLY_TOKEN} -- explanation`);
});
it("preserves ordering across tool, block, and final replies", async () => {