@happyvertical/ai 0.78.3 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/AGENT.md +1 -1
  2. package/README.md +63 -5
  3. package/dist/chunks/{anthropic-BRwbhwIl.js → anthropic-2z-82zgr.js} +75 -8
  4. package/dist/chunks/anthropic-2z-82zgr.js.map +1 -0
  5. package/dist/chunks/{bedrock-Cf1xUerN.js → bedrock-Dc2eVPUD.js} +153 -41
  6. package/dist/chunks/bedrock-Dc2eVPUD.js.map +1 -0
  7. package/dist/chunks/{bifrost-3mXtQsTj.js → bifrost-CEnCsciy.js} +36 -11
  8. package/dist/chunks/bifrost-CEnCsciy.js.map +1 -0
  9. package/dist/chunks/{claude-cli-BrHRfkry.js → claude-cli-X1ONjE8K.js} +3 -3
  10. package/dist/chunks/{claude-cli-BrHRfkry.js.map → claude-cli-X1ONjE8K.js.map} +1 -1
  11. package/dist/chunks/{gateway-admin-C4GFPbZF.js → gateway-admin-BUhBzXZb.js} +2 -2
  12. package/dist/chunks/{gateway-admin-C4GFPbZF.js.map → gateway-admin-BUhBzXZb.js.map} +1 -1
  13. package/dist/chunks/{gemini-BfpHXDIQ.js → gemini-CS56gY0D.js} +138 -32
  14. package/dist/chunks/gemini-CS56gY0D.js.map +1 -0
  15. package/dist/chunks/{huggingface-280qv9iv.js → huggingface-wQSfO5xA.js} +64 -19
  16. package/dist/chunks/huggingface-wQSfO5xA.js.map +1 -0
  17. package/dist/chunks/{index-BT4thAvS.js → index-DCXO0nZA.js} +383 -24
  18. package/dist/chunks/index-DCXO0nZA.js.map +1 -0
  19. package/dist/chunks/{litellm-DhPKa_Jz.js → litellm-BMFTYbWc.js} +36 -11
  20. package/dist/chunks/litellm-BMFTYbWc.js.map +1 -0
  21. package/dist/chunks/{ollama-Di1ldur0.js → ollama-DsGDrA-c.js} +171 -60
  22. package/dist/chunks/ollama-DsGDrA-c.js.map +1 -0
  23. package/dist/chunks/{openai-5snI2diE.js → openai-CJEo69jb.js} +145 -12
  24. package/dist/chunks/openai-CJEo69jb.js.map +1 -0
  25. package/dist/chunks/{qwen-tts-DgPgdXxG.js → qwen-tts-BLYZ6d9s.js} +2 -2
  26. package/dist/chunks/{qwen-tts-DgPgdXxG.js.map → qwen-tts-BLYZ6d9s.js.map} +1 -1
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +15 -12
  30. package/dist/shared/factory.d.ts.map +1 -1
  31. package/dist/shared/providers/anthropic.d.ts.map +1 -1
  32. package/dist/shared/providers/bedrock.d.ts.map +1 -1
  33. package/dist/shared/providers/bifrost.d.ts.map +1 -1
  34. package/dist/shared/providers/gemini.d.ts +0 -5
  35. package/dist/shared/providers/gemini.d.ts.map +1 -1
  36. package/dist/shared/providers/huggingface.d.ts.map +1 -1
  37. package/dist/shared/providers/litellm.d.ts.map +1 -1
  38. package/dist/shared/providers/ollama.d.ts +0 -1
  39. package/dist/shared/providers/ollama.d.ts.map +1 -1
  40. package/dist/shared/providers/openai.d.ts +2 -2
  41. package/dist/shared/providers/openai.d.ts.map +1 -1
  42. package/dist/shared/safety.d.ts +55 -0
  43. package/dist/shared/safety.d.ts.map +1 -0
  44. package/dist/shared/types.d.ts +74 -6
  45. package/dist/shared/types.d.ts.map +1 -1
  46. package/metadata.json +1 -1
  47. package/package.json +2 -2
  48. package/dist/chunks/anthropic-BRwbhwIl.js.map +0 -1
  49. package/dist/chunks/bedrock-Cf1xUerN.js.map +0 -1
  50. package/dist/chunks/bifrost-3mXtQsTj.js.map +0 -1
  51. package/dist/chunks/gemini-BfpHXDIQ.js.map +0 -1
  52. package/dist/chunks/huggingface-280qv9iv.js.map +0 -1
  53. package/dist/chunks/index-BT4thAvS.js.map +0 -1
  54. package/dist/chunks/litellm-DhPKa_Jz.js.map +0 -1
  55. package/dist/chunks/ollama-Di1ldur0.js.map +0 -1
  56. package/dist/chunks/openai-5snI2diE.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { ValidationError } from "@happyvertical/utils";
2
- import { C as ContentFilterError, a as ContextLengthError, A as AIError, R as RateLimitError, M as ModelNotFoundError, b as AuthenticationError, c as extractTextContent } from "./index-BT4thAvS.js";
2
+ import { b as normalizeBaseAIOptions, C as ContentFilterError, c as ContextLengthError, A as AIError, R as RateLimitError, M as ModelNotFoundError, d as AuthenticationError, f as extractTextContent, n as normalizeChatOptions, p as prepareRequestControls, a as normalizeImageGenerationOptions } from "./index-DCXO0nZA.js";
3
3
  import { e as emitUsage } from "./usage-DMWiJ2oB.js";
4
4
  const DEFAULT_OLLAMA_HOST = "http://localhost:11434";
5
5
  const OLLAMA_CAPABILITIES = {
@@ -164,10 +164,10 @@ class OllamaProvider {
164
164
  resolvedModelCache = /* @__PURE__ */ new Map();
165
165
  constructor(options) {
166
166
  this.host = normalizeHost(options.baseUrl);
167
- this.options = {
167
+ this.options = normalizeBaseAIOptions({
168
168
  ...options,
169
169
  baseUrl: this.host
170
- };
170
+ });
171
171
  this.configuredDefaultModel = options.defaultModel;
172
172
  }
173
173
  get nativeBaseUrl() {
@@ -188,19 +188,6 @@ class OllamaProvider {
188
188
  }
189
189
  return headers;
190
190
  }
191
- async fetchWithTimeout(url, init) {
192
- const controller = new AbortController();
193
- const timeout = typeof this.options.timeout === "number" ? this.options.timeout : 0;
194
- const timer = timeout ? setTimeout(() => controller.abort(), timeout) : void 0;
195
- try {
196
- return await fetch(url, {
197
- ...init,
198
- signal: controller.signal
199
- });
200
- } finally {
201
- if (timer) clearTimeout(timer);
202
- }
203
- }
204
191
  async buildHttpError(response) {
205
192
  const text = await response.text();
206
193
  const message = text && text.trim().length > 0 ? text.trim() : `Ollama request failed with status ${response.status}`;
@@ -236,25 +223,24 @@ class OllamaProvider {
236
223
  }
237
224
  async requestJson(path, body, options = {}) {
238
225
  const baseUrl = options.compatibility ? this.compatibilityBaseUrl : this.nativeBaseUrl;
239
- const response = await this.fetchWithTimeout(`${baseUrl}${path}`, {
226
+ const response = await fetch(`${baseUrl}${path}`, {
240
227
  method: body ? "POST" : "GET",
241
228
  headers: this.buildHeaders(),
242
- body: body ? JSON.stringify(body) : void 0
229
+ body: body ? JSON.stringify(body) : void 0,
230
+ signal: options.signal
243
231
  });
244
232
  if (!response.ok) {
245
233
  throw await this.buildHttpError(response);
246
234
  }
247
235
  return await response.json();
248
236
  }
249
- async requestStream(path, body) {
250
- const response = await this.fetchWithTimeout(
251
- `${this.nativeBaseUrl}${path}`,
252
- {
253
- method: "POST",
254
- headers: this.buildHeaders(true),
255
- body: JSON.stringify(body)
256
- }
257
- );
237
+ async requestStream(path, body, signal) {
238
+ const response = await fetch(`${this.nativeBaseUrl}${path}`, {
239
+ method: "POST",
240
+ headers: this.buildHeaders(true),
241
+ body: JSON.stringify(body),
242
+ signal
243
+ });
258
244
  if (!response.ok) {
259
245
  throw await this.buildHttpError(response);
260
246
  }
@@ -352,7 +338,7 @@ class OllamaProvider {
352
338
  (message) => Array.isArray(message.content) && message.content.some((part) => part.type === "image_url")
353
339
  );
354
340
  }
355
- async imageToBase64Payload(image) {
341
+ async imageToBase64Payload(image, signal) {
356
342
  if (Buffer.isBuffer(image)) {
357
343
  return image.toString("base64");
358
344
  }
@@ -360,7 +346,7 @@ class OllamaProvider {
360
346
  const commaIndex = image.indexOf(",");
361
347
  return commaIndex === -1 ? image : image.slice(commaIndex + 1);
362
348
  }
363
- const response = await fetch(image);
349
+ const response = await fetch(image, { signal });
364
350
  if (!response.ok) {
365
351
  throw new AIError(
366
352
  `Failed to fetch image: ${response.status} ${response.statusText}`,
@@ -371,14 +357,14 @@ class OllamaProvider {
371
357
  const arrayBuffer = await response.arrayBuffer();
372
358
  return Buffer.from(arrayBuffer).toString("base64");
373
359
  }
374
- async imageToDataUrl(image) {
360
+ async imageToDataUrl(image, signal) {
375
361
  if (Buffer.isBuffer(image)) {
376
362
  return `data:image/png;base64,${image.toString("base64")}`;
377
363
  }
378
364
  if (image.startsWith("data:")) {
379
365
  return image;
380
366
  }
381
- const response = await fetch(image);
367
+ const response = await fetch(image, { signal });
382
368
  if (!response.ok) {
383
369
  throw new AIError(
384
370
  `Failed to fetch image: ${response.status} ${response.statusText}`,
@@ -401,7 +387,7 @@ class OllamaProvider {
401
387
  return {};
402
388
  }
403
389
  }
404
- async mapMessagesToOllama(messages) {
390
+ async mapMessagesToOllama(messages, signal) {
405
391
  const mappedMessages = await Promise.all(
406
392
  messages.map(async (message) => {
407
393
  const content = extractTextContent(message.content);
@@ -416,7 +402,7 @@ class OllamaProvider {
416
402
  if (imageParts.length > 0) {
417
403
  mapped.images = await Promise.all(
418
404
  imageParts.map(
419
- (part) => this.imageToBase64Payload(part.image_url.url)
405
+ (part) => this.imageToBase64Payload(part.image_url.url, signal)
420
406
  )
421
407
  );
422
408
  }
@@ -478,6 +464,12 @@ class OllamaProvider {
478
464
  return Object.keys(runtimeOptions).length > 0 ? runtimeOptions : void 0;
479
465
  }
480
466
  mapThink(options) {
467
+ if (options.reasoning?.maxTokens === 0) {
468
+ return false;
469
+ }
470
+ if (options.reasoning?.effort) {
471
+ return options.reasoning.effort === "none" ? false : options.reasoning.effort;
472
+ }
481
473
  if (!Object.hasOwn(options, "thinkingLevel")) {
482
474
  return void 0;
483
475
  }
@@ -485,21 +477,33 @@ class OllamaProvider {
485
477
  }
486
478
  async chat(messages, options = {}) {
487
479
  const startTime = Date.now();
480
+ let controls;
488
481
  try {
482
+ options = normalizeChatOptions(
483
+ this.options,
484
+ options,
485
+ "ollama",
486
+ options.model || this.options.defaultModel
487
+ );
488
+ controls = prepareRequestControls(this.options, options);
489
489
  const model = await this.resolveModel(
490
490
  this.isVisionRequest(messages) ? "vision" : "chat",
491
491
  options.model
492
492
  );
493
- const response = await this.requestJson("/chat", {
494
- model,
495
- messages: await this.mapMessagesToOllama(messages),
496
- stream: false,
497
- format: options.responseFormat?.type === "json_object" ? "json" : void 0,
498
- tools: this.mapTools(options.tools, options.toolChoice),
499
- think: this.mapThink(options),
500
- keep_alive: this.options.keepAlive,
501
- options: this.buildRuntimeOptions(options)
502
- });
493
+ const response = await this.requestJson(
494
+ "/chat",
495
+ {
496
+ model,
497
+ messages: await this.mapMessagesToOllama(messages, controls.signal),
498
+ stream: false,
499
+ format: options.responseFormat?.type === "json_object" ? "json" : void 0,
500
+ tools: this.mapTools(options.tools, options.toolChoice),
501
+ think: this.mapThink(options),
502
+ keep_alive: this.options.keepAlive,
503
+ options: this.buildRuntimeOptions(options)
504
+ },
505
+ { signal: controls.signal }
506
+ );
503
507
  const usage = mapUsage(response.prompt_eval_count, response.eval_count);
504
508
  emitUsage(
505
509
  this.options,
@@ -526,12 +530,38 @@ class OllamaProvider {
526
530
  toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : void 0
527
531
  };
528
532
  } catch (error) {
533
+ if (controls?.didTimeout()) {
534
+ throw new AIError(
535
+ `AI request timed out after ${controls.timeout}ms`,
536
+ "AI_TIMEOUT",
537
+ "ollama",
538
+ options.model
539
+ );
540
+ }
541
+ if (options.signal?.aborted) {
542
+ throw new AIError(
543
+ "AI request aborted by caller",
544
+ "AI_ABORTED",
545
+ "ollama",
546
+ options.model
547
+ );
548
+ }
529
549
  throw this.mapError(error);
550
+ } finally {
551
+ controls?.cleanup();
530
552
  }
531
553
  }
532
554
  async complete(prompt, options = {}) {
533
555
  const startTime = Date.now();
556
+ let controls;
534
557
  try {
558
+ options = normalizeChatOptions(
559
+ this.options,
560
+ options,
561
+ "ollama",
562
+ options.model || this.options.defaultModel
563
+ );
564
+ controls = prepareRequestControls(this.options, options);
535
565
  const model = await this.resolveModel("chat", options.model);
536
566
  const response = await this.requestJson(
537
567
  "/generate",
@@ -541,7 +571,8 @@ class OllamaProvider {
541
571
  stream: false,
542
572
  keep_alive: this.options.keepAlive,
543
573
  options: this.buildRuntimeOptions(options)
544
- }
574
+ },
575
+ { signal: controls.signal }
545
576
  );
546
577
  const usage = mapUsage(response.prompt_eval_count, response.eval_count);
547
578
  emitUsage(
@@ -560,7 +591,25 @@ class OllamaProvider {
560
591
  finishReason: mapFinishReason(response.done_reason)
561
592
  };
562
593
  } catch (error) {
594
+ if (controls?.didTimeout()) {
595
+ throw new AIError(
596
+ `AI request timed out after ${controls.timeout}ms`,
597
+ "AI_TIMEOUT",
598
+ "ollama",
599
+ options.model
600
+ );
601
+ }
602
+ if (options.signal?.aborted) {
603
+ throw new AIError(
604
+ "AI request aborted by caller",
605
+ "AI_ABORTED",
606
+ "ollama",
607
+ options.model
608
+ );
609
+ }
563
610
  throw this.mapError(error);
611
+ } finally {
612
+ controls?.cleanup();
564
613
  }
565
614
  }
566
615
  async message(text, options = {}) {
@@ -582,6 +631,9 @@ class OllamaProvider {
582
631
  tools: options.tools,
583
632
  toolChoice: options.toolChoice,
584
633
  onProgress: options.onProgress,
634
+ signal: options.signal,
635
+ timeout: options.timeout,
636
+ reasoning: options.reasoning,
585
637
  usageTags: options.usageTags
586
638
  });
587
639
  return response.content;
@@ -636,7 +688,7 @@ class OllamaProvider {
636
688
  }
637
689
  async describeImage(image, prompt, options = {}) {
638
690
  const defaultPrompt = "Describe this image for a search index. Include objects, mood, lighting, and any visible text.";
639
- const imageUrl = await this.imageToDataUrl(image);
691
+ const imageUrl = await this.imageToDataUrl(image, options.signal);
640
692
  const response = await this.chat(
641
693
  [
642
694
  {
@@ -658,14 +710,25 @@ class OllamaProvider {
658
710
  ],
659
711
  {
660
712
  model: options.model,
661
- maxTokens: options.maxTokens || 500,
662
- thinkingLevel: false
713
+ maxTokens: options.maxTokens ?? 500,
714
+ reasoning: options.reasoning || { effort: "none", maxTokens: 0 },
715
+ signal: options.signal,
716
+ timeout: options.timeout,
717
+ usageTags: options.usageTags
663
718
  }
664
719
  );
665
720
  return response.content;
666
721
  }
667
722
  async generateImage(prompt, options = {}) {
723
+ let controls;
668
724
  try {
725
+ options = normalizeImageGenerationOptions(
726
+ this.options,
727
+ options,
728
+ "ollama",
729
+ options.model
730
+ );
731
+ controls = prepareRequestControls(this.options, options);
669
732
  if (options.imageInput) {
670
733
  throw new AIError(
671
734
  "Ollama image generation does not support imageInput in this adapter yet.",
@@ -686,13 +749,13 @@ class OllamaProvider {
686
749
  {
687
750
  model,
688
751
  prompt,
689
- n: options.n || 1,
752
+ n: options.n,
690
753
  size: options.size || "1024x1024",
691
754
  response_format: "b64_json",
692
755
  quality: options.quality,
693
756
  style: options.style
694
757
  },
695
- { compatibility: true }
758
+ { compatibility: true, signal: controls.signal }
696
759
  );
697
760
  const images = (response.data || []).map((item) => {
698
761
  const b64 = item.b64_json || "";
@@ -707,26 +770,56 @@ class OllamaProvider {
707
770
  model
708
771
  };
709
772
  } catch (error) {
773
+ if (controls?.didTimeout()) {
774
+ throw new AIError(
775
+ `AI request timed out after ${controls.timeout}ms`,
776
+ "AI_TIMEOUT",
777
+ "ollama",
778
+ options.model
779
+ );
780
+ }
781
+ if (options.signal?.aborted) {
782
+ throw new AIError(
783
+ "AI request aborted by caller",
784
+ "AI_ABORTED",
785
+ "ollama",
786
+ options.model
787
+ );
788
+ }
710
789
  throw this.mapError(error);
790
+ } finally {
791
+ controls?.cleanup();
711
792
  }
712
793
  }
713
794
  async *stream(messages, options = {}) {
714
795
  const startTime = Date.now();
796
+ let controls;
715
797
  try {
798
+ options = normalizeChatOptions(
799
+ this.options,
800
+ options,
801
+ "ollama",
802
+ options.model || this.options.defaultModel
803
+ );
804
+ controls = prepareRequestControls(this.options, options);
716
805
  const model = await this.resolveModel(
717
806
  this.isVisionRequest(messages) ? "vision" : "chat",
718
807
  options.model
719
808
  );
720
- const response = await this.requestStream("/chat", {
721
- model,
722
- messages: await this.mapMessagesToOllama(messages),
723
- stream: true,
724
- format: options.responseFormat?.type === "json_object" ? "json" : void 0,
725
- tools: this.mapTools(options.tools, options.toolChoice),
726
- think: this.mapThink(options),
727
- keep_alive: this.options.keepAlive,
728
- options: this.buildRuntimeOptions(options)
729
- });
809
+ const response = await this.requestStream(
810
+ "/chat",
811
+ {
812
+ model,
813
+ messages: await this.mapMessagesToOllama(messages, controls.signal),
814
+ stream: true,
815
+ format: options.responseFormat?.type === "json_object" ? "json" : void 0,
816
+ tools: this.mapTools(options.tools, options.toolChoice),
817
+ think: this.mapThink(options),
818
+ keep_alive: this.options.keepAlive,
819
+ options: this.buildRuntimeOptions(options)
820
+ },
821
+ controls.signal
822
+ );
730
823
  let finalUsage;
731
824
  let finalModel = model;
732
825
  for await (const chunk of this.parseNdjson(
@@ -755,7 +848,25 @@ class OllamaProvider {
755
848
  options.usageTags
756
849
  );
757
850
  } catch (error) {
851
+ if (controls?.didTimeout()) {
852
+ throw new AIError(
853
+ `AI request timed out after ${controls.timeout}ms`,
854
+ "AI_TIMEOUT",
855
+ "ollama",
856
+ options.model
857
+ );
858
+ }
859
+ if (options.signal?.aborted) {
860
+ throw new AIError(
861
+ "AI request aborted by caller",
862
+ "AI_ABORTED",
863
+ "ollama",
864
+ options.model
865
+ );
866
+ }
758
867
  throw this.mapError(error);
868
+ } finally {
869
+ controls?.cleanup();
759
870
  }
760
871
  }
761
872
  async countTokens(text) {
@@ -848,4 +959,4 @@ class OllamaProvider {
848
959
  export {
849
960
  OllamaProvider
850
961
  };
851
- //# sourceMappingURL=ollama-Di1ldur0.js.map
962
+ //# sourceMappingURL=ollama-DsGDrA-c.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama-DsGDrA-c.js","sources":["../../src/shared/providers/ollama.ts"],"sourcesContent":["/**\n * Ollama provider implementation.\n *\n * Uses Ollama's native `/api/*` endpoints for chat, completions, embeddings,\n * and model discovery, while bridging to the experimental OpenAI-compatible\n * image-generation endpoint when available.\n */\n\nimport { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n OllamaOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContentFilterError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n RateLimitError,\n} from '../types';\nimport { emitUsage } from './usage';\n\nconst DEFAULT_OLLAMA_HOST = 'http://localhost:11434';\n\nconst OLLAMA_CAPABILITIES: AICapabilities = {\n chat: true,\n completion: true,\n embeddings: true,\n streaming: true,\n functions: true,\n vision: true,\n fineTuning: false,\n imageEmbeddings: true,\n imageGeneration: true,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 131072,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\ntype ResolvedOllamaCapability =\n | 'chat'\n | 'vision'\n | 'embedding'\n | 'image_generation';\n\ninterface OllamaModelSummary {\n name?: string;\n model?: string;\n modified_at?: string;\n size?: number;\n details?: {\n family?: string;\n families?: string[];\n format?: string;\n parameter_size?: string;\n quantization_level?: string;\n };\n}\n\ninterface OllamaTagsResponse {\n models?: OllamaModelSummary[];\n}\n\ninterface OllamaShowResponse {\n capabilities?: string[];\n parameters?: string;\n modified_at?: string;\n details?: {\n parent_model?: string;\n format?: string;\n family?: string;\n families?: string[];\n parameter_size?: string;\n quantization_level?: string;\n };\n model_info?: Record<string, unknown>;\n}\n\ninterface OllamaToolCall {\n type?: 'function';\n function?: {\n index?: number;\n name?: string;\n arguments?: Record<string, unknown>;\n };\n}\n\ninterface OllamaMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content?: string;\n thinking?: string;\n images?: string[];\n tool_name?: string;\n tool_calls?: OllamaToolCall[];\n}\n\ninterface OllamaChatResponse {\n model?: string;\n message?: OllamaMessage;\n done?: boolean;\n done_reason?: string;\n prompt_eval_count?: number;\n eval_count?: number;\n}\n\ninterface OllamaGenerateResponse {\n model?: string;\n response?: string;\n thinking?: string;\n done?: boolean;\n done_reason?: string;\n prompt_eval_count?: number;\n eval_count?: number;\n}\n\ninterface OllamaEmbedResponse {\n model?: string;\n embeddings?: number[][];\n embedding?: number[];\n prompt_eval_count?: number;\n}\n\ninterface OllamaImageGenerationResponse {\n created?: number;\n data?: Array<{\n b64_json?: string;\n revised_prompt?: string;\n }>;\n}\n\nfunction stripTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, '');\n}\n\nfunction normalizeHost(baseUrl?: string): string {\n const rawBase = baseUrl?.trim() || DEFAULT_OLLAMA_HOST;\n const withScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(rawBase)\n ? rawBase\n : `http://${rawBase}`;\n const base = stripTrailingSlash(withScheme);\n if (base.endsWith('/api')) return base.slice(0, -4);\n if (base.endsWith('/v1')) return base.slice(0, -3);\n return base;\n}\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /(?:^|[-_:/])(?:embed|embedding)|nomic-embed|mxbai-embed/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /(?:^|[-_:/])(flux|sdxl|stable(?:[-_ ]?diffusion)?|z-image|image(?:[-_ ]?(?:turbo|gen|generator)))/i.test(\n modelId,\n );\n}\n\nfunction inferVisionSupport(\n modelId: string,\n capabilities: Set<string>,\n): boolean {\n if (capabilities.has('vision')) return true;\n return /vision|llava|bakllava|moondream|pixtral|qwen.*vl|vl-|gemma3/i.test(\n modelId,\n );\n}\n\nfunction inferFunctionSupport(\n modelId: string,\n capabilities: Set<string>,\n): boolean {\n if (\n capabilities.has('tools') ||\n capabilities.has('tool_calling') ||\n capabilities.has('function_calling')\n ) {\n return true;\n }\n\n if (isEmbeddingModel(modelId) || isImageGenerationModel(modelId)) {\n return false;\n }\n\n return /qwen|llama3|gpt-oss|mistral|deepseek|command-r|phi4/i.test(modelId);\n}\n\nfunction parseCapabilities(\n modelId: string,\n show?: OllamaShowResponse | null,\n): string[] {\n const capabilities = new Set(\n (show?.capabilities || []).map((capability) => capability.toLowerCase()),\n );\n\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (\n capabilities.has('embedding') ||\n capabilities.has('embeddings') ||\n isEmbeddingModel(modelId)\n ) {\n return ['embeddings'];\n }\n\n const supported = new Set<string>(['text', 'chat']);\n\n if (inferVisionSupport(modelId, capabilities)) {\n supported.add('vision');\n }\n\n if (inferFunctionSupport(modelId, capabilities)) {\n supported.add('functions');\n }\n\n return [...supported];\n}\n\nfunction parseContextLength(\n modelId: string,\n show?: OllamaShowResponse | null,\n): number {\n const modelInfo = show?.model_info || {};\n\n for (const [key, value] of Object.entries(modelInfo)) {\n if (key.endsWith('.context_length') && typeof value === 'number') {\n return value;\n }\n }\n\n const numCtxMatch = show?.parameters?.match(/\\bnum_ctx\\s+(\\d+)/);\n if (numCtxMatch?.[1]) {\n return Number(numCtxMatch[1]);\n }\n\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemma3|qwen3|gpt-oss|llama3/i.test(modelId)) return 131072;\n return 32768;\n}\n\nfunction mapUsage(\n promptTokens?: number,\n completionTokens?: number,\n): TokenUsage | undefined {\n if (\n typeof promptTokens !== 'number' &&\n typeof completionTokens !== 'number'\n ) {\n return undefined;\n }\n\n const prompt = promptTokens || 0;\n const completion = completionTokens || 0;\n return {\n promptTokens: prompt,\n completionTokens: completion,\n totalTokens: prompt + completion,\n };\n}\n\nfunction mapFinishReason(reason?: string): AIResponse['finishReason'] {\n switch (reason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content_filter';\n default:\n return 'stop';\n }\n}\n\nfunction scoreModelForCapability(\n model: AIModel,\n capability: ResolvedOllamaCapability,\n): number {\n const id = model.id.toLowerCase();\n let score = 0;\n\n if (id.includes(':latest')) score += 6;\n if (id.includes('instruct') || id.includes('-it')) score += 6;\n if (id.startsWith('hf.co/')) score -= 8;\n if (/ocr|rerank|embed|image|diffusion|flux/.test(id)) score -= 12;\n\n switch (capability) {\n case 'vision':\n if (model.supportsVision) score += 25;\n if (/gemma4|gemma3/.test(id)) score += 12;\n if (/qwen.*vl|llava|moondream|vision/.test(id)) score += 8;\n if (/ocr/.test(id)) score -= 10;\n break;\n case 'embedding':\n if (model.capabilities.includes('embeddings')) score += 20;\n if (/nomic|mxbai|embed/.test(id)) score += 6;\n break;\n case 'image_generation':\n if (model.capabilities.includes('image_generation')) score += 20;\n if (/flux|sdxl|stable/.test(id)) score += 8;\n break;\n case 'chat':\n default:\n if (model.capabilities.includes('chat')) score += 12;\n if (model.supportsFunctions) score += 4;\n if (/llama|mistral|qwen|gemma|phi|command-r|deepseek-coder/.test(id)) {\n score += 8;\n }\n if (/gpt-oss/.test(id)) score -= 3;\n break;\n }\n\n return score;\n}\n\nexport class OllamaProvider implements AIInterface {\n private readonly options: OllamaOptions;\n private readonly host: string;\n private readonly configuredDefaultModel?: string;\n private modelListPromise?: Promise<AIModel[]>;\n private readonly modelShowCache = new Map<\n string,\n Promise<OllamaShowResponse | null>\n >();\n private readonly resolvedModelCache = new Map<\n ResolvedOllamaCapability,\n Promise<string>\n >();\n\n constructor(options: OllamaOptions) {\n this.host = normalizeHost(options.baseUrl);\n this.options = normalizeBaseAIOptions({\n ...options,\n baseUrl: this.host,\n });\n this.configuredDefaultModel = options.defaultModel;\n }\n\n private get nativeBaseUrl(): string {\n return `${this.host}/api`;\n }\n\n private get compatibilityBaseUrl(): string {\n return `${this.host}/v1`;\n }\n\n private buildHeaders(stream = false): Headers {\n const headers = new Headers(this.options.headers);\n headers.set('Content-Type', 'application/json');\n headers.set(\n 'Accept',\n stream ? 'application/x-ndjson, application/json' : 'application/json',\n );\n if (this.options.apiKey) {\n headers.set('Authorization', `Bearer ${this.options.apiKey}`);\n }\n return headers;\n }\n\n private async buildHttpError(response: Response): Promise<AIError> {\n const text = await response.text();\n const message =\n text && text.trim().length > 0\n ? text.trim()\n : `Ollama request failed with status ${response.status}`;\n\n switch (response.status) {\n case 401:\n case 403:\n return new AuthenticationError('ollama');\n case 404:\n return new ModelNotFoundError(message, 'ollama');\n case 413:\n return new ContextLengthError('ollama');\n case 429:\n return new RateLimitError('ollama');\n default:\n if (/content[_ -]?filter/i.test(message)) {\n return new ContentFilterError('ollama');\n }\n if (/context|too long|maximum context/i.test(message)) {\n return new ContextLengthError('ollama');\n }\n return new AIError(message, 'API_ERROR', 'ollama');\n }\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n return new AIError('Ollama request timed out', 'TIMEOUT', 'ollama');\n }\n\n const message =\n error instanceof Error ? error.message : 'Unknown error occurred';\n return new AIError(message, 'UNKNOWN_ERROR', 'ollama');\n }\n\n private async requestJson<T>(\n path: string,\n body?: Record<string, unknown>,\n options: { compatibility?: boolean; signal?: AbortSignal } = {},\n ): Promise<T> {\n const baseUrl = options.compatibility\n ? this.compatibilityBaseUrl\n : this.nativeBaseUrl;\n const response = await fetch(`${baseUrl}${path}`, {\n method: body ? 'POST' : 'GET',\n headers: this.buildHeaders(),\n body: body ? JSON.stringify(body) : undefined,\n signal: options.signal,\n });\n\n if (!response.ok) {\n throw await this.buildHttpError(response);\n }\n\n return (await response.json()) as T;\n }\n\n private async requestStream(\n path: string,\n body: Record<string, unknown>,\n signal: AbortSignal,\n ): Promise<Response> {\n const response = await fetch(`${this.nativeBaseUrl}${path}`, {\n method: 'POST',\n headers: this.buildHeaders(true),\n body: JSON.stringify(body),\n signal,\n });\n\n if (!response.ok) {\n throw await this.buildHttpError(response);\n }\n\n return response;\n }\n\n private async *parseNdjson<T>(response: Response): AsyncIterable<T> {\n const reader = response.body?.getReader();\n if (!reader) {\n return;\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n let newlineIndex = buffer.indexOf('\\n');\n while (newlineIndex !== -1) {\n const line = buffer.slice(0, newlineIndex).trim();\n buffer = buffer.slice(newlineIndex + 1);\n if (line) {\n yield JSON.parse(line) as T;\n }\n newlineIndex = buffer.indexOf('\\n');\n }\n }\n\n buffer += decoder.decode();\n const line = buffer.trim();\n if (line) {\n yield JSON.parse(line) as T;\n }\n }\n\n private async showModel(model: string): Promise<OllamaShowResponse | null> {\n const cached = this.modelShowCache.get(model);\n if (cached) {\n return cached;\n }\n\n const pending = this.requestJson<OllamaShowResponse>('/show', {\n model,\n verbose: false,\n }).catch((_error) => null);\n\n this.modelShowCache.set(model, pending);\n return pending;\n }\n\n private async resolveModel(\n capability: ResolvedOllamaCapability,\n explicitModel?: string,\n ): Promise<string> {\n if (explicitModel) {\n return explicitModel;\n }\n\n if (\n this.configuredDefaultModel &&\n (capability === 'chat' || capability === 'vision')\n ) {\n return this.configuredDefaultModel;\n }\n\n const cached = this.resolvedModelCache.get(capability);\n if (cached) {\n return cached;\n }\n\n const pending = this.selectModel(capability).catch((error) => {\n this.resolvedModelCache.delete(capability);\n throw error;\n });\n this.resolvedModelCache.set(capability, pending);\n return pending;\n }\n\n private async selectModel(\n capability: ResolvedOllamaCapability,\n ): Promise<string> {\n const models = await this.getModels();\n const candidates = models.filter((candidate) => {\n switch (capability) {\n case 'vision':\n return (\n candidate.capabilities.includes('vision') ||\n candidate.supportsVision === true\n );\n case 'embedding':\n return candidate.capabilities.includes('embeddings');\n case 'image_generation':\n return candidate.capabilities.includes('image_generation');\n case 'chat':\n default:\n return candidate.capabilities.includes('chat');\n }\n });\n\n const model = candidates.sort(\n (left, right) =>\n scoreModelForCapability(right, capability) -\n scoreModelForCapability(left, capability),\n )[0];\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the Ollama host`,\n {\n provider: 'ollama',\n capability,\n hint: 'Pass model/defaultModel explicitly or make sure the Ollama host has a compatible model installed',\n },\n );\n }\n\n return model.id;\n }\n\n private isVisionRequest(messages: AIMessage[]): boolean {\n return messages.some(\n (message) =>\n Array.isArray(message.content) &&\n message.content.some((part) => part.type === 'image_url'),\n );\n }\n\n private async imageToBase64Payload(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return image.toString('base64');\n }\n\n if (image.startsWith('data:')) {\n const commaIndex = image.indexOf(',');\n return commaIndex === -1 ? image : image.slice(commaIndex + 1);\n }\n\n const response = await fetch(image, { signal });\n if (!response.ok) {\n throw new AIError(\n `Failed to fetch image: ${response.status} ${response.statusText}`,\n 'IMAGE_FETCH_ERROR',\n 'ollama',\n );\n }\n\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer).toString('base64');\n }\n\n private async imageToDataUrl(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return `data:image/png;base64,${image.toString('base64')}`;\n }\n\n if (image.startsWith('data:')) {\n return image;\n }\n\n const response = await fetch(image, { signal });\n if (!response.ok) {\n throw new AIError(\n `Failed to fetch image: ${response.status} ${response.statusText}`,\n 'IMAGE_FETCH_ERROR',\n 'ollama',\n );\n }\n\n const contentType = response.headers.get('content-type') || 'image/png';\n const arrayBuffer = await response.arrayBuffer();\n return `data:${contentType};base64,${Buffer.from(arrayBuffer).toString('base64')}`;\n }\n\n private parseToolArguments(argumentsText?: string): Record<string, unknown> {\n if (!argumentsText) {\n return {};\n }\n\n try {\n const parsed = JSON.parse(argumentsText);\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n }\n\n private async mapMessagesToOllama(\n messages: AIMessage[],\n signal?: AbortSignal,\n ): Promise<OllamaMessage[]> {\n const mappedMessages = await Promise.all(\n messages.map(async (message) => {\n const content = extractTextContent(message.content);\n const mapped: OllamaMessage = {\n role:\n message.role === 'function'\n ? 'tool'\n : (message.role as OllamaMessage['role']),\n content,\n };\n\n if (Array.isArray(message.content)) {\n const imageParts = message.content.filter(\n (part) => part.type === 'image_url',\n );\n if (imageParts.length > 0) {\n mapped.images = await Promise.all(\n imageParts.map((part) =>\n this.imageToBase64Payload(part.image_url.url, signal),\n ),\n );\n }\n }\n\n if (\n mapped.role === 'assistant' &&\n Array.isArray(message.tool_calls) &&\n message.tool_calls.length > 0\n ) {\n mapped.tool_calls = message.tool_calls.map((toolCall, index) => ({\n type: 'function',\n function: {\n index,\n name: toolCall.function.name,\n arguments: this.parseToolArguments(toolCall.function.arguments),\n },\n }));\n }\n\n if (mapped.role === 'tool' && message.name) {\n mapped.tool_name = message.name;\n }\n\n return mapped;\n }),\n );\n\n return mappedMessages;\n }\n\n private mapTools(\n tools: ChatOptions['tools'],\n toolChoice: ChatOptions['toolChoice'],\n ): Array<Record<string, unknown>> | undefined {\n if (!tools || tools.length === 0 || toolChoice === 'none') {\n return undefined;\n }\n\n const scopedTools =\n toolChoice && typeof toolChoice === 'object'\n ? tools.filter(\n (tool) => tool.function.name === toolChoice.function.name,\n )\n : tools;\n\n if (scopedTools.length === 0) {\n return undefined;\n }\n\n return scopedTools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.function.name,\n description: tool.function.description,\n parameters: tool.function.parameters || { type: 'object' },\n },\n }));\n }\n\n private buildRuntimeOptions(options: {\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n stop?: string | string[];\n seed?: number;\n }): Record<string, unknown> | undefined {\n const runtimeOptions: Record<string, unknown> = {};\n\n if (typeof options.maxTokens === 'number') {\n runtimeOptions.num_predict = options.maxTokens;\n }\n if (typeof options.temperature === 'number') {\n runtimeOptions.temperature = options.temperature;\n }\n if (typeof options.topP === 'number') {\n runtimeOptions.top_p = options.topP;\n }\n if (options.stop) {\n runtimeOptions.stop = Array.isArray(options.stop)\n ? options.stop\n : [options.stop];\n }\n if (typeof options.seed === 'number') {\n runtimeOptions.seed = options.seed;\n }\n\n return Object.keys(runtimeOptions).length > 0 ? runtimeOptions : undefined;\n }\n\n private mapThink(\n options: Pick<ChatOptions, 'thinkingLevel' | 'reasoning'>,\n ): boolean | string | undefined {\n if (options.reasoning?.maxTokens === 0) {\n return false;\n }\n if (options.reasoning?.effort) {\n return options.reasoning.effort === 'none'\n ? false\n : options.reasoning.effort;\n }\n if (!Object.hasOwn(options, 'thinkingLevel')) {\n return undefined;\n }\n\n return options.thinkingLevel;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n options = normalizeChatOptions(\n this.options,\n options,\n 'ollama',\n options.model || this.options.defaultModel,\n );\n controls = prepareRequestControls(this.options, options);\n const model = await this.resolveModel(\n this.isVisionRequest(messages) ? 'vision' : 'chat',\n options.model,\n );\n\n const response = await this.requestJson<OllamaChatResponse>(\n '/chat',\n {\n model,\n messages: await this.mapMessagesToOllama(messages, controls.signal),\n stream: false,\n format:\n options.responseFormat?.type === 'json_object' ? 'json' : undefined,\n tools: this.mapTools(options.tools, options.toolChoice),\n think: this.mapThink(options),\n keep_alive: this.options.keepAlive,\n options: this.buildRuntimeOptions(options),\n },\n { signal: controls.signal },\n );\n\n const usage = mapUsage(response.prompt_eval_count, response.eval_count);\n\n emitUsage(\n this.options,\n 'ollama',\n 'chat',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n const toolCalls =\n response.message?.tool_calls\n ?.filter((call) => call.function?.name)\n .map((call, index) => ({\n id: `${response.model || model}-tool-${index + 1}`,\n type: 'function' as const,\n function: {\n name: call.function?.name || '',\n arguments: JSON.stringify(call.function?.arguments || {}),\n },\n })) || undefined;\n\n return {\n content: response.message?.content || '',\n model: response.model || model,\n usage,\n finishReason:\n toolCalls && toolCalls.length > 0\n ? 'tool_calls'\n : mapFinishReason(response.done_reason),\n toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n options = normalizeChatOptions(\n this.options,\n options,\n 'ollama',\n options.model || this.options.defaultModel,\n );\n controls = prepareRequestControls(this.options, options);\n const model = await this.resolveModel('chat', options.model);\n const response = await this.requestJson<OllamaGenerateResponse>(\n '/generate',\n {\n model,\n prompt,\n stream: false,\n keep_alive: this.options.keepAlive,\n options: this.buildRuntimeOptions(options),\n },\n { signal: controls.signal },\n );\n\n const usage = mapUsage(response.prompt_eval_count, response.eval_count);\n\n emitUsage(\n this.options,\n 'ollama',\n 'complete',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n content: response.response || '',\n model: response.model || model,\n usage,\n finishReason: mapFinishReason(response.done_reason),\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async message(text: string, options: MessageOptions = {}): Promise<string> {\n const messages: AIMessage[] = [\n ...(options.history || []),\n { role: options.role || 'user', content: text },\n ];\n\n const response = await this.chat(messages, {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n stream: options.stream,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n responseFormat: options.responseFormat,\n seed: options.seed,\n tools: options.tools,\n toolChoice: options.toolChoice,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n });\n\n return response.content;\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n const model = await this.resolveModel('embedding', options.model);\n const input = Array.isArray(text) ? text : [text];\n const response = await this.requestJson<OllamaEmbedResponse>('/embed', {\n model,\n input,\n keep_alive: this.options.keepAlive,\n });\n\n const embeddings =\n response.embeddings ||\n (response.embedding ? [response.embedding] : undefined);\n\n if (!embeddings || embeddings.length === 0) {\n throw new AIError(\n 'Invalid embedding response from Ollama',\n 'INVALID_RESPONSE',\n 'ollama',\n );\n }\n\n const usage = mapUsage(response.prompt_eval_count, 0);\n emitUsage(\n this.options,\n 'ollama',\n 'embed',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n embeddings,\n usage,\n model: response.model || model,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const description = await this.describeImage(\n image,\n 'Describe this image in detail for semantic embedding. Include objects, people, text, setting, colors, composition, and notable visual relationships.',\n );\n\n return this.embed(description, {\n model: options.model,\n dimensions: options.dimensions,\n user: options.user,\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const defaultPrompt =\n 'Describe this image for a search index. Include objects, mood, lighting, and any visible text.';\n\n const imageUrl = await this.imageToDataUrl(image, options.signal);\n const response = await this.chat(\n [\n {\n role: 'user',\n content: [\n {\n type: 'text',\n text: prompt || defaultPrompt,\n },\n {\n type: 'image_url',\n image_url: {\n url: imageUrl,\n detail: options.detail || 'auto',\n },\n },\n ],\n },\n ],\n {\n model: options.model,\n maxTokens: options.maxTokens ?? 500,\n reasoning: options.reasoning || { effort: 'none', maxTokens: 0 },\n signal: options.signal,\n timeout: options.timeout,\n usageTags: options.usageTags,\n },\n );\n\n return response.content;\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n let controls: PreparedRequestControls | undefined;\n try {\n options = normalizeImageGenerationOptions(\n this.options,\n options,\n 'ollama',\n options.model,\n );\n controls = prepareRequestControls(this.options, options);\n if (options.imageInput) {\n throw new AIError(\n 'Ollama image generation does not support imageInput in this adapter yet.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n if (options.outputFormat === 'url') {\n throw new AIError(\n 'Ollama image generation only supports buffer or base64 outputs in this adapter.',\n 'NOT_SUPPORTED',\n 'ollama',\n );\n }\n\n const model = await this.resolveModel('image_generation', options.model);\n const response = await this.requestJson<OllamaImageGenerationResponse>(\n '/images/generations',\n {\n model,\n prompt,\n n: options.n,\n size: options.size || '1024x1024',\n response_format: 'b64_json',\n quality: options.quality,\n style: options.style,\n },\n { compatibility: true, signal: controls.signal },\n );\n\n const images = (response.data || []).map((item) => {\n const b64 = item.b64_json || '';\n return {\n data:\n options.outputFormat === 'base64'\n ? b64\n : Buffer.from(b64, 'base64'),\n mimeType: 'image/png',\n revisedPrompt: item.revised_prompt,\n };\n });\n\n return {\n images,\n model,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n options = normalizeChatOptions(\n this.options,\n options,\n 'ollama',\n options.model || this.options.defaultModel,\n );\n controls = prepareRequestControls(this.options, options);\n const model = await this.resolveModel(\n this.isVisionRequest(messages) ? 'vision' : 'chat',\n options.model,\n );\n\n const response = await this.requestStream(\n '/chat',\n {\n model,\n messages: await this.mapMessagesToOllama(messages, controls.signal),\n stream: true,\n format:\n options.responseFormat?.type === 'json_object' ? 'json' : undefined,\n tools: this.mapTools(options.tools, options.toolChoice),\n think: this.mapThink(options),\n keep_alive: this.options.keepAlive,\n options: this.buildRuntimeOptions(options),\n },\n controls.signal,\n );\n\n let finalUsage: TokenUsage | undefined;\n let finalModel = model;\n\n for await (const chunk of this.parseNdjson<OllamaChatResponse>(\n response,\n )) {\n if (chunk.model) {\n finalModel = chunk.model;\n }\n\n if (\n typeof chunk.message?.content === 'string' &&\n chunk.message.content\n ) {\n if (options.onProgress) {\n options.onProgress(chunk.message.content);\n }\n yield chunk.message.content;\n }\n\n if (chunk.done) {\n finalUsage = mapUsage(chunk.prompt_eval_count, chunk.eval_count);\n }\n }\n\n emitUsage(\n this.options,\n 'ollama',\n 'stream',\n finalModel,\n finalUsage,\n startTime,\n options.usageTags,\n );\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async countTokens(text: string): Promise<number> {\n return Math.ceil(text.length / 4);\n }\n\n async getModels(): Promise<AIModel[]> {\n if (this.modelListPromise) {\n return this.modelListPromise;\n }\n\n this.modelListPromise = (async () => {\n const response = await this.requestJson<OllamaTagsResponse>('/tags');\n const summaries = response.models || [];\n\n return Promise.all(\n summaries.map(async (summary) => {\n const modelId = summary.name || summary.model;\n if (!modelId) {\n throw new AIError(\n 'Ollama returned a model without an identifier',\n 'INVALID_RESPONSE',\n 'ollama',\n );\n }\n\n const show = await this.showModel(modelId);\n const capabilities = parseCapabilities(modelId, show);\n const vision = capabilities.includes('vision');\n const functions = capabilities.includes('functions');\n const parameterSize =\n show?.details?.parameter_size || summary.details?.parameter_size;\n const family = show?.details?.family || summary.details?.family;\n\n return {\n id: modelId,\n name: modelId,\n description:\n parameterSize || family\n ? `${family || 'Ollama'} ${parameterSize || ''}`.trim()\n : `Ollama model: ${modelId}`,\n contextLength: parseContextLength(modelId, show),\n capabilities,\n supportsFunctions: functions,\n supportsVision: vision,\n } satisfies AIModel;\n }),\n );\n })().catch((error) => {\n this.modelListPromise = undefined;\n throw this.mapError(error);\n });\n\n return this.modelListPromise;\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return { ...OLLAMA_CAPABILITIES };\n }\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n}\n"],"names":["line"],"mappings":"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"}