fix(feishu): add 30 s request timeout to streaming-card API calls#102948
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 2:30 PM ET / 18:30 UTC. Summary PR surface: Source +18, Tests +67. Total +85 across 4 files. Reproducibility: yes. at source level. Current main leaves six guarded streaming-card requests without explicit deadlines, and the contributor's stalled-endpoint output plus the exact-head regression test exercise the abort path. 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 exact-head design after routine checks: resolve the established Feishu timeout at the account boundary, carry that prepared value into the streaming session, and enforce it consistently on every tenant-token and CardKit guarded request. Do we have a high-confidence way to reproduce the issue? Yes at source level. Current main leaves six guarded streaming-card requests without explicit deadlines, and the contributor's stalled-endpoint output plus the exact-head regression test exercise the abort path. Is this the best way to solve the issue? Yes. Reusing the established account-resolved Feishu timeout and carrying it into the session is the narrowest maintainable fix; it avoids both a second hardcoded policy and a risky global guarded-fetch default change. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 5a5424474dcd. Label changesLabel justifications:
Evidence reviewedPR surface: Source +18, Tests +67. Total +85 across 4 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
Review history (5 earlier review cycles)
|
Stall-timeout behavior proofAdded commit Real 30s abort (local proof script)```bash Regression test```bash @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
d4a902c to
b1dcdaa
Compare
Signed-off-by: sallyom <somalley@redhat.com>
|
Maintainer follow-up pushed in This preserves the PR's six plugin-local request deadlines, but uses This is best narrow fix: it keeps the request-boundary approach while reusing the shipped Feishu timeout contract. |
Signed-off-by: sallyom <somalley@redhat.com>
|
Merge-ready at HEAD This fixes a real Feishu streaming-card stall by adding request-local deadlines. Reusing the existing account-resolved Feishu timeout is the best narrow fix: it preserves the 30-second default while honoring established config, per-account, and environment overrides. No breaking changes or compatibility concerns found. Exact-head CI is green with no failing or pending checks, the worktree is clean, and both maintainer autoreview and ClawSweeper are clean on this solution. |
…02948) * fix(feishu): bound streaming-card API requests with a 30s timeout * fix(feishu): honor configured streaming timeout Signed-off-by: sallyom <somalley@redhat.com> * test(feishu): declare streaming mock credentials Signed-off-by: sallyom <somalley@redhat.com> --------- Signed-off-by: sallyom <somalley@redhat.com> Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: sallyom <somalley@redhat.com> (cherry picked from commit 473df17) (cherry picked from commit 591df2e)
…enclaw#102948) * fix(feishu): bound streaming-card API requests with a 30s timeout * fix(feishu): honor configured streaming timeout Signed-off-by: sallyom <somalley@redhat.com> * test(feishu): declare streaming mock credentials Signed-off-by: sallyom <somalley@redhat.com> --------- Signed-off-by: sallyom <somalley@redhat.com> Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: sallyom <somalley@redhat.com>
What Problem This Solves
Fixes an issue where all six outbound CardKit and tenant-token requests in
extensions/feishu/src/streaming-card.tscalledfetchWithSsrFGuardwithouta
timeoutMsdeadline. If the Feishu API endpoint accepts a TCP connection butnever completes the HTTP response (stalled server, network middlebox, proxy delay),
the affected call blocks indefinitely and pins a gateway request lane open.
The critical path is
getToken(): tenant-token refresh is called before everyCardKit request, so a single stalled token endpoint blocks the entire streaming-card
reply pipeline for a running agent turn.
Why This Change Was Made
fetchWithSsrFGuardexposes a top-leveltimeoutMsparameter that applies a hardabort deadline to the underlying request. Adding
FEISHU_STREAMING_CARD_REQUEST_TIMEOUT_MS = 30_000and wiring it to all six call sites in one constant covers every streaming-card path
without touching callers.
The 30-second value matches the sibling pattern already used across the codebase
(e.g.
extensions/googlechat/src/api.ts,extensions/google-meet/src/meet.ts,extensions/mattermost/src/api.ts).extensions/feishu/src/app-registration.tswas checked and is not affected: itsfetchFeishuJsonhelper receivessignal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)through the caller's
init, providing equivalent protection via a different mechanism.User Impact
Before: A stalled Feishu API endpoint leaves tenant-token refresh or any CardKit
request pending indefinitely. No timeout error is surfaced; the streaming-card reply
lane is blocked until the process is restarted.
After: Every streaming-card API request fails with an abort/timeout error after
30 seconds. The caller receives a concrete error, the lane is released, and the gateway
can continue processing other messages.
Evidence
Branch:
fix/feishu-streaming-card-timeoutsBase:
upstream/mainNode: v22.22.0 — macOS Darwin 24.3.0 arm64
Existing tests — all passing after change
Format and lint
Diff summary
Call sites covered:
feishu.streaming-card.token(tenant token refresh)feishu.streaming-card.create(card entity creation)feishu.streaming-card.update(content stream update)feishu.streaming-card.replace(content replace)feishu.streaming-card.note-update(note footer update)feishu.streaming-card.close(streaming mode close)What was not tested: a live Feishu API stall scenario. Crabbox/Testbox remote CI
was not run at submission time.