mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-05 22:32:12 +00:00
fix: keep NO_REPLY detection case-insensitive
This commit is contained in:
@@ -120,6 +120,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/exec: restore `host=node` routing for node-pinned and `host=auto` sessions, while still blocking sandboxed `auto` sessions from jumping to gateway. (#60788) Thanks @openperf.
|
||||
- Agents/compaction: keep assistant tool calls and displaced tool results in the same compaction chunk so strict summarization providers stop rejecting orphaned tool pairs. (#58849) Thanks @openperf.
|
||||
- Cron: suppress exact `NO_REPLY` sentinel direct-delivery payloads, keep silent direct replies from falling back into duplicate main-summary sends, and treat structured `deleteAfterRun` silent replies the same as text silent replies. (#45737) Thanks @openperf.
|
||||
- Cron: keep exact silent-token detection case-insensitive again so mixed-case `NO_REPLY` outputs still stay silent in text and direct delivery paths. Thanks @obviyus.
|
||||
|
||||
## 2026.4.2
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ describe("isSilentReplyText", () => {
|
||||
expect(isSilentReplyText("\nNO_REPLY\n")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true for mixed-case token", () => {
|
||||
expect(isSilentReplyText("no_reply")).toBe(true);
|
||||
expect(isSilentReplyText(" No_RePlY ")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false for undefined/empty", () => {
|
||||
expect(isSilentReplyText(undefined)).toBe(false);
|
||||
expect(isSilentReplyText("")).toBe(false);
|
||||
|
||||
@@ -12,7 +12,7 @@ function getSilentExactRegex(token: string): RegExp {
|
||||
return cached;
|
||||
}
|
||||
const escaped = escapeRegExp(token);
|
||||
const regex = new RegExp(`^\\s*${escaped}\\s*$`);
|
||||
const regex = new RegExp(`^\\s*${escaped}\\s*$`, "i");
|
||||
silentExactRegexByToken.set(token, regex);
|
||||
return regex;
|
||||
}
|
||||
|
||||
@@ -673,6 +673,32 @@ describe("dispatchCronDelivery — double-announce guard", () => {
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("suppresses mixed-case NO_REPLY in text delivery", async () => {
|
||||
vi.mocked(countActiveDescendantRuns).mockReturnValue(0);
|
||||
vi.mocked(isLikelyInterimCronMessage).mockReturnValue(false);
|
||||
|
||||
const params = makeBaseParams({ synthesizedText: "No_Reply" });
|
||||
const state = await dispatchCronDelivery(params);
|
||||
|
||||
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
|
||||
expect(state.result).toEqual(
|
||||
expect.objectContaining({
|
||||
status: "ok",
|
||||
delivered: false,
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
shouldEnqueueCronMainSummary({
|
||||
summaryText: "No_Reply",
|
||||
deliveryRequested: true,
|
||||
delivered: state.result?.delivered,
|
||||
deliveryAttempted: state.result?.deliveryAttempted,
|
||||
suppressMainSummary: false,
|
||||
isCronSystemEvent: () => true,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("cleans up the direct cron session after a structured silent reply when deleteAfterRun is enabled", async () => {
|
||||
vi.mocked(countActiveDescendantRuns).mockReturnValue(0);
|
||||
vi.mocked(isLikelyInterimCronMessage).mockReturnValue(false);
|
||||
|
||||
Reference in New Issue
Block a user