feat(agents): add agent configuration and thinking aliases

This commit is contained in:
lzt404 committed 2026-07-17 21:47:44 +08:00
1 parent 24b4d1f74e
commit 41efeebcbb
16 files changed
+8154 -224

No files matched your search

+52
View File
@@ -0,0 +1,52 @@
import { describe, expect, test } from 'bun:test';
import {
agentModelAlias,
filterAgentModels,
findAgentModel,
hasExactAgentModel,
resolveAgentModelSelection,
} from '../src/services/agentModelPicker';
const models = [
{ name: 'claude-sonnet-4-5', alias: 'Sonnet' },
{ name: 'gpt-5.2-codex', alias: 'Codex' },
{ name: 'gpt-5.2' },
{ name: 'deepseek-chat', alias: 'DeepSeek V3' },
];
describe('智能体模型选择器', () => {
test('按名称和别名搜索且忽略大小写', () => {
expect(filterAgentModels(models, 'SONNET').map((model) => model.name))
.toEqual(['claude-sonnet-4-5']);
expect(filterAgentModels(models, 'deepseek').map((model) => model.name))
.toEqual(['deepseek-chat']);
});
test('精确匹配和前缀匹配排在包含匹配之前', () => {
expect(filterAgentModels(models, 'gpt-5.2').map((model) => model.name))
.toEqual(['gpt-5.2', 'gpt-5.2-codex']);
});
test('识别名称或别名的精确匹配', () => {
expect(hasExactAgentModel(models, 'Codex')).toBeTrue();
expect(hasExactAgentModel(models, 'gpt-5.2-codex')).toBeTrue();
expect(hasExactAgentModel(models, 'custom-model')).toBeFalse();
});
test('根据当前模型显示别名', () => {
expect(agentModelAlias(models, 'CLAUDE-SONNET-4-5')).toBe('Sonnet');
expect(agentModelAlias(models, 'gpt-5.2')).toBe('');
});
test('没有历史选择时默认第一项,旧选择失效时也回退第一项', () => {
expect(resolveAgentModelSelection(models, '')).toBe('claude-sonnet-4-5');
expect(resolveAgentModelSelection(models, 'removed-model')).toBe('claude-sonnet-4-5');
expect(resolveAgentModelSelection(models, 'GPT-5.2-CODEX')).toBe('gpt-5.2-codex');
expect(resolveAgentModelSelection([], 'gpt-5.2')).toBe('');
});
test('配置前只能解析模型列表中真实存在的模型', () => {
expect(findAgentModel(models, 'codex')?.name).toBeUndefined();
expect(findAgentModel(models, 'gpt-5.2-codex')?.name).toBe('gpt-5.2-codex');
});
});
+18 -3
View File
@@ -1,5 +1,6 @@
import { describe, expect, it } from 'bun:test';
import {
allModelSelectionForDiscovery,
applyProviderPreset,
buildProviderRecord,
createProviderDraft,
@@ -67,7 +68,7 @@ describe('API 接入配置合并', () => {
apiKey: 'openai-key',
name: 'custom-openai',
baseUrl: 'https://api.example.com',
thinkingLevels: ['low', 'high'],
thinkingLevels: ['fast', 'ultra'],
models: [
{ name: 'reasoning-a' },
{ name: 'reasoning-b', thinking: { effort: 'high' } },
@@ -76,10 +77,10 @@ describe('API 接入配置合并', () => {
const result = buildProviderRecord('openai-compatibility', draft);
expect(result.models).toEqual([
{ name: 'reasoning-a', thinking: { levels: ['low', 'high'] } },
{ name: 'reasoning-a', thinking: { levels: ['fast', 'ultra'] } },
{
name: 'reasoning-b',
thinking: { effort: 'high', levels: ['low', 'high'] },
thinking: { effort: 'high', levels: ['fast', 'ultra'] },
},
]);
});
@@ -255,4 +256,18 @@ describe('API 接入配置合并', () => {
expect(Array.from(selected)).toEqual(['model-a', 'model-b']);
});
it('模型选择窗口每次打开都以接口返回的全部模型作为默认选择', () => {
const selected = allModelSelectionForDiscovery([
{ name: 'deepseek-chat' },
{ name: 'deepseek-reasoner' },
{ name: 'deepseek-new-model' },
]);
expect(Array.from(selected)).toEqual([
'deepseek-chat',
'deepseek-reasoner',
'deepseek-new-model',
]);
});
});
+11
View File
@@ -0,0 +1,11 @@
import { describe, expect, test } from 'bun:test';
import { thinkingAliasSourceKindLabel } from '../src/pages/ThinkingAliasesPage';
describe('思考别名', () => {
test('区分同名模型的接入来源', () => {
expect(thinkingAliasSourceKindLabel('codex-oauth')).toBe('Codex OAuth');
expect(thinkingAliasSourceKindLabel('codex-api')).toBe('Codex API');
expect(thinkingAliasSourceKindLabel('openai-compatible')).toBe('OpenAI 兼容');
expect(thinkingAliasSourceKindLabel('custom')).toBe('其他来源');
});
});