Skip to content

Commit c99add6

Browse files
moeedahmedamittell
andauthored
fix(reply): honor suppressToolErrors for progress
5.22 already drops the tool-error WARNING text via payloads.ts, but the error tool-result payload was still delivered as channel progress unless sourceReplyDeliveryMode was message_tool_only. Operators who opt into messages.suppressToolErrors expect no tool-error noise in chat at all. Add a config-gated early-return in the onToolResult dispatch path so the visible progress delivery is dropped too, matching the warning-text policy. No-op unless messages.suppressToolErrors is true. Folds the mac-mini deploy hotfix into the tracked branch. (cherry picked from commit a973410) Co-authored-by: amittell <[email protected]>
1 parent 1cf6ff3 commit c99add6

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4262,6 +4262,39 @@ describe("dispatchReplyFromConfig", () => {
42624262
expect(dispatcher.sendFinalReply).not.toHaveBeenCalled();
42634263
});
42644264

4265+
it("suppresses tool error payloads when messages.suppressToolErrors is enabled", async () => {
4266+
setNoAbort();
4267+
const dispatcher = createDispatcher();
4268+
const onToolResult = vi.fn();
4269+
const ctx = buildTestCtx({
4270+
Provider: "telegram",
4271+
ChatType: "direct",
4272+
SessionKey: "agent:main:main",
4273+
});
4274+
4275+
const replyResolver = async (_ctx: MsgContext, opts?: GetReplyOptions) => {
4276+
await opts?.onToolResult?.({ text: "⚠️ 🛠️ sqlite3 failed", isError: true });
4277+
return { text: "handled" } satisfies ReplyPayload;
4278+
};
4279+
4280+
await dispatchReplyFromConfig({
4281+
ctx,
4282+
cfg: {
4283+
agents: { defaults: { verboseDefault: "on" } },
4284+
messages: {
4285+
suppressToolErrors: true,
4286+
},
4287+
} as OpenClawConfig,
4288+
dispatcher,
4289+
replyResolver,
4290+
replyOptions: { onToolResult },
4291+
});
4292+
4293+
expect(onToolResult).not.toHaveBeenCalled();
4294+
expect(dispatcher.sendToolResult).not.toHaveBeenCalled();
4295+
expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "handled" });
4296+
});
4297+
42654298
it("keeps message-tool-only failed tool output compact in normal verbose mode", async () => {
42664299
setNoAbort();
42674300
sessionStoreMocks.currentEntry = {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3132,6 +3132,13 @@ export async function dispatchReplyFromConfig(
31323132
markInboundDedupeReplayUnsafe();
31333133
// Buffered commentary preceded this tool; land it before the summary.
31343134
await flushPendingCommentaryProgress();
3135+
// When the operator opts into messages.suppressToolErrors, never
3136+
// surface tool-error tool-result payloads as channel progress,
3137+
// regardless of source delivery mode. payloads.ts already drops
3138+
// the warning text; this drops the visible progress delivery too.
3139+
if (payload.isError === true && replyConfig.messages?.suppressToolErrors === true) {
3140+
return;
3141+
}
31353142
const isFastModeAutoProgress = isFastModeAutoProgressPayload(payload);
31363143
const isForcedToolProgress =
31373144
shouldDeliverForcedToolProgressDespiteSourceSuppression();

0 commit comments

Comments
 (0)