From 69dabd5186f2c5f6872b7f6f974ac2a7ddcf27e4 Mon Sep 17 00:00:00 2001 From: john Date: Sat, 25 Jul 2026 07:46:00 +0800 Subject: [PATCH] fix: update DeepSeek direct models to v4 --- llm-providers.mjs | 4 +-- llm-providers.test.mjs | 53 +++++++++++++++++++-------------- scripts/fix-deepseek-direct.mjs | 8 ++--- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/llm-providers.mjs b/llm-providers.mjs index 903ae67..78c2139 100644 --- a/llm-providers.mjs +++ b/llm-providers.mjs @@ -21,8 +21,8 @@ export const LLM_PROVIDER_CATALOG = [ label: 'DeepSeek', kind: 'builtin', apiKeyEnv: 'DEEPSEEK_API_KEY', - defaultModel: 'deepseek-chat', - models: ['deepseek-chat', 'deepseek-reasoner'], + defaultModel: 'deepseek-v4-pro', + models: ['deepseek-v4-pro', 'deepseek-v4-flash'], }, { id: 'openai', diff --git a/llm-providers.test.mjs b/llm-providers.test.mjs index ea66a63..656f41f 100644 --- a/llm-providers.test.mjs +++ b/llm-providers.test.mjs @@ -129,7 +129,7 @@ test('createKey selects first profile and syncs to goosed', async () => { providerId: 'custom_deepseek', name: 'DeepSeek 主账号', apiKey: 'sk-deepseek-test', - defaultModel: 'deepseek-chat', + defaultModel: 'deepseek-v4-pro', }); assert.equal(result.ok, true); assert.equal(result.key.isSelected, true); @@ -220,7 +220,7 @@ test('selectKey rejects disabled profile', async () => { api_key_ciphertext: encryptSecret('sk-x', 'unit-test-secret').ciphertext, api_key_iv: encryptSecret('sk-x', 'unit-test-secret').iv, api_key_tag: encryptSecret('sk-x', 'unit-test-secret').tag, - default_model: 'deepseek-chat', + default_model: 'deepseek-v4-pro', status: 'disabled', is_selected: 0, created_at: 1, @@ -250,6 +250,13 @@ test('catalog includes custom provider template', () => { assert.equal(custom.kind, 'custom'); }); +test('DeepSeek catalog uses the currently supported V4 model names', () => { + const deepseek = LLM_PROVIDER_CATALOG.find((item) => item.id === 'custom_deepseek'); + assert.ok(deepseek); + assert.equal(deepseek.defaultModel, 'deepseek-v4-pro'); + assert.deepEqual(deepseek.models, ['deepseek-v4-pro', 'deepseek-v4-flash']); +}); + test('listExecutorBindings returns all executor placeholders', async () => { const pool = { async query(sql) { @@ -295,7 +302,7 @@ test('testKey checks builtin DeepSeek through OpenAI compatible endpoint', async api_key_ciphertext: encrypted.ciphertext, api_key_iv: encrypted.iv, api_key_tag: encrypted.tag, - default_model: 'deepseek-chat', + default_model: 'deepseek-v4-pro', status: 'active', is_selected: 1, created_at: 1, @@ -324,11 +331,11 @@ test('testKey checks builtin DeepSeek through OpenAI compatible endpoint', async encryptionKey: 'unit-test-secret', apiFetchImpl: mockFetch, }); - const result = await service.testKey('key-deepseek', 'deepseek-chat'); + const result = await service.testKey('key-deepseek', 'deepseek-v4-pro'); assert.equal(result.ok, true); assert.equal(calls[0].url, 'https://api.deepseek.com/v1/chat/completions'); assert.equal(calls[0].init.headers.Authorization, 'Bearer sk-deepseek-test'); - assert.equal(calls[0].body.model, 'deepseek-chat'); + assert.equal(calls[0].body.model, 'deepseek-v4-pro'); }); test('createChatCompletion uses selected OpenAI-compatible provider', async () => { @@ -477,7 +484,7 @@ test('getExecutorRuntimeConfig resolves aider env from binding', async () => { api_key_ciphertext: encrypted.ciphertext, api_key_iv: encrypted.iv, api_key_tag: encrypted.tag, - default_model: 'deepseek-chat', + default_model: 'deepseek-v4-pro', status: 'active', is_selected: 1, created_at: 1, @@ -488,7 +495,7 @@ test('getExecutorRuntimeConfig resolves aider env from binding', async () => { executor: 'aider', purpose: 'default', provider_key_id: 'key-deepseek', - model: 'deepseek-reasoner', + model: 'deepseek-v4-flash', enabled: 1, created_at: 1, updated_at: 1, @@ -510,8 +517,8 @@ test('getExecutorRuntimeConfig resolves aider env from binding', async () => { }); const runtime = await service.getExecutorRuntimeConfig('aider'); assert.equal(runtime.ok, true); - assert.equal(runtime.model, 'deepseek-reasoner'); - assert.equal(runtime.env.AIDER_MODEL, 'deepseek/deepseek-reasoner'); + assert.equal(runtime.model, 'deepseek-v4-flash'); + assert.equal(runtime.env.AIDER_MODEL, 'deepseek/deepseek-v4-flash'); assert.equal(runtime.env.DEEPSEEK_API_KEY, '[hidden]'); }); @@ -522,8 +529,8 @@ test('buildExecutorLaunchPlan creates openhands headless command', () => { executorLabel: 'OpenHands', purpose: 'default', providerName: 'DeepSeek 主账号', - model: 'deepseek-reasoner', - env: { LLM_MODEL: 'deepseek-reasoner', LLM_API_KEY: '[hidden]' }, + model: 'deepseek-v4-flash', + env: { LLM_MODEL: 'deepseek-v4-flash', LLM_API_KEY: '[hidden]' }, }, { mode: 'headless', cwd: '/repo/memind', @@ -543,8 +550,8 @@ test('buildExecutorLaunchPlan creates openhands serve command', () => { executorLabel: 'OpenHands', purpose: 'default', providerName: 'DeepSeek 主账号', - model: 'deepseek-reasoner', - env: { LLM_MODEL: 'deepseek-reasoner', LLM_API_KEY: '[hidden]' }, + model: 'deepseek-v4-flash', + env: { LLM_MODEL: 'deepseek-v4-flash', LLM_API_KEY: '[hidden]' }, }, { mode: 'serve', cwd: '/repo/memind', @@ -561,9 +568,9 @@ test('buildExecutorLaunchPlan adds aider one-shot message when provided', () => executorLabel: 'Aider', purpose: 'default', providerName: 'DeepSeek 主账号', - model: 'deepseek-chat', + model: 'deepseek-v4-pro', env: { - AIDER_MODEL: 'deepseek/deepseek-chat', + AIDER_MODEL: 'deepseek/deepseek-v4-pro', OPENAI_API_KEY: '[hidden]', TKMIND_EXECUTOR_PROVIDER: 'custom_deepseek', }, @@ -573,7 +580,7 @@ test('buildExecutorLaunchPlan adds aider one-shot message when provided', () => }); assert.equal(plan.ok, true); assert.equal(plan.command, 'aider'); - assert.deepEqual(plan.args.slice(0, 2), ['--model', 'deepseek/deepseek-chat']); + assert.deepEqual(plan.args.slice(0, 2), ['--model', 'deepseek/deepseek-v4-pro']); assert.ok(plan.args.includes('--message')); assert.ok(plan.args.includes('fix login button')); }); @@ -585,8 +592,8 @@ test('buildExecutorLaunchPlan rejects openhands headless without instruction', ( executorLabel: 'OpenHands', purpose: 'default', providerName: 'DeepSeek 主账号', - model: 'deepseek-reasoner', - env: { LLM_MODEL: 'deepseek-reasoner', LLM_API_KEY: '[hidden]' }, + model: 'deepseek-v4-flash', + env: { LLM_MODEL: 'deepseek-v4-flash', LLM_API_KEY: '[hidden]' }, }, { mode: 'headless', cwd: '/repo/memind', @@ -637,7 +644,7 @@ test('launchExecutor returns friendly error when command is missing', async () = api_key_ciphertext: encryptedKey.ciphertext, api_key_iv: encryptedKey.iv, api_key_tag: encryptedKey.tag, - default_model: 'deepseek-chat', + default_model: 'deepseek-v4-pro', status: 'active', is_selected: 1, created_at: 1, @@ -648,7 +655,7 @@ test('launchExecutor returns friendly error when command is missing', async () = executor: 'aider', purpose: 'default', provider_key_id: 'key-1', - model: 'deepseek-chat', + model: 'deepseek-v4-pro', enabled: 1, created_at: 1, updated_at: 1, @@ -735,7 +742,7 @@ test('syncProfileToGoosed writes provider, model and secret keys for builtin', a { providerKind: 'builtin', providerId: 'custom_deepseek', - defaultModel: 'deepseek-chat', + defaultModel: 'deepseek-v4-pro', apiKey: 'sk-test', }, mockFetch, @@ -755,14 +762,14 @@ test('syncSelectedToGoosed writes selected provider to every configured target', name: 'DeepSeek', api_url: null, base_path: null, - models_json: JSON.stringify(['deepseek-chat']), + models_json: JSON.stringify(['deepseek-v4-pro']), goosed_provider_id: null, engine: 'openai', relay_provider: null, api_key_ciphertext: encrypted.ciphertext, api_key_iv: encrypted.iv, api_key_tag: encrypted.tag, - default_model: 'deepseek-chat', + default_model: 'deepseek-v4-pro', status: 'active', is_selected: 1, created_at: 1, diff --git a/scripts/fix-deepseek-direct.mjs b/scripts/fix-deepseek-direct.mjs index 742db04..d047dcb 100644 --- a/scripts/fix-deepseek-direct.mjs +++ b/scripts/fix-deepseek-direct.mjs @@ -40,14 +40,14 @@ const CONFIG_NAME = 'DeepSeek 直连'; async function testDirectDeepSeek() { const dispatcher = new Agent({ connect: { rejectUnauthorized: true } }); const started = Date.now(); - const res = await fetch('https://api.deepseek.com/chat/completions', { + const res = await fetch('https://api.deepseek.com/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ - model: 'deepseek-chat', + model: 'deepseek-v4-pro', messages: [{ role: 'user', content: 'Hello' }], stream: false, }), @@ -78,7 +78,7 @@ if (rowId) { const updated = await svc.updateKey(rowId, { name: CONFIG_NAME, apiKey, - defaultModel: 'deepseek-chat', + defaultModel: 'deepseek-v4-pro', }); if (!updated.ok) { console.error('更新 DeepSeek 配置失败:', updated.message); @@ -90,7 +90,7 @@ if (rowId) { providerId: 'custom_deepseek', name: CONFIG_NAME, apiKey, - defaultModel: 'deepseek-chat', + defaultModel: 'deepseek-v4-pro', }); if (!created.ok) { console.error('创建 DeepSeek 配置失败:', created.message);