File size: 4,728 Bytes
39e315a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | import { describe, expect, test } from 'bun:test'
import { resolveAgentProvider } from './agentRouting.js'
import type { SettingsJson } from '../../utils/settings/types.js'
const baseSettings = {
agentModels: {
'deepseek-chat': { base_url: 'https://api.deepseek.com/v1', api_key: 'sk-ds' },
'gpt-4o': { base_url: 'https://api.openai.com/v1', api_key: 'sk-oai' },
},
agentRouting: {
Explore: 'deepseek-chat',
'general-purpose': 'gpt-4o',
'frontend-dev': 'deepseek-chat',
default: 'gpt-4o',
},
} as unknown as SettingsJson
describe('resolveAgentProvider', () => {
// ββ Priority chain ββββββββββββββββββββββββββββββββββββββββββ
test('name takes priority over subagentType', () => {
const result = resolveAgentProvider('frontend-dev', 'Explore', baseSettings)
expect(result).toEqual({
model: 'deepseek-chat',
baseURL: 'https://api.deepseek.com/v1',
apiKey: 'sk-ds',
})
})
test('subagentType used when name has no match', () => {
const result = resolveAgentProvider('unknown-name', 'Explore', baseSettings)
expect(result).toEqual({
model: 'deepseek-chat',
baseURL: 'https://api.deepseek.com/v1',
apiKey: 'sk-ds',
})
})
test('falls back to "default" when neither name nor subagentType match', () => {
const result = resolveAgentProvider('nobody', 'unknown-type', baseSettings)
expect(result).toEqual({
model: 'gpt-4o',
baseURL: 'https://api.openai.com/v1',
apiKey: 'sk-oai',
})
})
test('returns null when no routing match and no default', () => {
const settings = {
agentModels: baseSettings.agentModels,
agentRouting: { Explore: 'deepseek-chat' },
} as unknown as SettingsJson
const result = resolveAgentProvider('nobody', 'unknown-type', settings)
expect(result).toBeNull()
})
test('returns null when name and subagentType are both undefined', () => {
const settings = {
agentModels: baseSettings.agentModels,
agentRouting: { Explore: 'deepseek-chat' },
} as unknown as SettingsJson
const result = resolveAgentProvider(undefined, undefined, settings)
expect(result).toBeNull()
})
// ββ normalize() matching ββββββββββββββββββββββββββββββββββββ
test('matching is case-insensitive', () => {
const result = resolveAgentProvider(undefined, 'explore', baseSettings)
expect(result?.model).toBe('deepseek-chat')
})
test('matching is case-insensitive (UPPER)', () => {
const result = resolveAgentProvider(undefined, 'EXPLORE', baseSettings)
expect(result?.model).toBe('deepseek-chat')
})
test('hyphen and underscore are equivalent', () => {
const result = resolveAgentProvider(undefined, 'general_purpose', baseSettings)
expect(result?.model).toBe('gpt-4o')
})
test('underscore in config matches hyphen in input', () => {
const settings = {
agentModels: baseSettings.agentModels,
agentRouting: { general_purpose: 'deepseek-chat' },
} as unknown as SettingsJson
const result = resolveAgentProvider(undefined, 'general-purpose', settings)
expect(result?.model).toBe('deepseek-chat')
})
// ββ Edge cases ββββββββββββββββββββββββββββββββββββββββββββββ
test('returns null when settings is null', () => {
expect(resolveAgentProvider('Explore', 'Explore', null)).toBeNull()
})
test('returns null when agentRouting is missing', () => {
const settings = { agentModels: baseSettings.agentModels } as unknown as SettingsJson
expect(resolveAgentProvider(undefined, 'Explore', settings)).toBeNull()
})
test('returns null when agentModels is missing', () => {
const settings = { agentRouting: baseSettings.agentRouting } as unknown as SettingsJson
expect(resolveAgentProvider(undefined, 'Explore', settings)).toBeNull()
})
test('returns null when routing references non-existent model', () => {
const settings = {
agentModels: {},
agentRouting: { Explore: 'non-existent-model' },
} as unknown as SettingsJson
expect(resolveAgentProvider(undefined, 'Explore', settings)).toBeNull()
})
test('subagentType only (no name)', () => {
const result = resolveAgentProvider(undefined, 'Explore', baseSettings)
expect(result?.model).toBe('deepseek-chat')
})
test('name only (no subagentType)', () => {
const result = resolveAgentProvider('frontend-dev', undefined, baseSettings)
expect(result?.model).toBe('deepseek-chat')
})
})
|