






















@@ -467,6 +467,68 @@ describe("ollama plugin", () => {
467467}
468468});
469469470+it("preserves explicit api for configured dynamic Ollama models", async () => {
471+const provider = registerProvider();
472+const previous = process.env.OLLAMA_API_KEY;
473+process.env.OLLAMA_API_KEY = "ollama-live";
474+buildOllamaProviderMock.mockResolvedValueOnce({
475+baseUrl: "https://ollama.example.com",
476+api: "ollama",
477+models: [
478+{
479+id: "qwen3-coder:cloud",
480+name: "qwen3-coder:cloud",
481+reasoning: false,
482+input: ["text"],
483+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
484+contextWindow: 8192,
485+maxTokens: 2048,
486+},
487+],
488+});
489+490+try {
491+const config = {
492+models: {
493+providers: {
494+ollama: {
495+baseUrl: "https://ollama.example.com/v1",
496+api: "openai-completions",
497+models: [],
498+},
499+},
500+},
501+};
502+503+await provider.prepareDynamicModel?.({
504+ config,
505+provider: "ollama",
506+modelId: "qwen3-coder:cloud",
507+modelRegistry: { find: vi.fn(() => null) },
508+} as never);
509+510+const resolved = provider.resolveDynamicModel?.({
511+ config,
512+provider: "ollama",
513+modelId: "qwen3-coder:cloud",
514+modelRegistry: { find: vi.fn(() => null) },
515+} as never);
516+expect(resolved?.provider).toBe("ollama");
517+expect(resolved?.id).toBe("qwen3-coder:cloud");
518+expect(resolved?.api).toBe("openai-completions");
519+expect(resolved?.baseUrl).toBe("https://ollama.example.com/v1");
520+expect(buildOllamaProviderMock).toHaveBeenCalledWith("https://ollama.example.com/v1", {
521+quiet: true,
522+});
523+} finally {
524+if (previous === undefined) {
525+delete process.env.OLLAMA_API_KEY;
526+} else {
527+process.env.OLLAMA_API_KEY = previous;
528+}
529+}
530+});
531+470532it("resolves requested Ollama cloud models that are omitted from tags but confirmed by show", async () => {
471533const provider = registerProvider();
472534const previous = process.env.OLLAMA_API_KEY;
@@ -1335,7 +1397,7 @@ describe("ollama plugin", () => {
1335139713361398provider.createStreamFn?.({
13371399config: {},
1338-model: { id: "kimi-k2.5:cloud" },
1400+model: { api: "ollama", id: "kimi-k2.5:cloud" },
13391401provider: "ollama-cloud",
13401402} as never);
13411403expect(requireConfiguredStreamParams().providerBaseUrl).toBe("https://ollama.com");
@@ -1434,6 +1496,55 @@ describe("ollama plugin", () => {
14341496expect(nativePolicy?.validateAnthropicTurns).toBe(true);
14351497});
143614981499+it.each([
1500+{
1501+providerId: "ollama",
1502+register: registerProvider,
1503+nativeBaseUrl: "http://127.0.0.1:11434",
1504+},
1505+{
1506+providerId: "ollama-cloud",
1507+register: registerOllamaCloudProvider,
1508+nativeBaseUrl: "https://ollama.com",
1509+},
1510+])(
1511+"$providerId selects native /api/chat transport only for api=ollama",
1512+({ providerId, register, nativeBaseUrl }) => {
1513+const provider = register();
1514+const createStream = (api: "ollama" | "openai-completions", baseUrl: string) =>
1515+provider.createStreamFn?.({
1516+config: {
1517+models: {
1518+providers: {
1519+[providerId]: {
1520+ api,
1521+ baseUrl,
1522+models: [],
1523+},
1524+},
1525+},
1526+},
1527+model: {
1528+ api,
1529+id: "qwen3:32b",
1530+provider: providerId,
1531+},
1532+provider: providerId,
1533+} as never);
1534+1535+const compatibleStream = createStream("openai-completions", `${nativeBaseUrl}/v1`);
1536+1537+expect(compatibleStream).toBeUndefined();
1538+expect(createConfiguredOllamaStreamFnMock).not.toHaveBeenCalled();
1539+1540+const nativeStream = createStream("ollama", nativeBaseUrl);
1541+1542+expect(nativeStream).toBeDefined();
1543+expect(createConfiguredOllamaStreamFnMock).toHaveBeenCalledOnce();
1544+expect(requireConfiguredStreamParams().providerBaseUrl).toBe(nativeBaseUrl);
1545+},
1546+);
1547+14371548it("routes createStreamFn to the correct provider baseUrl for ollama2", () => {
14381549const provider = registerProvider();
14391550const config = {
@@ -1452,7 +1563,7 @@ describe("ollama plugin", () => {
14521563},
14531564},
14541565};
1455-const model = { id: "llama3.2", provider: "ollama2", baseUrl: undefined };
1566+const model = { id: "llama3.2", provider: "ollama2", api: "ollama", baseUrl: undefined };
1456156714571568provider.createStreamFn?.({ config, model, provider: "ollama2" } as never);
14581569@@ -1472,7 +1583,7 @@ describe("ollama plugin", () => {
14721583},
14731584},
14741585};
1475-const model = { id: "llama3.2", provider: "ollama2", baseUrl: undefined };
1586+const model = { id: "llama3.2", provider: "ollama2", api: "ollama", baseUrl: undefined };
1476158714771588provider.createStreamFn?.({ config, model, provider: "ollama2" } as never);
14781589@@ -1497,7 +1608,7 @@ describe("ollama plugin", () => {
14971608},
14981609},
14991610};
1500-const model = { id: "llama3.2", provider: "ollama", baseUrl: undefined };
1611+const model = { id: "llama3.2", provider: "ollama", api: "ollama", baseUrl: undefined };
1501161215021613provider.createStreamFn?.({ config, model, provider: "ollama" } as never);
15031614此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。