Skip to content

feat: opt-in Claude 1M beta header with safe 200k fallback#514

Open
ndycode wants to merge 3 commits intoNoeFabris:devfrom
ndycode:fix/issue-506-claude-1m-beta-fallback
Open

feat: opt-in Claude 1M beta header with safe 200k fallback#514
ndycode wants to merge 3 commits intoNoeFabris:devfrom
ndycode:fix/issue-506-claude-1m-beta-fallback

Conversation

@ndycode
Copy link
Contributor

@ndycode ndycode commented Feb 28, 2026

Summary

  • Add opt-in experimental Claude long-context beta header support for Claude 4.6 models (claude_long_context_beta, claude_long_context_beta_header).
  • Keep Claude Antigravity metadata at 200k base context and clarify provider-path behavior in docs/model labels.
  • Add one-time automatic fallback: if provider rejects the beta header, retry once without it (stable 200k path).
  • Add request/config schema tests for header injection, dedupe, retry-disable behavior, and rejection detection.

Deep Audit Notes

Behavior Matrix

  • claude_long_context_beta=false (default): unchanged 200k behavior.
  • claude_long_context_beta=true + provider accepts beta: request carries configured header.
  • claude_long_context_beta=true + provider rejects beta: plugin logs reason, shows warning toast once per session, retries once without beta.

Validation

pm run typecheck

pm test

pm run build

All passed locally in this branch.

Refs #506
Related duplicate context: #512

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 6bf75c9 and 714c2ea.

📒 Files selected for processing (2)
  • src/plugin/logging-utils.test.ts
  • src/plugin/logging-utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/plugin/logging-utils.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
🧬 Code graph analysis (1)
src/plugin/logging-utils.test.ts (1)
src/plugin/logging-utils.ts (1)
  • scrubTextForLog (79-96)
🔇 Additional comments (1)
src/plugin/logging-utils.test.ts (1)

71-89: LGTM! Good test coverage for the scrubbing function.

The test cases correctly verify:

  • Redaction of sensitive fields (token, email, authorization header with Bearer prefix, card numbers)
  • Negative assertions ensuring raw sensitive values don't leak
  • Whitespace normalization and truncation behavior

The assertions align with the regex patterns in the implementation.


Walkthrough

Adds two new configuration fields, claude_long_context_beta and claude_long_context_beta_header, and documents them across schema and docs. Updates two Claude model display names to indicate a 200k base context. Implements long-context beta handling: header construction and injection, eligibility checks for Claude 4.6 models, detection of provider 4xx rejections, per-session disablement of the beta for retries, retry-loop adjustments to retry after a fallback, truncated rejection reason logging, and throttled per-session user fallback toasts. Adds unit tests for header logic, rejection detection, schema entries, and logging sanitization.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: adding opt-in Claude 1M beta header support with automatic 200k fallback on rejection.
Description check ✅ Passed The description comprehensively explains the feature, behavior matrix, implementation details, and validation steps performed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

Add experimental Claude long-context beta header support for Claude 4.6 models behind config flags, with automatic one-time fallback to stable 200k behavior when provider rejects the beta header.

Includes schema/docs/model metadata updates and request-level tests covering header injection, dedupe, retry-disable behavior, and rejection detection.

Refs NoeFabris#506

Co-authored-by: Codex <noreply@openai.com>
@ndycode ndycode force-pushed the fix/issue-506-claude-1m-beta-fallback branch from b2e0b50 to fe568b7 Compare February 28, 2026 14:03
@ndycode ndycode changed the base branch from main to dev February 28, 2026 14:03
@ndycode ndycode marked this pull request as ready for review February 28, 2026 15:12
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (3)
src/plugin/config/schema.test.ts (1)

72-86: Add an assertion for minLength on claude_long_context_beta_header.

The schema enforces non-empty header values; locking that in tests will prevent silent regression.

✅ Proposed test hardening
-    const schema = JSON.parse(readFileSync(schemaPath, "utf8")) as {
-      properties?: Record<string, { type?: string; default?: unknown; description?: string }>;
-    };
+    const schema = JSON.parse(readFileSync(schemaPath, "utf8")) as {
+      properties?: Record<string, { type?: string; default?: unknown; description?: string; minLength?: number }>;
+    };
@@
     expect(claudeLongContextBetaHeader).toMatchObject({
       type: "string",
       default: "context-1m-2025-08-07",
+      minLength: 1,
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugin/config/schema.test.ts` around lines 72 - 86, The test for
claude_long_context_beta_header misses asserting the schema's non-empty
constraint; update the "documents claude_long_context_beta_header in the JSON
schema" test to assert that schema.properties?.claude_long_context_beta_header
has a minLength of 1 (or a numeric minLength > 0), e.g. check the existence and
numeric value of minLength on the claude_long_context_beta_header object so the
non-empty header requirement is locked into the test.
src/plugin.ts (1)

2379-2388: Consider redacting reasonPreview before debug logging.

At Line 2379, the preview is taken from raw provider body text; those payloads can occasionally echo user/tool content. A lightweight scrub before logging would reduce accidental sensitive-data exposure.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugin.ts` around lines 2379 - 2388, The preview derived from
errorBodyText (reasonPreview) may contain echoed user/tool content and should be
redacted before logging; update the code around reasonPreview, pushDebug, and
log.debug to run a lightweight scrub function (e.g., redactSensitive or
scrubText) on the extracted string — trimming, replacing likely secrets (emails,
tokens, long hex sequences, credit-card patterns) with placeholders and/or
masking everything after a short safe length — and then log the redactedPreview
(not the raw reasonPreview) and continue to include
prepared.claudeLongContextBetaHeader and prepared.effectiveModel as before so
logs no longer contain unredacted provider payloads.
src/plugin/request.test.ts (1)

95-125: Add one positive 403 case for rejection detection.

At Line 116, the suite verifies non-4xx behavior, but there is no positive 403 scenario. Since the detector intentionally supports both 400 and 403, adding a 403-positive test would lock that contract in.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugin/request.test.ts` around lines 95 - 125, Add a positive 403 test
for the isUnsupportedClaudeLongContextBetaError detector: inside the existing
"isUnsupportedClaudeLongContextBetaError" describe block add an it case that
constructs a JSON body with error.message containing "unsupported anthropic-beta
header context-1m-2025-08-07" (same pattern as the 400 positive case) calls
isUnsupportedClaudeLongContextBetaError(403, body) and asserts the result is
true so the test suite verifies both 400 and 403 are detected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/plugin/config/schema.ts`:
- Line 245: The schema for claude_long_context_beta_header currently uses
z.string().min(1) which allows whitespace-only values; update the validator for
claude_long_context_beta_header to trim input before length check by using
z.string().trim().min(1).default("context-1m-2025-08-07") so whitespace-only
headers are rejected prior to being sent to the provider.

---

Nitpick comments:
In `@src/plugin.ts`:
- Around line 2379-2388: The preview derived from errorBodyText (reasonPreview)
may contain echoed user/tool content and should be redacted before logging;
update the code around reasonPreview, pushDebug, and log.debug to run a
lightweight scrub function (e.g., redactSensitive or scrubText) on the extracted
string — trimming, replacing likely secrets (emails, tokens, long hex sequences,
credit-card patterns) with placeholders and/or masking everything after a short
safe length — and then log the redactedPreview (not the raw reasonPreview) and
continue to include prepared.claudeLongContextBetaHeader and
prepared.effectiveModel as before so logs no longer contain unredacted provider
payloads.

In `@src/plugin/config/schema.test.ts`:
- Around line 72-86: The test for claude_long_context_beta_header misses
asserting the schema's non-empty constraint; update the "documents
claude_long_context_beta_header in the JSON schema" test to assert that
schema.properties?.claude_long_context_beta_header has a minLength of 1 (or a
numeric minLength > 0), e.g. check the existence and numeric value of minLength
on the claude_long_context_beta_header object so the non-empty header
requirement is locked into the test.

In `@src/plugin/request.test.ts`:
- Around line 95-125: Add a positive 403 test for the
isUnsupportedClaudeLongContextBetaError detector: inside the existing
"isUnsupportedClaudeLongContextBetaError" describe block add an it case that
constructs a JSON body with error.message containing "unsupported anthropic-beta
header context-1m-2025-08-07" (same pattern as the 400 positive case) calls
isUnsupportedClaudeLongContextBetaError(403, body) and asserts the result is
true so the test suite verifies both 400 and 403 are detected.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 610bbcc and fe568b7.

📒 Files selected for processing (11)
  • README.md
  • assets/antigravity.schema.json
  • docs/CONFIGURATION.md
  • docs/MODEL-VARIANTS.md
  • script/build-schema.ts
  • src/plugin.ts
  • src/plugin/config/models.ts
  • src/plugin/config/schema.test.ts
  • src/plugin/config/schema.ts
  • src/plugin/request.test.ts
  • src/plugin/request.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
🧬 Code graph analysis (3)
src/plugin/config/schema.test.ts (1)
src/plugin/config/schema.ts (1)
  • DEFAULT_CONFIG (469-524)
src/plugin/request.test.ts (1)
src/plugin/request.ts (2)
  • isUnsupportedClaudeLongContextBetaError (760-788)
  • prepareAntigravityRequest (810-1654)
src/plugin.ts (1)
src/plugin/request.ts (1)
  • isUnsupportedClaudeLongContextBetaError (760-788)
🔇 Additional comments (14)
assets/antigravity.schema.json (1)

123-133: Looks good: new long-context config fields are well-scoped and backward-compatible.

The defaults, types, and descriptions for both new keys are clear and align with the fallback behavior described in the PR.

README.md (1)

123-124: Docs update is clear and consistent.

The 200k-base labeling and explicit opt-in/fallback note reduce ambiguity for users selecting Claude models.

Also applies to: 143-143, 194-194, 199-199

script/build-schema.ts (1)

44-47: Nice schema-generation sync.

Adding these keys to optionDescriptions keeps generated schema docs aligned with runtime config surface.

src/plugin/config/models.ts (1)

71-71: Model label clarification is good.

The added “200k base” suffix improves UX without affecting behavior.

Also applies to: 76-76

src/plugin/config/schema.test.ts (1)

50-70: Good test coverage for the new config defaults and schema docs.

This block cleanly validates the new boolean flag contract.

docs/MODEL-VARIANTS.md (1)

107-109: Clear and helpful clarification.

The 200k-default note plus beta fallback behavior is documented in the right place for variant users.

Also applies to: 115-115

docs/CONFIGURATION.md (1)

38-39: Strong configuration docs update.

The option table, behavior section, and defaults table are aligned and make the opt-in fallback path easy to understand.

Also applies to: 56-72, 191-191

src/plugin/config/schema.ts (1)

483-484: Default config wiring for new fields looks correct.

DEFAULT_CONFIG is aligned with the new opt-in behavior and default header token.

src/plugin/request.test.ts (1)

692-789: Strong coverage for long-context header behavior.

This block cleanly validates apply/non-apply conditions, header deduplication, and retry-disable behavior.

src/plugin.ts (2)

123-140: Toast dedupe helper is well-bounded and practical.

The per-session gate plus capped set size is a solid anti-spam guard for fallback warnings.


2359-2393: The 4xx beta-rejection fallback flow is implemented cleanly.

The guard on claudeLongContextBetaApplied, one-time retry disable, toast throttling, and same-endpoint retry (i -= 1) all align with a safe fallback path.

src/plugin/request.ts (3)

724-746: Header append and long-context state plumbing look solid.

The shared appendAnthropicBetaHeader path avoids duplicate token insertion, and the applied/header return metadata cleanly supports outer retry fallback decisions.

Also applies to: 1596-1606, 1612-1612, 1649-1650


760-788: Unsupported-beta detector logic is pragmatic for fallback triggering.

The status gate plus keyword checks are a reasonable balance for safely switching to the stable path when provider beta-header support is absent.


748-751: No change needed—the exact match for Sonnet is intentional and correct.

The model resolver only emits tier variants (-low, -medium, -high) for Claude Opus-thinking models, not for Sonnet. Sonnet 4.6 resolves to the exact base name claude-sonnet-4-6 without suffix variants. The asymmetric matching—exact equality for Sonnet vs. prefix for Opus—correctly reflects this design difference.

Likely an incorrect or invalid review comment.

@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Feb 28, 2026

Code Review Summary

Status: No New Issues | Recommendation: Merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 0

Previous Issues Status

File Line Issue Status
src/plugin/config/schema.ts 245 Whitespace-only header validation ✅ Addressed
src/plugin/logging-utils.ts 93 Bearer token redaction ✅ Addressed

Files Reviewed (8 files)

  • README.md - Documentation update for 200k base context and beta opt-in
  • assets/antigravity.schema.json - Added new config schema options
  • docs/CONFIGURATION.md - Configuration documentation update
  • src/plugin/config/schema.ts - Added config options with proper defaults
  • src/plugin/config/default.ts - Added default values for new options
  • src/plugin/logging-utils.ts - Added scrubTextForLog for sensitive data redaction
  • src/plugin/request.ts - Core implementation of long-context beta header injection
  • src/plugin/request.test.ts - Comprehensive tests for new functionality

Code Quality

The implementation is well-structured and the previous issues have been resolved:

  • Config Layer: claude_long_context_beta (default: false) and claude_long_context_beta_header (default: "context-1m-2025-08-07") properly validated with .trim().min(1)
  • Logging: scrubTextForLog correctly handles Bearer/Basic auth schemes in redaction
  • Request Layer: Beta header injection only applies to eligible Claude 4.6 models
  • Error Handling: Proper detection of provider rejection with automatic fallback
  • Testing: Comprehensive test coverage including edge cases

TypeScript compilation and all tests pass successfully.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

This PR adds opt-in experimental Claude long-context beta header support for Claude 4.6 models with automatic fallback to stable 200k context when providers reject the beta header.

Key Changes:

  • Added claude_long_context_beta (default: false) and claude_long_context_beta_header config options
  • Implemented header injection with proper deduplication for eligible Claude 4.6 models (Sonnet 4.6, Opus 4.6 Thinking)
  • Added intelligent error detection to identify beta header rejections via status code and error message analysis
  • Implemented one-time automatic retry without beta header when rejection is detected
  • Added session-based toast notifications to inform users about fallback (shown once per session)
  • Introduced scrubTextForLog utility to redact sensitive data (credentials, tokens, emails) from error logs
  • Updated all documentation to clarify 200k base context for Claude Antigravity models
  • Added comprehensive test coverage for all new functionality

Implementation Quality:
The implementation is well-structured with proper separation of concerns. The retry logic prevents infinite loops by setting a flag before retry, and the error detection is conservative to avoid false positives. The fallback mechanism is transparent to users via toast notifications while maintaining detailed debug logging.

Confidence Score: 5/5

  • This PR is safe to merge with no significant risks
  • The implementation is well-designed with comprehensive test coverage, proper error handling, and safe fallback behavior. The retry logic prevents infinite loops, the error detection is conservative, and the feature is opt-in by default. All tests pass and the code follows established patterns in the codebase.
  • No files require special attention

Important Files Changed

Filename Overview
src/plugin/config/schema.ts Added two new config options for Claude long-context beta with proper defaults and validation
src/plugin/request.ts Implemented header injection, deduplication, and error detection logic for Claude 1M beta with proper model eligibility checks
src/plugin.ts Added one-time automatic fallback retry logic with toast notifications and session tracking when provider rejects beta header
src/plugin/logging-utils.ts Added scrubTextForLog function to redact sensitive data (emails, tokens, credentials) from error logs
src/plugin/request.test.ts Added comprehensive tests for beta header injection, deduplication, retry disable, and error detection scenarios
src/plugin/config/schema.test.ts Added tests validating new config options exist in defaults and JSON schema with correct types

Sequence Diagram

sequenceDiagram
    participant Client
    participant Plugin
    participant PrepareRequest
    participant Provider
    participant ErrorDetector
    
    Client->>Plugin: Request with Claude 4.6 model
    Plugin->>PrepareRequest: prepareAntigravityRequest(claudeLongContextBeta=true)
    
    alt Model is eligible (Sonnet 4.6 / Opus 4.6 Thinking)
        PrepareRequest->>PrepareRequest: appendAnthropicBetaHeader(context-1m-2025-08-07)
        PrepareRequest-->>Plugin: Request with beta header
    else Model not eligible or beta disabled
        PrepareRequest-->>Plugin: Request without beta header
    end
    
    Plugin->>Provider: Send request with beta header
    Provider-->>Plugin: 400/403 Error (unsupported beta)
    
    Plugin->>ErrorDetector: isUnsupportedClaudeLongContextBetaError()
    ErrorDetector->>ErrorDetector: Check error message for beta rejection
    
    alt Beta rejection detected
        ErrorDetector-->>Plugin: true
        Plugin->>Plugin: Set disableClaudeLongContextBetaForRetry=true
        Plugin->>Plugin: Show toast notification (once per session)
        Plugin->>Plugin: Log rejection reason (scrubbed)
        Plugin->>PrepareRequest: Retry with disableClaudeLongContextBetaForRetry=true
        PrepareRequest-->>Plugin: Request without beta header (200k fallback)
        Plugin->>Provider: Retry without beta header
        Provider-->>Plugin: 200 Success
        Plugin-->>Client: Response with 200k context
    else Not a beta rejection
        ErrorDetector-->>Plugin: false
        Plugin->>Plugin: Normal error handling
        Plugin-->>Client: Error response
    end
Loading

Last reviewed commit: 714c2ea

- trim beta header config to reject whitespace-only values
- assert minLength in schema JSON test
- add positive 403 detection test for beta rejection
- scrub provider error preview before debug logging

Co-authored-by: Codex <noreply@openai.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@src/plugin/logging-utils.ts`:
- Around line 85-90: The current redaction chain assigned to the scrubbed
variable misses credentials when the value is prefixed with a scheme like
"Bearer"; update the authorization/api key/token/password regex used in the
.replace on scrubbed to also accept and redact an optional auth scheme and its
token (e.g., match patterns like "authorization\s*[:=]\s*Bearer\s+[^\s,;]+" or
generalize to capture an optional word scheme before the secret), so that both
"authorization: Bearer abc123" and "authorization: abc123" result in the secret
being replaced with "[redacted]" while preserving the header label; modify the
replace call that references the group for
(?:authorization|api[_-]?key|token|secret|password) to include an optional
scheme capture and redact the token portion.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between fe568b7 and 6bf75c9.

📒 Files selected for processing (6)
  • src/plugin.ts
  • src/plugin/config/schema.test.ts
  • src/plugin/config/schema.ts
  • src/plugin/logging-utils.test.ts
  • src/plugin/logging-utils.ts
  • src/plugin/request.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/plugin/config/schema.ts
  • src/plugin/config/schema.test.ts
📜 Review details
🧰 Additional context used
🧬 Code graph analysis (3)
src/plugin/logging-utils.test.ts (1)
src/plugin/logging-utils.ts (1)
  • scrubTextForLog (79-93)
src/plugin/request.test.ts (1)
src/plugin/request.ts (2)
  • isUnsupportedClaudeLongContextBetaError (760-788)
  • prepareAntigravityRequest (810-1654)
src/plugin.ts (2)
src/plugin/request.ts (1)
  • isUnsupportedClaudeLongContextBetaError (760-788)
src/plugin/logging-utils.ts (1)
  • scrubTextForLog (79-93)
🔇 Additional comments (6)
src/plugin/logging-utils.test.ts (1)

72-88: Good targeted coverage for the new scrub utility.

The tests validate both redaction markers and post-scrub truncation/normalization paths clearly.

src/plugin/request.test.ts (2)

95-135: Detection tests for unsupported long-context beta errors are well-scoped.

Nice mix of true/false cases across status classes and message variants.


702-799: Claude beta-header request-path tests cover the critical branches.

The added cases (apply, skip, dedupe, retry-disable) are exactly the right integration checks here.

src/plugin.ts (3)

125-142: One-time fallback toast dedupe is implemented cleanly.

The set-based guard plus bounded eviction keeps behavior predictable and memory-controlled.


2049-2052: Request option wiring for long-context beta controls looks correct.

These fields are passed through in the right place to support initial apply + retry downgrade behavior.


2361-2397: The beta-rejection downgrade path is robust and safely retried once.

Good use of single-shot disablement, per-session toast throttling, and scrubbed reason logging before retry.

Co-authored-by: Codex <noreply@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant