Merge pull request #951 from kaitranntt/kai/feat/765-huggingface-inference-providers

feat: add Hugging Face API profile preset
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-04-10 18:27:24 -04:00
commit dcc584e375
10 files changed
+158 -4

No files matched your search

@@ -85,6 +85,52 @@ describe('profile-writer Anthropic direct', () => {
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', () => {
const result = createApiProfile(
'openrouter-test',
+19
View File
@@ -73,6 +73,25 @@ describe('provider-presets', () => {
expect(preset?.defaultProfileName).toBe('qwen-api');
});
it('resolves Hugging Face preset metadata', () => {
const preset = getPresetById('huggingface');
expect(preset?.id).toBe('huggingface');
expect(preset?.baseUrl).toBe('https://router.huggingface.co/v1');
expect(preset?.defaultProfileName).toBe('hf');
expect(preset?.defaultModel).toBe('openai/gpt-oss-120b:fastest');
expect(preset?.defaultTarget).toBe('droid');
expect(preset?.apiKeyPlaceholder).toBe('hf_...');
});
it('resolves hf alias to the Hugging Face preset', () => {
const preset = getPresetById('hf');
expect(preset?.id).toBe('huggingface');
});
it('treats hf alias as a valid preset id', () => {
expect(isValidPresetId('hf')).toBe(true);
});
it('keeps Anthropic direct last in the recommended preset order and reuses the Claude logo', () => {
const recommendedPresetIds = PROVIDER_PRESETS.filter(
(preset) => preset.category === 'recommended'
@@ -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();
});
});