feat(api-access): unify DeepSeek model discovery and selection
- require explicit model discovery before saving DeepSeek connections - preserve selected models when refreshing the catalog - mark model lists stale when connection details change - add model refresh support to easy mode - apply built-in DeepSeek reasoning levels consistently
This commit is contained in:
1 parent
c5f68157e5
commit
2a99db2908
10 files changed
+287
-68
No files matched your search
@@ -0,0 +1,60 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import {
|
||||
applyDeepSeekModelPreset,
|
||||
DEEPSEEK_THINKING_LEVELS,
|
||||
mergeModelOptions,
|
||||
reconcileModelSelection,
|
||||
} from '../src/services/modelService';
|
||||
|
||||
describe('model discovery selection', () => {
|
||||
const discovered = [
|
||||
{ name: 'deepseek-chat' },
|
||||
{ name: 'deepseek-reasoner' },
|
||||
{ name: 'deepseek-new-model' },
|
||||
];
|
||||
|
||||
it('selects every discovered model on the first fetch for a new connection', () => {
|
||||
expect(Array.from(reconcileModelSelection(discovered, [], [], 'initial'))).toEqual([
|
||||
'deepseek-chat',
|
||||
'deepseek-reasoner',
|
||||
'deepseek-new-model',
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps saved selections and leaves newly discovered models unchecked', () => {
|
||||
expect(Array.from(reconcileModelSelection(
|
||||
discovered,
|
||||
[{ name: 'deepseek-chat' }],
|
||||
['deepseek-chat'],
|
||||
'initial',
|
||||
))).toEqual(['deepseek-chat']);
|
||||
});
|
||||
|
||||
it('preserves refresh selections, drops unavailable discoveries, and keeps configured models', () => {
|
||||
expect(Array.from(reconcileModelSelection(
|
||||
[{ name: 'deepseek-reasoner' }, { name: 'deepseek-new-model' }],
|
||||
[{ name: 'custom-model' }],
|
||||
['DEEPSEEK-REASONER', 'removed-model', 'custom-model'],
|
||||
'refresh',
|
||||
))).toEqual(['deepseek-reasoner', 'custom-model']);
|
||||
});
|
||||
|
||||
it('deduplicates model names case-insensitively and keeps configured metadata', () => {
|
||||
expect(mergeModelOptions(
|
||||
[{ name: 'deepseek-chat' }],
|
||||
[{ name: ' DEEPSEEK-CHAT ', alias: 'Chat' }],
|
||||
)).toEqual([{ name: 'DEEPSEEK-CHAT', alias: 'Chat' }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('DeepSeek model preset', () => {
|
||||
it('adds built-in thinking levels while preserving existing metadata', () => {
|
||||
expect(applyDeepSeekModelPreset([{
|
||||
name: 'deepseek-reasoner',
|
||||
thinking: { custom: true, levels: ['legacy'] },
|
||||
}])).toEqual([{
|
||||
name: 'deepseek-reasoner',
|
||||
thinking: { custom: true, levels: [...DEEPSEEK_THINKING_LEVELS] },
|
||||
}]);
|
||||
});
|
||||
});
|
||||
@@ -37,6 +37,21 @@ describe('控件自身反馈', () => {
|
||||
expect(nonEmptyCalls[0].arguments[1].getText()).toBe("'error'");
|
||||
});
|
||||
|
||||
it('API 接入提示固定在右下角,不插入页面布局', () => {
|
||||
const source = readFileSync(new URL('../src/pages/ApiAccessPage.tsx', import.meta.url), 'utf8');
|
||||
expect(source).toContain("import { createPortal } from 'react-dom';");
|
||||
expect(source).toContain('className="api-access-page-notice"');
|
||||
expect(source).toContain('createPortal(');
|
||||
expect(source).toContain('document.body');
|
||||
expect(source).not.toContain('feedbackRow');
|
||||
expect(source.indexOf('createPortal(')).toBeGreaterThan(source.indexOf('provider-workbench real-provider-workbench'));
|
||||
expect(source.slice(source.indexOf('provider-workbench real-provider-workbench'), source.lastIndexOf('createPortal('))).not.toContain('<InlineNotice');
|
||||
const styles = readFileSync(new URL('../src/styles.css', import.meta.url), 'utf8');
|
||||
expect(styles).toMatch(/\.action-feedback\.inline-notice\.api-access-page-notice\s*\{[\s\S]*?position:\s*fixed;/);
|
||||
expect(styles).toMatch(/\.action-feedback\.inline-notice\.api-access-page-notice\s*\{[\s\S]*?right:\s*24px;/);
|
||||
expect(styles).toMatch(/\.action-feedback\.inline-notice\.api-access-page-notice\s*\{[\s\S]*?bottom:\s*24px;/);
|
||||
});
|
||||
|
||||
it('凭证文件的启用停用由按钮与状态标签反馈', () => {
|
||||
expect(actionCalls('AuthFileManagementPage.tsx', 'toggleStatus', 'showNotice').calls).toHaveLength(0);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import {
|
||||
allModelSelectionForDiscovery,
|
||||
applyProviderRemarkIdentity,
|
||||
applyProviderPreset,
|
||||
buildProviderRecord,
|
||||
@@ -51,7 +50,7 @@ describe('API 接入配置合并', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('DeepSeek 新增预设默认发现全部模型并应用内置思考等级', () => {
|
||||
it('DeepSeek 对选定模型应用内置思考等级', () => {
|
||||
expect(DEEPSEEK_THINKING_LEVELS).toEqual(['low', 'high', 'max']);
|
||||
const draft = createProviderDraft('deepseek');
|
||||
const discovered = [
|
||||
@@ -387,18 +386,4 @@ 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',
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user