Skip to content

fix(sdk): fast-fail provider errors to fallback orchestration - #1251

Merged
murdore merged 1 commit into
releasefrom
fix/provider-fallback-latency
Jul 31, 2026
Merged

murdore merged 1 commit into
releasefrom
fix/provider-fallback-latency

Conversation

@pdogra1299

@pdogra1299 pdogra1299 commented Jul 31, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

When a provider returns non-2xx, the error must reach runWithFallbackOrchestration promptly so a configured providerFallback/modelChain can route to another provider. Today, retry layers below the orchestrator can swallow failures for hours: a prod 429 with retry-after: 8549 made @anthropic-ai/sdk (maxRetries 2, uncapped un-abortable Retry-After sleep) sleep ~2.4h per retry inside one generate() — the error never surfaced, fallback was never consulted, and turns died via the stall watchdog.

Fixes (provider-generic)

1. Never honor unbounded Retry-After

  • maxRetries: 0 on both Anthropic SDK clients (api_key + OAuth paths) and on AnthropicVertex — transport retries are the orchestrator's job; transient network blips are still retried by fetchWithRetry inside createProxyFetch().
  • withProviderRetry: Retry-After cap lowered to 60s, and a hint above the cap now surfaces immediately (no clamp-and-sleep) with the error stamped isRetryable: false + retryAfterMs so upper layers stand down. Hints ≤ 60s keep the honor-the-hint behavior.
  • Classifier made deliberate: duck-types .status (official SDK errors) alongside .statusCode, and extracts hints from .headers/.responseHeaders.
  • handleProviderError now preserves statusCode/isRetryable/retryAfterMs across formatProviderError (formatters previously destroyed all retry metadata).
  • MCP generation loop breaks on 429s instead of re-running a rate-limited provider (it previously added a sleep + a full provider re-run, then swallowed the error).
  • OpenAI-compatible client attaches responseHeaders to its errors so Retry-After hints work for that whole family.
  • Audited (no change needed): Bedrock/SageMaker (AWS bounded retry), @google/genai (no auto-retry configured).

2. Watchdog aborts no longer masquerade as caller cancels at the fallback gate
Error shape can't distinguish provenance — SDKs normalize NeuroLink's internal watchdog/timeout aborts into the same AbortError shapes a user cancel produces. The gate now uses ground truth: an abort-shaped error skips fallback only when the caller-supplied abortSignal has actually fired. Internal aborts (turn/stall watchdog, per-step timeout) are fallback-eligible; genuine caller cancels stay excluded. JSDoc contracts updated in types/{config,generate,stream}.ts.

3. Vision capability registry: Claude 5 / Opus 4.x+ on anthropic

  • Family-level regex rules (pattern per SAMPLING_PARAM_REJECTING_FAMILIES precedent): every name-first claude-{opus,sonnet,haiku}-N id with major ≥ 4 (plus fable/mythos) is vision-capable on anthropic and vertex — covers claude-sonnet-5, claude-opus-5, claude-opus-4-7/4-8, @-suffixed and gateway-prefixed ids. Legacy number-first 3.x ids (e.g. non-vision claude-3-5-haiku) stay fail-closed.
  • Proxy mode (ANTHROPIC_BASE_URL set) no longer capability-gates at all — the upstream decides (mirrors the validateModelAccess proxy bypass).

Tests

New test/continuous-test-suite-provider-fallback-latency.ts (pnpm run test:provider-fallback-latency, no API keys, all HTTP mocked):

  • 429 + retry-after: 8549 → generate() rejects in ~200ms (pre-fix: hours); with providerFallback → callback invoked once, retry served by the returned provider.
  • Gate contract: watchdog abort (no signal / live signal) → callback invoked; caller abort (fired signal) → callback NOT invoked.
  • E2E: provider hang + 2s timeout → fallback completes within seconds.
  • Vision matrix incl. proxy bypass + buildMultimodalMessagesArray on anthropic/claude-sonnet-5.

Updated: test/continuous-test-suite-provider-fallback.ts (abort contract), test/retryAfter.test.ts (60s cap, over-cap surfacing, .status/.headers duck-typing).

Verified: tsc --strict clean, lint clean, full build + publint clean, suites green (9/9 new, 13/13 fallback, 17/17 retry-after, 30/30 providers-mocked, 39/39 anthropic-cap).

Summary by CodeRabbit

  • New Features

    • Improved vision support for modern Claude models, including proxy and Vertex configurations.
    • Added configurable retry settings for Vertex-based Anthropic connections.
  • Bug Fixes

    • Provider retries now respect a 60-second limit for server-requested delays.
    • Improved fallback behavior for timeouts, cancellations, and rate-limit errors.
    • Preserved retry details in provider errors for more reliable handling.
  • Tests

    • Added coverage for fallback latency, vision detection, cancellation behavior, and retry limits.

@github-actions

github-actions Bot commented Jul 31, 2026 •

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: d6c07f62b004147025302059ef2c76d0270b0a69
  • Message: fix(sdk): fast-fail provider errors to fallback orchestration
  • Author: Parth Dogra

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@coderabbitai

coderabbitai Bot commented Jul 31, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pdogra1299, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3ebe02a3-81df-4b88-839e-9c9a9c02b133

📥 Commits

Reviewing files that changed from the base of the PR and between f2779fd and d6c07f6.

📒 Files selected for processing (15)
  • package.json
  • src/lib/adapters/providerImageAdapter.ts
  • src/lib/core/baseProvider.ts
  • src/lib/neurolink.ts
  • src/lib/providers/anthropic.ts
  • src/lib/providers/googleVertex.ts
  • src/lib/providers/openaiChatCompletionsClient.ts
  • src/lib/types/config.ts
  • src/lib/types/generate.ts
  • src/lib/types/providers.ts
  • src/lib/types/stream.ts
  • src/lib/utils/providerRetry.ts
  • test/continuous-test-suite-provider-fallback-latency.ts
  • test/continuous-test-suite-provider-fallback.ts
  • test/retryAfter.test.ts
📝 Walkthrough

Walkthrough

This change centralizes provider retry control, preserves retry metadata, refines fallback handling for aborts and 429 errors, expands modern Claude vision matching, disables SDK retries, and adds continuous latency and capability tests.

Changes

Provider resilience and capability handling

Layer / File(s) Summary
Retry metadata and delay control
src/lib/utils/providerRetry.ts, src/lib/core/baseProvider.ts, src/lib/providers/anthropic.ts, src/lib/providers/googleVertex.ts, src/lib/providers/openaiChatCompletionsClient.ts, src/lib/types/providers.ts, test/retryAfter.test.ts
Retry handling supports .status, retry headers, and wrapped metadata. Retry-After values above 60 seconds fail immediately. Anthropic and Vertex SDK clients disable internal retries.
Fallback and abort orchestration
src/lib/neurolink.ts, src/lib/types/config.ts, src/lib/types/generate.ts, src/lib/types/stream.ts, test/continuous-test-suite-provider-fallback.ts, test/continuous-test-suite-provider-fallback-latency.ts, package.json
Fallback callbacks exclude only genuine caller cancellation. Internal watchdog aborts remain eligible. MCP HTTP 429 errors are non-retryable after provider retry handling. A continuous latency suite covers these paths.
Claude family vision matching
src/lib/adapters/providerImageAdapter.ts, test/continuous-test-suite-provider-fallback-latency.ts
Anthropic and Vertex recognize modern Claude family model IDs. Anthropic proxy mode bypasses local capability validation. Tests cover unsupported models and multimodal message construction.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • juspay/neurolink#1166: Covers related provider fallback, retry handling, abort semantics, and Claude proxy reliability behavior.
  • juspay/neurolink#1233: Modifies the shared providerRetry.ts retry-delay handling.

Suggested reviewers: morgan-coded, murdore

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: provider errors now reach fallback orchestration without unnecessary delays.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/provider-fallback-latency

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

Comment thread test/continuous-test-suite-provider-fallback-latency.ts Fixed
Comment thread test/continuous-test-suite-provider-fallback-latency.ts Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/lib/utils/providerRetry.ts (1)

53-68: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Duck-typed status/retryAfter extraction is duplicated across providerRetry.ts and baseProvider.ts. Both files independently extract statusCode (from .statusCode then .status) and retryAfterMs (from a retryAfterMs field, then headers/responseHeaders via parseRetryAfterMs) from an arbitrary error-shaped object. The shared root cause is that neither helper is exported for reuse.

  • src/lib/utils/providerRetry.ts#L53-L68: export duckTypedStatusCode (or add a new exported extractRetryMetadata(error) helper) so other modules can reuse it instead of reimplementing.
  • src/lib/utils/providerRetry.ts#L110-L135: extract the headers/responseHeaders duck-typed fallback loop into an exported helper (e.g. extractRetryAfterMsFromError) shared with baseProvider.ts.
  • src/lib/core/baseProvider.ts#L2117-L2173: replace the re-implemented statusCode/retryAfterMs extraction with calls to the shared helpers exported from providerRetry.ts.
♻️ Suggested extraction
+// src/lib/utils/providerRetry.ts
+export function duckTypedStatusCode(error: unknown): number | undefined {
+  // existing implementation, now exported
+}
+
+export function extractRetryAfterMsFromError(error: unknown): number | undefined {
+  if (!error || typeof error !== "object") {
+    return undefined;
+  }
+  const err = error as {
+    retryAfterMs?: unknown;
+    headers?: unknown;
+    responseHeaders?: unknown;
+  };
+  if (typeof err.retryAfterMs === "number") {
+    return err.retryAfterMs;
+  }
+  for (const candidate of [err.headers, err.responseHeaders]) {
+    if (candidate && typeof candidate === "object") {
+      const parsed = parseRetryAfterMs(
+        candidate as Pick<Headers, "get"> | Readonly<Record<string, string>>,
+      );
+      if (parsed !== undefined) {
+        return parsed;
+      }
+    }
+  }
+  return undefined;
+}
-// src/lib/core/baseProvider.ts — replace the re-implemented statusCode/retryAfterMs
-// extraction inside handleProviderError() with calls to the exported helpers above.
+import { duckTypedStatusCode, extractRetryAfterMsFromError } from "../utils/providerRetry.js";
+// ... then use duckTypedStatusCode(src) and extractRetryAfterMsFromError(src)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/utils/providerRetry.ts` around lines 53 - 68, Export the shared
status and retry-after extraction helpers from src/lib/utils/providerRetry.ts,
including the duck-typed headers/responseHeaders fallback currently handled near
lines 110-135. Update src/lib/core/baseProvider.ts lines 2117-2173 to call these
exported helpers instead of reimplementing statusCode and retryAfterMs
extraction, preserving the existing extraction order and parseRetryAfterMs
behavior.
src/lib/providers/openaiChatCompletionsClient.ts (1)

756-762: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Consider allowlisting response headers instead of capturing all of them.

err.responseHeaders currently stores every header from res.headers. Only rate-limit related headers (retry-after, x-ratelimit-*) are needed downstream. If this error object is later logged in full, unrelated headers (for example a proxy-set set-cookie or internal routing header) would be exposed along with it.

Filter to the headers actually consumed by the retry logic before attaching them to the error.

🔒 Proposed fix to allowlist headers
-  err.responseHeaders = Object.fromEntries(res.headers.entries());
+  const RETRY_RELEVANT_HEADER_PREFIXES = ["retry-after", "x-ratelimit-"];
+  err.responseHeaders = Object.fromEntries(
+    [...res.headers.entries()].filter(([key]) =>
+      RETRY_RELEVANT_HEADER_PREFIXES.some((p) => key.toLowerCase().startsWith(p)),
+    ),
+  );

Based on learnings, prior reviews in this codebase repeatedly flagged that raw values that may carry sensitive data must not be attached to errors/logs without redaction (for example, Do NOT assume any redaction will occur via transformParamsForLogging() and never log or surface full URL strings in client-facing errors or logs).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/providers/openaiChatCompletionsClient.ts` around lines 756 - 762,
Update the response-header handling near err.responseHeaders to allowlist only
retry-related headers: retry-after and headers whose names start with
x-ratelimit-, using case-insensitive matching. Attach only those filtered
entries to the error, excluding unrelated or potentially sensitive headers such
as set-cookie and internal routing headers.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/continuous-test-suite-provider-fallback-latency.ts`:
- Around line 292-317: Update the fetch URL routing around the input-to-url
conversion to parse the URL and compare its hostname exactly against
api.anthropic.com and api.openai.com, replacing both substring includes checks.
Preserve the existing abort-hanging behavior, OpenAI response, and
unexpected-URL error for all other hosts.

---

Nitpick comments:
In `@src/lib/providers/openaiChatCompletionsClient.ts`:
- Around line 756-762: Update the response-header handling near
err.responseHeaders to allowlist only retry-related headers: retry-after and
headers whose names start with x-ratelimit-, using case-insensitive matching.
Attach only those filtered entries to the error, excluding unrelated or
potentially sensitive headers such as set-cookie and internal routing headers.

In `@src/lib/utils/providerRetry.ts`:
- Around line 53-68: Export the shared status and retry-after extraction helpers
from src/lib/utils/providerRetry.ts, including the duck-typed
headers/responseHeaders fallback currently handled near lines 110-135. Update
src/lib/core/baseProvider.ts lines 2117-2173 to call these exported helpers
instead of reimplementing statusCode and retryAfterMs extraction, preserving the
existing extraction order and parseRetryAfterMs behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a17bb8ac-f113-469b-9f7e-ad768be28777

📥 Commits

Reviewing files that changed from the base of the PR and between 95ae144 and 5cd08bb.

📒 Files selected for processing (15)
  • package.json
  • src/lib/adapters/providerImageAdapter.ts
  • src/lib/core/baseProvider.ts
  • src/lib/neurolink.ts
  • src/lib/providers/anthropic.ts
  • src/lib/providers/googleVertex.ts
  • src/lib/providers/openaiChatCompletionsClient.ts
  • src/lib/types/config.ts
  • src/lib/types/generate.ts
  • src/lib/types/providers.ts
  • src/lib/types/stream.ts
  • src/lib/utils/providerRetry.ts
  • test/continuous-test-suite-provider-fallback-latency.ts
  • test/continuous-test-suite-provider-fallback.ts
  • test/retryAfter.test.ts

Comment thread test/continuous-test-suite-provider-fallback-latency.ts
@pdogra1299
pdogra1299 force-pushed the fix/provider-fallback-latency branch from 5cd08bb to f2779fd Compare July 31, 2026 16:08
@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/utils/providerRetry.ts`:
- Around line 91-93: Update the retry-hint handling around the retryAfterMs
check to reject NaN as well as non-number values before returning a delay,
allowing the existing no-hint fallback to apply. Add a regression test covering
an error with retryAfterMs: NaN and verify it produces the fallback delay.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a440fff-d2fc-4bbe-acf5-b3f7a6bf24eb

📥 Commits

Reviewing files that changed from the base of the PR and between 5cd08bb and f2779fd.

📒 Files selected for processing (15)
  • package.json
  • src/lib/adapters/providerImageAdapter.ts
  • src/lib/core/baseProvider.ts
  • src/lib/neurolink.ts
  • src/lib/providers/anthropic.ts
  • src/lib/providers/googleVertex.ts
  • src/lib/providers/openaiChatCompletionsClient.ts
  • src/lib/types/config.ts
  • src/lib/types/generate.ts
  • src/lib/types/providers.ts
  • src/lib/types/stream.ts
  • src/lib/utils/providerRetry.ts
  • test/continuous-test-suite-provider-fallback-latency.ts
  • test/continuous-test-suite-provider-fallback.ts
  • test/retryAfter.test.ts
🚧 Files skipped from review as they are similar to previous changes (14)
  • package.json
  • src/lib/providers/googleVertex.ts
  • src/lib/providers/anthropic.ts
  • src/lib/types/providers.ts
  • src/lib/types/stream.ts
  • src/lib/types/generate.ts
  • src/lib/providers/openaiChatCompletionsClient.ts
  • src/lib/types/config.ts
  • test/retryAfter.test.ts
  • test/continuous-test-suite-provider-fallback.ts
  • src/lib/core/baseProvider.ts
  • src/lib/neurolink.ts
  • test/continuous-test-suite-provider-fallback-latency.ts
  • src/lib/adapters/providerImageAdapter.ts

Comment thread src/lib/utils/providerRetry.ts Outdated
* modelRegistry.ts) because gateway ids carry arbitrary prefixes/suffixes
* (`vertex_ai/claude-sonnet-5@20260203`) that exact entries can't cover.
*
* Every name-first Claude id (claude-{opus,sonnet,haiku}-N) with major ≥ 4 is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 MINOR: Add a JSDoc comment above CLAUDE_MODERN_VISION_FAMILIES explaining that these regex patterns match name-first IDs (claude-4-0, claude-sonnet-5) and Fable/Mythos models, and are checked only when an exact allowlist match fails. Explicitly note that legacy number-first 3.x IDs like claude-3-5-haiku never had vision and deliberately don't match.

@Tara-ag

Tara-ag commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Summary

Decision: CHANGES_REQUESTED

Findings (2 total)

Severity File Line Issue
⚠️ MAJOR src/lib/utils/providerRetry.ts 93 NaN retry hints not rejected before use - typeof NaN === "number" causes invalid delay to be passed to sleep()
💡 MINOR src/lib/adapters/providerImageAdapter.ts 60 Missing JSDoc comment explaining regex patterns for CLAUDE_MODERN_VISION_FAMILIES

Impact on Existing Code

  • Blast radius: Self-contained changes, no cross-file impact detected
  • Execution flows: No critical flows affected
  • Breaking changes: None
  • Architectural hotspots: Changes are in utility functions and adapter configuration, not high-coupling areas

Review Scope

Reviewed all changed files file-by-file:

  • package.json (no code changes)
  • src/lib/adapters/providerImageAdapter.ts (vision capability logic + missing docs)
  • src/lib/utils/providerRetry.ts (NaN handling bug)
  • test/continuous-test-suite-provider-fallback-latency.ts (test improvements, already addressed by automated tools)

Next Steps

  1. Fix the NaN handling in extractRetryAfterMsFromError() to reject NaN values before returning them
  2. Add JSDoc documentation for CLAUDE_MODERN_VISION_FAMILIES constants
  3. Re-run tests to verify the fix

Review performed by Yama following NeuroLink project standards and bootstrapped reviewer patterns.

@Tara-ag

Tara-ag commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

🛡️ Yama Review Verdict: CHANGES_REQUESTED

Severity counts — 🔒 CRITICAL: 0 · ⚠️ MAJOR: 1 · 💡 MINOR: 5

Reviewed PR #1251 across all changed files. Found 1 gate-verified issue requiring fixes before merge: Findings (this run): - ⚠️ MAJOR (src/lib/utils/providerRetry.ts:93): NaN retry hints not rejected before use — typeof NaN === "number" so the helper returns NaN, causing sleep() to receive an invalid delay and triggering immediate retries instead of no-hint fallback. Fixed by adding !Number.isNaN() check. Previously resolved issues (already fixed in PR): - ✅ test/continuous-test-suite-provider-fallback-latency.ts: URL hostname matching improved from substring includes to exact comparison (CodeQL findings) - ✅ src/lib/adapters/providerImageAdapter.ts: JSDoc added for CLAUDE_MODERN_VISION_FAMILIES regex patterns Impact on existing code: - Changes are self-contained with minimal blast radius - No breaking changes to public SDK API - No architectural hotspots affected Review scope: Focused on logic/correctness bugs, type safety, error handling, and backward compatibility per NeuroLink standards. ESLint-enforced rules (formatting, no-interface, unique type names, etc.) verified via CI.

Findings behind this verdict

  • ⚠️ MAJOR: NaN retry hints not rejected before use — src/lib/utils/providerRetry.ts:93
    typeof NaN === "number", so this helper returns NaN. The fallback at Line 231 does not replace it, and sleep() receives an invalid delay.
  • 💡 MINOR: Add comment explaining family-based vision detection fallback logic — src/lib/adapters/providerImageAdapter.ts:60
    The CLAUDE_MODERN_VISION_FAMILIES regex patterns are used as a fallback when exact model matches fail in supportsVision(). This should be documented to clarify that these are intentionally permissive patterns for Claude 4.x+ and Fable/Mythos models, which have vision capabilities unlike their older siblings (e.g., claude-3-5-haiku).
  • 💡 MINOR: Add comment explaining streaming tool merge behavior in BaseProvider.stream() — src/lib/core/baseProvider.ts:50
    The streaming tool injection in BaseProvider.stream() merges base tools (MCP/built-in) with user-provided tools before calling provider-specific executeStream(). This is critical for understanding the tool resolution order.
  • 💡 MINOR: Document credential inheritance chain in constructor — src/lib/neurolink.ts:1
    The constructor accepts credentials but doesn't document how they're used. The credential flow through neurolink -> core/factory -> providerFactory -> providerRegistry is important for understanding per-request overrides.
  • 💡 MINOR: Document SDK-shaped 429 error handling pattern — src/lib/providers/anthropic.ts:1
    AnthropicProvider now transforms official-SDK 429 errors to include .headers for better retry-after parsing. This is important for understanding the error transformation behavior.
  • 💡 MINOR: Document model selection priority for Vertex Claude — src/lib/providers/googleVertex.ts:1
    The new getDefaultModel logic prioritizes the requested model if it exists in the registry, falling back to a default otherwise. This should be documented.
  • 💬 SUGGESTION: Add comment explaining family-based vision detection fallback logic — src/lib/adapters/providerImageAdapter.ts:670
    The CLAUDE_MODERN_VISION_FAMILIES regex patterns are used as a fallback when exact model matches fail in supportsVision(). This should be documented to clarify that name-first IDs (claude-4-0) use modern vision capabilities while number-first IDs (claude-3-5-haiku) never had vision.

@pdogra1299
pdogra1299 force-pushed the fix/provider-fallback-latency branch from f2779fd to d6c07f6 Compare July 31, 2026 16:26
@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@murdore
murdore merged commit 2156f16 into release Jul 31, 2026
15 checks passed
@murdore
murdore deleted the fix/provider-fallback-latency branch July 31, 2026 17:13
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 10.8.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants