mirror of https://github.com/openclaw/openclaw.git
fix: only suppress synthesizedText errors when no valid payloads exist
The delivery path prefers deliveryPayloads over synthesizedText when payloads are non-empty. If synthesizedText contains stale error text but deliveryPayloads has valid content (media, structured data), the guard was incorrectly suppressing delivery. Now only checks synthesizedText when there are no active delivery payloads. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
df896b49df
commit
fb456b4f3f
|
|
@ -320,6 +320,22 @@ describe("dispatchCronDelivery — error output guard", () => {
|
|||
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows delivery when synthesizedText has error but deliveryPayloads has valid content", async () => {
|
||||
const errorJson = JSON.stringify({
|
||||
type: "error",
|
||||
error: { type: "server_error", message: "fail" },
|
||||
});
|
||||
const params = makeBaseParams({ synthesizedText: errorJson });
|
||||
// Override with valid structured payload — delivery path prefers these
|
||||
params.deliveryPayloads = [{ text: "Your weekly report is attached." }];
|
||||
const state = await dispatchCronDelivery(params);
|
||||
|
||||
// Valid payloads take priority; error in synthesizedText should not
|
||||
// suppress delivery of non-error payload content.
|
||||
expect(state.delivered).toBe(true);
|
||||
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("preserves shared-delivery flags when skipMessagingToolDelivery is true", async () => {
|
||||
const errorJson = JSON.stringify({
|
||||
type: "error",
|
||||
|
|
|
|||
|
|
@ -323,14 +323,17 @@ export async function dispatchCronDelivery(
|
|||
// Guard: never deliver raw error output (provider JSON errors, runtime
|
||||
// exceptions) to user-facing channels. The error is still logged internally
|
||||
// and visible via `cron runs`, but should not be posted to channels.
|
||||
// Check both synthesizedText and deliveryPayloads — the delivery path
|
||||
// prefers deliveryPayloads when non-empty, so error text arriving there
|
||||
// would bypass a synthesizedText-only guard.
|
||||
//
|
||||
// The delivery path prefers deliveryPayloads when non-empty, so we only
|
||||
// suppress based on synthesizedText when there are no valid payloads that
|
||||
// would take priority (e.g., media or structured content). When payloads
|
||||
// exist, we check whether ALL of them contain error text instead.
|
||||
// See: https://github.com/openclaw/openclaw/issues/42243
|
||||
const errorInSynthesized = synthesizedText && isLikelyRawErrorOutput(synthesizedText);
|
||||
const hasActivePayloads = deliveryPayloads.length > 0;
|
||||
const errorInSynthesized =
|
||||
!hasActivePayloads && synthesizedText && isLikelyRawErrorOutput(synthesizedText);
|
||||
const errorInPayloads =
|
||||
!errorInSynthesized &&
|
||||
deliveryPayloads.length > 0 &&
|
||||
hasActivePayloads &&
|
||||
deliveryPayloads.every((p) => typeof p.text === "string" && isLikelyRawErrorOutput(p.text));
|
||||
if (errorInSynthesized || errorInPayloads) {
|
||||
const source = errorInSynthesized ? "synthesizedText" : "deliveryPayloads";
|
||||
|
|
|
|||
Loading…
Reference in New Issue