fix(agents): register Ollama in the runtime model factory and cover the picker wiring with tests

Review follow-up: the runtime model factory rejected ollama (createModel threw Unsupported provider), so the picker entry alone was incomplete. Registers ollama in PROVIDER_CREDENTIAL_SCHEMAS (apiKey optional, matching ollamaApi) and in the model factory through the existing OpenAI-compatible adapter, normalizing the credential base URL to Ollama's /v1 chat endpoint. Updates the model-discovery registry test to expect ollama, and adds credential mapping (baseUrl to baseURL) and endpoint-only lookup policy tests.

Signed-off-by: Rene Turcios <95189389+CloudCorpRecords@users.noreply.github.com>
This commit is contained in:
Rene Turcios 2026-10-15 19:59:32 -07:00
parent 62c274bedb
commit 149ee80f82
2 changed files with 50 additions and 0 deletions

View File

@ -218,6 +218,33 @@ describe('BuilderModelLiveLookupService', () => {
expect(result).toEqual({ status: 'unavailable', policy: 'endpoint-only', error });
});
it('returns endpoint-only models for ollama and maps baseUrl', async () => {
const { service, credentialsService, credentialsHelper } = makeService();
credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue(
usable('cred-1', 'ollamaApi'),
);
credentialsHelper.getDecrypted.mockResolvedValue({
baseUrl: 'http://localhost:11434',
apiKey: '',
});
listModelsForProvider.mockResolvedValue([{ id: 'llama3.1', name: 'llama3.1' }]);
const result = await service.lookup(user, projectId, 'cred-1', 'ollamaApi', 'ollama');
expect(result).toEqual({
status: 'success',
policy: 'endpoint-only',
models: [{ name: 'llama3.1', value: 'llama3.1' }],
});
expect(listModelsForProvider).toHaveBeenCalledWith(
'ollama',
expect.objectContaining({
apiKey: '',
baseURL: 'http://localhost:11434',
}),
);
});
it('preserves endpoint-only policy when custom OpenAI discovery is empty', async () => {
const { service, credentialsService, credentialsHelper } = makeService();
credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue(

View File

@ -38,6 +38,29 @@ describe('mapCredentialForProvider', () => {
});
});
describe('ollama', () => {
it('maps the credential baseUrl onto baseURL', () => {
expect(
mapCredentialForProvider('ollama', {
apiKey: 'test-key',
baseUrl: 'http://localhost:11434',
}),
).toEqual({ apiKey: 'test-key', baseURL: 'http://localhost:11434' });
});
it('passes through when the optional apiKey is unset', () => {
expect(mapCredentialForProvider('ollama', { baseUrl: 'http://srv:11434' })).toEqual({
apiKey: undefined,
baseURL: 'http://srv:11434',
});
});
it('is a supported agent provider', () => {
expect(isSupportedAgentProvider('ollama')).toBe(true);
expect(SUPPORTED_AGENT_PROVIDERS).toContain('ollama');
});
});
it('passes an unmapped provider through unchanged', () => {
const raw = { apiKey: 'key', url: 'https://example.com', someOtherField: 'kept' };