fix: make goosed mcp paths container safe
This commit is contained in:
+66
-6
@@ -487,14 +487,15 @@ test('launchExecutor rejects openhands headless without instruction', async () =
|
||||
});
|
||||
|
||||
test('launchExecutor returns friendly error when command is missing', async () => {
|
||||
const encryptedKey = encryptSecret('sk-x', 'unit-test-secret');
|
||||
const keyRow = {
|
||||
id: 'key-1',
|
||||
provider_id: 'custom_deepseek',
|
||||
provider_kind: 'builtin',
|
||||
name: 'DeepSeek',
|
||||
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,
|
||||
api_key_ciphertext: encryptedKey.ciphertext,
|
||||
api_key_iv: encryptedKey.iv,
|
||||
api_key_tag: encryptedKey.tag,
|
||||
default_model: 'deepseek-chat',
|
||||
status: 'active',
|
||||
is_selected: 1,
|
||||
@@ -513,13 +514,13 @@ test('launchExecutor returns friendly error when command is missing', async () =
|
||||
};
|
||||
const pool = {
|
||||
async query(sql) {
|
||||
if (sql.includes('SELECT * FROM h5_llm_executor_bindings WHERE executor = ? AND purpose = ? LIMIT 1')) {
|
||||
return [[bindingRow]];
|
||||
}
|
||||
if (sql.includes('SELECT * FROM h5_llm_executor_bindings')) return [[]];
|
||||
if (sql.includes('SELECT * FROM h5_llm_provider_keys WHERE id = ?')) {
|
||||
return [[keyRow]];
|
||||
}
|
||||
if (sql.includes('SELECT * FROM h5_llm_executor_bindings WHERE executor = ? AND purpose = ? LIMIT 1')) {
|
||||
return [[bindingRow]];
|
||||
}
|
||||
throw new Error(`Unexpected SQL: ${sql}`);
|
||||
},
|
||||
};
|
||||
@@ -597,6 +598,65 @@ test('syncProfileToGoosed writes provider, model and secret keys for builtin', a
|
||||
);
|
||||
});
|
||||
|
||||
test('syncSelectedToGoosed writes selected provider to every configured target', async () => {
|
||||
const encrypted = encryptSecret('sk-test', 'unit-test-secret');
|
||||
const row = {
|
||||
id: 'key-deepseek',
|
||||
provider_id: 'custom_deepseek',
|
||||
provider_kind: 'builtin',
|
||||
name: 'DeepSeek',
|
||||
api_url: null,
|
||||
base_path: null,
|
||||
models_json: JSON.stringify(['deepseek-chat']),
|
||||
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',
|
||||
status: 'active',
|
||||
is_selected: 1,
|
||||
created_at: 1,
|
||||
updated_at: 1,
|
||||
};
|
||||
const pool = {
|
||||
async query(sql) {
|
||||
if (sql.includes('SELECT * FROM h5_llm_executor_bindings')) return [[]];
|
||||
if (sql.includes('is_selected = 1')) return [[row]];
|
||||
throw new Error(`Unexpected SQL: ${sql}`);
|
||||
},
|
||||
};
|
||||
const calls = [];
|
||||
const mockFetch = async (url, init) => {
|
||||
calls.push({ url: String(url), body: JSON.parse(init.body) });
|
||||
if (String(url).includes('/chat/completions')) {
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({ choices: [{ message: { content: 'ok' } }] }),
|
||||
text: async () => JSON.stringify({ choices: [{ message: { content: 'ok' } }] }),
|
||||
};
|
||||
}
|
||||
return { ok: true, text: async () => '' };
|
||||
};
|
||||
const service = createLlmProviderService(pool, {
|
||||
apiTarget: 'https://127.0.0.1:18006',
|
||||
apiTargets: ['https://127.0.0.1:18006', 'https://127.0.0.1:18007'],
|
||||
apiSecret: 'secret',
|
||||
encryptionKey: 'unit-test-secret',
|
||||
apiFetchImpl: mockFetch,
|
||||
});
|
||||
const result = await service.syncSelectedToGoosed();
|
||||
assert.equal(result.ok, true);
|
||||
assert.deepEqual(result.targets, ['https://127.0.0.1:18006', 'https://127.0.0.1:18007']);
|
||||
assert.deepEqual(
|
||||
calls
|
||||
.filter((call) => call.url.includes('/config/upsert') && call.body.key === 'GOOSE_PROVIDER')
|
||||
.map((call) => new URL(call.url).port),
|
||||
['18006', '18007'],
|
||||
);
|
||||
});
|
||||
|
||||
test('syncProfileToGoosed tolerates missing /config/upsert endpoint', async () => {
|
||||
const mockFetch = async (_url, init) => {
|
||||
if (String(_url).includes('/config/custom-providers')) {
|
||||
|
||||
Reference in New Issue
Block a user