mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-15 18:15:40 +00:00
fix(extended-context): suffix the Fable tier and default it on 1M launches
The previous commit assumed Claude Code's fable resolver strips [1m] and therefore never wrote the suffix into ANTHROPIC_DEFAULT_FABLE_MODEL. That premise only holds when ANTHROPIC_BASE_URL is unset or points at api.anthropic.com. Behind a proxy (CLIProxy, headroom, ...) Claude Code 2.1.259 does the opposite: - the fable alias resolver passes the env value through untouched, so a saved `claude-fable-5-1[1m]` reaches the model picker as-is; - the context-window resolver grants 1M unconditionally when the model id carries [1m], and otherwise trusts a natively-1M model only when the base URL is first-party. Bare `claude-fable-5-1` via 127.0.0.1 is clamped to 200k even though CLIProxy's /v1/models advertises max_input_tokens 1M. So the suffix is the only thing that turns the long window on for CCS, and stripping it from the Fable key is what kept `ccs claude --model fable` at 200k. A headroom settings profile with the suffix saved on that key showed the 1M window in the same Claude Code build, which is how the inversion was caught. Changes: - Drop the suffix-stripping key guard; ANTHROPIC_DEFAULT_FABLE_MODEL now receives and keeps [1m] exactly like the opus/sonnet tiers. - On a long-context launch (explicit --1m, or a saved [1m] on any Anthropic tier key) fill a missing Fable tier with the catalog Fable model plus [1m]. The model-neutral claude profile pins no Fable model, so `--model fable` used to fall back to Claude Code's bare default and lose the window even when every other tier asked for 1M. An explicit mapping always wins, --no-1m never fills, and providers without a catalog Fable model are left alone. - Add getDefaultFableTierModel() to the model catalog for that default. Verified with a stub Claude binary that dumps its environment: ccs claude --model fable -> ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5-1[1m] ccs claude --1m -> ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5-1[1m] ccs claude --no-1m --model fable -> no Fable tier written, ANTHROPIC_MODEL stripped
This commit is contained in:
1 parent
2b780ceae3
commit
02c45e088a
6 files changed
+162
-44
No files matched your search
@@ -4,7 +4,6 @@ import {
|
||||
ANTHROPIC_MODEL_ENV_KEYS,
|
||||
EXTENDED_CONTEXT_MODEL_ENV_KEYS,
|
||||
applyExtendedContextPreferenceToAnthropicModels,
|
||||
envKeyAcceptsExtendedContextSuffix,
|
||||
hasAnthropicExtendedContextEnabled,
|
||||
isAnthropicModelEnvKey,
|
||||
isExtendedContextModelEnvKey,
|
||||
@@ -37,22 +36,17 @@ describe('extended-context model env keys', () => {
|
||||
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', () => {
|
||||
it('writes [1m] into every managed key, the fable tier included', () => {
|
||||
// Behind a proxy base URL Claude Code clamps a bare Fable id to 200k, so the
|
||||
// fable tier needs the suffix exactly like the opus/sonnet tiers do.
|
||||
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]',
|
||||
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1',
|
||||
CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1',
|
||||
},
|
||||
true
|
||||
@@ -61,7 +55,7 @@ describe('applyExtendedContextPreferenceToAnthropicModels', () => {
|
||||
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',
|
||||
ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1[1m]',
|
||||
CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1[1m]',
|
||||
});
|
||||
});
|
||||
@@ -83,7 +77,7 @@ describe('applyExtendedContextPreferenceToAnthropicModels', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('honors a caller compatibility predicate on top of the key guard', () => {
|
||||
it('honors a caller compatibility predicate', () => {
|
||||
const env = applyExtendedContextPreferenceToAnthropicModels(
|
||||
{
|
||||
ANTHROPIC_MODEL: 'claude-opus-5',
|
||||
@@ -99,10 +93,13 @@ describe('applyExtendedContextPreferenceToAnthropicModels', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('reads saved intent from the subagent key too', () => {
|
||||
it('reads saved intent from any managed key', () => {
|
||||
expect(
|
||||
hasAnthropicExtendedContextEnabled({ CLAUDE_CODE_SUBAGENT_MODEL: 'claude-fable-5-1[1m]' })
|
||||
).toBe(true);
|
||||
expect(
|
||||
hasAnthropicExtendedContextEnabled({ ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1[1m]' })
|
||||
).toBe(true);
|
||||
expect(
|
||||
hasAnthropicExtendedContextEnabled({ ANTHROPIC_DEFAULT_FABLE_MODEL: 'claude-fable-5-1' })
|
||||
).toBe(false);
|
||||
|
||||
Reference in new issue
Block a user