惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
量子位
M
Microsoft Research Blog - Microsoft Research
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
罗磊的独立博客
V
Visual Studio Blog
Last Week in AI
Last Week in AI
阮一峰的网络日志
阮一峰的网络日志
IT之家
IT之家
aimingoo的专栏
aimingoo的专栏
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog

Recent Commits to openclaw:main

fix(release): accept sha-verified publish evidence · openclaw/openclaw@7439d78 fix(ui): handle empty strings with minLength constraint in config sav… · openclaw/openclaw@3b3b2cc fix(agents): treat aborted subagent runs as terminal fix: treat aborted subagent lifecycle events as killed fix: prefer aborted stop reason over blocked lifecycle docs: add changelog for aborted subagent fix docs: update changelog for whatsapp reply fence fix(cli): preserve command option state · openclaw/openclaw@15ff89b fix(cli): preserve explicit command intent · openclaw/openclaw@9410eb3 fix(cli): keep plugin command metadata intact · openclaw/openclaw@9ab0af2 fix(twitch): wait through auth retry disconnects · openclaw/openclaw@9177860 fix(cli): keep secrets configure JSON singular · openclaw/openclaw@97c63e6 fix(twitch): cancel pending clients during shutdown · openclaw/openclaw@e9bf111 fix(plugins): avoid Signal and Twitch setup regressions · openclaw/openclaw@5b2703e fix(plugins): fail stalled runtime operations · openclaw/openclaw@eeb5f12 fix: address PR review comments · openclaw/openclaw@08159d8 fix(tools): tolerate out-of-scope autoreview findings · openclaw/openclaw@8cc9329 fix(twitch): cancel auth retry disconnects · openclaw/openclaw@841cb12 fix(ci): address review sweep regressions fix(plugins): stabilize Twitch and Signal setup docs(changelog): note CLI and plugin bug fixes · openclaw/openclaw@181d55e fix(browser): validate inputs and redact remote URLs · openclaw/openclaw@bee15d4 fix(acp): require allow option for auto approvals · openclaw/openclaw@25ccadd fix(node): avoid stale TLS pins when retargeting · openclaw/openclaw@679b677 fix(cli): bound node media file writes · openclaw/openclaw@a4e95cf fix(gateway): scope imported history identity · openclaw/openclaw@6d6b247 fix(cli): keep completion and Twitch races bounded · openclaw/openclaw@6ce9e0d fix: avoid duplicate media source reply transcripts · openclaw/openclaw@a10e152 test: cover source reply media transcript backing · openclaw/openclaw@321d98b fix: broadcast source reply finals for chat runs · openclaw/openclaw@84ac31b fix: ignore replayed empty TUI finals · openclaw/openclaw@17fc1d1 fix: bound Codex post-reasoning source reply waits · openclaw/openclaw@f5b415f fix: preserve source reply metadata through TTS test: narrow transcript rewrite message content access · openclaw/openclaw@81dee15 fix: preserve reply metadata through media normalization · openclaw/openclaw@a238f03 fix: preserve reply payload metadata · openclaw/openclaw@bfcd801 test: cover control ui source reply final retention · openclaw/openclaw@5534cad fix: keep source reply finals live in control ui · openclaw/openclaw@5e28574 fix: guard transcript source reply rewrites · openclaw/openclaw@b074dc5 fix: keep TUI watchdog runs active · openclaw/openclaw@84d278a fix: render late source reply finals in TUI · openclaw/openclaw@59b8aea docs: add TUI source reply changelog · openclaw/openclaw@589fd92 fix: keep long Codex source replies alive · openclaw/openclaw@c93dda9 fix: avoid double terminal chat events for source replies · openclaw/openclaw@6a0e030 fix: back source reply media in transcripts · openclaw/openclaw@39226ea fix: gracefully escalate process supervisor cancellations (#85865) · openclaw/openclaw@b13166b fix: preserve internal handoff status attribution [AI-assisted] (#85726) · openclaw/openclaw@f55e986 fix(browser): thread snapshot timeoutMs through agent tool and helper… · openclaw/openclaw@069c7b8 Disable Chrome MCP telemetry watchdog by default (#85886) · openclaw/openclaw@d581415 perf: cache stable gateway metadata · openclaw/openclaw@12f8227 chore(release): update appcast for 2026.5.22 · openclaw/openclaw@fc3c979 fix(codex): ensure codex subagent bootstrap parity with pi subagents … · openclaw/openclaw@7b3be04 fix(update): escape systemd update handoffs (#85414) · openclaw/openclaw@1f28c3e fix(media-understanding): restore image description token default · openclaw/openclaw@5dcbd38 chore: bump version to 2026.5.24 · openclaw/openclaw@0cba872 fix(ui): delay WebChat done indicator until reply renders docs: note WebChat done ordering fix · openclaw/openclaw@6c21066 feat(talk): add realtime active-run control · openclaw/openclaw@bbf9c45 feat(ui): control active realtime talk runs docs(talk): document realtime active-run control · openclaw/openclaw@40d36b5 feat(gateway): steer realtime relay agent runs feat(discord): control active realtime voice runs fix(tui): handle German AltGr input (#83947) · openclaw/openclaw@ee09481 docs: clarify commit fallback provenance · openclaw/openclaw@6e03d1c fix(pdf): move MiniMax PDF fallback policy to metadata · openclaw/openclaw@d92501d fix(pdf): use MiniMax text model fallback · openclaw/openclaw@89bb62e fix(pdf): preserve image fallback precedence fix(ui): preserve source config for Control UI saves (#85879) · openclaw/openclaw@1a60c19 fix(doctor): repair stale contextWindow for DeepSeek V4 Flash (#85840) · openclaw/openclaw@aa050a6 Feat/fix dashboard timeout error display (#85815) · openclaw/openclaw@a668982 fix(memory): write fallback dream diary on narrative timeout (#85821) · openclaw/openclaw@27a3290 fix(twitch): fail fast when auth provider cannot bind user (#85794) · openclaw/openclaw@72744fd docs: clarify PR provenance roles · openclaw/openclaw@9a73ddc fix(scripts): harden Windows QA runners · openclaw/openclaw@32f9150 docs(skills): prefer latest Parallels snapshots fix(telegram): normalize durable group retry targets (#85656) · openclaw/openclaw@f05f243 fix #84857: skip CLI runtime harness preflight during compaction (#85… · openclaw/openclaw@fa39bef docs(policy): add policy rule reference tables (#85795) · openclaw/openclaw@4ffbd07 Policy: add tool posture conformance checks (#85482) · openclaw/openclaw@1e2e614 fix(session-lock): enforce maxHoldMs in shouldReclaim during lock acq… · openclaw/openclaw@a1eb765 refactor: simplify channel catalog cache · openclaw/openclaw@a1c2d09 docs: codify gateway plugin metadata stability · openclaw/openclaw@d4299dc perf: reduce gateway benchmark filesystem churn · openclaw/openclaw@e5534dd fix: order meeting notes startup around channels · openclaw/openclaw@e2249d8 fix(sandbox): block bridge writes to workspace skills · openclaw/openclaw@9e5b416 fix(sandbox): mount workspace skills read-only · openclaw/openclaw@1b7bf4a fix: guard remote sandbox skill roots (#85591) · openclaw/openclaw@a8f6887 fix(sandbox): block remote bridge writes to skills fix: harden sandbox skill mounts (#85591) · openclaw/openclaw@a352678 test(sandbox): resolve skill roots read-only · openclaw/openclaw@07abb19 fix: close remote sandbox skill symlink aliases (#85591) · openclaw/openclaw@68487f4 fix(sandbox): filter remote skill mounts by existing roots · openclaw/openclaw@dd5fb1e test(sandbox): allow remote writes under absent skill roots · openclaw/openclaw@1094210 fix: preserve sandbox skill overlay precedence (#85591) fix(cli-runner): keep recent tail when reseed history exceeds maxHist… · openclaw/openclaw@5c4a733 docs: thank backup hardlink contributor (#83938) · openclaw/openclaw@846f566 test: drain Codex app-server attempts · openclaw/openclaw@a705a9c feat(agents): expose estimated context budget status · openclaw/openclaw@05c6e7a test: isolate Codex native item release guard · openclaw/openclaw@cd102ef fix: route Codex image API keys through OpenAI · openclaw/openclaw@38e1654
Fix foreground reply fence visibility · openclaw/openclaw@bd91107
cavit99 · 2026-05-24 · via Recent Commits to openclaw:main
Original file line numberDiff line numberDiff line change

@@ -466,6 +466,30 @@ describe("deliverWebReply", () => {

466466

expect(logVerbose).toHaveBeenCalled();

467467

});

468468
469+

it("marks errors visible after accepted media delivery", async () => {

470+

const msg = makeMsg();

471+

const error = new Error("tail send failed");

472+

mockLoadedImageMedia();

473+

vi.mocked(msg.reply).mockRejectedValue(error);

474+
475+

await expect(

476+

deliverWebReply({

477+

replyResult: { text: "captiontail", mediaUrl: "http://example.com/img.jpg" },

478+

msg,

479+

maxMediaBytes: 1024 * 1024,

480+

textLimit: 7,

481+

replyLogger,

482+

skipLog: true,

483+

}),

484+

).rejects.toMatchObject({

485+

sentBeforeError: true,

486+

visibleReplySent: true,

487+

});

488+
489+

expect(msg.sendMedia).toHaveBeenCalledTimes(1);

490+

expect(msg.reply).toHaveBeenCalled();

491+

});

492+
469493

it("preserves leading indentation after trimming only leading blank lines", async () => {

470494

const msg = makeMsg();

471495
Original file line numberDiff line numberDiff line change

@@ -83,6 +83,20 @@ function createWhatsAppReplyDeliveryReceipt(

8383

});

8484

}

8585
86+

function markWhatsAppVisibleDeliveryError(error: unknown): unknown {

87+

if (typeof error === "object" && error !== null && !Array.isArray(error)) {

88+

try {

89+

Object.assign(error, { sentBeforeError: true, visibleReplySent: true });

90+

return error;

91+

} catch {

92+

// Fall back to a wrapper when a platform error object is non-extensible.

93+

}

94+

}

95+

const visibleError = new Error("visible WhatsApp reply delivery failed", { cause: error });

96+

Object.assign(visibleError, { sentBeforeError: true, visibleReplySent: true });

97+

return visibleError;

98+

}

99+
86100

export async function deliverWebReply(params: {

87101

replyResult: ReplyPayload;

88102

normalizedReplyResult?: DeliverableWhatsAppOutboundPayload<ReplyPayload>;

@@ -150,15 +164,22 @@ export async function deliverWebReply(params: {

150164

};

151165
152166

const sendWithRetry = async <T>(fn: () => Promise<T>, label: string, maxAttempts = 3) => {

153-

return await sendWhatsAppOutboundWithRetry({

154-

send: fn,

155-

maxAttempts,

156-

onRetry: ({ attempt, maxAttempts: retryMaxAttempts, backoffMs, errorText }) => {

157-

logVerbose(

158-

`Retrying ${label} to ${msg.from} after failure (${attempt}/${retryMaxAttempts - 1}) in ${backoffMs}ms: ${errorText}`,

159-

);

160-

},

161-

});

167+

try {

168+

return await sendWhatsAppOutboundWithRetry({

169+

send: fn,

170+

maxAttempts,

171+

onRetry: ({ attempt, maxAttempts: retryMaxAttempts, backoffMs, errorText }) => {

172+

logVerbose(

173+

`Retrying ${label} to ${msg.from} after failure (${attempt}/${retryMaxAttempts - 1}) in ${backoffMs}ms: ${errorText}`,

174+

);

175+

},

176+

});

177+

} catch (error: unknown) {

178+

if (sendResults.some((result) => result.providerAccepted)) {

179+

throw markWhatsAppVisibleDeliveryError(error);

180+

}

181+

throw error;

182+

}

162183

};

163184
164185

// Text-only replies