import { describe, it, expect } from 'vitest'; import type { SessionConfigOption } from '@agentclientprotocol/sdk'; import { deriveModesFromACP, deriveModelDefinitionsFromACP, findThoughtLevelConfigId, } from '../acp-derive.js'; describe('deriveModesFromACP', () => { it('prefers modeState.availableModes when present', () => { const { modes, currentModeId } = deriveModesFromACP( [{ id: 'fallback', label: 'Fallback' }], { currentModeId: 'plan', availableModes: [ { id: 'plan', name: 'Plan', description: 'Read-only planning' }, { id: 'code', name: 'Code' }, ], }, ); expect(modes).toEqual([ { id: 'plan', label: 'Plan', description: 'Read-only planning' }, { id: 'code', label: 'Code', description: undefined }, ]); expect(currentModeId).toBe('plan'); }); it('falls back to configOptions mode select', () => { const configOptions: SessionConfigOption[] = [ { type: 'select', id: 'mode', category: 'mode', currentValue: 'auto', options: [ { value: 'auto', name: 'Auto' }, { value: 'manual', name: 'Manual', description: 'Ask first' }, ], }, ]; const { modes, currentModeId } = deriveModesFromACP([], null, configOptions); expect(modes).toEqual([ { id: 'auto', label: 'Auto', description: undefined }, { id: 'manual', label: 'Manual', description: 'Ask first' }, ]); expect(currentModeId).toBe('auto'); }); it('uses static fallback when no ACP mode data', () => { const fallback = [{ id: 'default', label: 'Default' }]; const { modes, currentModeId } = deriveModesFromACP(fallback, null, null); expect(modes).toEqual(fallback); expect(currentModeId).toBeNull(); }); }); describe('deriveModelDefinitionsFromACP', () => { it('maps availableModels with thought_level options', () => { const configOptions: SessionConfigOption[] = [ { type: 'select', id: 'thought', category: 'thought_level', currentValue: 'medium', options: [ { value: 'low', name: 'Low' }, { value: 'medium', name: 'Medium' }, ], }, ]; const models = deriveModelDefinitionsFromACP( { currentModelId: 'gpt-4', availableModels: [ { modelId: 'gpt-4', name: 'GPT-4' }, { modelId: 'gpt-4-mini', name: 'Mini', description: 'Cheaper' }, ], }, configOptions, ); expect(models).toEqual([ { id: 'gpt-4', label: 'GPT-4', description: undefined, isDefault: true, thinkingOptions: [ { id: 'low', label: 'Low', isDefault: false }, { id: 'medium', label: 'Medium', isDefault: true }, ], defaultThinkingOptionId: 'medium', }, { id: 'gpt-4-mini', label: 'Mini', description: 'Cheaper', isDefault: false, thinkingOptions: [ { id: 'low', label: 'Low', isDefault: false }, { id: 'medium', label: 'Medium', isDefault: true }, ], defaultThinkingOptionId: 'medium', }, ]); }); it('falls back to model select config when no availableModels', () => { const configOptions: SessionConfigOption[] = [ { type: 'select', id: 'model', category: 'model', currentValue: 'sonnet', options: [ { value: 'sonnet', name: 'Sonnet' }, { value: 'opus', name: 'Opus' }, ], }, ]; const models = deriveModelDefinitionsFromACP(null, configOptions); expect(models).toEqual([ { id: 'sonnet', label: 'Sonnet', isDefault: true, defaultThinkingOptionId: undefined }, { id: 'opus', label: 'Opus', isDefault: false, defaultThinkingOptionId: undefined }, ]); }); }); describe('findThoughtLevelConfigId', () => { it('returns thought_level select id', () => { const configOptions: SessionConfigOption[] = [ { type: 'select', id: 'effort', category: 'thought_level', currentValue: 'high', options: [{ value: 'high', name: 'High' }], }, ]; expect(findThoughtLevelConfigId(configOptions)).toBe('effort'); }); it('returns null when missing', () => { expect(findThoughtLevelConfigId(null)).toBeNull(); }); });