mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-11 03:13:12 +00:00
fix(api): constrain preset target defaults
- limit preset default targets to persisted API profile targets - add regression coverage for preset target resolution and profile target persistence
This commit is contained in:
1 parent
414e8c80f5
commit
52ac29e7a8
4 files changed
+83
-7
No files matched your search
@@ -269,12 +269,12 @@ async function resolveDefaultTarget(
|
|||||||
providedTarget: TargetType | undefined,
|
providedTarget: TargetType | undefined,
|
||||||
yes: boolean | undefined
|
yes: boolean | undefined
|
||||||
): Promise<TargetType> {
|
): Promise<TargetType> {
|
||||||
if (providedTarget) {
|
const resolvedTarget = resolvePresetDefaultTarget(preset, providedTarget);
|
||||||
return providedTarget;
|
if (resolvedTarget) {
|
||||||
}
|
if (preset?.defaultTarget && !providedTarget) {
|
||||||
if (preset?.defaultTarget) {
|
console.log(info(`Using preset default target: ${preset.defaultTarget}`));
|
||||||
console.log(info(`Using preset default target: ${preset.defaultTarget}`));
|
}
|
||||||
return preset.defaultTarget;
|
return resolvedTarget;
|
||||||
}
|
}
|
||||||
if (yes) {
|
if (yes) {
|
||||||
return 'claude';
|
return 'claude';
|
||||||
@@ -287,6 +287,19 @@ async function resolveDefaultTarget(
|
|||||||
return useDroidByDefault ? 'droid' : 'claude';
|
return useDroidByDefault ? 'droid' : 'claude';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolvePresetDefaultTarget(
|
||||||
|
preset: Pick<ProviderPreset, 'defaultTarget'> | null,
|
||||||
|
providedTarget: TargetType | undefined
|
||||||
|
): TargetType | null {
|
||||||
|
if (providedTarget) {
|
||||||
|
return providedTarget;
|
||||||
|
}
|
||||||
|
if (preset?.defaultTarget) {
|
||||||
|
return preset.defaultTarget;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
async function resolveClaudeLongContextPreference(
|
async function resolveClaudeLongContextPreference(
|
||||||
models: ModelMapping,
|
models: ModelMapping,
|
||||||
explicitPreference: boolean | undefined,
|
explicitPreference: boolean | undefined,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export type PresetCategory = 'recommended' | 'alternative';
|
export type PresetCategory = 'recommended' | 'alternative';
|
||||||
export type ProviderPresetTarget = 'claude' | 'droid' | 'codex';
|
export type ProviderPresetTarget = 'claude' | 'droid';
|
||||||
|
|
||||||
export const PROVIDER_PRESET_IDS = [
|
export const PROVIDER_PRESET_IDS = [
|
||||||
'openrouter',
|
'openrouter',
|
||||||
|
|||||||
@@ -85,6 +85,52 @@ describe('profile-writer Anthropic direct', () => {
|
|||||||
expect(settings.env.ANTHROPIC_API_KEY).toBeUndefined();
|
expect(settings.env.ANTHROPIC_API_KEY).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('persists droid as the saved target for generic API profiles', () => {
|
||||||
|
const result = createApiProfile(
|
||||||
|
'hf-target',
|
||||||
|
'https://router.huggingface.co/v1',
|
||||||
|
'hf_testkey123',
|
||||||
|
{
|
||||||
|
default: 'openai/gpt-oss-120b:fastest',
|
||||||
|
opus: 'openai/gpt-oss-120b:fastest',
|
||||||
|
sonnet: 'openai/gpt-oss-120b:fastest',
|
||||||
|
haiku: 'openai/gpt-oss-120b:fastest',
|
||||||
|
},
|
||||||
|
'droid'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
|
||||||
|
const configPath = path.join(tempHome, '.ccs', 'config.json');
|
||||||
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
|
|
||||||
|
expect(config.profiles['hf-target']).toBe('~/.ccs/hf-target.settings.json');
|
||||||
|
expect(config.profile_targets['hf-target']).toBe('droid');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not persist a non-default target entry when the target is claude', () => {
|
||||||
|
const result = createApiProfile(
|
||||||
|
'hf-target-claude',
|
||||||
|
'https://router.huggingface.co/v1',
|
||||||
|
'hf_testkey123',
|
||||||
|
{
|
||||||
|
default: 'openai/gpt-oss-120b:fastest',
|
||||||
|
opus: 'openai/gpt-oss-120b:fastest',
|
||||||
|
sonnet: 'openai/gpt-oss-120b:fastest',
|
||||||
|
haiku: 'openai/gpt-oss-120b:fastest',
|
||||||
|
},
|
||||||
|
'claude'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
|
||||||
|
const configPath = path.join(tempHome, '.ccs', 'config.json');
|
||||||
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
|
|
||||||
|
expect(config.profiles['hf-target-claude']).toBe('~/.ccs/hf-target-claude.settings.json');
|
||||||
|
expect(config.profile_targets?.['hf-target-claude']).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it('preserves OpenRouter ANTHROPIC_API_KEY blank behavior', () => {
|
it('preserves OpenRouter ANTHROPIC_API_KEY blank behavior', () => {
|
||||||
const result = createApiProfile(
|
const result = createApiProfile(
|
||||||
'openrouter-test',
|
'openrouter-test',
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { describe, expect, it } from 'bun:test';
|
||||||
|
|
||||||
|
import { resolvePresetDefaultTarget } from '../../../src/commands/api-command/create-command';
|
||||||
|
|
||||||
|
describe('api create target resolution', () => {
|
||||||
|
it('uses the preset default target when no explicit target is provided', () => {
|
||||||
|
expect(resolvePresetDefaultTarget({ defaultTarget: 'droid' }, undefined)).toBe('droid');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('lets an explicit target override the preset default target', () => {
|
||||||
|
expect(resolvePresetDefaultTarget({ defaultTarget: 'droid' }, 'claude')).toBe('claude');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null when neither an explicit target nor a preset default exists', () => {
|
||||||
|
expect(resolvePresetDefaultTarget(null, undefined)).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user