← Back to PRs

#9220: Fix: TUI drops API responses silently when runID already finalized

by vishaltandale00 open 2026-02-05 01:05 View on GitHub →
channel: googlechat channel: line channel: mattermost channel: tlon commands stale
## Summary Fixes #9203 - TUI was silently discarding API responses when events arrived out of order or were duplicated. ## Problem The event handler returned early for BOTH "delta" AND "final" events when a runId existed in finalizedRuns. This caused the actual API response to be silently dropped if: - Events arrived out of order - Duplicate/retry events came from the server - Race conditions caused finalization before the final event ## Root Cause Lines 91-97 in `tui-event-handlers.ts` checked if finalizedRuns contained the runId and returned early for both delta and final states: \`\`\`typescript if (finalizedRuns.has(evt.runId)) { if (evt.state === "delta") return; if (evt.state === "final") return; // BUG! } \`\`\` While skipping delta events is correct (no need to stream updates for finalized runs), skipping final events discards the complete response. ## Solution Modified the check to only skip delta events, allowing final events to always be processed: \`\`\`typescript if (finalizedRuns.has(evt.runId)) { // Only skip delta events - final events must always render if (evt.state === "delta") return; // Don't return for "final" state - it needs to render } \`\`\` ## Why This Works - **Delta events**: Streaming updates are skipped for finalized runs (correct - no UI updates needed) - **Final events**: Always processed, even if duplicate or out-of-order (ensures complete response displays) - **Idempotent**: Processing duplicate final events is safe - finalization updates the same chat log entry ## Impact ✅ Fixes silent response drops when events arrive out of order ✅ Handles duplicate/retry events gracefully ✅ No breaking changes - only fixes broken behavior ✅ Minimal code change (removed buggy final state check, added clarifying comment) ## Testing - TypeScript compilation passes - Code formatted with oxfmt - Logic verified: delta events skipped, final events processed for finalized runs - Safe to merge: change is idempotent and handles edge cases --- 🤖 Generated with Claude Code (agent-f46b0548a3aa) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adjusts the TUI chat event handler so that once a runId is marked finalized, **only** subsequent `delta` events are ignored; `final` events are still processed. This prevents the UI from silently dropping the completed response when events arrive out-of-order or are duplicated. It also updates several channel extension manifests to prefer `defaultChoice: "local"`, and updates onboarding plugin install logic to respect a plugin’s `defaultChoice` for `stable`/`beta` channels (with a fallback to npm when the local path isn’t present). <h3>Confidence Score: 4/5</h3> - This PR is likely safe to merge, with one behavioral inconsistency to resolve in onboarding default selection. - The TUI fix is a narrow conditional change and aligns with existing comments about out-of-order tool events. The main concern is that the updated stable/beta default-choice logic only partially respects the catalog’s `defaultChoice` and can’t represent `skip` as a default, which is a real UX/behavior mismatch if any entry uses it. - src/commands/onboarding/plugin-install.ts <!-- greptile_other_comments_section --> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) - Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13)) <!-- /greptile_comment -->

Most Similar PRs