fix: sync Ollama provider config to gateway runtime (fixes #448) (#745)

This commit is contained in:
Octopus
2026-04-02 00:48:11 -05:00
committed by GitHub
Unverified
parent c14bdfa204
commit fa2131ab13
2 changed files with 59 additions and 5 deletions

View File

@@ -286,7 +286,7 @@ async function syncProviderSecretToRuntime(
async function resolveRuntimeSyncContext(config: ProviderConfig): Promise<RuntimeProviderSyncContext | null> {
const runtimeProviderKey = await resolveRuntimeProviderKey(config);
const meta = getProviderConfig(config.type);
const api = config.apiProtocol || (config.type === 'custom' ? 'openai-completions' : meta?.api);
const api = config.apiProtocol || ((config.type === 'custom' || config.type === 'ollama') ? 'openai-completions' : meta?.api);
if (!api) {
return null;
}
@@ -315,7 +315,7 @@ async function syncCustomProviderAgentModel(
runtimeProviderKey: string,
apiKey: string | undefined,
): Promise<void> {
if (config.type !== 'custom') {
if (config.type !== 'custom' && config.type !== 'ollama') {
return;
}
@@ -402,7 +402,7 @@ async function buildAgentModelProviderEntry(
authHeader?: boolean;
} | null> {
const meta = getProviderConfig(config.type);
const api = config.apiProtocol || (config.type === 'custom' ? 'openai-completions' : meta?.api);
const api = config.apiProtocol || ((config.type === 'custom' || config.type === 'ollama') ? 'openai-completions' : meta?.api);
const baseUrl = normalizeProviderBaseUrl(config, config.baseUrl || meta?.baseUrl, api);
if (!api || !baseUrl) {
return null;
@@ -593,7 +593,7 @@ export async function syncDefaultProviderToRuntime(
? (provider.model.startsWith(`${ock}/`) ? provider.model : `${ock}/${provider.model}`)
: undefined;
if (provider.type === 'custom') {
if (provider.type === 'custom' || provider.type === 'ollama') {
await setOpenClawDefaultModelWithOverride(ock, modelOverride, {
baseUrl: normalizeProviderBaseUrl(provider, provider.baseUrl, provider.apiProtocol || 'openai-completions'),
api: provider.apiProtocol || 'openai-completions',
@@ -689,7 +689,7 @@ export async function syncDefaultProviderToRuntime(
}
if (
provider.type === 'custom' &&
(provider.type === 'custom' || provider.type === 'ollama') &&
providerKey &&
provider.baseUrl
) {

View File

@@ -256,4 +256,58 @@ describe('provider-runtime-sync refresh strategy', () => {
}),
);
});
it('syncs Ollama provider config to runtime without adding model prefix', async () => {
const ollamaProvider = createProvider({
id: 'ollamafd',
type: 'ollama',
name: 'Ollama',
model: 'qwen3:30b',
baseUrl: 'http://localhost:11434/v1',
});
mocks.getProviderConfig.mockReturnValue(undefined);
mocks.getProviderSecret.mockResolvedValue({ type: 'local', apiKey: 'ollama-local' });
const gateway = createGateway('running');
await syncSavedProviderToRuntime(ollamaProvider, undefined, gateway as GatewayManager);
expect(mocks.syncProviderConfigToOpenClaw).toHaveBeenCalledWith(
'ollama-ollamafd',
'qwen3:30b',
expect.objectContaining({
baseUrl: 'http://localhost:11434/v1',
api: 'openai-completions',
}),
);
expect(gateway.debouncedReload).toHaveBeenCalledTimes(1);
});
it('syncs Ollama as default provider with correct baseUrl and api protocol', async () => {
const ollamaProvider = createProvider({
id: 'ollamafd',
type: 'ollama',
name: 'Ollama',
model: 'qwen3:30b',
baseUrl: 'http://localhost:11434/v1',
});
mocks.getProvider.mockResolvedValue(ollamaProvider);
mocks.getDefaultProvider.mockResolvedValue('ollamafd');
mocks.getProviderConfig.mockReturnValue(undefined);
mocks.getApiKey.mockResolvedValue('ollama-local');
const gateway = createGateway('running');
await syncDefaultProviderToRuntime('ollamafd', gateway as GatewayManager);
expect(mocks.setOpenClawDefaultModelWithOverride).toHaveBeenCalledWith(
'ollama-ollamafd',
'ollama-ollamafd/qwen3:30b',
expect.objectContaining({
baseUrl: 'http://localhost:11434/v1',
api: 'openai-completions',
}),
expect.any(Array),
);
});
});