mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-17 06:14:30 +00:00
fix(droid): avoid interactive model arg prompt pollution
- persist selector in ~/.factory/settings.json as settings.model - stop injecting '-m custom:...' for interactive droid launches - improve provider inference for localhost /v1 and qwen/deepseek/kimi - add regression tests for adapter, provider, and config manager
This commit is contained in:
1 parent
60b1c043c7
commit
f1567c0090
8 files changed
+65
-13
No files matched your search
@@ -5,9 +5,9 @@ import { describe, it, expect } from 'bun:test';
|
||||
import { DroidAdapter } from '../../../src/targets/droid-adapter';
|
||||
|
||||
describe('DroidAdapter.buildArgs', () => {
|
||||
it('builds droid model args for valid profile names', () => {
|
||||
it('passes user args without model injection for valid profile names', () => {
|
||||
const adapter = new DroidAdapter();
|
||||
expect(adapter.buildArgs('gemini_01', ['--help'])).toEqual(['-m', 'custom:ccs-gemini_01', '--help']);
|
||||
expect(adapter.buildArgs('gemini_01', ['--help'])).toEqual(['--help']);
|
||||
});
|
||||
|
||||
it('rejects unsafe profile names', () => {
|
||||
|
||||
@@ -45,6 +45,10 @@ describe('droid-config-manager', () => {
|
||||
expect(ref.selectorAlias).toBe('CCS-gemini-0');
|
||||
expect(ref.selector).toBe('custom:CCS-gemini-0');
|
||||
expect(ref.index).toBe(0);
|
||||
|
||||
const settingsPath = path.join(tmpDir, '.factory', 'settings.json');
|
||||
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
||||
expect(settings.model).toBe('custom:CCS-gemini-0');
|
||||
});
|
||||
|
||||
it('should create settings.json with customModels', async () => {
|
||||
@@ -63,6 +67,7 @@ describe('droid-config-manager', () => {
|
||||
expect(settings.customModels).toHaveLength(1);
|
||||
expect(settings.customModels[0].displayName).toBe('CCS gemini');
|
||||
expect(settings.customModels[0].baseUrl).toBe('http://localhost:8317');
|
||||
expect(settings.model).toBe('custom:CCS-gemini-0');
|
||||
});
|
||||
|
||||
it('should update existing entry on second upsert', async () => {
|
||||
|
||||
@@ -46,6 +46,18 @@ describe('droid-provider', () => {
|
||||
'generic-chat-completion-api'
|
||||
);
|
||||
});
|
||||
|
||||
it('detects localhost openai-compatible /v1 endpoints', () => {
|
||||
expect(inferDroidProviderFromBaseUrl('http://127.0.0.1:1234/v1')).toBe(
|
||||
'generic-chat-completion-api'
|
||||
);
|
||||
expect(inferDroidProviderFromBaseUrl('http://localhost:8317/v1/chat/completions')).toBe(
|
||||
'generic-chat-completion-api'
|
||||
);
|
||||
expect(inferDroidProviderFromBaseUrl('http://[::1]:8317/v1')).toBe(
|
||||
'generic-chat-completion-api'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('inferDroidProviderFromModel', () => {
|
||||
@@ -56,6 +68,12 @@ describe('droid-provider', () => {
|
||||
it('detects openai model naming', () => {
|
||||
expect(inferDroidProviderFromModel('gpt-5-codex')).toBe('openai');
|
||||
});
|
||||
|
||||
it('detects generic openai-compatible model families', () => {
|
||||
expect(inferDroidProviderFromModel('qwen3-coder-plus')).toBe('generic-chat-completion-api');
|
||||
expect(inferDroidProviderFromModel('deepseek-v3.1')).toBe('generic-chat-completion-api');
|
||||
expect(inferDroidProviderFromModel('kimi-k2')).toBe('generic-chat-completion-api');
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveDroidProvider', () => {
|
||||
|
||||
@@ -125,10 +125,16 @@ describe('DroidAdapter', () => {
|
||||
expect(adapter.supportsProfileType('copilot')).toBe(false);
|
||||
});
|
||||
|
||||
it('should build args with -m custom:ccs- prefix', () => {
|
||||
it('should keep interactive args clean (no model argv injection)', () => {
|
||||
const isolatedAdapter = new DroidAdapter();
|
||||
const args = isolatedAdapter.buildArgs('gemini', ['--verbose']);
|
||||
expect(args).toEqual(['-m', 'custom:ccs-gemini', '--verbose']);
|
||||
expect(args).toEqual(['--verbose']);
|
||||
});
|
||||
|
||||
it('should not queue model selector as prompt when no user args', () => {
|
||||
const isolatedAdapter = new DroidAdapter();
|
||||
const args = isolatedAdapter.buildArgs('codex', []);
|
||||
expect(args).toEqual([]);
|
||||
});
|
||||
|
||||
it('should build minimal env (no ANTHROPIC_ vars)', () => {
|
||||
@@ -200,7 +206,7 @@ describe('DroidAdapter', () => {
|
||||
});
|
||||
|
||||
const args = isolatedAdapter.buildArgs('gemini', ['--verbose']);
|
||||
expect(args).toEqual(['-m', 'custom:CCS-gemini-0', '--verbose']);
|
||||
expect(args).toEqual(['--verbose']);
|
||||
} finally {
|
||||
if (originalCcsHome !== undefined) process.env.CCS_HOME = originalCcsHome;
|
||||
else delete process.env.CCS_HOME;
|
||||
|
||||
Reference in new issue
Block a user