@happyvertical/ai 0.103.4 → 0.103.6

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.
package/README.md CHANGED
@@ -1073,3 +1073,13 @@ npx have-ai-context
1073
1073
  ## License
1074
1074
 
1075
1075
  MIT
1076
+
1077
+ ## JSON schema response formats
1078
+
1079
+ `AIResponseFormat` is exported for chat, completion, legacy OpenAI completion,
1080
+ and message options. OpenAI-compatible providers pass `responseFormat: {
1081
+ type: 'json_schema', json_schema: { name, schema, description?, strict? }
1082
+ }` to the API unchanged. Schema enforcement depends on the selected provider;
1083
+ this type does not add support to providers that do not implement that format.
1084
+ Automatic length continuation is disabled for JSON schema output, as it is for
1085
+ JSON-object output, so truncated structured responses are never concatenated.
@@ -1,5 +1,5 @@
1
1
  import { c as normalizeImageGenerationOptions, s as normalizeChatOptions } from "./usage-DS7uDhi1.js";
2
- import { _ as OpenAIProvider } from "./src-BnMUshQt.js";
2
+ import { _ as OpenAIProvider } from "./src-DBah9G3i.js";
3
3
  import { i as BifrostAdmin, n as isSpeechModel, o as normalizeGatewayBaseUrl, r as isTranscriptionModel, s as resolveGatewayAdminBaseUrl, t as isAudioModel } from "./gateway-audio-models-DuXbi_2q.js";
4
4
  import { ValidationError } from "@happyvertical/utils";
5
5
  //#region src/shared/providers/bifrost.ts
@@ -199,4 +199,4 @@ var BifrostProvider = class extends OpenAIProvider {
199
199
  //#endregion
200
200
  export { BifrostProvider };
201
201
 
202
- //# sourceMappingURL=bifrost-DZxTeE1Q.js.map
202
+ //# sourceMappingURL=bifrost-BPQ0aL1i.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bifrost-DZxTeE1Q.js","names":[],"sources":["../../src/shared/providers/bifrost.ts"],"sourcesContent":["import { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n} from '../safety';\nimport type {\n AICapabilities,\n AIMessage,\n AIModel,\n AIResponse,\n BifrostOptions,\n ChatOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n} from '../types';\nimport {\n BifrostAdmin,\n normalizeGatewayBaseUrl,\n resolveGatewayAdminBaseUrl,\n} from './gateway-admin';\nimport {\n isAudioModel,\n isSpeechModel,\n isTranscriptionModel,\n} from './gateway-audio-models';\nimport { type OpenAICompatibleProfile, OpenAIProvider } from './openai';\n\nconst BIFROST_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 videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 128000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /embed/i.test(modelId);\n}\n\nfunction isImageEmbeddingModel(modelId: string): boolean {\n return /titan-embed-image|multimodalembedding|image[-_]?embed|clip/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(\n modelId,\n );\n}\n\nfunction isFilteredBifrostModel(modelId: string): boolean {\n return /moderation|rerank/i.test(modelId);\n}\n\nfunction inferBifrostContextLength(modelId: string): number {\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemini-1\\.5|gemini-2\\.0|gemini-2\\.5|gemini-3/i.test(modelId)) {\n return 1000000;\n }\n if (/claude/i.test(modelId)) return 200000;\n if (/gpt-4o|gpt-4\\.1|o1|o3|o4|llama|mistral|qwen|deepseek/i.test(modelId)) {\n return 128000;\n }\n return 32768;\n}\n\nfunction inferBifrostFunctions(modelId: string): boolean {\n if (isEmbeddingModel(modelId) || isAudioModel(modelId)) return false;\n return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostVision(modelId: string): boolean {\n if (isAudioModel(modelId)) return false;\n return /gpt-4o|gpt-4\\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostCapabilities(modelId: string): string[] {\n if (isTranscriptionModel(modelId)) {\n return ['transcription'];\n }\n\n if (isSpeechModel(modelId)) {\n return ['speech'];\n }\n\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (isImageEmbeddingModel(modelId)) {\n return ['embeddings', 'image_embedding'];\n }\n\n if (isEmbeddingModel(modelId)) {\n return ['embeddings'];\n }\n\n const capabilities = ['text', 'chat'];\n\n if (inferBifrostFunctions(modelId)) {\n capabilities.push('functions');\n }\n\n if (inferBifrostVision(modelId)) {\n capabilities.push('vision');\n }\n\n return capabilities;\n}\n\nfunction ensureBifrostOptions(options: BifrostOptions): BifrostOptions {\n if (!options.baseUrl?.trim()) {\n throw new ValidationError('Bifrost baseUrl is required', {\n provider: 'bifrost',\n hint: 'Pass baseUrl like http://localhost:8080, http://localhost:8080/openai, or http://localhost:8080/v1 and optionally adminBaseUrl for governance endpoints',\n });\n }\n\n const baseUrl = normalizeGatewayBaseUrl(options.baseUrl);\n const inferenceBaseUrl = /\\/(?:openai|v1|pydanticai\\/v1)$/.test(baseUrl)\n ? baseUrl\n : `${baseUrl}/openai`;\n const headers = options.apiKey\n ? {\n ...options.headers,\n 'x-bf-vk': options.apiKey,\n 'x-api-key': options.apiKey,\n }\n : options.headers;\n\n return {\n ...options,\n baseUrl: inferenceBaseUrl,\n headers,\n };\n}\n\nconst BIFROST_PROFILE: OpenAICompatibleProfile = {\n providerLabel: 'Bifrost',\n providerName: 'bifrost',\n defaultModel: 'openai/gpt-4o-mini',\n capabilities: BIFROST_CAPABILITIES,\n describeModel: (modelId) => `Bifrost model: ${modelId}`,\n getContextLength: inferBifrostContextLength,\n getModelCapabilities: inferBifrostCapabilities,\n shouldIncludeModel: (modelId) => !isFilteredBifrostModel(modelId),\n supportsFunctions: inferBifrostFunctions,\n supportsVision: inferBifrostVision,\n};\n\ntype BifrostResolvedCapability =\n | 'chat'\n | 'vision'\n | 'embeddings'\n | 'image_generation';\n\nfunction supportsCapability(\n model: AIModel,\n capability: BifrostResolvedCapability,\n): boolean {\n if (capability === 'vision') {\n return (\n model.capabilities.includes('vision') || model.supportsVision === true\n );\n }\n\n if (capability === 'embeddings') {\n return model.capabilities.includes('embeddings');\n }\n\n if (capability === 'image_generation') {\n return model.capabilities.includes('image_generation');\n }\n\n return model.capabilities.includes('chat');\n}\n\n/**\n * Bifrost provider implementation.\n *\n * Bifrost exposes OpenAI-compatible inference and governance admin APIs. This\n * provider reuses the OpenAI-compatible transport for inference and exposes\n * `admin` for tenant project and virtual-key provisioning.\n */\nexport class BifrostProvider extends OpenAIProvider {\n readonly admin: BifrostAdmin;\n private readonly configuredDefaultModel?: string;\n private readonly resolvedModelCache = new Map<\n BifrostResolvedCapability,\n Promise<string>\n >();\n\n constructor(options: BifrostOptions) {\n const normalized = ensureBifrostOptions(options);\n super(normalized, BIFROST_PROFILE);\n const adminKey = normalized.adminApiKey || normalized.apiKey;\n const adminUsername = normalized.adminUser || normalized.adminUsername;\n this.admin = new BifrostAdmin({\n provider: 'bifrost',\n baseUrl: resolveGatewayAdminBaseUrl(\n normalized.baseUrl,\n normalized.adminUrl || normalized.adminBaseUrl,\n 'bifrost',\n ),\n apiKey: adminKey,\n username: adminUsername,\n password: normalized.adminPassword,\n headers:\n adminKey && !(adminUsername && normalized.adminPassword)\n ? {\n ...normalized.adminHeaders,\n 'x-bf-vk': adminKey,\n 'x-api-key': adminKey,\n }\n : normalized.adminHeaders,\n timeout: normalized.timeout,\n });\n this.configuredDefaultModel = normalized.defaultModel;\n }\n\n private async resolveModel(\n capability: BifrostResolvedCapability,\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: BifrostResolvedCapability,\n ): Promise<string> {\n const models = await super.getModels();\n const model = models.find((candidate) =>\n supportsCapability(candidate, capability),\n );\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the Bifrost gateway`,\n {\n provider: 'bifrost',\n capability,\n hint: 'Pass defaultModel explicitly or ensure the gateway returns a compatible model for this key',\n },\n );\n }\n\n return model.id;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.chat(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n yield* super.stream(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.describeImage(image, prompt, {\n ...safe,\n model: await this.resolveModel('vision', safe.model),\n });\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embed(text, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embedImage(image, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n const safe = normalizeImageGenerationOptions(\n this.options,\n options,\n 'bifrost',\n options.model,\n );\n return super.generateImage(prompt, {\n ...safe,\n model: await this.resolveModel('image_generation', safe.model),\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bifrost-BPQ0aL1i.js","names":[],"sources":["../../src/shared/providers/bifrost.ts"],"sourcesContent":["import { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n} from '../safety';\nimport type {\n AICapabilities,\n AIMessage,\n AIModel,\n AIResponse,\n BifrostOptions,\n ChatOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n} from '../types';\nimport {\n BifrostAdmin,\n normalizeGatewayBaseUrl,\n resolveGatewayAdminBaseUrl,\n} from './gateway-admin';\nimport {\n isAudioModel,\n isSpeechModel,\n isTranscriptionModel,\n} from './gateway-audio-models';\nimport { type OpenAICompatibleProfile, OpenAIProvider } from './openai';\n\nconst BIFROST_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 videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 128000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /embed/i.test(modelId);\n}\n\nfunction isImageEmbeddingModel(modelId: string): boolean {\n return /titan-embed-image|multimodalembedding|image[-_]?embed|clip/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(\n modelId,\n );\n}\n\nfunction isFilteredBifrostModel(modelId: string): boolean {\n return /moderation|rerank/i.test(modelId);\n}\n\nfunction inferBifrostContextLength(modelId: string): number {\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemini-1\\.5|gemini-2\\.0|gemini-2\\.5|gemini-3/i.test(modelId)) {\n return 1000000;\n }\n if (/claude/i.test(modelId)) return 200000;\n if (/gpt-4o|gpt-4\\.1|o1|o3|o4|llama|mistral|qwen|deepseek/i.test(modelId)) {\n return 128000;\n }\n return 32768;\n}\n\nfunction inferBifrostFunctions(modelId: string): boolean {\n if (isEmbeddingModel(modelId) || isAudioModel(modelId)) return false;\n return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostVision(modelId: string): boolean {\n if (isAudioModel(modelId)) return false;\n return /gpt-4o|gpt-4\\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostCapabilities(modelId: string): string[] {\n if (isTranscriptionModel(modelId)) {\n return ['transcription'];\n }\n\n if (isSpeechModel(modelId)) {\n return ['speech'];\n }\n\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (isImageEmbeddingModel(modelId)) {\n return ['embeddings', 'image_embedding'];\n }\n\n if (isEmbeddingModel(modelId)) {\n return ['embeddings'];\n }\n\n const capabilities = ['text', 'chat'];\n\n if (inferBifrostFunctions(modelId)) {\n capabilities.push('functions');\n }\n\n if (inferBifrostVision(modelId)) {\n capabilities.push('vision');\n }\n\n return capabilities;\n}\n\nfunction ensureBifrostOptions(options: BifrostOptions): BifrostOptions {\n if (!options.baseUrl?.trim()) {\n throw new ValidationError('Bifrost baseUrl is required', {\n provider: 'bifrost',\n hint: 'Pass baseUrl like http://localhost:8080, http://localhost:8080/openai, or http://localhost:8080/v1 and optionally adminBaseUrl for governance endpoints',\n });\n }\n\n const baseUrl = normalizeGatewayBaseUrl(options.baseUrl);\n const inferenceBaseUrl = /\\/(?:openai|v1|pydanticai\\/v1)$/.test(baseUrl)\n ? baseUrl\n : `${baseUrl}/openai`;\n const headers = options.apiKey\n ? {\n ...options.headers,\n 'x-bf-vk': options.apiKey,\n 'x-api-key': options.apiKey,\n }\n : options.headers;\n\n return {\n ...options,\n baseUrl: inferenceBaseUrl,\n headers,\n };\n}\n\nconst BIFROST_PROFILE: OpenAICompatibleProfile = {\n providerLabel: 'Bifrost',\n providerName: 'bifrost',\n defaultModel: 'openai/gpt-4o-mini',\n capabilities: BIFROST_CAPABILITIES,\n describeModel: (modelId) => `Bifrost model: ${modelId}`,\n getContextLength: inferBifrostContextLength,\n getModelCapabilities: inferBifrostCapabilities,\n shouldIncludeModel: (modelId) => !isFilteredBifrostModel(modelId),\n supportsFunctions: inferBifrostFunctions,\n supportsVision: inferBifrostVision,\n};\n\ntype BifrostResolvedCapability =\n | 'chat'\n | 'vision'\n | 'embeddings'\n | 'image_generation';\n\nfunction supportsCapability(\n model: AIModel,\n capability: BifrostResolvedCapability,\n): boolean {\n if (capability === 'vision') {\n return (\n model.capabilities.includes('vision') || model.supportsVision === true\n );\n }\n\n if (capability === 'embeddings') {\n return model.capabilities.includes('embeddings');\n }\n\n if (capability === 'image_generation') {\n return model.capabilities.includes('image_generation');\n }\n\n return model.capabilities.includes('chat');\n}\n\n/**\n * Bifrost provider implementation.\n *\n * Bifrost exposes OpenAI-compatible inference and governance admin APIs. This\n * provider reuses the OpenAI-compatible transport for inference and exposes\n * `admin` for tenant project and virtual-key provisioning.\n */\nexport class BifrostProvider extends OpenAIProvider {\n readonly admin: BifrostAdmin;\n private readonly configuredDefaultModel?: string;\n private readonly resolvedModelCache = new Map<\n BifrostResolvedCapability,\n Promise<string>\n >();\n\n constructor(options: BifrostOptions) {\n const normalized = ensureBifrostOptions(options);\n super(normalized, BIFROST_PROFILE);\n const adminKey = normalized.adminApiKey || normalized.apiKey;\n const adminUsername = normalized.adminUser || normalized.adminUsername;\n this.admin = new BifrostAdmin({\n provider: 'bifrost',\n baseUrl: resolveGatewayAdminBaseUrl(\n normalized.baseUrl,\n normalized.adminUrl || normalized.adminBaseUrl,\n 'bifrost',\n ),\n apiKey: adminKey,\n username: adminUsername,\n password: normalized.adminPassword,\n headers:\n adminKey && !(adminUsername && normalized.adminPassword)\n ? {\n ...normalized.adminHeaders,\n 'x-bf-vk': adminKey,\n 'x-api-key': adminKey,\n }\n : normalized.adminHeaders,\n timeout: normalized.timeout,\n });\n this.configuredDefaultModel = normalized.defaultModel;\n }\n\n private async resolveModel(\n capability: BifrostResolvedCapability,\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: BifrostResolvedCapability,\n ): Promise<string> {\n const models = await super.getModels();\n const model = models.find((candidate) =>\n supportsCapability(candidate, capability),\n );\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the Bifrost gateway`,\n {\n provider: 'bifrost',\n capability,\n hint: 'Pass defaultModel explicitly or ensure the gateway returns a compatible model for this key',\n },\n );\n }\n\n return model.id;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.chat(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n yield* super.stream(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.describeImage(image, prompt, {\n ...safe,\n model: await this.resolveModel('vision', safe.model),\n });\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embed(text, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embedImage(image, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n const safe = normalizeImageGenerationOptions(\n this.options,\n options,\n 'bifrost',\n options.model,\n );\n return super.generateImage(prompt, {\n ...safe,\n model: await this.resolveModel('image_generation', safe.model),\n });\n }\n}\n"],"mappings":";;;;;AAgCA,IAAM,uBAAuC;CAC3C,MAAM;CACN,YAAY;CACZ,YAAY;CACZ,WAAW;CACX,WAAW;CACX,QAAQ;CACR,YAAY;CACZ,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,KAAK;CACL,cAAc;CACd,aAAa;CACb,kBAAkB;CAClB,qBAAqB;EACnB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,SAAS,iBAAiB,SAA0B;CAClD,OAAO,SAAS,KAAK,OAAO;AAC9B;AAEA,SAAS,sBAAsB,SAA0B;CACvD,OAAO,8DAA8D,KACnE,OACF;AACF;AAEA,SAAS,uBAAuB,SAA0B;CACxD,OAAO,sFAAsF,KAC3F,OACF;AACF;AAEA,SAAS,uBAAuB,SAA0B;CACxD,OAAO,qBAAqB,KAAK,OAAO;AAC1C;AAEA,SAAS,0BAA0B,SAAyB;CAC1D,IAAI,iBAAiB,OAAO,GAAG,OAAO;CACtC,IAAI,gDAAgD,KAAK,OAAO,GAC9D,OAAO;CAET,IAAI,UAAU,KAAK,OAAO,GAAG,OAAO;CACpC,IAAI,wDAAwD,KAAK,OAAO,GACtE,OAAO;CAET,OAAO;AACT;AAEA,SAAS,sBAAsB,SAA0B;CACvD,IAAI,iBAAiB,OAAO,KAAK,aAAa,OAAO,GAAG,OAAO;CAC/D,OAAO,kEAAkE,KACvE,OACF;AACF;AAEA,SAAS,mBAAmB,SAA0B;CACpD,IAAI,aAAa,OAAO,GAAG,OAAO;CAClC,OAAO,qEAAqE,KAC1E,OACF;AACF;AAEA,SAAS,yBAAyB,SAA2B;CAC3D,IAAI,qBAAqB,OAAO,GAC9B,OAAO,CAAC,eAAe;CAGzB,IAAI,cAAc,OAAO,GACvB,OAAO,CAAC,QAAQ;CAGlB,IAAI,uBAAuB,OAAO,GAChC,OAAO,CAAC,kBAAkB;CAG5B,IAAI,sBAAsB,OAAO,GAC/B,OAAO,CAAC,cAAc,iBAAiB;CAGzC,IAAI,iBAAiB,OAAO,GAC1B,OAAO,CAAC,YAAY;CAGtB,MAAM,eAAe,CAAC,QAAQ,MAAM;CAEpC,IAAI,sBAAsB,OAAO,GAC/B,aAAa,KAAK,WAAW;CAG/B,IAAI,mBAAmB,OAAO,GAC5B,aAAa,KAAK,QAAQ;CAG5B,OAAO;AACT;AAEA,SAAS,qBAAqB,SAAyC;CACrE,IAAI,CAAC,QAAQ,SAAS,KAAK,GACzB,MAAM,IAAI,gBAAgB,+BAA+B;EACvD,UAAU;EACV,MAAM;CACR,CAAC;CAGH,MAAM,UAAU,wBAAwB,QAAQ,OAAO;CACvD,MAAM,mBAAmB,kCAAkC,KAAK,OAAO,IACnE,UACA,GAAG,QAAQ;CACf,MAAM,UAAU,QAAQ,SACpB;EACE,GAAG,QAAQ;EACX,WAAW,QAAQ;EACnB,aAAa,QAAQ;CACvB,IACA,QAAQ;CAEZ,OAAO;EACL,GAAG;EACH,SAAS;EACT;CACF;AACF;AAEA,IAAM,kBAA2C;CAC/C,eAAe;CACf,cAAc;CACd,cAAc;CACd,cAAc;CACd,gBAAgB,YAAY,kBAAkB;CAC9C,kBAAkB;CAClB,sBAAsB;CACtB,qBAAqB,YAAY,CAAC,uBAAuB,OAAO;CAChE,mBAAmB;CACnB,gBAAgB;AAClB;AAQA,SAAS,mBACP,OACA,YACS;CACT,IAAI,eAAe,UACjB,OACE,MAAM,aAAa,SAAS,QAAQ,KAAK,MAAM,mBAAmB;CAItE,IAAI,eAAe,cACjB,OAAO,MAAM,aAAa,SAAS,YAAY;CAGjD,IAAI,eAAe,oBACjB,OAAO,MAAM,aAAa,SAAS,kBAAkB;CAGvD,OAAO,MAAM,aAAa,SAAS,MAAM;AAC3C;;;;;;;;AASA,IAAa,kBAAb,cAAqC,eAAe;CAClD;CACA;CACA,qCAAsC,IAAI,IAGxC;CAEF,YAAY,SAAyB;EACnC,MAAM,aAAa,qBAAqB,OAAO;EAC/C,MAAM,YAAY,eAAe;EACjC,MAAM,WAAW,WAAW,eAAe,WAAW;EACtD,MAAM,gBAAgB,WAAW,aAAa,WAAW;EACzD,KAAK,QAAQ,IAAI,aAAa;GAC5B,UAAU;GACV,SAAS,2BACP,WAAW,SACX,WAAW,YAAY,WAAW,cAClC,SACF;GACA,QAAQ;GACR,UAAU;GACV,UAAU,WAAW;GACrB,SACE,YAAY,EAAE,iBAAiB,WAAW,iBACtC;IACE,GAAG,WAAW;IACd,WAAW;IACX,aAAa;GACf,IACA,WAAW;GACjB,SAAS,WAAW;EACtB,CAAC;EACD,KAAK,yBAAyB,WAAW;CAC3C;CAEA,MAAc,aACZ,YACA,eACiB;EACjB,IAAI,eACF,OAAO;EAGT,IACE,KAAK,2BACJ,eAAe,UAAU,eAAe,WAEzC,OAAO,KAAK;EAGd,MAAM,SAAS,KAAK,mBAAmB,IAAI,UAAU;EACrD,IAAI,QACF,OAAO;EAGT,MAAM,UAAU,KAAK,YAAY,UAAU,CAAC,CAAC,OAAO,UAAU;GAC5D,KAAK,mBAAmB,OAAO,UAAU;GACzC,MAAM;EACR,CAAC;EACD,KAAK,mBAAmB,IAAI,YAAY,OAAO;EAC/C,OAAO;CACT;CAEA,MAAc,YACZ,YACiB;EAEjB,MAAM,SAAQ,MADO,MAAM,UAAU,EAAA,CAChB,MAAM,cACzB,mBAAmB,WAAW,UAAU,CAC1C;EAEA,IAAI,CAAC,OACH,MAAM,IAAI,gBACR,MAAM,WAAW,+CACjB;GACE,UAAU;GACV;GACA,MAAM;EACR,CACF;EAGF,OAAO,MAAM;CACf;CAEA,MAAM,KACJ,UACA,UAAuB,CAAC,GACH;EACrB,MAAM,OAAO,qBACX,KAAK,SACL,SACA,WACA,QAAQ,SAAS,KAAK,QAAQ,YAChC;EACA,OAAO,MAAM,KAAK,UAAU;GAC1B,GAAG;GACH,OAAO,MAAM,KAAK,aAAa,QAAQ,KAAK,KAAK;EACnD,CAAC;CACH;CAEA,OAAO,OACL,UACA,UAAuB,CAAC,GACD;EACvB,MAAM,OAAO,qBACX,KAAK,SACL,SACA,WACA,QAAQ,SAAS,KAAK,QAAQ,YAChC;EACA,OAAO,MAAM,OAAO,UAAU;GAC5B,GAAG;GACH,OAAO,MAAM,KAAK,aAAa,QAAQ,KAAK,KAAK;EACnD,CAAC;CACH;CAEA,MAAM,cACJ,OACA,QACA,UAAmC,CAAC,GACnB;EACjB,MAAM,OAAO,qBACX,KAAK,SACL,SACA,WACA,QAAQ,SAAS,KAAK,QAAQ,YAChC;EACA,OAAO,MAAM,cAAc,OAAO,QAAQ;GACxC,GAAG;GACH,OAAO,MAAM,KAAK,aAAa,UAAU,KAAK,KAAK;EACrD,CAAC;CACH;CAEA,MAAM,MACJ,MACA,UAA4B,CAAC,GACD;EAC5B,OAAO,MAAM,MAAM,MAAM;GACvB,GAAG;GACH,OAAO,MAAM,KAAK,aAAa,cAAc,QAAQ,KAAK;EAC5D,CAAC;CACH;CAEA,MAAM,WACJ,OACA,UAAiC,CAAC,GACN;EAC5B,OAAO,MAAM,WAAW,OAAO;GAC7B,GAAG;GACH,OAAO,MAAM,KAAK,aAAa,cAAc,QAAQ,KAAK;EAC5D,CAAC;CACH;CAEA,MAAM,cACJ,QACA,UAAkC,CAAC,GACD;EAClC,MAAM,OAAO,gCACX,KAAK,SACL,SACA,WACA,QAAQ,KACV;EACA,OAAO,MAAM,cAAc,QAAQ;GACjC,GAAG;GACH,OAAO,MAAM,KAAK,aAAa,oBAAoB,KAAK,KAAK;EAC/D,CAAC;CACH;AACF"}
@@ -12,7 +12,7 @@ var CONTINUE_PROMPT = "Continue exactly where you stopped. Do not repeat anythin
12
12
  function resolveContinuation(providerOptions, options) {
13
13
  const setting = options.continueOnLength ?? providerOptions.continueOnLength;
14
14
  if (!setting) return void 0;
15
- if (options.tools?.length || options.responseFormat?.type === "json_object" || options.responseSchema) return;
15
+ if (options.tools?.length || options.responseFormat?.type === "json_object" || options.responseFormat?.type === "json_schema" || options.responseSchema) return;
16
16
  const requested = typeof setting === "object" ? setting.maxContinuations ?? 3 : 3;
17
17
  if (!Number.isFinite(requested) || requested < 0) throw new AIError("continueOnLength.maxContinuations must be a non-negative finite number", "AI_LIMIT_INVALID");
18
18
  const maxContinuations = Math.trunc(requested);
@@ -206,4 +206,4 @@ function createContinuingAI(client, providerOptions, adapter = client) {
206
206
  //#endregion
207
207
  export { resolveContinuation as n, createContinuingAI as t };
208
208
 
209
- //# sourceMappingURL=continuation-KdrnmvzP.js.map
209
+ //# sourceMappingURL=continuation-BMGvMlzq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"continuation-BMGvMlzq.js","names":[],"sources":["../../src/shared/continuation.ts"],"sourcesContent":["import type {\n AIFinishReason,\n AIInterface,\n AIMessage,\n AIResponse,\n BaseAIOptions,\n ChatOptions,\n ContinueOnLengthOption,\n TokenUsage,\n} from './types';\nimport { AIError } from './types';\n\n/** Default number of extra requests allowed after the first one. */\nexport const DEFAULT_MAX_CONTINUATIONS = 3;\n\n/** Shortest seam overlap (in characters) that is trimmed as a repeat. */\nconst MIN_OVERLAP = 12;\n/** Longest seam overlap (in characters) that is searched for. */\nconst MAX_OVERLAP = 400;\n\nexport const CONTINUE_PROMPT =\n 'Continue exactly where you stopped. Do not repeat anything you already wrote and do not add an introduction.';\n\ninterface ResolvedContinuation {\n maxContinuations: number;\n}\n\n/**\n * Resolve the per-call option over the client default. Returns undefined when\n * continuation is off. Structured output and tool use never continue because\n * stitching two JSON documents or tool-call turns is not safe.\n */\nexport function resolveContinuation(\n providerOptions: BaseAIOptions,\n options: Pick<ChatOptions, 'tools' | 'responseFormat' | 'responseSchema'> & {\n continueOnLength?: ContinueOnLengthOption;\n },\n): ResolvedContinuation | undefined {\n const setting = options.continueOnLength ?? providerOptions.continueOnLength;\n if (!setting) return undefined;\n if (\n options.tools?.length ||\n options.responseFormat?.type === 'json_object' ||\n options.responseFormat?.type === 'json_schema' ||\n options.responseSchema\n ) {\n return undefined;\n }\n const requested =\n typeof setting === 'object'\n ? (setting.maxContinuations ?? DEFAULT_MAX_CONTINUATIONS)\n : DEFAULT_MAX_CONTINUATIONS;\n if (!Number.isFinite(requested) || requested < 0) {\n throw new AIError(\n 'continueOnLength.maxContinuations must be a non-negative finite number',\n 'AI_LIMIT_INVALID',\n );\n }\n const maxContinuations = Math.trunc(requested);\n return maxContinuations > 0 ? { maxContinuations } : undefined;\n}\n\n/**\n * Continuation replies usually start without a leading space. When the text\n * so far ends a sentence and the addition starts a new one, add the space the\n * model dropped at the seam (\"over.\" + \"Next\" -> \"over. Next\"). Only a capital\n * letter or an opening quote/bracket counts as a new sentence, so a word or\n * number split across parts (\"exam\" + \"ple\", \"1.\" + \"5\") is left joined.\n */\nfunction spaceSeam(accumulated: string, addition: string): string {\n if (!addition || /\\s$/.test(accumulated) || /^\\s/.test(addition)) {\n return addition;\n }\n return /[.!?:;][\"')\\]\\u201d\\u2019]?$/.test(accumulated) &&\n /^[\\p{Lu}\"'([\\u201c\\u2018]/u.test(addition)\n ? ` ${addition}`\n : addition;\n}\n\n/**\n * The text to append after `accumulated`: `next` minus any leading run that\n * repeats the end of `accumulated`. Whitespace already emitted is kept, and a\n * dropped space between sentences is restored.\n */\nexport function continuationAddition(\n accumulated: string,\n next: string,\n): string {\n const tail = accumulated.trimEnd();\n const head = next.trimStart();\n const max = Math.min(tail.length, head.length, MAX_OVERLAP);\n for (let length = max; length >= MIN_OVERLAP; length--) {\n if (tail.endsWith(head.slice(0, length))) {\n return spaceSeam(accumulated, head.slice(length));\n }\n }\n return spaceSeam(accumulated, next);\n}\n\nfunction continuationMessages(\n messages: AIMessage[],\n accumulated: string,\n): AIMessage[] {\n return [\n ...messages,\n // Some providers reject an assistant turn that ends in whitespace.\n { role: 'assistant', content: accumulated.trimEnd() },\n { role: 'user', content: CONTINUE_PROMPT },\n ];\n}\n\n/** Do not start another (billed) part once the caller has aborted. */\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new AIError('AI request aborted by caller', 'AI_ABORTED');\n }\n}\n\nfunction addUsage(\n a: TokenUsage | undefined,\n b: TokenUsage | undefined,\n): TokenUsage | undefined {\n if (!a) return b;\n if (!b) return a;\n return {\n promptTokens: a.promptTokens + b.promptTokens,\n completionTokens: a.completionTokens + b.completionTokens,\n totalTokens: a.totalTokens + b.totalTokens,\n };\n}\n\n/**\n * Run a chat call and, when the reply stopped on the output limit, keep asking\n * the model to continue and stitch the pieces together.\n */\nexport async function chatWithContinuation(\n chat: (messages: AIMessage[], options?: ChatOptions) => Promise<AIResponse>,\n providerOptions: BaseAIOptions,\n messages: AIMessage[],\n options: ChatOptions & { continueOnLength?: ContinueOnLengthOption } = {},\n): Promise<AIResponse> {\n const config = resolveContinuation(providerOptions, options);\n const first = await chat(messages, options);\n const hitLimit = (response: AIResponse) =>\n response.finishReason === 'length' && !response.toolCalls?.length;\n\n // A first part with no text (reasoning used the whole budget) has nothing to\n // continue from, and providers reject an empty assistant turn.\n if (!config || !hitLimit(first) || !first.content.trim()) {\n return first.finishReason === 'length'\n ? { ...first, truncated: true }\n : first;\n }\n\n // Parts after the first are deduplicated, so progress is reported once with\n // the stitched text instead of with each raw chunk.\n const { onProgress, ...partOptions } = options;\n let content = first.content;\n let usage = first.usage;\n let last = first;\n let parts = 1;\n\n while (parts <= config.maxContinuations && hitLimit(last)) {\n throwIfAborted(options.signal);\n const next = await chat(continuationMessages(messages, content), {\n ...partOptions,\n stream: false,\n });\n parts++;\n usage = addUsage(usage, next.usage);\n last = next;\n const addition = continuationAddition(content, next.content);\n if (!addition) break; // no new text: stop looping\n content += addition;\n if (onProgress) onProgress(addition);\n }\n\n return {\n ...last,\n content,\n usage,\n model: last.model ?? first.model,\n parts,\n truncated: hitLimit(last),\n };\n}\n\n/**\n * Stream a reply across continuations as one continuous stream. A continuation\n * part's first characters are held back briefly so a repeated seam can be\n * trimmed before it reaches the consumer.\n */\nexport async function* streamWithContinuation(\n stream: (\n messages: AIMessage[],\n options?: ChatOptions,\n ) => AsyncIterable<string>,\n providerOptions: BaseAIOptions,\n messages: AIMessage[],\n options: ChatOptions & { continueOnLength?: ContinueOnLengthOption } = {},\n): AsyncIterable<string> {\n const config = resolveContinuation(providerOptions, options);\n if (!config) {\n yield* stream(messages, options);\n return;\n }\n\n const { onProgress, onFinishReason, ...rest } = options;\n let accumulated = '';\n // Reported once, for the last part: an earlier part's 'length' is not the\n // reply's finish reason.\n let reason: AIFinishReason = 'stop';\n for (let part = 0; part <= config.maxContinuations; part++) {\n const finish: { reason?: AIFinishReason } = {};\n const partOptions: ChatOptions = {\n ...rest,\n onFinishReason: (value) => {\n finish.reason = value;\n },\n };\n if (part > 0) throwIfAborted(options.signal);\n const source = stream(\n part === 0 ? messages : continuationMessages(messages, accumulated),\n partOptions,\n );\n let pending = '';\n let seam = part > 0;\n const emit = (text: string) => {\n if (!text) return null;\n accumulated += text;\n onProgress?.(text);\n return text;\n };\n for await (const chunk of source) {\n if (!seam) {\n const out = emit(chunk);\n if (out) yield out;\n continue;\n }\n pending += chunk;\n if (pending.length >= MAX_OVERLAP + MIN_OVERLAP) {\n seam = false;\n const out = emit(continuationAddition(accumulated, pending));\n if (out) yield out;\n pending = '';\n }\n }\n if (seam && pending) {\n const out = emit(continuationAddition(accumulated, pending));\n if (out) yield out;\n }\n reason = finish.reason ?? 'stop';\n // Stop unless the part hit the limit and there is text to continue from\n // (see chatWithContinuation).\n if (reason !== 'length' || !accumulated.trim()) break;\n }\n onFinishReason?.(reason);\n}\n\n/**\n * Wrap a provider so chat, complete, message and stream continue replies that\n * stop on the output limit. Continuation is off unless the call (or the\n * client's `continueOnLength` option) enables it.\n *\n * `client` is what each request goes through, normally the rate-limited\n * provider, so every continuation part is paced and retried on its own and a\n * rate-limit retry on part N never re-requests parts 1..N-1. `adapter` is the\n * unwrapped provider: a continued `complete`/`message` runs the adapter's own\n * method against this proxy so its internal `this.chat` reaches the continuing\n * (and per-part paced) chat instead of being paced as one opaque call.\n */\nexport function createContinuingAI<T extends AIInterface>(\n client: T,\n providerOptions: BaseAIOptions,\n adapter: AIInterface = client,\n): T {\n const wrapped = new Map<PropertyKey, unknown>();\n const proxy: T = new Proxy(client, {\n get(target, property) {\n const value = Reflect.get(target, property, target);\n if (typeof value !== 'function') return value;\n if (!wrapped.has(property)) {\n let fn: unknown;\n switch (property) {\n case 'chat':\n fn = (messages: AIMessage[], options?: ChatOptions) =>\n chatWithContinuation(\n (m, o) => value.call(target, m, o),\n providerOptions,\n messages,\n options,\n );\n break;\n case 'stream':\n fn = (messages: AIMessage[], options?: ChatOptions) =>\n streamWithContinuation(\n (m, o) => value.call(target, m, o),\n providerOptions,\n messages,\n options,\n );\n break;\n case 'complete':\n case 'message':\n fn = (...args: unknown[]) => {\n const options = (args[1] ?? {}) as Parameters<\n typeof resolveContinuation\n >[1];\n if (!resolveContinuation(providerOptions, options)) {\n return value.apply(target, args);\n }\n // Adapters implement these through this.chat, so run the\n // adapter's method against the proxy to reach the continuing\n // chat().\n const own = Reflect.get(adapter, property, adapter) as (\n ...a: unknown[]\n ) => unknown;\n return own.apply(proxy, args);\n };\n break;\n default:\n fn = value.bind(target);\n }\n wrapped.set(property, fn);\n }\n return wrapped.get(property);\n },\n });\n return proxy;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { c as normalizeImageGenerationOptions, s as normalizeChatOptions } from "./usage-DS7uDhi1.js";
2
- import { _ as OpenAIProvider } from "./src-BnMUshQt.js";
2
+ import { _ as OpenAIProvider } from "./src-DBah9G3i.js";
3
3
  import { a as LiteLLMAdmin, n as isSpeechModel, r as isTranscriptionModel, s as resolveGatewayAdminBaseUrl, t as isAudioModel } from "./gateway-audio-models-DuXbi_2q.js";
4
4
  import { ValidationError } from "@happyvertical/utils";
5
5
  //#region src/shared/providers/litellm.ts
@@ -194,4 +194,4 @@ var LiteLLMProvider = class extends OpenAIProvider {
194
194
  //#endregion
195
195
  export { LiteLLMProvider };
196
196
 
197
- //# sourceMappingURL=litellm-8k7PMuh_.js.map
197
+ //# sourceMappingURL=litellm-C5Ek8B0K.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"litellm-8k7PMuh_.js","names":[],"sources":["../../src/shared/providers/litellm.ts"],"sourcesContent":["import { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n} from '../safety';\nimport type {\n AICapabilities,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n LiteLLMOptions,\n} from '../types';\nimport { LiteLLMAdmin, resolveGatewayAdminBaseUrl } from './gateway-admin';\nimport {\n isAudioModel,\n isSpeechModel,\n isTranscriptionModel,\n} from './gateway-audio-models';\nimport { type OpenAICompatibleProfile, OpenAIProvider } from './openai';\n\n/** Chat Completions has effort, not a generic reasoning budget/thoughts envelope. */\nfunction assertChatReasoningControls(\n options: Pick<ChatOptions, 'reasoning' | 'includeThoughts'>,\n): void {\n if (\n options.reasoning?.maxTokens !== undefined ||\n options.reasoning?.includeThoughts !== undefined ||\n options.includeThoughts !== undefined\n ) {\n throw new ValidationError(\n 'LiteLLM Chat Completions does not support generic reasoning.maxTokens or includeThoughts controls; use reasoning.effort and an output token limit',\n { provider: 'litellm' },\n );\n }\n}\n\nconst LITELLM_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 videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 128000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /embed/i.test(modelId);\n}\n\nfunction isImageEmbeddingModel(modelId: string): boolean {\n return /titan-embed-image|multimodalembedding|image[-_]?embed|clip/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(\n modelId,\n );\n}\n\nfunction isFilteredLiteLLMModel(modelId: string): boolean {\n return /moderation|rerank/i.test(modelId);\n}\n\nfunction inferLiteLLMContextLength(modelId: string): number {\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemini-1\\.5|gemini-2\\.0|gemini-2\\.5|gemini-3/i.test(modelId)) {\n return 1000000;\n }\n if (/claude/i.test(modelId)) return 200000;\n if (/gpt-4o|gpt-4\\.1|o1|o3|o4|llama|mistral|qwen|deepseek/i.test(modelId)) {\n return 128000;\n }\n return 32768;\n}\n\nfunction inferLiteLLMFunctions(modelId: string): boolean {\n if (isEmbeddingModel(modelId) || isAudioModel(modelId)) return false;\n return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(\n modelId,\n );\n}\n\nfunction inferLiteLLMVision(modelId: string): boolean {\n if (isAudioModel(modelId)) return false;\n return /gpt-4o|gpt-4\\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(\n modelId,\n );\n}\n\nfunction inferLiteLLMCapabilities(modelId: string): string[] {\n if (isTranscriptionModel(modelId)) {\n return ['transcription'];\n }\n\n if (isSpeechModel(modelId)) {\n return ['speech'];\n }\n\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (isImageEmbeddingModel(modelId)) {\n return ['embeddings', 'image_embedding'];\n }\n\n if (isEmbeddingModel(modelId)) {\n return ['embeddings'];\n }\n\n const capabilities = ['text', 'chat'];\n\n if (inferLiteLLMFunctions(modelId)) {\n capabilities.push('functions');\n }\n\n if (inferLiteLLMVision(modelId)) {\n capabilities.push('vision');\n }\n\n return capabilities;\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n}\n\nfunction ensureLiteLLMOptions(options: LiteLLMOptions): LiteLLMOptions {\n if (!options.baseUrl?.trim()) {\n throw new ValidationError('LiteLLM baseUrl is required', {\n provider: 'litellm',\n hint: 'Pass baseUrl like https://llm.happyvertical.com/v1 or set HAVE_AI_BASE_URL / LITELLM_BASE_URL',\n });\n }\n\n return {\n ...options,\n baseUrl: normalizeBaseUrl(options.baseUrl.trim()),\n };\n}\n\nconst LITELLM_PROFILE: OpenAICompatibleProfile = {\n providerLabel: 'LiteLLM',\n providerName: 'litellm',\n defaultModel: 'gpt-4',\n capabilities: LITELLM_CAPABILITIES,\n describeModel: (modelId) => `LiteLLM model: ${modelId}`,\n getContextLength: inferLiteLLMContextLength,\n getModelCapabilities: inferLiteLLMCapabilities,\n shouldIncludeModel: (modelId) => !isFilteredLiteLLMModel(modelId),\n supportsFunctions: inferLiteLLMFunctions,\n supportsVision: inferLiteLLMVision,\n};\n\ntype LiteLLMResolvedCapability =\n | 'chat'\n | 'vision'\n | 'embeddings'\n | 'image_generation';\n\nfunction supportsCapability(\n model: AIModel,\n capability: LiteLLMResolvedCapability,\n): boolean {\n if (capability === 'vision') {\n return (\n model.capabilities.includes('vision') || model.supportsVision === true\n );\n }\n\n if (capability === 'embeddings') {\n return model.capabilities.includes('embeddings');\n }\n\n if (capability === 'image_generation') {\n return model.capabilities.includes('image_generation');\n }\n\n return model.capabilities.includes('chat');\n}\n\n/**\n * LiteLLM provider implementation.\n *\n * LiteLLM exposes an OpenAI-compatible API surface, so this provider reuses the\n * OpenAI transport while customizing provider identity, model discovery, and\n * capability heuristics for gateway-backed deployments.\n */\nexport class LiteLLMProvider extends OpenAIProvider {\n readonly admin: LiteLLMAdmin;\n private readonly configuredDefaultModel?: string;\n private readonly resolvedModelCache = new Map<\n LiteLLMResolvedCapability,\n Promise<string>\n >();\n\n constructor(options: LiteLLMOptions) {\n const normalized = ensureLiteLLMOptions(options);\n super(normalized, LITELLM_PROFILE);\n this.admin = new LiteLLMAdmin({\n provider: 'litellm',\n baseUrl: resolveGatewayAdminBaseUrl(\n normalized.baseUrl,\n normalized.adminUrl || normalized.adminBaseUrl,\n 'litellm',\n ),\n apiKey: normalized.adminApiKey || normalized.apiKey,\n headers: normalized.adminHeaders,\n timeout: normalized.timeout,\n });\n this.configuredDefaultModel = normalized.defaultModel;\n }\n\n private async resolveModel(\n capability: LiteLLMResolvedCapability,\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: LiteLLMResolvedCapability,\n ): Promise<string> {\n const models = await super.getModels();\n const model = models.find((candidate) =>\n supportsCapability(candidate, capability),\n );\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the LiteLLM gateway`,\n {\n provider: 'litellm',\n capability,\n hint: 'Pass defaultModel explicitly or ensure /models returns a compatible model for this key',\n },\n );\n }\n\n return model.id;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n assertChatReasoningControls(options);\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n return super.chat(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n assertChatReasoningControls(options);\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n yield* super.stream(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n assertChatReasoningControls(options);\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n return super.describeImage(image, prompt, {\n ...safe,\n // The inherited image path calls this.chat(); do not reclassify the\n // normalization-inferred budget as an explicit caller control.\n reasoning: options.reasoning,\n model: await this.resolveModel('vision', safe.model),\n });\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embed(text, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embedImage(image, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n const safe = normalizeImageGenerationOptions(\n this.options,\n options,\n 'litellm',\n options.model,\n );\n return super.generateImage(prompt, {\n ...safe,\n model: await this.resolveModel('image_generation', safe.model),\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"litellm-C5Ek8B0K.js","names":[],"sources":["../../src/shared/providers/litellm.ts"],"sourcesContent":["import { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n} from '../safety';\nimport type {\n AICapabilities,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n LiteLLMOptions,\n} from '../types';\nimport { LiteLLMAdmin, resolveGatewayAdminBaseUrl } from './gateway-admin';\nimport {\n isAudioModel,\n isSpeechModel,\n isTranscriptionModel,\n} from './gateway-audio-models';\nimport { type OpenAICompatibleProfile, OpenAIProvider } from './openai';\n\n/** Chat Completions has effort, not a generic reasoning budget/thoughts envelope. */\nfunction assertChatReasoningControls(\n options: Pick<ChatOptions, 'reasoning' | 'includeThoughts'>,\n): void {\n if (\n options.reasoning?.maxTokens !== undefined ||\n options.reasoning?.includeThoughts !== undefined ||\n options.includeThoughts !== undefined\n ) {\n throw new ValidationError(\n 'LiteLLM Chat Completions does not support generic reasoning.maxTokens or includeThoughts controls; use reasoning.effort and an output token limit',\n { provider: 'litellm' },\n );\n }\n}\n\nconst LITELLM_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 videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 128000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /embed/i.test(modelId);\n}\n\nfunction isImageEmbeddingModel(modelId: string): boolean {\n return /titan-embed-image|multimodalembedding|image[-_]?embed|clip/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(\n modelId,\n );\n}\n\nfunction isFilteredLiteLLMModel(modelId: string): boolean {\n return /moderation|rerank/i.test(modelId);\n}\n\nfunction inferLiteLLMContextLength(modelId: string): number {\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemini-1\\.5|gemini-2\\.0|gemini-2\\.5|gemini-3/i.test(modelId)) {\n return 1000000;\n }\n if (/claude/i.test(modelId)) return 200000;\n if (/gpt-4o|gpt-4\\.1|o1|o3|o4|llama|mistral|qwen|deepseek/i.test(modelId)) {\n return 128000;\n }\n return 32768;\n}\n\nfunction inferLiteLLMFunctions(modelId: string): boolean {\n if (isEmbeddingModel(modelId) || isAudioModel(modelId)) return false;\n return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(\n modelId,\n );\n}\n\nfunction inferLiteLLMVision(modelId: string): boolean {\n if (isAudioModel(modelId)) return false;\n return /gpt-4o|gpt-4\\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(\n modelId,\n );\n}\n\nfunction inferLiteLLMCapabilities(modelId: string): string[] {\n if (isTranscriptionModel(modelId)) {\n return ['transcription'];\n }\n\n if (isSpeechModel(modelId)) {\n return ['speech'];\n }\n\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (isImageEmbeddingModel(modelId)) {\n return ['embeddings', 'image_embedding'];\n }\n\n if (isEmbeddingModel(modelId)) {\n return ['embeddings'];\n }\n\n const capabilities = ['text', 'chat'];\n\n if (inferLiteLLMFunctions(modelId)) {\n capabilities.push('functions');\n }\n\n if (inferLiteLLMVision(modelId)) {\n capabilities.push('vision');\n }\n\n return capabilities;\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n}\n\nfunction ensureLiteLLMOptions(options: LiteLLMOptions): LiteLLMOptions {\n if (!options.baseUrl?.trim()) {\n throw new ValidationError('LiteLLM baseUrl is required', {\n provider: 'litellm',\n hint: 'Pass baseUrl like https://llm.happyvertical.com/v1 or set HAVE_AI_BASE_URL / LITELLM_BASE_URL',\n });\n }\n\n return {\n ...options,\n baseUrl: normalizeBaseUrl(options.baseUrl.trim()),\n };\n}\n\nconst LITELLM_PROFILE: OpenAICompatibleProfile = {\n providerLabel: 'LiteLLM',\n providerName: 'litellm',\n defaultModel: 'gpt-4',\n capabilities: LITELLM_CAPABILITIES,\n describeModel: (modelId) => `LiteLLM model: ${modelId}`,\n getContextLength: inferLiteLLMContextLength,\n getModelCapabilities: inferLiteLLMCapabilities,\n shouldIncludeModel: (modelId) => !isFilteredLiteLLMModel(modelId),\n supportsFunctions: inferLiteLLMFunctions,\n supportsVision: inferLiteLLMVision,\n};\n\ntype LiteLLMResolvedCapability =\n | 'chat'\n | 'vision'\n | 'embeddings'\n | 'image_generation';\n\nfunction supportsCapability(\n model: AIModel,\n capability: LiteLLMResolvedCapability,\n): boolean {\n if (capability === 'vision') {\n return (\n model.capabilities.includes('vision') || model.supportsVision === true\n );\n }\n\n if (capability === 'embeddings') {\n return model.capabilities.includes('embeddings');\n }\n\n if (capability === 'image_generation') {\n return model.capabilities.includes('image_generation');\n }\n\n return model.capabilities.includes('chat');\n}\n\n/**\n * LiteLLM provider implementation.\n *\n * LiteLLM exposes an OpenAI-compatible API surface, so this provider reuses the\n * OpenAI transport while customizing provider identity, model discovery, and\n * capability heuristics for gateway-backed deployments.\n */\nexport class LiteLLMProvider extends OpenAIProvider {\n readonly admin: LiteLLMAdmin;\n private readonly configuredDefaultModel?: string;\n private readonly resolvedModelCache = new Map<\n LiteLLMResolvedCapability,\n Promise<string>\n >();\n\n constructor(options: LiteLLMOptions) {\n const normalized = ensureLiteLLMOptions(options);\n super(normalized, LITELLM_PROFILE);\n this.admin = new LiteLLMAdmin({\n provider: 'litellm',\n baseUrl: resolveGatewayAdminBaseUrl(\n normalized.baseUrl,\n normalized.adminUrl || normalized.adminBaseUrl,\n 'litellm',\n ),\n apiKey: normalized.adminApiKey || normalized.apiKey,\n headers: normalized.adminHeaders,\n timeout: normalized.timeout,\n });\n this.configuredDefaultModel = normalized.defaultModel;\n }\n\n private async resolveModel(\n capability: LiteLLMResolvedCapability,\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: LiteLLMResolvedCapability,\n ): Promise<string> {\n const models = await super.getModels();\n const model = models.find((candidate) =>\n supportsCapability(candidate, capability),\n );\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the LiteLLM gateway`,\n {\n provider: 'litellm',\n capability,\n hint: 'Pass defaultModel explicitly or ensure /models returns a compatible model for this key',\n },\n );\n }\n\n return model.id;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n assertChatReasoningControls(options);\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n return super.chat(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n assertChatReasoningControls(options);\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n yield* super.stream(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n assertChatReasoningControls(options);\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n return super.describeImage(image, prompt, {\n ...safe,\n // The inherited image path calls this.chat(); do not reclassify the\n // normalization-inferred budget as an explicit caller control.\n reasoning: options.reasoning,\n model: await this.resolveModel('vision', safe.model),\n });\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embed(text, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embedImage(image, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n const safe = normalizeImageGenerationOptions(\n this.options,\n options,\n 'litellm',\n options.model,\n );\n return super.generateImage(prompt, {\n ...safe,\n model: await this.resolveModel('image_generation', safe.model),\n });\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { b as extractTextContent, c as normalizeImageGenerationOptions, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, p as ContentFilterError, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-DS7uDhi1.js";
2
2
  import { n as rateLimitErrorFrom } from "./rate-limit-Dwyde1BY.js";
3
- import { n as resolveContinuation } from "./continuation-KdrnmvzP.js";
3
+ import { n as resolveContinuation } from "./continuation-BMGvMlzq.js";
4
4
  import { i as resolveToolResultName, n as indexToolCallNames } from "./tool-messages-0ND35mYX.js";
5
5
  import { ValidationError } from "@happyvertical/utils";
6
6
  //#region src/shared/providers/ollama.ts
@@ -669,4 +669,4 @@ var OllamaProvider = class {
669
669
  //#endregion
670
670
  export { OllamaProvider };
671
671
 
672
- //# sourceMappingURL=ollama-DHbYj2lH.js.map
672
+ //# sourceMappingURL=ollama-CuDjAyTy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ollama-DHbYj2lH.js","names":[],"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';\nimport { resolveContinuation } from '../continuation';\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport { indexToolCallNames, resolveToolResultName } from '../tool-messages';\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 VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\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} 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 videoGeneration: false,\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 rateLimitErrorFrom('ollama', {\n headers: response.headers,\n message: text,\n });\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 toolCallNames = indexToolCallNames(messages);\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') {\n // Ollama pairs results with calls by function name.\n const toolName = resolveToolResultName(message, toolCallNames);\n if (toolName) {\n mapped.tool_name = toolName;\n }\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 if (resolveContinuation(this.options, options)) {\n // /generate has no assistant turn to continue from, so a completion that\n // may continue on the output limit runs as a one-message chat.\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n }\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 continueOnLength: options.continueOnLength,\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 let streamFinish: AIResponse['finishReason'] = 'stop';\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 streamFinish = mapFinishReason(chunk.done_reason);\n }\n }\n options.onFinishReason?.(streamFinish ?? 'stop');\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 // ============================================================================\n // Video Generation Methods (Not supported - use gemini, byteplus-modelark,\n // or openai-compat-video provider)\n // ============================================================================\n\n async submitVideoGenerationJob(\n _options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async getVideoGenerationJob(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async fetchVideoGenerationResult(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async cancelVideoGenerationJob(_handle: VideoGenerationJob): Promise<void> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async validateVideoGenerationAccess(): Promise<boolean> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\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"],"mappings":"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"}
1
+ {"version":3,"file":"ollama-CuDjAyTy.js","names":[],"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';\nimport { resolveContinuation } from '../continuation';\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport { indexToolCallNames, resolveToolResultName } from '../tool-messages';\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 VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\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} 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 videoGeneration: false,\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 rateLimitErrorFrom('ollama', {\n headers: response.headers,\n message: text,\n });\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 toolCallNames = indexToolCallNames(messages);\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') {\n // Ollama pairs results with calls by function name.\n const toolName = resolveToolResultName(message, toolCallNames);\n if (toolName) {\n mapped.tool_name = toolName;\n }\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 if (resolveContinuation(this.options, options)) {\n // /generate has no assistant turn to continue from, so a completion that\n // may continue on the output limit runs as a one-message chat.\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n }\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 continueOnLength: options.continueOnLength,\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 let streamFinish: AIResponse['finishReason'] = 'stop';\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 streamFinish = mapFinishReason(chunk.done_reason);\n }\n }\n options.onFinishReason?.(streamFinish ?? 'stop');\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 // ============================================================================\n // Video Generation Methods (Not supported - use gemini, byteplus-modelark,\n // or openai-compat-video provider)\n // ============================================================================\n\n async submitVideoGenerationJob(\n _options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async getVideoGenerationJob(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async fetchVideoGenerationResult(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async cancelVideoGenerationJob(_handle: VideoGenerationJob): Promise<void> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async validateVideoGenerationAccess(): Promise<boolean> {\n throw new AIError(\n 'Video generation is not supported by the Ollama provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\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"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { a as createObservedAI, c as normalizeImageGenerationOptions, d as AI_PROVIDER_TYPES, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, p as ContentFilterError, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-DS7uDhi1.js";
3
3
  import { n as rateLimitErrorFrom, t as createRateLimitedAI } from "./rate-limit-Dwyde1BY.js";
4
- import { t as createContinuingAI } from "./continuation-KdrnmvzP.js";
4
+ import { t as createContinuingAI } from "./continuation-BMGvMlzq.js";
5
5
  import { ApiError, ValidationError, loadEnvConfig } from "@happyvertical/utils";
6
6
  import OpenAI from "openai";
7
7
  //#region src/shared/providers/openai.ts
@@ -1221,13 +1221,13 @@ async function getAI(options = {}) {
1221
1221
  const { ChatGPTPlanProvider } = await Promise.resolve().then(() => chatgpt_plan_exports);
1222
1222
  client = new ChatGPTPlanProvider(options);
1223
1223
  } else if (isLiteLLMOptions(options)) {
1224
- const { LiteLLMProvider } = await import("./litellm-8k7PMuh_.js");
1224
+ const { LiteLLMProvider } = await import("./litellm-C5Ek8B0K.js");
1225
1225
  client = new LiteLLMProvider(options);
1226
1226
  } else if (isBifrostOptions(options)) {
1227
- const { BifrostProvider } = await import("./bifrost-DZxTeE1Q.js");
1227
+ const { BifrostProvider } = await import("./bifrost-BPQ0aL1i.js");
1228
1228
  client = new BifrostProvider(options);
1229
1229
  } else if (isOllamaOptions(options)) {
1230
- const { OllamaProvider } = await import("./ollama-DHbYj2lH.js");
1230
+ const { OllamaProvider } = await import("./ollama-CuDjAyTy.js");
1231
1231
  client = new OllamaProvider(options);
1232
1232
  } else if (isGeminiOptions(options)) {
1233
1233
  const { GeminiProvider } = await import("./gemini-DCo6d-n1.js");
@@ -1973,4 +1973,4 @@ var PACKAGE_VERSION_INITIALIZED = true;
1973
1973
  //#endregion
1974
1974
  export { OpenAIProvider as _, ChatGPTPlanSessionRevokedError as a, ChatGPTPlanWorkspaceError as c, getAI as d, getAIAuto as f, getOpenAI as g, getAIClient as h, ChatGPTPlanProvider as i, AIMessage as l, OpenAIClient as m, AIThread as n, ChatGPTPlanUsageLimitError as o, AIClient as p, ChatGPTPlanError as r, ChatGPTPlanUsageUnavailableError as s, PACKAGE_VERSION_INITIALIZED as t, factory_exports as u };
1975
1975
 
1976
- //# sourceMappingURL=src-BnMUshQt.js.map
1976
+ //# sourceMappingURL=src-DBah9G3i.js.map