From af05c6b4e92915160e0edd2329fbed4af9253bb3 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 24 Jan 2026 22:38:21 +0000 Subject: [PATCH] test: restore Ollama provider tests (#1606) (thanks @abhaymundhara) --- .../models-config.providers.ollama.test.ts | 93 ++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/src/agents/models-config.providers.ollama.test.ts b/src/agents/models-config.providers.ollama.test.ts index 0dab1b22c..c06657ad5 100644 --- a/src/agents/models-config.providers.ollama.test.ts +++ b/src/agents/models-config.providers.ollama.test.ts @@ -1,10 +1,23 @@ -import { describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { resolveImplicitProviders } from "./models-config.providers.js"; import { mkdtempSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; describe("Ollama provider", () => { + const previousEnv = { ...process.env }; + + afterEach(() => { + for (const key of Object.keys(process.env)) { + if (!(key in previousEnv)) delete process.env[key]; + } + for (const [key, value] of Object.entries(previousEnv)) { + process.env[key] = value; + } + vi.restoreAllMocks(); + vi.unstubAllGlobals(); + }); + it("should not include ollama when no API key is configured", async () => { const agentDir = mkdtempSync(join(tmpdir(), "clawd-test-")); const providers = await resolveImplicitProviders({ agentDir }); @@ -12,4 +25,82 @@ describe("Ollama provider", () => { // Ollama requires explicit configuration via OLLAMA_API_KEY env var or profile expect(providers?.ollama).toBeUndefined(); }); + + it("discovers tool-capable models when OLLAMA_API_KEY is set", async () => { + process.env.OLLAMA_API_KEY = "ollama-local"; + delete process.env.VITEST; + process.env.NODE_ENV = "development"; + + const fetchMock = vi + .fn() + .mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => ({ + models: [{ name: "llama3.3" }, { name: "no-tools-model" }], + }), + }) + .mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => ({ + capabilities: ["tools", "thinking"], + model_info: { + "general.architecture": "llama", + "llama.context_length": "4096", + }, + }), + }) + .mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => ({ + capabilities: ["thinking"], + model_info: { + "general.architecture": "llama", + "llama.context_length": "2048", + }, + }), + }); + vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch); + + const agentDir = mkdtempSync(join(tmpdir(), "clawd-test-")); + const providers = await resolveImplicitProviders({ agentDir }); + + expect(fetchMock).toHaveBeenCalledTimes(3); + expect(fetchMock.mock.calls[0]?.[0]).toBe("http://127.0.0.1:11434/api/tags"); + expect(fetchMock.mock.calls[1]?.[0]).toBe("http://127.0.0.1:11434/api/show"); + + const provider = providers?.ollama; + expect(provider?.baseUrl).toBe("http://127.0.0.1:11434/v1"); + expect(provider?.models).toHaveLength(1); + expect(provider?.models?.[0]?.id).toBe("llama3.3"); + expect(provider?.models?.[0]?.reasoning).toBe(true); + expect(provider?.models?.[0]?.contextWindow).toBe(4096); + expect(provider?.models?.[0]?.maxTokens).toBe(4096 * 10); + }); + + it("skips discovery when ollama is explicitly configured", async () => { + process.env.OLLAMA_API_KEY = "ollama-local"; + delete process.env.VITEST; + process.env.NODE_ENV = "development"; + + const fetchMock = vi.fn(); + vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch); + + const agentDir = mkdtempSync(join(tmpdir(), "clawd-test-")); + const providers = await resolveImplicitProviders({ + agentDir, + explicitProviders: { + ollama: { + baseUrl: "http://example.com/v1", + api: "openai-completions", + models: [], + }, + }, + }); + + expect(fetchMock).not.toHaveBeenCalled(); + expect(providers?.ollama).toBeUndefined(); + }); });