Merge pull request 'fix: update DeepSeek direct models to v4' (#33) from codex/fix-deepseek-v4-models into main
Memind CI / Test, build, and release guards (push) Successful in 2m57s
Memind CI / Test, build, and release guards (push) Successful in 2m57s
This commit was merged in pull request #33.
This commit is contained in:
+2
-2
@@ -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',
|
||||
|
||||
+30
-23
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user