Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/api/providers/__tests__/native-ollama.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,50 @@ describe("NativeOllamaHandler", () => {
})
})

describe("ensureModelFetched", () => {
it("makes the detected context window available before a request", async () => {
mockGetOllamaModels.mockResolvedValueOnce({
llama2: {
contextWindow: 1_000_000,
maxTokens: 4096,
supportsImages: false,
supportsPromptCache: true,
},
})

expect(handler.getModel().info.contextWindow).toBe(128_000)

await handler.ensureModelFetched()

expect(handler.getModel().info.contextWindow).toBe(1_000_000)
expect(mockGetOllamaModels).toHaveBeenCalledTimes(1)
})

it("skips subsequent fetches after models are populated", async () => {
await handler.ensureModelFetched()
mockGetOllamaModels.mockClear()

await handler.fetchModel()

expect(mockGetOllamaModels).not.toHaveBeenCalled()
})

it("deduplicates concurrent metadata fetches", async () => {
await Promise.all([handler.ensureModelFetched(), handler.ensureModelFetched()])

expect(mockGetOllamaModels).toHaveBeenCalledTimes(1)
})

it("allows a later fetch after a rejected request", async () => {
mockGetOllamaModels.mockRejectedValueOnce(new Error("network down"))

await expect(handler.ensureModelFetched()).rejects.toThrow("network down")
await handler.ensureModelFetched()

expect(mockGetOllamaModels).toHaveBeenCalledTimes(2)
})
})

describe("tool calling", () => {
it("should include tools when tools are provided", async () => {
// Model metadata should not gate tool inclusion; metadata.tools controls it.
Expand Down
23 changes: 21 additions & 2 deletions src/api/providers/native-ollama.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ export class NativeOllamaHandler extends BaseProvider implements SingleCompletio
protected options: ApiHandlerOptions
private client: Ollama | undefined
protected models: Record<string, ModelInfo> = {}
private modelFetchPromise?: Promise<{ id: string; info: ModelInfo }>

constructor(options: ApiHandlerOptions) {
super()
Expand Down Expand Up @@ -538,8 +539,26 @@ export class NativeOllamaHandler extends BaseProvider implements SingleCompletio
}

async fetchModel() {
this.models = await getOllamaModels(this.options.ollamaBaseUrl, this.options.ollamaApiKey)
return this.getModel()
if (Object.keys(this.models).length > 0) {
return this.getModel()
}

if (!this.modelFetchPromise) {
this.modelFetchPromise = getOllamaModels(this.options.ollamaBaseUrl, this.options.ollamaApiKey)
.then((models) => {
this.models = models
return this.getModel()
})
.finally(() => {
this.modelFetchPromise = undefined
})
}

return this.modelFetchPromise
}

async ensureModelFetched(): Promise<void> {
await this.fetchModel()
}

override getModel(): { id: string; info: ModelInfo } {
Expand Down
Loading