fix: strict proxy propagation, client error fallback prevention, and stream gating - #3403
Open
v01dgrace wants to merge 7 commits into
Open
fix: strict proxy propagation, client error fallback prevention, and stream gating#3403v01dgrace wants to merge 7 commits into
v01dgrace wants to merge 7 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📝 Description
Fixes #2951
This PR addresses the root causes behind multi-key pool exhaustion (observed in multi-key NVIDIA NIM and generic provider setups) caused by three interacting reliability issues identified in #2951:
strictProxyFlag Dropping: Proxy pools configured withstrictProxy: truelost this flag during credential assembly, causingproxyAwareFetch()to silently fall back to direct unproxied connections when the proxy failed.modelLockon each valid key until 0 accounts remained available.onRequestSuccess()and cleared account error states before reading the first upstream byte. Empty streams (0 bytes) or JSON error payloads disguised within HTTP 200 responses were falsely treated as completed requests without giving outer router layers the opportunity to fall over.🔍 Key Changes
1. End-to-End
strictProxyPropagation (Finding 2)src/sse/services/auth.js: Explicitly propagatestrictProxy: resolvedProxy.strictProxy === trueintoproviderSpecificDatafor both standard credential resolution and the virtual no-auth connection path.open-sse/handlers/chatCore.js: ForwardstrictProxyintoproxyOptionsconsumed byproxyAwareFetch().2. Client-Side Request Error Classification & Fallback Protection (Finding 1)
open-sse/config/errorConfig.js: Introduced{ pass: true }rule mappings for status400as well as deterministic error signatures (invalid_request_error,bad request,improperly formed request,unsupported parameter,maximum context length,context_length_exceeded,prompt is too long,exceeds the limit).open-sse/services/accountFallback.js: When a rule matches{ pass: true }, return{ shouldFallback: false, cooldownMs: 0 }. This halts key rotation immediately and avoids writing persistentmodelLock_*entries for client-induced errors.3. Streaming First-Valid-Event Gate (Finding 3)
open-sse/handlers/chatCore/streamingHandler.js:onRequestSuccess().error,error_code, or unexpecteddetail).success: false(HTTP 502/4xx), enabling outer retry/fallback loops.prefixedBodypreserving the initial chunk so zero stream bytes or events are lost when data is valid.reader.cancel(reason)promise is propagated on client disconnects to prevent socket leakage.4. NVIDIA Reasoning Timeout & Model Registry
open-sse/providers/registry/nvidia.js: AddedstallTimeoutMs: 600000(10 minutes) to accommodate long silent thinking phases on reasoning models, and addedstepfun-ai/step-3.7-flashmodel definition.🏗️ Architecture & Control Flow
flowchart TD A[Incoming Request] --> B{Stream or JSON?} %% Error classification flow B -->|Error Occurs| C{checkFallbackError} C -->|Client-side 400 / Context Length| D[pass: true -> Return 400 Immediately] D --> D1[No Key Rotation / No modelLock] C -->|401/403/429/5xx Provider Error| E[shouldFallback: true] E --> E1[Rotate Next Account / Backoff] %% Stream gate flow B -->|Stream: true| F[Fetch Provider Upstream] F --> G{First Chunk Gate} G -->|0 bytes / Disguised JSON Error| H[Return 502 / Failover] G -->|Valid Event / Content| I[Trigger onRequestSuccess] I --> J[Prepend Buffered Chunk -> Stream to Client]🧪 Test Coverage & Validation
Added comprehensive unit tests covering all edge cases:
tests/unit/strict-proxy-propagation.test.js:strictProxy=truepropagation through normal and no-auth credential resolution.strictProxy=trueencounters proxy failures.strictProxy=false.tests/unit/account-fallback-rules.test.js:invalid_request_error,unsupported parameter, and context-length errors return{ shouldFallback: false, cooldownMs: 0 }.tests/unit/stream-first-valid-event-gate.test.js:detailerrors."error"in assistant content is safely delivered without false positives.nullbody graceful handling.Test Results
📋 Checklist
master(v0.5.55) with zero merge conflicts.npm run build).vitest run).