fix(auto-reply): guard missing dispatcher getFailedCounts without weakening the SDK type#89148
fix(auto-reply): guard missing dispatcher getFailedCounts without weakening the SDK type#89148Alix-007 wants to merge 1 commit into
Conversation
|
Codex review: passed. Reviewed June 1, 2026, 11:47 PM ET / 03:47 UTC. Summary PR surface: Source +24, Tests +35. Total +59 across 5 files. Reproducibility: yes. Source inspection shows current main calls Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Next step before merge
Security Review detailsBest possible solution: Land the narrow internal guard with the focused regression coverage while keeping the plugin-facing dispatcher API unchanged. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main calls Is this the best way to solve the issue? Yes. The PR fixes the crash at the internal count-reading boundary and covers the sibling direct call sites without changing the SDK-visible AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 7c4fb1bd2cde. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +24, Tests +35. Total +59 across 5 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
0839372 to
2ab1a0d
Compare
2ab1a0d to
38abdc7
Compare
|
@clawsweeper re-review Addressed the rank-up move: the two Feishu On the [P1] SDK-visibility note: making |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
38abdc7 to
8993d63
Compare
|
Rebased onto latest @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
…kening the SDK type getDispatcherFinalOutcomeCounts called dispatcher.getFailedCounts() without optional chaining while the adjacent getCancelledCounts?.() was guarded, so dispatcher variants omitting getFailedCounts threw "TypeError: dispatcher.getFailedCounts is not a function". Keep the public ReplyDispatcher.getFailedCounts contract required (no plugin-facing SDK break) and add an internal DispatcherOutcomeCountsView plus a readDispatcherFailedCounts helper for the defensive accounting paths in core dispatch (dispatch-from-config, dispatch-acp-delivery) and the Feishu extension bot, each falling back to zero counts when a non-conforming runtime dispatcher omits the method. Fixes openclaw#89116 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8993d63 to
9a1d408
Compare
|
Reworked per the P1 review feedback. Instead of making the SDK-visible Re-verified at head @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper automerge |
|
🦞🔧 Source: I will update this PR branch, or open a safe credited replacement, if the repair worker finds a narrow CI fix. Automerge progress:
|
|
ClawSweeper 🐠 reef update Thanks for the contribution here. ClawSweeper tried the original lane first, but branch permissions blocked the push, so a replacement PR is carrying the fix forward. Why replacement: ClawSweeper could not update the source PR branch directly; GitHub did not grant sufficient push rights to the bot for that branch.
fish notes: model gpt-5.5, reasoning high; reviewed against 0bdfb4a. |
Fixes #89116
Summary
getDispatcherFinalOutcomeCounts()insrc/auto-reply/reply/dispatch-from-config.tscalleddispatcher.getFailedCounts().finalwithout optional chaining, while the adjacentgetCancelledCounts?.().final ?? 0line already guarded against the method being absent. SomeReplyDispatchervariants omit count methods at runtime (e.g. plugin-provided dispatchers), so the unguarded call threwTypeError: dispatcher.getFailedCounts is not a function.Per the P1 review feedback, this revision preserves the public
ReplyDispatcher.getFailedCountscontract as required (no plugin-facing SDK break) and tolerates missing readers internally instead:reply-dispatcher.types.ts—getFailedCountsstays required in the SDK-visibleReplyDispatcher(diff is purely additive vs main); adds an internalDispatcherOutcomeCountsView(optional readers) + areadDispatcherFailedCounts()helper for tolerant readsdispatch-from-config.ts—getDispatcherFinalOutcomeCountstakes the narrowerDispatcherOutcomeCountsView; the active-dispatch wrapper falls back to empty counts via the helperdispatch-acp-delivery.ts— visible-text delivery reads failed counts through the helperbot.ts— Feishu no-visible-reply fallback reads failed counts defensivelyThe crash is fixed through tolerant internal reads without changing the exported dispatcher type.
Real behavior proof
Behavior addressed: A
ReplyDispatchervariant that omitsgetFailedCountsat runtime no longer crashes the final-outcome accounting path; the failed count safely resolves to0, while dispatchers that implement it keep using the real counts. The SDK-visible type is unchanged from main.Real environment tested: Linux x86_64, Node.js v22.22.0, HEAD
9a1d408b520a44cfe00abb0538ca039c2460035arebased ontoorigin/main489efc8f5eb15066f007f820ea71398357ad08e8. The production functiongetDispatcherFinalOutcomeCountsis driven directly vianode --import tsx, plus the focused Vitest regression.Exact steps or command run after this patch:
Evidence after fix:
Observed result after fix: The unguarded pre-fix call reproduces the reported
TypeError. After the patch, the productiongetDispatcherFinalOutcomeCountsreturns{cancelled: 2, failed: 0}for the method-less dispatcher (no throw) and{cancelled: 1, failed: 5}for a full dispatcher. The focused regression + Feishu bot suites pass 73/73, and CIcheck-test-types/check-prod-types/check-lintare green on this head. The publicReplyDispatcher.getFailedCountstype is identical to main.What was not tested: End-to-end live dispatch against a real gateway run; the fix is exercised through the production accounting function with representative dispatcher variants and unit tests rather than a full live reply cycle.