Repository navigation
feat: add CC Compatible connection-level 1M context toggle #1357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -46,7 +46,10 @@ import { resolveManagedModelAlias } from "@/shared/utils/providerModelAliases"; | |||||
| import { maskEmail, pickMaskedDisplayValue, pickDisplayValue } from "@/shared/utils/maskEmail"; | ||||||
| import useEmailPrivacyStore from "@/store/emailPrivacyStore"; | ||||||
| import EmailPrivacyToggle from "@/shared/components/EmailPrivacyToggle"; | ||||||
| import { getCodexRequestDefaults as _getCodexRequestDefaults } from "@/lib/providers/requestDefaults"; | ||||||
| import { | ||||||
| getClaudeCodeCompatibleRequestDefaults as _getClaudeCodeCompatibleRequestDefaults, | ||||||
| getCodexRequestDefaults as _getCodexRequestDefaults, | ||||||
| } from "@/lib/providers/requestDefaults"; | ||||||
|
|
||||||
| type CompatByProtocolMap = Partial< | ||||||
| Record< | ||||||
|
|
@@ -573,6 +576,15 @@ function getCodexRequestDefaults(providerSpecificData: unknown): { | |||||
| }; | ||||||
| } | ||||||
|
|
||||||
| function getClaudeCodeCompatibleRequestDefaults(providerSpecificData: unknown): { | ||||||
| context1m: boolean; | ||||||
| } { | ||||||
| const defaults = _getClaudeCodeCompatibleRequestDefaults(providerSpecificData); | ||||||
| return { | ||||||
| context1m: defaults.context1m === true, | ||||||
| }; | ||||||
| } | ||||||
|
|
||||||
| function compatProtocolLabelKey(protocol: string): string { | ||||||
| if (protocol === "openai") return "compatProtocolOpenAI"; | ||||||
| if (protocol === "openai-responses") return "compatProtocolOpenAIResponses"; | ||||||
|
|
@@ -5186,6 +5198,7 @@ function AddApiKeyModal({ | |||||
| customUserAgent: "", | ||||||
| accountId: "", | ||||||
| consoleApiKey: "", | ||||||
| ccCompatibleContext1m: false, | ||||||
| }); | ||||||
| const [validating, setValidating] = useState(false); | ||||||
| const [validationResult, setValidationResult] = useState(null); | ||||||
|
|
@@ -5278,6 +5291,9 @@ function AddApiKeyModal({ | |||||
| } else if (isCloudflare && formData.accountId.trim()) { | ||||||
| providerSpecificData.accountId = formData.accountId.trim(); | ||||||
| } | ||||||
| if (isCcCompatible && formData.ccCompatibleContext1m) { | ||||||
| providerSpecificData.requestDefaults = { context1m: true }; | ||||||
| } | ||||||
|
|
||||||
| const payload = { | ||||||
| name: formData.name, | ||||||
|
|
@@ -5352,6 +5368,16 @@ function AddApiKeyModal({ | |||||
| {saveError} | ||||||
| </div> | ||||||
| )} | ||||||
| {isCcCompatible && ( | ||||||
| <div className="flex flex-col gap-4 rounded-lg border border-border/50 bg-surface/20 p-4"> | ||||||
| <Toggle | ||||||
| checked={formData.ccCompatibleContext1m} | ||||||
| onChange={(checked) => setFormData({ ...formData, ccCompatibleContext1m: checked })} | ||||||
| label="CC Compatible 1M Context" | ||||||
| description="When enabled, this connection appends `anthropic-beta: context-1m-2025-08-07`." | ||||||
| /> | ||||||
| </div> | ||||||
| )} | ||||||
| {isCompatible && ( | ||||||
| <p className="text-xs text-text-muted"> | ||||||
| {isCcCompatible | ||||||
|
|
@@ -5526,6 +5552,7 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec | |||||
| codexFastServiceTier: false, | ||||||
| codexOpenaiStoreEnabled: false, | ||||||
| consoleApiKey: "", | ||||||
| ccCompatibleContext1m: false, | ||||||
| }); | ||||||
| const [testing, setTesting] = useState(false); | ||||||
| const [testResult, setTestResult] = useState(null); | ||||||
|
|
@@ -5545,6 +5572,7 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec | |||||
| const isGlm = connection?.provider === "glm" || connection?.provider === "glmt"; | ||||||
| const isCloudflare = connection?.provider === "cloudflare-ai"; | ||||||
| const isCodex = connection?.provider === "codex"; | ||||||
| const isCcCompatible = isClaudeCodeCompatibleProvider(connection?.provider); | ||||||
| const defaultRegion = "us-central1"; | ||||||
|
|
||||||
| useEffect(() => { | ||||||
|
|
@@ -5559,6 +5587,9 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec | |||||
| const rawAccountId = connection.providerSpecificData?.accountId; | ||||||
| const existingAccountId = typeof rawAccountId === "string" ? rawAccountId : ""; | ||||||
| const codexRequestDefaults = getCodexRequestDefaults(connection.providerSpecificData); | ||||||
| const ccRequestDefaults = getClaudeCodeCompatibleRequestDefaults( | ||||||
| connection.providerSpecificData | ||||||
| ); | ||||||
| const rawConsoleApiKey = connection.providerSpecificData?.consoleApiKey; | ||||||
| const existingConsoleApiKey = typeof rawConsoleApiKey === "string" ? rawConsoleApiKey : ""; | ||||||
| setFormData({ | ||||||
|
|
@@ -5577,6 +5608,7 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec | |||||
| codexFastServiceTier: codexRequestDefaults.serviceTier === "priority", | ||||||
| codexOpenaiStoreEnabled: connection.providerSpecificData?.openaiStoreEnabled === true, | ||||||
| consoleApiKey: existingConsoleApiKey, | ||||||
| ccCompatibleContext1m: ccRequestDefaults.context1m, | ||||||
| }); | ||||||
| // Load existing extra keys from providerSpecificData | ||||||
| const existing = connection.providerSpecificData?.extraApiKeys; | ||||||
|
|
@@ -5728,6 +5760,21 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec | |||||
| } else if (isCloudflare && formData.accountId.trim()) { | ||||||
| updates.providerSpecificData.accountId = formData.accountId.trim(); | ||||||
| } | ||||||
| if (isCcCompatible) { | ||||||
| const currentRequestDefaults = | ||||||
| updates.providerSpecificData.requestDefaults && | ||||||
| typeof updates.providerSpecificData.requestDefaults === "object" && | ||||||
| !Array.isArray(updates.providerSpecificData.requestDefaults) | ||||||
| ? { ...(updates.providerSpecificData.requestDefaults as Record<string, unknown>) } | ||||||
| : {}; | ||||||
| if (formData.ccCompatibleContext1m) { | ||||||
| currentRequestDefaults.context1m = true; | ||||||
| } else { | ||||||
| delete currentRequestDefaults.context1m; | ||||||
| } | ||||||
| updates.providerSpecificData.requestDefaults = | ||||||
| Object.keys(currentRequestDefaults).length > 0 ? currentRequestDefaults : undefined; | ||||||
|
||||||
| Object.keys(currentRequestDefaults).length > 0 ? currentRequestDefaults : undefined; | |
| Object.keys(currentRequestDefaults).length > 0 ? currentRequestDefaults : {}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| type JsonRecord = Record<string, unknown>; | ||
| const CLAUDE_CODE_COMPATIBLE_PROVIDER_PREFIX = "anthropic-compatible-cc-"; | ||
|
|
||
| export const CODEX_REASONING_EFFORT_VALUES = ["none", "low", "medium", "high", "xhigh"] as const; | ||
|
|
||
|
|
@@ -20,6 +21,12 @@ function hasNonEmptyString(value: unknown): boolean { | |
| return typeof value === "string" && value.trim().length > 0; | ||
| } | ||
|
|
||
| function isClaudeCodeCompatibleProvider(provider: string | null | undefined): boolean { | ||
| return ( | ||
| typeof provider === "string" && provider.startsWith(CLAUDE_CODE_COMPATIBLE_PROVIDER_PREFIX) | ||
| ); | ||
| } | ||
|
Comment on lines
1
to
+28
|
||
|
|
||
| export function normalizeCodexReasoningEffort(value: unknown): CodexReasoningEffort | undefined { | ||
| const normalized = normalizeString(value); | ||
| if (!normalized || !CODEX_REASONING_EFFORT_SET.has(normalized)) { | ||
|
|
@@ -35,6 +42,10 @@ export function normalizeCodexServiceTier(value: unknown): "priority" | undefine | |
| return undefined; | ||
| } | ||
|
|
||
| export function normalizeClaudeCodeCompatibleContext1m(value: unknown): true | undefined { | ||
| return value === true ? true : undefined; | ||
| } | ||
|
|
||
| export function normalizeRequestDefaults( | ||
| provider: string | null | undefined, | ||
| value: unknown | ||
|
|
@@ -60,6 +71,15 @@ export function normalizeRequestDefaults( | |
| } | ||
| } | ||
|
|
||
| if (isClaudeCodeCompatibleProvider(provider)) { | ||
| const context1m = normalizeClaudeCodeCompatibleContext1m(record.context1m); | ||
| if (context1m) { | ||
| normalized.context1m = true; | ||
| } else { | ||
| delete normalized.context1m; | ||
| } | ||
| } | ||
|
|
||
| return Object.keys(normalized).length > 0 ? normalized : undefined; | ||
| } | ||
|
|
||
|
|
@@ -151,3 +171,16 @@ export function getCodexRequestDefaults(providerSpecificData: unknown): { | |
| ...(serviceTier ? { serviceTier } : {}), | ||
| }; | ||
| } | ||
|
|
||
| export function getClaudeCodeCompatibleRequestDefaults(providerSpecificData: unknown): { | ||
| context1m?: true; | ||
| } { | ||
| const defaults = getProviderRequestDefaults( | ||
| "anthropic-compatible-cc-default", | ||
| providerSpecificData | ||
| ); | ||
| const context1m = normalizeClaudeCodeCompatibleContext1m(defaults.context1m); | ||
| return { | ||
| ...(context1m ? { context1m } : {}), | ||
| }; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldForwardCcCompatibleContext1mappends the 1M beta header for CC-compatible providers without checking whether the selected model supports the context-1m beta. SincemodelSupportsContext1mBeta()and the supported model list already exist (and are used forextendedContext), consider applying the same model gating here to avoid sendinganthropic-beta: context-1m-2025-08-07on unsupported models.