mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-03 17:11:45 +00:00
fix(extended-context): never write [1m] into the Fable tier key
Claude Code resolves ANTHROPIC_DEFAULT_FABLE_MODEL through a resolver that strips the [1m] suffix before use, unlike the opus/sonnet resolvers which pass their env value through untouched. The stripped value is then treated as an env-supplied default and held to the standard 200k window instead of the model's native 1M, so writing [1m] into that key costs the long context window rather than granting it. Measured against a Claude Code 2.1.259 session (`/context` on a live proxy endpoint): ANTHROPIC_MODEL=claude-fable-5-1[1m] -> 1m window ANTHROPIC_MODEL=claude-fable-5-1 -> 200k window ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5-1[1m] -> 200k window The fix is key-scoped rather than model-scoped, since the suffix is what grants 1M on every other key. Adds envKeyAcceptsExtendedContextSuffix() as the single place recording which keys reject the suffix, enforces it as a floor inside applyExtendedContextPreferenceToAnthropicModels() so no caller can bypass it, and strips a previously saved suffix from that key on the next launch through the auto path. Also extends the preference to CLAUDE_CODE_SUBAGENT_MODEL. Subagent windows come from the same resolver as the main loop (the Explore inheritCap bounds the model tier, not the context window), so a bare subagent model id sits at 200k while the suffixed form gets 1M. The new key list is kept separate from ANTHROPIC_MODEL_ENV_KEYS, which also drives routing, model-id normalization and profile validation. Claude-Session: https://claude.ai/code/session_01NPkafQjVf4pSwPBwBistGk
This commit is contained in:
1 parent
3583b544d0
commit
2b780ceae3
6 files changed
+179
-9
No files matched your search
@@ -13,9 +13,10 @@ import type { CLIProxyProvider } from '../types';
|
|||||||
import { supportsExtendedContext } from '../model-catalog';
|
import { supportsExtendedContext } from '../model-catalog';
|
||||||
import { warn } from '../../utils/ui';
|
import { warn } from '../../utils/ui';
|
||||||
import {
|
import {
|
||||||
ANTHROPIC_MODEL_ENV_KEYS,
|
EXTENDED_CONTEXT_MODEL_ENV_KEYS,
|
||||||
applyExtendedContextPreferenceToAnthropicModels,
|
applyExtendedContextPreferenceToAnthropicModels,
|
||||||
applyExtendedContextSuffix as applyExtendedContextSuffixShared,
|
applyExtendedContextSuffix as applyExtendedContextSuffixShared,
|
||||||
|
envKeyAcceptsExtendedContextSuffix,
|
||||||
hasExtendedContextSuffix,
|
hasExtendedContextSuffix,
|
||||||
isNativeGeminiModel,
|
isNativeGeminiModel,
|
||||||
stripExtendedContextSuffix,
|
stripExtendedContextSuffix,
|
||||||
@@ -95,13 +96,20 @@ export function applyExtendedContextConfig(
|
|||||||
// previously saved [1m] preference just because the model is Claude — only
|
// previously saved [1m] preference just because the model is Claude — only
|
||||||
// strip when the model no longer supports extended context. Native Gemini
|
// strip when the model no longer supports extended context. Native Gemini
|
||||||
// models still get auto-toggled based on catalog support.
|
// models still get auto-toggled based on catalog support.
|
||||||
for (const key of ANTHROPIC_MODEL_ENV_KEYS) {
|
for (const key of EXTENDED_CONTEXT_MODEL_ENV_KEYS) {
|
||||||
const value = envVars[key];
|
const value = envVars[key];
|
||||||
if (typeof value !== 'string' || value.trim().length === 0) {
|
if (typeof value !== 'string' || value.trim().length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const modelId = stripModelConfigurationSuffixes(value);
|
const modelId = stripModelConfigurationSuffixes(value);
|
||||||
|
|
||||||
|
// Keys whose resolver strips [1m] must never keep a saved suffix: the
|
||||||
|
// stripped value loses the model's native long context window.
|
||||||
|
if (!envKeyAcceptsExtendedContextSuffix(key)) {
|
||||||
|
envVars[key] = stripExtendedContextSuffix(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (isNativeGeminiModel(modelId)) {
|
if (isNativeGeminiModel(modelId)) {
|
||||||
envVars[key] = supportsExtendedContext(provider, modelId)
|
envVars[key] = supportsExtendedContext(provider, modelId)
|
||||||
? applyExtendedContextSuffixShared(value)
|
? applyExtendedContextSuffixShared(value)
|
||||||
|
|||||||
@@ -14,8 +14,42 @@ export const ANTHROPIC_MODEL_ENV_KEYS = [
|
|||||||
|
|
||||||
export type AnthropicModelEnvKey = (typeof ANTHROPIC_MODEL_ENV_KEYS)[number];
|
export type AnthropicModelEnvKey = (typeof ANTHROPIC_MODEL_ENV_KEYS)[number];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model env keys outside the Anthropic tier mappings that still carry a plain
|
||||||
|
* model id, so the extended-context preference has to cover them too. Kept
|
||||||
|
* separate from ANTHROPIC_MODEL_ENV_KEYS, which also drives routing, model-id
|
||||||
|
* normalization and profile validation.
|
||||||
|
*/
|
||||||
|
export const EXTRA_EXTENDED_CONTEXT_MODEL_ENV_KEYS = ['CLAUDE_CODE_SUBAGENT_MODEL'] as const;
|
||||||
|
|
||||||
|
/** Every model env key the [1m] preference is applied to. */
|
||||||
|
export const EXTENDED_CONTEXT_MODEL_ENV_KEYS = [
|
||||||
|
...ANTHROPIC_MODEL_ENV_KEYS,
|
||||||
|
...EXTRA_EXTENDED_CONTEXT_MODEL_ENV_KEYS,
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type ExtendedContextModelEnvKey = (typeof EXTENDED_CONTEXT_MODEL_ENV_KEYS)[number];
|
||||||
|
|
||||||
const ANTHROPIC_MODEL_ENV_KEY_SET = new Set<string>(ANTHROPIC_MODEL_ENV_KEYS);
|
const ANTHROPIC_MODEL_ENV_KEY_SET = new Set<string>(ANTHROPIC_MODEL_ENV_KEYS);
|
||||||
|
|
||||||
|
const EXTENDED_CONTEXT_MODEL_ENV_KEY_SET = new Set<string>(EXTENDED_CONTEXT_MODEL_ENV_KEYS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keys whose value Claude Code resolves through a resolver that removes [1m]
|
||||||
|
* before use. ANTHROPIC_DEFAULT_FABLE_MODEL is the only one today: its resolver
|
||||||
|
* strips the suffix (unlike the opus/sonnet resolvers, which pass the value
|
||||||
|
* through), and the stripped env-supplied default is then held to the standard
|
||||||
|
* 200k window instead of the model's native 1M. Writing [1m] here therefore
|
||||||
|
* costs the long context window rather than granting it, and Fable models are
|
||||||
|
* natively 1M, so the suffix is never needed on this key.
|
||||||
|
*/
|
||||||
|
const SUFFIX_STRIPPING_MODEL_ENV_KEYS = new Set<string>(['ANTHROPIC_DEFAULT_FABLE_MODEL']);
|
||||||
|
|
||||||
|
/** True when writing an explicit [1m] suffix into this env key is meaningful. */
|
||||||
|
export function envKeyAcceptsExtendedContextSuffix(key: string): boolean {
|
||||||
|
return !SUFFIX_STRIPPING_MODEL_ENV_KEYS.has(key);
|
||||||
|
}
|
||||||
|
|
||||||
/** Check if model is a native Gemini model (auto-enabled behavior). */
|
/** Check if model is a native Gemini model (auto-enabled behavior). */
|
||||||
export function isNativeGeminiModel(modelId: string): boolean {
|
export function isNativeGeminiModel(modelId: string): boolean {
|
||||||
return modelId.toLowerCase().startsWith('gemini-');
|
return modelId.toLowerCase().startsWith('gemini-');
|
||||||
@@ -44,6 +78,11 @@ export function isAnthropicModelEnvKey(key: string): key is AnthropicModelEnvKey
|
|||||||
return ANTHROPIC_MODEL_ENV_KEY_SET.has(key);
|
return ANTHROPIC_MODEL_ENV_KEY_SET.has(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** True when key holds a model id the [1m] preference is applied to. */
|
||||||
|
export function isExtendedContextModelEnvKey(key: string): key is ExtendedContextModelEnvKey {
|
||||||
|
return EXTENDED_CONTEXT_MODEL_ENV_KEY_SET.has(key);
|
||||||
|
}
|
||||||
|
|
||||||
/** Strip transient config suffixes so model IDs can be checked against catalogs. */
|
/** Strip transient config suffixes so model IDs can be checked against catalogs. */
|
||||||
export function stripModelConfigurationSuffixes(modelId: string): string {
|
export function stripModelConfigurationSuffixes(modelId: string): string {
|
||||||
return stripExtendedContextSuffix(modelId.trim()).replace(/\([^)]+\)$/, '');
|
return stripExtendedContextSuffix(modelId.trim()).replace(/\([^)]+\)$/, '');
|
||||||
@@ -53,7 +92,7 @@ export function stripModelConfigurationSuffixes(modelId: string): string {
|
|||||||
export function hasAnthropicExtendedContextEnabled(
|
export function hasAnthropicExtendedContextEnabled(
|
||||||
env: Partial<Record<string, string | undefined>>
|
env: Partial<Record<string, string | undefined>>
|
||||||
): boolean {
|
): boolean {
|
||||||
return ANTHROPIC_MODEL_ENV_KEYS.some((key) => {
|
return EXTENDED_CONTEXT_MODEL_ENV_KEYS.some((key) => {
|
||||||
const value = env[key];
|
const value = env[key];
|
||||||
return typeof value === 'string' && hasExtendedContextSuffix(value);
|
return typeof value === 'string' && hasExtendedContextSuffix(value);
|
||||||
});
|
});
|
||||||
@@ -66,19 +105,21 @@ export function applyExtendedContextPreferenceToAnthropicModels<
|
|||||||
env: T,
|
env: T,
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
options: {
|
options: {
|
||||||
supportsExtendedContext?: (modelId: string, key: AnthropicModelEnvKey) => boolean;
|
supportsExtendedContext?: (modelId: string, key: ExtendedContextModelEnvKey) => boolean;
|
||||||
} = {}
|
} = {}
|
||||||
): T {
|
): T {
|
||||||
const nextEnv: Record<string, string | undefined> = { ...env };
|
const nextEnv: Record<string, string | undefined> = { ...env };
|
||||||
|
|
||||||
for (const key of ANTHROPIC_MODEL_ENV_KEYS) {
|
for (const key of EXTENDED_CONTEXT_MODEL_ENV_KEYS) {
|
||||||
const value = nextEnv[key];
|
const value = nextEnv[key];
|
||||||
if (typeof value !== 'string' || value.trim().length === 0) {
|
if (typeof value !== 'string' || value.trim().length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modelId = stripModelConfigurationSuffixes(value);
|
const modelId = stripModelConfigurationSuffixes(value);
|
||||||
const supported = options.supportsExtendedContext?.(modelId, key) ?? true;
|
const supported =
|
||||||
|
envKeyAcceptsExtendedContextSuffix(key) &&
|
||||||
|
(options.supportsExtendedContext?.(modelId, key) ?? true);
|
||||||
nextEnv[key] =
|
nextEnv[key] =
|
||||||
enabled && supported ? applyExtendedContextSuffix(value) : stripExtendedContextSuffix(value);
|
enabled && supported ? applyExtendedContextSuffix(value) : stripExtendedContextSuffix(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { describe, expect, it } from 'bun:test';
|
||||||
|
|
||||||
|
import { applyExtendedContextConfig } from '../../../src/cliproxy/config/extended-context-config';
|
||||||
|
|
||||||
|
describe('applyExtendedContextConfig', () => {
|
||||||
|
it('strips a saved [1m] from the fable tier key in auto mode', () => {
|
||||||
|
const env: NodeJS.ProcessEnv = {
|
||||||
|
ANTHROPIC_MODEL: 'claude-opus-5[1m]',
|
||||||
|
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1[1m]',
|
||||||
|
};
|
||||||
|
|
||||||
|
applyExtendedContextConfig(env, 'claude');
|
||||||
|
|
||||||
|
expect(env.ANTHROPIC_DEFAULT_FABLE_MODEL).toBe('claude-fable-5-1');
|
||||||
|
expect(env.ANTHROPIC_MODEL).toBe('claude-opus-5[1m]');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps the fable tier key plain when extended context is forced on', () => {
|
||||||
|
const env: NodeJS.ProcessEnv = {
|
||||||
|
ANTHROPIC_MODEL: 'claude-fable-5-1',
|
||||||
|
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1',
|
||||||
|
CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1',
|
||||||
|
};
|
||||||
|
|
||||||
|
applyExtendedContextConfig(env, 'claude', true);
|
||||||
|
|
||||||
|
expect(env.ANTHROPIC_DEFAULT_FABLE_MODEL).toBe('claude-fable-5-1');
|
||||||
|
expect(env.ANTHROPIC_MODEL).toBe('claude-fable-5-1[1m]');
|
||||||
|
expect(env.CLAUDE_CODE_SUBAGENT_MODEL).toBe('claude-fable-5-1[1m]');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,7 +2,12 @@ import { describe, expect, it } from 'bun:test';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ANTHROPIC_MODEL_ENV_KEYS,
|
ANTHROPIC_MODEL_ENV_KEYS,
|
||||||
|
EXTENDED_CONTEXT_MODEL_ENV_KEYS,
|
||||||
|
applyExtendedContextPreferenceToAnthropicModels,
|
||||||
|
envKeyAcceptsExtendedContextSuffix,
|
||||||
|
hasAnthropicExtendedContextEnabled,
|
||||||
isAnthropicModelEnvKey,
|
isAnthropicModelEnvKey,
|
||||||
|
isExtendedContextModelEnvKey,
|
||||||
} from '../../../src/shared/extended-context-utils';
|
} from '../../../src/shared/extended-context-utils';
|
||||||
|
|
||||||
describe('Anthropic model env keys', () => {
|
describe('Anthropic model env keys', () => {
|
||||||
@@ -22,3 +27,84 @@ describe('Anthropic model env keys', () => {
|
|||||||
expect(isAnthropicModelEnvKey('ANTHROPIC_BASE_URL')).toBe(false);
|
expect(isAnthropicModelEnvKey('ANTHROPIC_BASE_URL')).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('extended-context model env keys', () => {
|
||||||
|
it('covers the Anthropic tiers plus the subagent model key', () => {
|
||||||
|
expect([...EXTENDED_CONTEXT_MODEL_ENV_KEYS]).toEqual([
|
||||||
|
...ANTHROPIC_MODEL_ENV_KEYS,
|
||||||
|
'CLAUDE_CODE_SUBAGENT_MODEL',
|
||||||
|
]);
|
||||||
|
expect(isExtendedContextModelEnvKey('CLAUDE_CODE_SUBAGENT_MODEL')).toBe(true);
|
||||||
|
expect(isAnthropicModelEnvKey('CLAUDE_CODE_SUBAGENT_MODEL')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('marks the fable tier key as suffix-stripping', () => {
|
||||||
|
expect(envKeyAcceptsExtendedContextSuffix('ANTHROPIC_DEFAULT_FABLE_MODEL')).toBe(false);
|
||||||
|
expect(envKeyAcceptsExtendedContextSuffix('ANTHROPIC_MODEL')).toBe(true);
|
||||||
|
expect(envKeyAcceptsExtendedContextSuffix('ANTHROPIC_DEFAULT_OPUS_MODEL')).toBe(true);
|
||||||
|
expect(envKeyAcceptsExtendedContextSuffix('CLAUDE_CODE_SUBAGENT_MODEL')).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('applyExtendedContextPreferenceToAnthropicModels', () => {
|
||||||
|
it('never writes [1m] into the fable tier key and strips a saved one', () => {
|
||||||
|
const env = applyExtendedContextPreferenceToAnthropicModels(
|
||||||
|
{
|
||||||
|
ANTHROPIC_MODEL: 'claude-fable-5-1',
|
||||||
|
ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-opus-5',
|
||||||
|
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1[1m]',
|
||||||
|
CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1',
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(env).toEqual({
|
||||||
|
ANTHROPIC_MODEL: 'claude-fable-5-1[1m]',
|
||||||
|
ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-opus-5[1m]',
|
||||||
|
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1',
|
||||||
|
CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1[1m]',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('strips every managed key when the preference is off', () => {
|
||||||
|
const env = applyExtendedContextPreferenceToAnthropicModels(
|
||||||
|
{
|
||||||
|
ANTHROPIC_MODEL: 'claude-opus-5[1m]',
|
||||||
|
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1[1m]',
|
||||||
|
CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1[1m]',
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(env).toEqual({
|
||||||
|
ANTHROPIC_MODEL: 'claude-opus-5',
|
||||||
|
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1',
|
||||||
|
CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('honors a caller compatibility predicate on top of the key guard', () => {
|
||||||
|
const env = applyExtendedContextPreferenceToAnthropicModels(
|
||||||
|
{
|
||||||
|
ANTHROPIC_MODEL: 'claude-opus-5',
|
||||||
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: 'claude-haiku-4-5-20251001',
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
{ supportsExtendedContext: (modelId) => !modelId.startsWith('claude-haiku-') }
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(env).toEqual({
|
||||||
|
ANTHROPIC_MODEL: 'claude-opus-5[1m]',
|
||||||
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: 'claude-haiku-4-5-20251001',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reads saved intent from the subagent key too', () => {
|
||||||
|
expect(
|
||||||
|
hasAnthropicExtendedContextEnabled({ CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1[1m]' })
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
hasAnthropicExtendedContextEnabled({ ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1' })
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -12,7 +12,7 @@ import type { ProviderCatalog } from '../provider-model-selector';
|
|||||||
import {
|
import {
|
||||||
applyExtendedContextPreferenceToAnthropicModels,
|
applyExtendedContextPreferenceToAnthropicModels,
|
||||||
hasAnthropicExtendedContextEnabled,
|
hasAnthropicExtendedContextEnabled,
|
||||||
isAnthropicModelEnvKey,
|
isExtendedContextModelEnvKey,
|
||||||
} from '@/lib/extended-context-utils';
|
} from '@/lib/extended-context-utils';
|
||||||
import { supportsExtendedContext } from '@/lib/model-catalogs';
|
import { supportsExtendedContext } from '@/lib/model-catalogs';
|
||||||
import { isValidProvider } from '@/lib/provider-config';
|
import { isValidProvider } from '@/lib/provider-config';
|
||||||
@@ -104,7 +104,7 @@ export function useProviderEditor(
|
|||||||
const updateEnvValue = useCallback(
|
const updateEnvValue = useCallback(
|
||||||
(key: string, value: string) => {
|
(key: string, value: string) => {
|
||||||
const newEnv = { ...(currentSettings?.env || {}), [key]: value };
|
const newEnv = { ...(currentSettings?.env || {}), [key]: value };
|
||||||
const envWithIntent = isAnthropicModelEnvKey(key)
|
const envWithIntent = isExtendedContextModelEnvKey(key)
|
||||||
? applySavedLongContextIntent(newEnv, extendedContextEnabled)
|
? applySavedLongContextIntent(newEnv, extendedContextEnabled)
|
||||||
: newEnv;
|
: newEnv;
|
||||||
delete envWithIntent['CCS_EXTENDED_CONTEXT'];
|
delete envWithIntent['CCS_EXTENDED_CONTEXT'];
|
||||||
@@ -132,7 +132,7 @@ export function useProviderEditor(
|
|||||||
const updateEnvValues = useCallback(
|
const updateEnvValues = useCallback(
|
||||||
(updates: Record<string, string>) => {
|
(updates: Record<string, string>) => {
|
||||||
const newEnv = { ...(currentSettings?.env || {}), ...updates };
|
const newEnv = { ...(currentSettings?.env || {}), ...updates };
|
||||||
const touchesAnthropicModel = Object.keys(updates).some(isAnthropicModelEnvKey);
|
const touchesAnthropicModel = Object.keys(updates).some(isExtendedContextModelEnvKey);
|
||||||
const envWithIntent = touchesAnthropicModel
|
const envWithIntent = touchesAnthropicModel
|
||||||
? applySavedLongContextIntent(newEnv, extendedContextEnabled)
|
? applySavedLongContextIntent(newEnv, extendedContextEnabled)
|
||||||
: newEnv;
|
: newEnv;
|
||||||
|
|||||||
@@ -4,10 +4,14 @@
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
ANTHROPIC_MODEL_ENV_KEYS,
|
ANTHROPIC_MODEL_ENV_KEYS,
|
||||||
|
EXTENDED_CONTEXT_MODEL_ENV_KEYS,
|
||||||
EXTENDED_CONTEXT_SUFFIX,
|
EXTENDED_CONTEXT_SUFFIX,
|
||||||
|
EXTRA_EXTENDED_CONTEXT_MODEL_ENV_KEYS,
|
||||||
applyExtendedContextPreferenceToAnthropicModels,
|
applyExtendedContextPreferenceToAnthropicModels,
|
||||||
|
envKeyAcceptsExtendedContextSuffix,
|
||||||
isNativeGeminiModel,
|
isNativeGeminiModel,
|
||||||
isAnthropicModelEnvKey,
|
isAnthropicModelEnvKey,
|
||||||
|
isExtendedContextModelEnvKey,
|
||||||
hasAnthropicExtendedContextEnabled,
|
hasAnthropicExtendedContextEnabled,
|
||||||
hasExtendedContextSuffix,
|
hasExtendedContextSuffix,
|
||||||
applyExtendedContextSuffix,
|
applyExtendedContextSuffix,
|
||||||
|
|||||||
Reference in new issue
Block a user