@happyvertical/ai 0.111.2 → 0.111.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +60 -0
  2. package/dist/chunks/{anthropic-DQjBd3wu.js → anthropic-BXiE495e.js} +94 -20
  3. package/dist/chunks/anthropic-BXiE495e.js.map +1 -0
  4. package/dist/chunks/{bedrock-gtE6OU5Z.js → bedrock-fO9ix2hd.js} +37 -16
  5. package/dist/chunks/bedrock-fO9ix2hd.js.map +1 -0
  6. package/dist/chunks/{bifrost-B0191CPM.js → bifrost-CrLHqZQJ.js} +4 -4
  7. package/dist/chunks/{bifrost-B0191CPM.js.map → bifrost-CrLHqZQJ.js.map} +1 -1
  8. package/dist/chunks/{byteplus-modelark-C0rRxYwh.js → byteplus-modelark-CM0-yuF3.js} +3 -3
  9. package/dist/chunks/{byteplus-modelark-C0rRxYwh.js.map → byteplus-modelark-CM0-yuF3.js.map} +1 -1
  10. package/dist/chunks/cache-hint-BdVY0hrJ.js +39 -0
  11. package/dist/chunks/cache-hint-BdVY0hrJ.js.map +1 -0
  12. package/dist/chunks/{claude-cli-DysSNpKY.js → claude-cli-CD1quA61.js} +3 -3
  13. package/dist/chunks/{claude-cli-DysSNpKY.js.map → claude-cli-CD1quA61.js.map} +1 -1
  14. package/dist/chunks/{continuation-B-b0Iqgj.js → continuation-Dgw5Zujl.js} +10 -3
  15. package/dist/chunks/continuation-Dgw5Zujl.js.map +1 -0
  16. package/dist/chunks/{gateway-audio-models-57sR3hHE.js → gateway-audio-models-Cs7vu956.js} +2 -2
  17. package/dist/chunks/{gateway-audio-models-57sR3hHE.js.map → gateway-audio-models-Cs7vu956.js.map} +1 -1
  18. package/dist/chunks/{gemini-BHdv492T.js → gemini-DjUpgpM1.js} +3 -3
  19. package/dist/chunks/{gemini-BHdv492T.js.map → gemini-DjUpgpM1.js.map} +1 -1
  20. package/dist/chunks/{huggingface-vooWYknE.js → huggingface-C8P7DPFD.js} +3 -3
  21. package/dist/chunks/{huggingface-vooWYknE.js.map → huggingface-C8P7DPFD.js.map} +1 -1
  22. package/dist/chunks/{laya-B7aCsYqu.js → laya-DuRRHJHo.js} +3 -3
  23. package/dist/chunks/{laya-B7aCsYqu.js.map → laya-DuRRHJHo.js.map} +1 -1
  24. package/dist/chunks/{litellm-Bhns6CSh.js → litellm-Cc6xC6sj.js} +4 -4
  25. package/dist/chunks/{litellm-Bhns6CSh.js.map → litellm-Cc6xC6sj.js.map} +1 -1
  26. package/dist/chunks/{ollama-pL2WCpkS.js → ollama-D5dILl5b.js} +8 -5
  27. package/dist/chunks/ollama-D5dILl5b.js.map +1 -0
  28. package/dist/chunks/{openai-compat-video-BoLwWXJM.js → openai-compat-video-DMu4hsI5.js} +3 -3
  29. package/dist/chunks/{openai-compat-video-BoLwWXJM.js.map → openai-compat-video-DMu4hsI5.js.map} +1 -1
  30. package/dist/chunks/{qwen-tts-BbGkn1oW.js → qwen-tts-dvbQnMSK.js} +2 -2
  31. package/dist/chunks/{qwen-tts-BbGkn1oW.js.map → qwen-tts-dvbQnMSK.js.map} +1 -1
  32. package/dist/chunks/{rate-limit-B3Kz6v4j.js → rate-limit-B9BFC8ld.js} +2 -2
  33. package/dist/chunks/{rate-limit-B3Kz6v4j.js.map → rate-limit-B9BFC8ld.js.map} +1 -1
  34. package/dist/chunks/{seevio-Dt8kWgpg.js → seevio-BnmiByK2.js} +3 -3
  35. package/dist/chunks/{seevio-Dt8kWgpg.js.map → seevio-BnmiByK2.js.map} +1 -1
  36. package/dist/chunks/{src-CWFnwztw.js → src-EMvAiwjJ.js} +115 -46
  37. package/dist/chunks/src-EMvAiwjJ.js.map +1 -0
  38. package/dist/chunks/{typesafe-DDVSVUR_.js → typesafe-d5Jwafs7.js} +3 -3
  39. package/dist/chunks/{typesafe-DDVSVUR_.js.map → typesafe-d5Jwafs7.js.map} +1 -1
  40. package/dist/chunks/{usage-yIT5lpQm.js → usage-B40bJZ49.js} +86 -3
  41. package/dist/chunks/usage-B40bJZ49.js.map +1 -0
  42. package/dist/chunks/{webllm-DrwR5V-y.js → webllm-Cp4aHmyG.js} +2 -2
  43. package/dist/chunks/{webllm-DrwR5V-y.js.map → webllm-Cp4aHmyG.js.map} +1 -1
  44. package/dist/index.js +2 -2
  45. package/dist/local.js +2 -2
  46. package/dist/node.js +3 -3
  47. package/dist/shared/cache-hint.d.ts +26 -0
  48. package/dist/shared/cache-hint.d.ts.map +1 -0
  49. package/dist/shared/claude-models.d.ts +29 -0
  50. package/dist/shared/claude-models.d.ts.map +1 -0
  51. package/dist/shared/continuation.d.ts.map +1 -1
  52. package/dist/shared/providers/anthropic.d.ts +5 -0
  53. package/dist/shared/providers/anthropic.d.ts.map +1 -1
  54. package/dist/shared/providers/bedrock.d.ts.map +1 -1
  55. package/dist/shared/providers/ollama.d.ts.map +1 -1
  56. package/dist/shared/providers/openai.d.ts +14 -0
  57. package/dist/shared/providers/openai.d.ts.map +1 -1
  58. package/dist/shared/providers/usage.d.ts +5 -0
  59. package/dist/shared/providers/usage.d.ts.map +1 -1
  60. package/dist/shared/safety.d.ts.map +1 -1
  61. package/dist/shared/types.d.ts +87 -3
  62. package/dist/shared/types.d.ts.map +1 -1
  63. package/package.json +2 -2
  64. package/dist/chunks/anthropic-DQjBd3wu.js.map +0 -1
  65. package/dist/chunks/bedrock-gtE6OU5Z.js.map +0 -1
  66. package/dist/chunks/continuation-B-b0Iqgj.js.map +0 -1
  67. package/dist/chunks/ollama-pL2WCpkS.js.map +0 -1
  68. package/dist/chunks/src-CWFnwztw.js.map +0 -1
  69. package/dist/chunks/usage-yIT5lpQm.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"laya-B7aCsYqu.js","names":[],"sources":["../../src/shared/providers/laya.ts"],"sourcesContent":["/**\n * Laya typed-decision provider.\n *\n * Laya (https://github.com/NandhaKishorM/laya) is a self-hosted,\n * non-autoregressive decision engine. Its `laya-serve` HTTP server answers the\n * Jev `POST /v1/systemone` wire shape, with differences this adapter handles\n * itself rather than inheriting from the TypeSafe adapter: optional auth, a\n * checkpoint chosen by the server's router, a `max_len` token window,\n * probabilities rounded to four decimals one at a time, and truncation facts.\n *\n * The public SDK contract calls Laya's `noul` primitive a `predicate`; the\n * server's vocabulary stays confined to this wire translation.\n */\n\nimport { ValidationError } from '@happyvertical/utils';\n\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport { normalizeBaseAIOptions, prepareRequestControls } from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n DecisionAnswer,\n DecisionQuestion,\n DecisionRequest,\n DecisionResult,\n DecisionValue,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n LayaDecisionOptions,\n LayaOptions,\n MessageOptions,\n ScoreDecisionQuestion,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport { AIError, AuthenticationError } from '../types';\nimport { emitUsage } from './usage';\n\nconst PROVIDER = 'laya';\n\n/** Distributions this close to unit mass are used exactly as received. */\nconst STRICT_DISTRIBUTION_EPSILON = 1e-6;\n/**\n * `laya-serve` rounds every probability to four decimals on its own, so each\n * value is off by at most half of the last place and a distribution of `n`\n * values can be off by `n * 0.00005`.\n */\nconst ROUNDING_ERROR_PER_VALUE = 5e-5;\n/** No rounding story justifies renormalizing a distribution further out. */\nconst MAX_NORMALIZED_ERROR = 0.01;\n\ntype WireQuestion =\n | {\n type: 'noul';\n instructions: DecisionValue;\n criteria?: Record<string, DecisionValue>;\n }\n | {\n type: 'choice';\n instructions: DecisionValue;\n criteria: Record<string, DecisionValue | null>;\n }\n | { type: 'score'; instructions: DecisionValue; criteria: DecisionValue[] };\n\ninterface WireRequest {\n state: DecisionValue;\n questions: Record<string, WireQuestion>;\n model?: string;\n max_len?: number;\n}\n\ninterface WireResponse {\n model?: unknown;\n answers?: unknown;\n usage?: unknown;\n routing?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction invalid(message: string): AIError {\n return new AIError(`Laya response ${message}`, 'INVALID_RESPONSE', PROVIDER);\n}\n\nfunction finite(value: unknown, field: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value))\n throw invalid(`${field} must be finite`);\n return value;\n}\n\nfunction probability(value: unknown, field: string): number {\n const result = finite(value, field);\n if (result < 0 || result > 1)\n throw invalid(`${field} must be between 0 and 1`);\n return result;\n}\n\nfunction tokenCount(value: unknown, field: string): number {\n const result = finite(value, field);\n if (!Number.isSafeInteger(result) || result < 0)\n throw invalid(`${field} must be a non-negative integer`);\n return result;\n}\n\nfunction optionalString(\n source: Record<string, unknown>,\n key: string,\n field: string,\n): string | undefined {\n const value = source[key];\n if (value === undefined) return undefined;\n if (typeof value !== 'string' || !value)\n throw invalid(`${field} must be a non-empty string`);\n return value;\n}\n\nfunction sameDecisionValue(left: DecisionValue, right: unknown): boolean {\n if (left === right) return true;\n if (Array.isArray(left)) {\n return (\n Array.isArray(right) &&\n left.length === right.length &&\n left.every((value, index) => sameDecisionValue(value, right[index]))\n );\n }\n if (isRecord(left)) {\n return (\n isRecord(right) &&\n Object.keys(left).length === Object.keys(right).length &&\n Object.entries(left).every(\n ([key, value]) => key in right && sameDecisionValue(value, right[key]),\n )\n );\n }\n return false;\n}\n\n/**\n * `laya-serve` returns a rubric level in `legend` as sent when it is a string\n * and as Python's `json.dumps` text when it is anything else.\n */\nfunction legendMatches(level: DecisionValue, legend: unknown): boolean {\n if (sameDecisionValue(level, legend)) return true;\n if (typeof level === 'string' || typeof legend !== 'string') return false;\n try {\n return sameDecisionValue(level, JSON.parse(legend));\n } catch {\n return false;\n }\n}\n\nfunction validateValue(\n value: unknown,\n field: string,\n): asserts value is DecisionValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean')\n return;\n if (typeof value === 'number') {\n if (!Number.isFinite(value))\n throw new ValidationError(`${field} must contain finite numbers`, {\n provider: PROVIDER,\n });\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n validateValue(item, `${field}[${index}]`);\n });\n return;\n }\n if (isRecord(value)) {\n Object.entries(value).forEach(([key, item]) => {\n validateValue(item, `${field}.${key}`);\n });\n return;\n }\n throw new ValidationError(`${field} must be JSON-compatible`, {\n provider: PROVIDER,\n });\n}\n\nfunction validateMaxLen(value: unknown, field: string): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0)\n throw new ValidationError(`${field} must be a positive integer`, {\n provider: PROVIDER,\n });\n return value;\n}\n\n/**\n * Checks the provider-neutral request shape. Laya's own size limits (questions\n * per request, options per question, state length) are left to the server,\n * which reports them as explicit 413 errors.\n */\nfunction validateRequest(request: DecisionRequest): void {\n if (request.state === null || request.state === undefined)\n throw new ValidationError('state is required', { provider: PROVIDER });\n validateValue(request.state, 'state');\n const entries = Object.entries(request.questions || {});\n if (entries.length === 0)\n throw new ValidationError('questions must not be empty', {\n provider: PROVIDER,\n });\n for (const [id, question] of entries) {\n if (!id.trim())\n throw new ValidationError('question IDs must not be empty', {\n provider: PROVIDER,\n });\n validateValue(question.instructions, `questions.${id}.instructions`);\n if (question.type === 'predicate') {\n if (question.criteria) {\n for (const [key, value] of Object.entries(question.criteria))\n validateValue(value, `questions.${id}.criteria.${key}`);\n }\n } else if (question.type === 'choice') {\n const options = Object.keys(question.criteria || {});\n if (options.length === 0)\n throw new ValidationError(\n `questions.${id}.criteria must contain at least one option`,\n { provider: PROVIDER },\n );\n for (const [key, value] of Object.entries(question.criteria))\n if (value !== null)\n validateValue(value, `questions.${id}.criteria.${key}`);\n } else if (question.type === 'score') {\n if (!Array.isArray(question.criteria) || question.criteria.length < 2)\n throw new ValidationError(\n `questions.${id}.criteria must contain at least 2 ordered levels`,\n { provider: PROVIDER },\n );\n question.criteria.forEach((value, index) => {\n // Laya rejects a null level because its legend entry would be null.\n if (value === null)\n throw new ValidationError(\n `questions.${id}.criteria[${index}] must describe the level`,\n { provider: PROVIDER },\n );\n validateValue(value, `questions.${id}.criteria[${index}]`);\n });\n } else {\n throw new ValidationError(`questions.${id}.type is unsupported`, {\n provider: PROVIDER,\n });\n }\n }\n}\n\n/**\n * Builds each wire question field by field so unknown properties on a caller's\n * object (for example a generation control) are never forwarded.\n */\nfunction wireQuestion(question: DecisionQuestion): WireQuestion {\n if (question.type === 'predicate')\n return {\n type: 'noul',\n instructions: question.instructions,\n ...(question.criteria ? { criteria: question.criteria } : {}),\n };\n if (question.type === 'choice')\n return {\n type: 'choice',\n instructions: question.instructions,\n criteria: question.criteria,\n };\n return {\n type: 'score',\n instructions: question.instructions,\n criteria: question.criteria,\n };\n}\n\n/** Resolves the server root from a base URL that may carry the API path. */\nfunction serverRoot(value: string | undefined): string {\n const text = (value || '').trim();\n if (!text)\n throw new ValidationError(\n 'Laya requires baseUrl, for example http://localhost:8000',\n { provider: PROVIDER },\n );\n let url: URL;\n try {\n url = new URL(text);\n } catch {\n throw new ValidationError('Laya baseUrl must be an absolute http(s) URL', {\n provider: PROVIDER,\n });\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:')\n throw new ValidationError('Laya baseUrl must be an absolute http(s) URL', {\n provider: PROVIDER,\n });\n if (url.search || url.hash || url.username || url.password)\n throw new ValidationError(\n 'Laya baseUrl must not contain credentials, a query, or a fragment',\n { provider: PROVIDER },\n );\n const path = url.pathname\n .replace(/\\/+$/, '')\n .replace(/\\/v1(\\/systemone)?$/, '');\n return `${url.origin}${path}`;\n}\n\ninterface Distribution {\n values: Record<string, number>;\n /** The values as received, set only when they were renormalized. */\n raw?: Record<string, number>;\n}\n\n/**\n * Validates a choice or score distribution. Mass within the four-decimal\n * rounding bound is normalized by its actual sum; anything else is rejected.\n */\nfunction distribution(\n value: unknown,\n expected: string[],\n field: string,\n): Distribution {\n if (\n !isRecord(value) ||\n Object.keys(value).length !== expected.length ||\n expected.some((key) => !(key in value))\n )\n throw invalid(`${field} must cover exactly the requested values`);\n const values = Object.fromEntries(\n expected.map((key) => [key, probability(value[key], `${field}.${key}`)]),\n );\n const sum = Object.values(values).reduce((total, item) => total + item, 0);\n const drift = Math.abs(sum - 1);\n if (drift <= STRICT_DISTRIBUTION_EPSILON) return { values };\n const allowed =\n Math.min(expected.length * ROUNDING_ERROR_PER_VALUE, MAX_NORMALIZED_ERROR) +\n STRICT_DISTRIBUTION_EPSILON;\n if (sum <= 0 || drift > allowed) throw invalid(`${field} must sum to 1`);\n return {\n values: Object.fromEntries(\n Object.entries(values).map(([key, item]) => [key, item / sum]),\n ),\n raw: values,\n };\n}\n\nfunction answer(\n question: DecisionQuestion,\n raw: unknown,\n id: string,\n renormalized: Record<string, Record<string, number>>,\n): DecisionAnswer {\n if (!isRecord(raw)) throw invalid(`answers.${id} must be an object`);\n if (question.type === 'predicate') {\n if (raw.type !== 'noul')\n throw invalid(`answers.${id} type does not match predicate`);\n return {\n type: 'predicate',\n probability: probability(raw.noul, `answers.${id}.noul`),\n };\n }\n if (raw.type !== question.type)\n throw invalid(`answers.${id} type does not match request`);\n if (question.type === 'choice') {\n const choices = Object.keys(question.criteria);\n if (typeof raw.choice !== 'string' || !choices.includes(raw.choice))\n throw invalid(`answers.${id}.choice is not a requested option`);\n const probabilities = distribution(\n raw.probabilities,\n choices,\n `answers.${id}.probabilities`,\n );\n if (probabilities.raw) renormalized[id] = probabilities.raw;\n return {\n type: 'choice',\n choice: raw.choice,\n probabilities: probabilities.values,\n confidence: probability(raw.confidence, `answers.${id}.confidence`),\n };\n }\n const levels = (question as ScoreDecisionQuestion).criteria;\n const levelKeys = levels.map((_, index) => String(index));\n const score = finite(raw.score, `answers.${id}.score`);\n if (score < 0 || score > levels.length - 1)\n throw invalid(`answers.${id}.score is outside the requested rubric`);\n const legend = raw.legend;\n if (\n !isRecord(legend) ||\n levelKeys.some((key, index) => !legendMatches(levels[index], legend[key]))\n )\n throw invalid(`answers.${id}.legend does not match the requested rubric`);\n const probabilities = distribution(\n raw.probabilities,\n levelKeys,\n `answers.${id}.probabilities`,\n );\n if (probabilities.raw) renormalized[id] = probabilities.raw;\n return {\n type: 'score',\n score,\n probabilities: probabilities.values,\n confidence: probability(raw.confidence, `answers.${id}.confidence`),\n levels,\n };\n}\n\n/** A decision-only adapter for a `laya-serve` `/v1/systemone` endpoint. */\nexport class LayaProvider implements AIInterface {\n private readonly options: LayaOptions;\n private readonly root: string;\n private readonly maxLen?: number;\n\n constructor(options: LayaOptions) {\n this.root = serverRoot(options.baseUrl);\n this.maxLen = validateMaxLen(options.maxLen, 'maxLen');\n this.options = normalizeBaseAIOptions({ ...options, baseUrl: this.root });\n }\n\n async decide(\n request: DecisionRequest,\n options: LayaDecisionOptions = {},\n ): Promise<DecisionResult> {\n validateRequest(request);\n const maxLen = validateMaxLen(options.maxLen, 'maxLen') ?? this.maxLen;\n const controls = prepareRequestControls(this.options, options);\n const startedAt = Date.now();\n const requestedModel =\n options.model || this.options.defaultModel || undefined;\n const wire: WireRequest = {\n state: request.state,\n questions: Object.fromEntries(\n Object.entries(request.questions).map(([id, question]) => [\n id,\n wireQuestion(question),\n ]),\n ),\n ...(requestedModel ? { model: requestedModel } : {}),\n ...(maxLen !== undefined ? { max_len: maxLen } : {}),\n };\n try {\n const response = await fetch(`${this.root}/v1/systemone`, {\n method: 'POST',\n redirect: 'error',\n headers: {\n ...(this.options.apiKey\n ? { Authorization: `Bearer ${this.options.apiKey}` }\n : {}),\n 'Content-Type': 'application/json',\n ...this.options.headers,\n },\n body: JSON.stringify(wire),\n signal: controls.signal,\n });\n if (!response.ok) {\n if (response.status === 401) throw new AuthenticationError(PROVIDER);\n const text = await response.text();\n // 503 is laya-serve's admission limit (LAYA_MAX_CONCURRENT), which\n // sends Retry-After; 429 covers a rate-limiting proxy in front of it.\n if (response.status === 429 || response.status === 503)\n throw rateLimitErrorFrom(\n PROVIDER,\n { headers: response.headers, message: text },\n { model: requestedModel },\n );\n throw new AIError(\n `Laya request failed (${response.status}): ${text.slice(0, 500)}`,\n 'API_ERROR',\n PROVIDER,\n requestedModel,\n response.status >= 500,\n );\n }\n let body: WireResponse;\n try {\n body = (await response.json()) as WireResponse;\n } catch (error) {\n if (error instanceof SyntaxError)\n throw new AIError(\n 'Laya response contained invalid JSON',\n 'INVALID_RESPONSE',\n PROVIDER,\n requestedModel,\n );\n throw error;\n }\n return this.result(\n request,\n body,\n requestedModel,\n maxLen,\n options,\n startedAt,\n );\n } catch (error) {\n if (controls.didTimeout())\n throw new AIError(\n `Laya request timed out after ${controls.timeout}ms`,\n 'REQUEST_TIMEOUT',\n PROVIDER,\n requestedModel,\n true,\n );\n if (controls.signal.aborted && !(error instanceof AIError))\n throw new AIError(\n 'Laya request was aborted',\n 'REQUEST_ABORTED',\n PROVIDER,\n requestedModel,\n );\n if (!(error instanceof AIError)) {\n throw new AIError(\n `Network error calling Laya: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'NETWORK_ERROR',\n PROVIDER,\n requestedModel,\n true,\n );\n }\n throw error;\n } finally {\n controls.cleanup();\n }\n }\n\n private result(\n request: DecisionRequest,\n body: WireResponse,\n requestedModel: string | undefined,\n maxLen: number | undefined,\n options: LayaDecisionOptions,\n startedAt: number,\n ): DecisionResult {\n if (!isRecord(body)) throw invalid('must be an object');\n // The root `model` names Laya's decision head, not the checkpoint.\n if (typeof body.model !== 'string' || !body.model)\n throw invalid('model is required');\n if (!isRecord(body.answers)) throw invalid('answers is required');\n const responseAnswers = body.answers;\n const ids = Object.keys(request.questions);\n if (\n Object.keys(responseAnswers).length !== ids.length ||\n ids.some((id) => !(id in responseAnswers))\n )\n throw invalid('answers must match requested question IDs');\n const renormalized: Record<string, Record<string, number>> = {};\n const answers = Object.fromEntries(\n ids.map((id) => [\n id,\n answer(request.questions[id], responseAnswers[id], id, renormalized),\n ]),\n );\n\n let usage:\n | { promptTokens: number; completionTokens: number; totalTokens: number }\n | undefined;\n const facts: Record<string, DecisionValue> = {};\n if (body.usage !== undefined) {\n const wireUsage = body.usage;\n if (\n !isRecord(wireUsage) ||\n !('input_tokens' in wireUsage) ||\n !('output_tokens' in wireUsage)\n )\n throw invalid('usage must include input_tokens and output_tokens');\n const input = tokenCount(wireUsage.input_tokens, 'usage.input_tokens');\n const output = tokenCount(wireUsage.output_tokens, 'usage.output_tokens');\n usage = {\n promptTokens: input,\n completionTokens: output,\n totalTokens: input + output,\n };\n // Truncation is invisible anywhere else in the response.\n for (const [key, name] of [\n ['state_tokens', 'stateTokens'],\n ['state_tokens_dropped', 'stateTokensDropped'],\n ] as const)\n if (wireUsage[key] !== undefined)\n facts[name] = tokenCount(wireUsage[key], `usage.${key}`);\n if (wireUsage.truncated !== undefined) {\n if (typeof wireUsage.truncated !== 'boolean')\n throw invalid('usage.truncated must be a boolean');\n facts.truncated = wireUsage.truncated;\n }\n if (wireUsage.truncated_questions !== undefined) {\n const truncated = wireUsage.truncated_questions;\n if (\n !Array.isArray(truncated) ||\n truncated.some((id) => typeof id !== 'string')\n )\n throw invalid('usage.truncated_questions must list question IDs');\n facts.truncatedQuestions = truncated as string[];\n }\n }\n\n let checkpoint: string | undefined;\n if (body.routing !== undefined) {\n if (!isRecord(body.routing)) throw invalid('routing must be an object');\n checkpoint = optionalString(body.routing, 'model', 'routing.model');\n const repo = optionalString(body.routing, 'repo', 'routing.repo');\n const reason = optionalString(body.routing, 'reason', 'routing.reason');\n if (checkpoint) facts.checkpoint = checkpoint;\n if (repo) facts.checkpointRepo = repo;\n if (reason) facts.routeReason = reason;\n }\n\n // The checkpoint that answered is reported only in `routing`, which a\n // server running LAYA_JEV_STRICT omits. Without it, report the decision\n // head and leave `details.checkpoint` unset rather than guess.\n const model = checkpoint || body.model;\n const renormalizedIds = Object.keys(renormalized);\n const details: Record<string, DecisionValue> = {\n serverModel: body.model,\n ...(requestedModel ? { requestedModel } : {}),\n ...(maxLen !== undefined ? { maxLen } : {}),\n ...facts,\n ...(renormalizedIds.length\n ? { renormalized: renormalizedIds, rawProbabilities: renormalized }\n : {}),\n };\n emitUsage(\n this.options,\n PROVIDER,\n 'decide',\n model,\n usage,\n startedAt,\n options.usageTags,\n );\n return {\n model,\n ...(usage ? { usage } : {}),\n provenance: { provider: PROVIDER, model, details },\n answers,\n };\n }\n\n async getModels(): Promise<AIModel[]> {\n // laya-serve has no model-listing route; these are the checkpoints of the\n // convaiinnovations/laya bundle. A server may register others.\n const checkpoints: Array<[string, string, number]> = [\n ['typed-decisions', 'Laya typed decisions (421M)', 1024],\n ['english', 'Laya English (421M)', 512],\n ['multilingual', 'Laya multilingual (322M)', 1024],\n ];\n const configured = this.options.defaultModel;\n const models = checkpoints.map(([id, name, contextLength]) => ({\n id,\n name,\n description: 'Laya typed decisions',\n contextLength,\n capabilities: ['decisions'],\n supportsFunctions: false,\n supportsVision: false,\n }));\n if (configured && !models.some((model) => model.id === configured))\n models.push({\n id: configured,\n name: configured,\n description: 'Laya typed decisions (configured checkpoint)',\n contextLength: 0,\n capabilities: ['decisions'],\n supportsFunctions: false,\n supportsVision: false,\n });\n return models;\n }\n async getCapabilities(): Promise<AICapabilities> {\n return {\n decisions: true,\n chat: false,\n completion: false,\n embeddings: false,\n streaming: false,\n functions: false,\n vision: false,\n fineTuning: false,\n imageEmbeddings: false,\n imageGeneration: false,\n videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 0,\n supportedOperations: ['decide'],\n };\n }\n private unsupported(): never {\n throw new AIError(\n 'This operation is not supported by the Laya decision-only provider.',\n 'NOT_IMPLEMENTED',\n PROVIDER,\n );\n }\n async chat(_a: AIMessage[], _b?: ChatOptions): Promise<AIResponse> {\n return this.unsupported();\n }\n async complete(_a: string, _b?: CompletionOptions): Promise<AIResponse> {\n return this.unsupported();\n }\n async message(_a: string, _b?: MessageOptions): Promise<string> {\n return this.unsupported();\n }\n async embed(\n _a: string | string[],\n _b?: EmbeddingOptions,\n ): Promise<EmbeddingResponse> {\n return this.unsupported();\n }\n async embedImage(\n _a: string | Buffer,\n _b?: ImageEmbeddingOptions,\n ): Promise<EmbeddingResponse> {\n return this.unsupported();\n }\n async describeImage(\n _a: string | Buffer,\n _b?: string,\n _c?: ImageDescriptionOptions,\n ): Promise<string> {\n return this.unsupported();\n }\n async generateImage(\n _a: string,\n _b?: ImageGenerationOptions,\n ): Promise<ImageGenerationResponse> {\n return this.unsupported();\n }\n stream(_a: AIMessage[], _b?: ChatOptions): AsyncIterable<string> {\n const error = new AIError(\n 'Chat streaming is not supported by the Laya decision-only provider.',\n 'NOT_IMPLEMENTED',\n PROVIDER,\n );\n return {\n [Symbol.asyncIterator]: () => ({ next: () => Promise.reject(error) }),\n };\n }\n async countTokens(_a: string): Promise<number> {\n return this.unsupported();\n }\n async submitVideoGenerationJob(\n _a: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n return this.unsupported();\n }\n async getVideoGenerationJob(\n _a: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n return this.unsupported();\n }\n async fetchVideoGenerationResult(\n _a: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n return this.unsupported();\n }\n async cancelVideoGenerationJob(_a: VideoGenerationJob): Promise<void> {\n return this.unsupported();\n }\n async validateVideoGenerationAccess(): Promise<boolean> {\n return this.unsupported();\n }\n async synthesizeSpeech(_a: string, _b?: TTSOptions): Promise<TTSResponse> {\n return this.unsupported();\n }\n streamSpeech(_a: string, _b?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by the Laya decision-only provider.',\n 'NOT_IMPLEMENTED',\n PROVIDER,\n );\n return {\n [Symbol.asyncIterator]: () => ({ next: () => Promise.reject(error) }),\n };\n }\n async cloneVoice(_a: VoiceCloneOptions): Promise<Voice> {\n return this.unsupported();\n }\n async designVoice(_a: VoiceDesignOptions): Promise<Voice> {\n return this.unsupported();\n }\n async getVoices(_a?: VoiceListOptions): Promise<Voice[]> {\n return this.unsupported();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"laya-DuRRHJHo.js","names":[],"sources":["../../src/shared/providers/laya.ts"],"sourcesContent":["/**\n * Laya typed-decision provider.\n *\n * Laya (https://github.com/NandhaKishorM/laya) is a self-hosted,\n * non-autoregressive decision engine. Its `laya-serve` HTTP server answers the\n * Jev `POST /v1/systemone` wire shape, with differences this adapter handles\n * itself rather than inheriting from the TypeSafe adapter: optional auth, a\n * checkpoint chosen by the server's router, a `max_len` token window,\n * probabilities rounded to four decimals one at a time, and truncation facts.\n *\n * The public SDK contract calls Laya's `noul` primitive a `predicate`; the\n * server's vocabulary stays confined to this wire translation.\n */\n\nimport { ValidationError } from '@happyvertical/utils';\n\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport { normalizeBaseAIOptions, prepareRequestControls } from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n DecisionAnswer,\n DecisionQuestion,\n DecisionRequest,\n DecisionResult,\n DecisionValue,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n LayaDecisionOptions,\n LayaOptions,\n MessageOptions,\n ScoreDecisionQuestion,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport { AIError, AuthenticationError } from '../types';\nimport { emitUsage } from './usage';\n\nconst PROVIDER = 'laya';\n\n/** Distributions this close to unit mass are used exactly as received. */\nconst STRICT_DISTRIBUTION_EPSILON = 1e-6;\n/**\n * `laya-serve` rounds every probability to four decimals on its own, so each\n * value is off by at most half of the last place and a distribution of `n`\n * values can be off by `n * 0.00005`.\n */\nconst ROUNDING_ERROR_PER_VALUE = 5e-5;\n/** No rounding story justifies renormalizing a distribution further out. */\nconst MAX_NORMALIZED_ERROR = 0.01;\n\ntype WireQuestion =\n | {\n type: 'noul';\n instructions: DecisionValue;\n criteria?: Record<string, DecisionValue>;\n }\n | {\n type: 'choice';\n instructions: DecisionValue;\n criteria: Record<string, DecisionValue | null>;\n }\n | { type: 'score'; instructions: DecisionValue; criteria: DecisionValue[] };\n\ninterface WireRequest {\n state: DecisionValue;\n questions: Record<string, WireQuestion>;\n model?: string;\n max_len?: number;\n}\n\ninterface WireResponse {\n model?: unknown;\n answers?: unknown;\n usage?: unknown;\n routing?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction invalid(message: string): AIError {\n return new AIError(`Laya response ${message}`, 'INVALID_RESPONSE', PROVIDER);\n}\n\nfunction finite(value: unknown, field: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value))\n throw invalid(`${field} must be finite`);\n return value;\n}\n\nfunction probability(value: unknown, field: string): number {\n const result = finite(value, field);\n if (result < 0 || result > 1)\n throw invalid(`${field} must be between 0 and 1`);\n return result;\n}\n\nfunction tokenCount(value: unknown, field: string): number {\n const result = finite(value, field);\n if (!Number.isSafeInteger(result) || result < 0)\n throw invalid(`${field} must be a non-negative integer`);\n return result;\n}\n\nfunction optionalString(\n source: Record<string, unknown>,\n key: string,\n field: string,\n): string | undefined {\n const value = source[key];\n if (value === undefined) return undefined;\n if (typeof value !== 'string' || !value)\n throw invalid(`${field} must be a non-empty string`);\n return value;\n}\n\nfunction sameDecisionValue(left: DecisionValue, right: unknown): boolean {\n if (left === right) return true;\n if (Array.isArray(left)) {\n return (\n Array.isArray(right) &&\n left.length === right.length &&\n left.every((value, index) => sameDecisionValue(value, right[index]))\n );\n }\n if (isRecord(left)) {\n return (\n isRecord(right) &&\n Object.keys(left).length === Object.keys(right).length &&\n Object.entries(left).every(\n ([key, value]) => key in right && sameDecisionValue(value, right[key]),\n )\n );\n }\n return false;\n}\n\n/**\n * `laya-serve` returns a rubric level in `legend` as sent when it is a string\n * and as Python's `json.dumps` text when it is anything else.\n */\nfunction legendMatches(level: DecisionValue, legend: unknown): boolean {\n if (sameDecisionValue(level, legend)) return true;\n if (typeof level === 'string' || typeof legend !== 'string') return false;\n try {\n return sameDecisionValue(level, JSON.parse(legend));\n } catch {\n return false;\n }\n}\n\nfunction validateValue(\n value: unknown,\n field: string,\n): asserts value is DecisionValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean')\n return;\n if (typeof value === 'number') {\n if (!Number.isFinite(value))\n throw new ValidationError(`${field} must contain finite numbers`, {\n provider: PROVIDER,\n });\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n validateValue(item, `${field}[${index}]`);\n });\n return;\n }\n if (isRecord(value)) {\n Object.entries(value).forEach(([key, item]) => {\n validateValue(item, `${field}.${key}`);\n });\n return;\n }\n throw new ValidationError(`${field} must be JSON-compatible`, {\n provider: PROVIDER,\n });\n}\n\nfunction validateMaxLen(value: unknown, field: string): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0)\n throw new ValidationError(`${field} must be a positive integer`, {\n provider: PROVIDER,\n });\n return value;\n}\n\n/**\n * Checks the provider-neutral request shape. Laya's own size limits (questions\n * per request, options per question, state length) are left to the server,\n * which reports them as explicit 413 errors.\n */\nfunction validateRequest(request: DecisionRequest): void {\n if (request.state === null || request.state === undefined)\n throw new ValidationError('state is required', { provider: PROVIDER });\n validateValue(request.state, 'state');\n const entries = Object.entries(request.questions || {});\n if (entries.length === 0)\n throw new ValidationError('questions must not be empty', {\n provider: PROVIDER,\n });\n for (const [id, question] of entries) {\n if (!id.trim())\n throw new ValidationError('question IDs must not be empty', {\n provider: PROVIDER,\n });\n validateValue(question.instructions, `questions.${id}.instructions`);\n if (question.type === 'predicate') {\n if (question.criteria) {\n for (const [key, value] of Object.entries(question.criteria))\n validateValue(value, `questions.${id}.criteria.${key}`);\n }\n } else if (question.type === 'choice') {\n const options = Object.keys(question.criteria || {});\n if (options.length === 0)\n throw new ValidationError(\n `questions.${id}.criteria must contain at least one option`,\n { provider: PROVIDER },\n );\n for (const [key, value] of Object.entries(question.criteria))\n if (value !== null)\n validateValue(value, `questions.${id}.criteria.${key}`);\n } else if (question.type === 'score') {\n if (!Array.isArray(question.criteria) || question.criteria.length < 2)\n throw new ValidationError(\n `questions.${id}.criteria must contain at least 2 ordered levels`,\n { provider: PROVIDER },\n );\n question.criteria.forEach((value, index) => {\n // Laya rejects a null level because its legend entry would be null.\n if (value === null)\n throw new ValidationError(\n `questions.${id}.criteria[${index}] must describe the level`,\n { provider: PROVIDER },\n );\n validateValue(value, `questions.${id}.criteria[${index}]`);\n });\n } else {\n throw new ValidationError(`questions.${id}.type is unsupported`, {\n provider: PROVIDER,\n });\n }\n }\n}\n\n/**\n * Builds each wire question field by field so unknown properties on a caller's\n * object (for example a generation control) are never forwarded.\n */\nfunction wireQuestion(question: DecisionQuestion): WireQuestion {\n if (question.type === 'predicate')\n return {\n type: 'noul',\n instructions: question.instructions,\n ...(question.criteria ? { criteria: question.criteria } : {}),\n };\n if (question.type === 'choice')\n return {\n type: 'choice',\n instructions: question.instructions,\n criteria: question.criteria,\n };\n return {\n type: 'score',\n instructions: question.instructions,\n criteria: question.criteria,\n };\n}\n\n/** Resolves the server root from a base URL that may carry the API path. */\nfunction serverRoot(value: string | undefined): string {\n const text = (value || '').trim();\n if (!text)\n throw new ValidationError(\n 'Laya requires baseUrl, for example http://localhost:8000',\n { provider: PROVIDER },\n );\n let url: URL;\n try {\n url = new URL(text);\n } catch {\n throw new ValidationError('Laya baseUrl must be an absolute http(s) URL', {\n provider: PROVIDER,\n });\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:')\n throw new ValidationError('Laya baseUrl must be an absolute http(s) URL', {\n provider: PROVIDER,\n });\n if (url.search || url.hash || url.username || url.password)\n throw new ValidationError(\n 'Laya baseUrl must not contain credentials, a query, or a fragment',\n { provider: PROVIDER },\n );\n const path = url.pathname\n .replace(/\\/+$/, '')\n .replace(/\\/v1(\\/systemone)?$/, '');\n return `${url.origin}${path}`;\n}\n\ninterface Distribution {\n values: Record<string, number>;\n /** The values as received, set only when they were renormalized. */\n raw?: Record<string, number>;\n}\n\n/**\n * Validates a choice or score distribution. Mass within the four-decimal\n * rounding bound is normalized by its actual sum; anything else is rejected.\n */\nfunction distribution(\n value: unknown,\n expected: string[],\n field: string,\n): Distribution {\n if (\n !isRecord(value) ||\n Object.keys(value).length !== expected.length ||\n expected.some((key) => !(key in value))\n )\n throw invalid(`${field} must cover exactly the requested values`);\n const values = Object.fromEntries(\n expected.map((key) => [key, probability(value[key], `${field}.${key}`)]),\n );\n const sum = Object.values(values).reduce((total, item) => total + item, 0);\n const drift = Math.abs(sum - 1);\n if (drift <= STRICT_DISTRIBUTION_EPSILON) return { values };\n const allowed =\n Math.min(expected.length * ROUNDING_ERROR_PER_VALUE, MAX_NORMALIZED_ERROR) +\n STRICT_DISTRIBUTION_EPSILON;\n if (sum <= 0 || drift > allowed) throw invalid(`${field} must sum to 1`);\n return {\n values: Object.fromEntries(\n Object.entries(values).map(([key, item]) => [key, item / sum]),\n ),\n raw: values,\n };\n}\n\nfunction answer(\n question: DecisionQuestion,\n raw: unknown,\n id: string,\n renormalized: Record<string, Record<string, number>>,\n): DecisionAnswer {\n if (!isRecord(raw)) throw invalid(`answers.${id} must be an object`);\n if (question.type === 'predicate') {\n if (raw.type !== 'noul')\n throw invalid(`answers.${id} type does not match predicate`);\n return {\n type: 'predicate',\n probability: probability(raw.noul, `answers.${id}.noul`),\n };\n }\n if (raw.type !== question.type)\n throw invalid(`answers.${id} type does not match request`);\n if (question.type === 'choice') {\n const choices = Object.keys(question.criteria);\n if (typeof raw.choice !== 'string' || !choices.includes(raw.choice))\n throw invalid(`answers.${id}.choice is not a requested option`);\n const probabilities = distribution(\n raw.probabilities,\n choices,\n `answers.${id}.probabilities`,\n );\n if (probabilities.raw) renormalized[id] = probabilities.raw;\n return {\n type: 'choice',\n choice: raw.choice,\n probabilities: probabilities.values,\n confidence: probability(raw.confidence, `answers.${id}.confidence`),\n };\n }\n const levels = (question as ScoreDecisionQuestion).criteria;\n const levelKeys = levels.map((_, index) => String(index));\n const score = finite(raw.score, `answers.${id}.score`);\n if (score < 0 || score > levels.length - 1)\n throw invalid(`answers.${id}.score is outside the requested rubric`);\n const legend = raw.legend;\n if (\n !isRecord(legend) ||\n levelKeys.some((key, index) => !legendMatches(levels[index], legend[key]))\n )\n throw invalid(`answers.${id}.legend does not match the requested rubric`);\n const probabilities = distribution(\n raw.probabilities,\n levelKeys,\n `answers.${id}.probabilities`,\n );\n if (probabilities.raw) renormalized[id] = probabilities.raw;\n return {\n type: 'score',\n score,\n probabilities: probabilities.values,\n confidence: probability(raw.confidence, `answers.${id}.confidence`),\n levels,\n };\n}\n\n/** A decision-only adapter for a `laya-serve` `/v1/systemone` endpoint. */\nexport class LayaProvider implements AIInterface {\n private readonly options: LayaOptions;\n private readonly root: string;\n private readonly maxLen?: number;\n\n constructor(options: LayaOptions) {\n this.root = serverRoot(options.baseUrl);\n this.maxLen = validateMaxLen(options.maxLen, 'maxLen');\n this.options = normalizeBaseAIOptions({ ...options, baseUrl: this.root });\n }\n\n async decide(\n request: DecisionRequest,\n options: LayaDecisionOptions = {},\n ): Promise<DecisionResult> {\n validateRequest(request);\n const maxLen = validateMaxLen(options.maxLen, 'maxLen') ?? this.maxLen;\n const controls = prepareRequestControls(this.options, options);\n const startedAt = Date.now();\n const requestedModel =\n options.model || this.options.defaultModel || undefined;\n const wire: WireRequest = {\n state: request.state,\n questions: Object.fromEntries(\n Object.entries(request.questions).map(([id, question]) => [\n id,\n wireQuestion(question),\n ]),\n ),\n ...(requestedModel ? { model: requestedModel } : {}),\n ...(maxLen !== undefined ? { max_len: maxLen } : {}),\n };\n try {\n const response = await fetch(`${this.root}/v1/systemone`, {\n method: 'POST',\n redirect: 'error',\n headers: {\n ...(this.options.apiKey\n ? { Authorization: `Bearer ${this.options.apiKey}` }\n : {}),\n 'Content-Type': 'application/json',\n ...this.options.headers,\n },\n body: JSON.stringify(wire),\n signal: controls.signal,\n });\n if (!response.ok) {\n if (response.status === 401) throw new AuthenticationError(PROVIDER);\n const text = await response.text();\n // 503 is laya-serve's admission limit (LAYA_MAX_CONCURRENT), which\n // sends Retry-After; 429 covers a rate-limiting proxy in front of it.\n if (response.status === 429 || response.status === 503)\n throw rateLimitErrorFrom(\n PROVIDER,\n { headers: response.headers, message: text },\n { model: requestedModel },\n );\n throw new AIError(\n `Laya request failed (${response.status}): ${text.slice(0, 500)}`,\n 'API_ERROR',\n PROVIDER,\n requestedModel,\n response.status >= 500,\n );\n }\n let body: WireResponse;\n try {\n body = (await response.json()) as WireResponse;\n } catch (error) {\n if (error instanceof SyntaxError)\n throw new AIError(\n 'Laya response contained invalid JSON',\n 'INVALID_RESPONSE',\n PROVIDER,\n requestedModel,\n );\n throw error;\n }\n return this.result(\n request,\n body,\n requestedModel,\n maxLen,\n options,\n startedAt,\n );\n } catch (error) {\n if (controls.didTimeout())\n throw new AIError(\n `Laya request timed out after ${controls.timeout}ms`,\n 'REQUEST_TIMEOUT',\n PROVIDER,\n requestedModel,\n true,\n );\n if (controls.signal.aborted && !(error instanceof AIError))\n throw new AIError(\n 'Laya request was aborted',\n 'REQUEST_ABORTED',\n PROVIDER,\n requestedModel,\n );\n if (!(error instanceof AIError)) {\n throw new AIError(\n `Network error calling Laya: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'NETWORK_ERROR',\n PROVIDER,\n requestedModel,\n true,\n );\n }\n throw error;\n } finally {\n controls.cleanup();\n }\n }\n\n private result(\n request: DecisionRequest,\n body: WireResponse,\n requestedModel: string | undefined,\n maxLen: number | undefined,\n options: LayaDecisionOptions,\n startedAt: number,\n ): DecisionResult {\n if (!isRecord(body)) throw invalid('must be an object');\n // The root `model` names Laya's decision head, not the checkpoint.\n if (typeof body.model !== 'string' || !body.model)\n throw invalid('model is required');\n if (!isRecord(body.answers)) throw invalid('answers is required');\n const responseAnswers = body.answers;\n const ids = Object.keys(request.questions);\n if (\n Object.keys(responseAnswers).length !== ids.length ||\n ids.some((id) => !(id in responseAnswers))\n )\n throw invalid('answers must match requested question IDs');\n const renormalized: Record<string, Record<string, number>> = {};\n const answers = Object.fromEntries(\n ids.map((id) => [\n id,\n answer(request.questions[id], responseAnswers[id], id, renormalized),\n ]),\n );\n\n let usage:\n | { promptTokens: number; completionTokens: number; totalTokens: number }\n | undefined;\n const facts: Record<string, DecisionValue> = {};\n if (body.usage !== undefined) {\n const wireUsage = body.usage;\n if (\n !isRecord(wireUsage) ||\n !('input_tokens' in wireUsage) ||\n !('output_tokens' in wireUsage)\n )\n throw invalid('usage must include input_tokens and output_tokens');\n const input = tokenCount(wireUsage.input_tokens, 'usage.input_tokens');\n const output = tokenCount(wireUsage.output_tokens, 'usage.output_tokens');\n usage = {\n promptTokens: input,\n completionTokens: output,\n totalTokens: input + output,\n };\n // Truncation is invisible anywhere else in the response.\n for (const [key, name] of [\n ['state_tokens', 'stateTokens'],\n ['state_tokens_dropped', 'stateTokensDropped'],\n ] as const)\n if (wireUsage[key] !== undefined)\n facts[name] = tokenCount(wireUsage[key], `usage.${key}`);\n if (wireUsage.truncated !== undefined) {\n if (typeof wireUsage.truncated !== 'boolean')\n throw invalid('usage.truncated must be a boolean');\n facts.truncated = wireUsage.truncated;\n }\n if (wireUsage.truncated_questions !== undefined) {\n const truncated = wireUsage.truncated_questions;\n if (\n !Array.isArray(truncated) ||\n truncated.some((id) => typeof id !== 'string')\n )\n throw invalid('usage.truncated_questions must list question IDs');\n facts.truncatedQuestions = truncated as string[];\n }\n }\n\n let checkpoint: string | undefined;\n if (body.routing !== undefined) {\n if (!isRecord(body.routing)) throw invalid('routing must be an object');\n checkpoint = optionalString(body.routing, 'model', 'routing.model');\n const repo = optionalString(body.routing, 'repo', 'routing.repo');\n const reason = optionalString(body.routing, 'reason', 'routing.reason');\n if (checkpoint) facts.checkpoint = checkpoint;\n if (repo) facts.checkpointRepo = repo;\n if (reason) facts.routeReason = reason;\n }\n\n // The checkpoint that answered is reported only in `routing`, which a\n // server running LAYA_JEV_STRICT omits. Without it, report the decision\n // head and leave `details.checkpoint` unset rather than guess.\n const model = checkpoint || body.model;\n const renormalizedIds = Object.keys(renormalized);\n const details: Record<string, DecisionValue> = {\n serverModel: body.model,\n ...(requestedModel ? { requestedModel } : {}),\n ...(maxLen !== undefined ? { maxLen } : {}),\n ...facts,\n ...(renormalizedIds.length\n ? { renormalized: renormalizedIds, rawProbabilities: renormalized }\n : {}),\n };\n emitUsage(\n this.options,\n PROVIDER,\n 'decide',\n model,\n usage,\n startedAt,\n options.usageTags,\n );\n return {\n model,\n ...(usage ? { usage } : {}),\n provenance: { provider: PROVIDER, model, details },\n answers,\n };\n }\n\n async getModels(): Promise<AIModel[]> {\n // laya-serve has no model-listing route; these are the checkpoints of the\n // convaiinnovations/laya bundle. A server may register others.\n const checkpoints: Array<[string, string, number]> = [\n ['typed-decisions', 'Laya typed decisions (421M)', 1024],\n ['english', 'Laya English (421M)', 512],\n ['multilingual', 'Laya multilingual (322M)', 1024],\n ];\n const configured = this.options.defaultModel;\n const models = checkpoints.map(([id, name, contextLength]) => ({\n id,\n name,\n description: 'Laya typed decisions',\n contextLength,\n capabilities: ['decisions'],\n supportsFunctions: false,\n supportsVision: false,\n }));\n if (configured && !models.some((model) => model.id === configured))\n models.push({\n id: configured,\n name: configured,\n description: 'Laya typed decisions (configured checkpoint)',\n contextLength: 0,\n capabilities: ['decisions'],\n supportsFunctions: false,\n supportsVision: false,\n });\n return models;\n }\n async getCapabilities(): Promise<AICapabilities> {\n return {\n decisions: true,\n chat: false,\n completion: false,\n embeddings: false,\n streaming: false,\n functions: false,\n vision: false,\n fineTuning: false,\n imageEmbeddings: false,\n imageGeneration: false,\n videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 0,\n supportedOperations: ['decide'],\n };\n }\n private unsupported(): never {\n throw new AIError(\n 'This operation is not supported by the Laya decision-only provider.',\n 'NOT_IMPLEMENTED',\n PROVIDER,\n );\n }\n async chat(_a: AIMessage[], _b?: ChatOptions): Promise<AIResponse> {\n return this.unsupported();\n }\n async complete(_a: string, _b?: CompletionOptions): Promise<AIResponse> {\n return this.unsupported();\n }\n async message(_a: string, _b?: MessageOptions): Promise<string> {\n return this.unsupported();\n }\n async embed(\n _a: string | string[],\n _b?: EmbeddingOptions,\n ): Promise<EmbeddingResponse> {\n return this.unsupported();\n }\n async embedImage(\n _a: string | Buffer,\n _b?: ImageEmbeddingOptions,\n ): Promise<EmbeddingResponse> {\n return this.unsupported();\n }\n async describeImage(\n _a: string | Buffer,\n _b?: string,\n _c?: ImageDescriptionOptions,\n ): Promise<string> {\n return this.unsupported();\n }\n async generateImage(\n _a: string,\n _b?: ImageGenerationOptions,\n ): Promise<ImageGenerationResponse> {\n return this.unsupported();\n }\n stream(_a: AIMessage[], _b?: ChatOptions): AsyncIterable<string> {\n const error = new AIError(\n 'Chat streaming is not supported by the Laya decision-only provider.',\n 'NOT_IMPLEMENTED',\n PROVIDER,\n );\n return {\n [Symbol.asyncIterator]: () => ({ next: () => Promise.reject(error) }),\n };\n }\n async countTokens(_a: string): Promise<number> {\n return this.unsupported();\n }\n async submitVideoGenerationJob(\n _a: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n return this.unsupported();\n }\n async getVideoGenerationJob(\n _a: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n return this.unsupported();\n }\n async fetchVideoGenerationResult(\n _a: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n return this.unsupported();\n }\n async cancelVideoGenerationJob(_a: VideoGenerationJob): Promise<void> {\n return this.unsupported();\n }\n async validateVideoGenerationAccess(): Promise<boolean> {\n return this.unsupported();\n }\n async synthesizeSpeech(_a: string, _b?: TTSOptions): Promise<TTSResponse> {\n return this.unsupported();\n }\n streamSpeech(_a: string, _b?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by the Laya decision-only provider.',\n 'NOT_IMPLEMENTED',\n PROVIDER,\n );\n return {\n [Symbol.asyncIterator]: () => ({ next: () => Promise.reject(error) }),\n };\n }\n async cloneVoice(_a: VoiceCloneOptions): Promise<Voice> {\n return this.unsupported();\n }\n async designVoice(_a: VoiceDesignOptions): Promise<Voice> {\n return this.unsupported();\n }\n async getVoices(_a?: VoiceListOptions): Promise<Voice[]> {\n return this.unsupported();\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { c as normalizeChatOptions, l as normalizeImageGenerationOptions } from "./usage-yIT5lpQm.js";
2
- import { _ as OpenAIProvider } from "./src-CWFnwztw.js";
3
- import { a as LiteLLMAdmin, n as isSpeechModel, r as isTranscriptionModel, s as resolveGatewayAdminBaseUrl, t as isAudioModel } from "./gateway-audio-models-57sR3hHE.js";
1
+ import { l as normalizeChatOptions, u as normalizeImageGenerationOptions } from "./usage-B40bJZ49.js";
2
+ import { _ as OpenAIProvider } from "./src-EMvAiwjJ.js";
3
+ import { a as LiteLLMAdmin, n as isSpeechModel, r as isTranscriptionModel, s as resolveGatewayAdminBaseUrl, t as isAudioModel } from "./gateway-audio-models-Cs7vu956.js";
4
4
  import { ValidationError } from "@happyvertical/utils";
5
5
  //#region src/shared/providers/litellm.ts
6
6
  /** Chat Completions has effort, not a generic reasoning budget/thoughts envelope. */
@@ -194,4 +194,4 @@ var LiteLLMProvider = class extends OpenAIProvider {
194
194
  //#endregion
195
195
  export { LiteLLMProvider };
196
196
 
197
- //# sourceMappingURL=litellm-Bhns6CSh.js.map
197
+ //# sourceMappingURL=litellm-Cc6xC6sj.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"litellm-Bhns6CSh.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-Cc6xC6sj.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,7 +1,7 @@
1
- import { _ as ModelNotFoundError, c as normalizeChatOptions, d as AIError, h as ContextLengthError, l as normalizeImageGenerationOptions, m as ContentFilterError, p as AuthenticationError, s as normalizeBaseAIOptions, t as emitUsage, u as prepareRequestControls, x as extractTextContent } from "./usage-yIT5lpQm.js";
2
- import { n as rateLimitErrorFrom } from "./rate-limit-B3Kz6v4j.js";
1
+ import { T as extractTextContent, _ as AuthenticationError, c as normalizeBaseAIOptions, d as prepareRequestControls, h as AIError, l as normalizeChatOptions, n as emitUsage, u as normalizeImageGenerationOptions, v as ContentFilterError, x as ModelNotFoundError, y as ContextLengthError } from "./usage-B40bJZ49.js";
2
+ import { n as rateLimitErrorFrom } from "./rate-limit-B9BFC8ld.js";
3
3
  import { n as reportReasoning } from "./reasoning-DCCN0I3I.js";
4
- import { n as resolveContinuation } from "./continuation-B-b0Iqgj.js";
4
+ import { n as resolveContinuation } from "./continuation-Dgw5Zujl.js";
5
5
  import { i as resolveToolResultName, n as indexToolCallNames } from "./tool-messages-0ND35mYX.js";
6
6
  import { ValidationError } from "@happyvertical/utils";
7
7
  //#region src/shared/providers/ollama.ts
@@ -345,7 +345,10 @@ var OllamaProvider = class {
345
345
  }
346
346
  mapThink(options) {
347
347
  if (options.reasoning?.maxTokens === 0) return false;
348
- if (options.reasoning?.effort) return options.reasoning.effort === "none" ? false : options.reasoning.effort;
348
+ if (options.reasoning?.effort) {
349
+ if (options.reasoning.effort === "none") return false;
350
+ return options.reasoning.effort === "xhigh" || options.reasoning.effort === "max" ? "high" : options.reasoning.effort;
351
+ }
349
352
  if (!Object.hasOwn(options, "thinkingLevel")) return;
350
353
  return options.thinkingLevel;
351
354
  }
@@ -676,4 +679,4 @@ var OllamaProvider = class {
676
679
  //#endregion
677
680
  export { OllamaProvider };
678
681
 
679
- //# sourceMappingURL=ollama-pL2WCpkS.js.map
682
+ //# sourceMappingURL=ollama-D5dILl5b.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama-D5dILl5b.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 { reportReasoning } from '../reasoning';\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 if (options.reasoning.effort === 'none') return false;\n // Ollama's levels stop at 'high'.\n return options.reasoning.effort === 'xhigh' ||\n options.reasoning.effort === 'max'\n ? 'high'\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 ...(response.message?.thinking\n ? { reasoning: response.message.thinking }\n : {}),\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 ...(response.thinking ? { reasoning: response.thinking } : {}),\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 // Delivered in `finally`, so a failed, aborted, or abandoned stream still\n // reports the thinking that arrived before it ended.\n let reasoning = '';\n const onReasoning = options.onReasoning;\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 (typeof chunk.message?.thinking === 'string') {\n reasoning += chunk.message.thinking;\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 reportReasoning(onReasoning, reasoning);\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,5 +1,5 @@
1
- import { d as AIError, p as AuthenticationError, s as normalizeBaseAIOptions, t as emitUsage } from "./usage-yIT5lpQm.js";
2
- import { n as rateLimitErrorFrom } from "./rate-limit-B3Kz6v4j.js";
1
+ import { _ as AuthenticationError, c as normalizeBaseAIOptions, h as AIError, n as emitUsage } from "./usage-B40bJZ49.js";
2
+ import { n as rateLimitErrorFrom } from "./rate-limit-B9BFC8ld.js";
3
3
  import { ValidationError } from "@happyvertical/utils";
4
4
  //#region src/shared/providers/openai-compat-video.ts
5
5
  /**
@@ -367,4 +367,4 @@ var OpenAICompatVideoProvider = class {
367
367
  //#endregion
368
368
  export { OpenAICompatVideoProvider };
369
369
 
370
- //# sourceMappingURL=openai-compat-video-BoLwWXJM.js.map
370
+ //# sourceMappingURL=openai-compat-video-DMu4hsI5.js.map