@mastra/core 0.20.0 → 0.20.1-alpha.2

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 (200) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/agent/agent.d.ts +375 -9
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/index.cjs +11 -11
  5. package/dist/agent/index.js +2 -2
  6. package/dist/agent/input-processor/index.cjs +6 -6
  7. package/dist/agent/input-processor/index.js +1 -1
  8. package/dist/agent/types.d.ts +66 -0
  9. package/dist/agent/types.d.ts.map +1 -1
  10. package/dist/agent/workflows/prepare-stream/index.d.ts +19 -3
  11. package/dist/agent/workflows/prepare-stream/index.d.ts.map +1 -1
  12. package/dist/agent/workflows/prepare-stream/prepare-memory-step.d.ts +5 -1
  13. package/dist/agent/workflows/prepare-stream/prepare-memory-step.d.ts.map +1 -1
  14. package/dist/agent/workflows/prepare-stream/prepare-tools-step.d.ts +5 -1
  15. package/dist/agent/workflows/prepare-stream/prepare-tools-step.d.ts.map +1 -1
  16. package/dist/agent/workflows/prepare-stream/stream-step.d.ts +5 -1
  17. package/dist/agent/workflows/prepare-stream/stream-step.d.ts.map +1 -1
  18. package/dist/ai-tracing/index.cjs +32 -32
  19. package/dist/ai-tracing/index.js +1 -1
  20. package/dist/{chunk-3NNB72OL.cjs → chunk-33DTPWTJ.cjs} +7 -7
  21. package/dist/{chunk-3NNB72OL.cjs.map → chunk-33DTPWTJ.cjs.map} +1 -1
  22. package/dist/{chunk-CJDOU6WP.js → chunk-3KBXOXG6.js} +3 -3
  23. package/dist/{chunk-CJDOU6WP.js.map → chunk-3KBXOXG6.js.map} +1 -1
  24. package/dist/{chunk-ZNK5RN5D.cjs → chunk-3Z3DP6S2.cjs} +6 -6
  25. package/dist/{chunk-ZNK5RN5D.cjs.map → chunk-3Z3DP6S2.cjs.map} +1 -1
  26. package/dist/{chunk-KGBDRSMX.js → chunk-5I6DXBUR.js} +4 -4
  27. package/dist/{chunk-KGBDRSMX.js.map → chunk-5I6DXBUR.js.map} +1 -1
  28. package/dist/{chunk-7EUC32F3.cjs → chunk-6K7IMZVR.cjs} +617 -24
  29. package/dist/chunk-6K7IMZVR.cjs.map +1 -0
  30. package/dist/{chunk-FV4QVXO4.js → chunk-6OLRLZJ3.js} +37 -2
  31. package/dist/chunk-6OLRLZJ3.js.map +1 -0
  32. package/dist/{chunk-OXLN4CWA.js → chunk-B5GBHE4E.js} +3 -3
  33. package/dist/{chunk-OXLN4CWA.js.map → chunk-B5GBHE4E.js.map} +1 -1
  34. package/dist/{chunk-2SH5WPUA.cjs → chunk-BG5FC6ZZ.cjs} +407 -803
  35. package/dist/chunk-BG5FC6ZZ.cjs.map +1 -0
  36. package/dist/{chunk-COYTVUIL.js → chunk-EKFF7JLS.js} +610 -17
  37. package/dist/chunk-EKFF7JLS.js.map +1 -0
  38. package/dist/{chunk-BOJNXNRV.js → chunk-FJIABZVI.js} +3 -3
  39. package/dist/{chunk-BOJNXNRV.js.map → chunk-FJIABZVI.js.map} +1 -1
  40. package/dist/{chunk-RYFQKXXS.js → chunk-H4KO46HZ.js} +3 -3
  41. package/dist/{chunk-RYFQKXXS.js.map → chunk-H4KO46HZ.js.map} +1 -1
  42. package/dist/{chunk-T4H33PBR.cjs → chunk-IKLSJCMT.cjs} +360 -69
  43. package/dist/chunk-IKLSJCMT.cjs.map +1 -0
  44. package/dist/{chunk-K4AYIXVH.cjs → chunk-L5A4MRCK.cjs} +4 -4
  45. package/dist/{chunk-K4AYIXVH.cjs.map → chunk-L5A4MRCK.cjs.map} +1 -1
  46. package/dist/{chunk-DVHBWEYY.cjs → chunk-LCJHFYJS.cjs} +7 -7
  47. package/dist/{chunk-DVHBWEYY.cjs.map → chunk-LCJHFYJS.cjs.map} +1 -1
  48. package/dist/{chunk-I6TOPBP6.cjs → chunk-MHHMY2K4.cjs} +49 -18
  49. package/dist/chunk-MHHMY2K4.cjs.map +1 -0
  50. package/dist/{chunk-DQISKQDE.js → chunk-OBAFLVGD.js} +342 -51
  51. package/dist/chunk-OBAFLVGD.js.map +1 -0
  52. package/dist/{chunk-6R46VE63.js → chunk-OPHFW56S.js} +39 -8
  53. package/dist/chunk-OPHFW56S.js.map +1 -0
  54. package/dist/{chunk-LCJP7LWN.cjs → chunk-P4ZPZKZY.cjs} +6 -6
  55. package/dist/{chunk-LCJP7LWN.cjs.map → chunk-P4ZPZKZY.cjs.map} +1 -1
  56. package/dist/{chunk-QR5VZWWT.js → chunk-P7WEYMRS.js} +3 -3
  57. package/dist/{chunk-QR5VZWWT.js.map → chunk-P7WEYMRS.js.map} +1 -1
  58. package/dist/{chunk-YEEAHLAK.cjs → chunk-PWPESTZZ.cjs} +4 -4
  59. package/dist/{chunk-YEEAHLAK.cjs.map → chunk-PWPESTZZ.cjs.map} +1 -1
  60. package/dist/{chunk-7HUKQ6SZ.cjs → chunk-Q3S3BXHO.cjs} +4 -4
  61. package/dist/{chunk-7HUKQ6SZ.cjs.map → chunk-Q3S3BXHO.cjs.map} +1 -1
  62. package/dist/{chunk-WP2KQXPV.js → chunk-RMMGYPXG.js} +3 -3
  63. package/dist/{chunk-WP2KQXPV.js.map → chunk-RMMGYPXG.js.map} +1 -1
  64. package/dist/{chunk-A4RAEU6X.cjs → chunk-SE4PA467.cjs} +37 -2
  65. package/dist/chunk-SE4PA467.cjs.map +1 -0
  66. package/dist/{chunk-AND6J5LG.js → chunk-W2WXYTYI.js} +407 -803
  67. package/dist/chunk-W2WXYTYI.js.map +1 -0
  68. package/dist/{chunk-OKIHIKXV.cjs → chunk-WE6ILDQY.cjs} +4 -4
  69. package/dist/{chunk-OKIHIKXV.cjs.map → chunk-WE6ILDQY.cjs.map} +1 -1
  70. package/dist/{chunk-ZJ2UFCTS.js → chunk-Y2TIJVKC.js} +3 -3
  71. package/dist/{chunk-ZJ2UFCTS.js.map → chunk-Y2TIJVKC.js.map} +1 -1
  72. package/dist/index.cjs +52 -52
  73. package/dist/index.cjs.map +1 -1
  74. package/dist/index.js +11 -11
  75. package/dist/index.js.map +1 -1
  76. package/dist/integration/index.cjs +3 -3
  77. package/dist/integration/index.js +1 -1
  78. package/dist/llm/index.cjs +6 -6
  79. package/dist/llm/index.d.ts +1 -1
  80. package/dist/llm/index.d.ts.map +1 -1
  81. package/dist/llm/index.js +1 -1
  82. package/dist/llm/model/gateway-resolver.d.ts +7 -5
  83. package/dist/llm/model/gateway-resolver.d.ts.map +1 -1
  84. package/dist/llm/model/gateways/base.d.ts +8 -6
  85. package/dist/llm/model/gateways/base.d.ts.map +1 -1
  86. package/dist/llm/model/gateways/constants.d.ts +3 -0
  87. package/dist/llm/model/gateways/constants.d.ts.map +1 -0
  88. package/dist/llm/model/gateways/index.d.ts +5 -0
  89. package/dist/llm/model/gateways/index.d.ts.map +1 -1
  90. package/dist/llm/model/gateways/models-dev.d.ts +8 -2
  91. package/dist/llm/model/gateways/models-dev.d.ts.map +1 -1
  92. package/dist/llm/model/gateways/netlify.d.ts +11 -2
  93. package/dist/llm/model/gateways/netlify.d.ts.map +1 -1
  94. package/dist/llm/model/index.d.ts +1 -1
  95. package/dist/llm/model/index.d.ts.map +1 -1
  96. package/dist/llm/model/model.loop.d.ts +1 -1
  97. package/dist/llm/model/model.loop.d.ts.map +1 -1
  98. package/dist/llm/model/provider-registry.generated.d.ts +6 -7
  99. package/dist/llm/model/provider-registry.generated.d.ts.map +1 -1
  100. package/dist/llm/model/router.d.ts +23 -0
  101. package/dist/llm/model/router.d.ts.map +1 -0
  102. package/dist/loop/index.cjs +2 -2
  103. package/dist/loop/index.js +1 -1
  104. package/dist/loop/network/index.d.ts +5 -1
  105. package/dist/loop/network/index.d.ts.map +1 -1
  106. package/dist/loop/workflows/agentic-execution/index.d.ts +5 -1
  107. package/dist/loop/workflows/agentic-execution/index.d.ts.map +1 -1
  108. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts +5 -1
  109. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts.map +1 -1
  110. package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts +5 -1
  111. package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts.map +1 -1
  112. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts +5 -1
  113. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts.map +1 -1
  114. package/dist/loop/workflows/agentic-loop/index.d.ts +5 -1
  115. package/dist/loop/workflows/agentic-loop/index.d.ts.map +1 -1
  116. package/dist/mastra/index.cjs +2 -2
  117. package/dist/mastra/index.d.ts +695 -12
  118. package/dist/mastra/index.d.ts.map +1 -1
  119. package/dist/mastra/index.js +1 -1
  120. package/dist/memory/index.cjs +4 -4
  121. package/dist/memory/index.js +1 -1
  122. package/dist/processors/index.cjs +11 -11
  123. package/dist/processors/index.js +1 -1
  124. package/dist/relevance/index.cjs +4 -4
  125. package/dist/relevance/index.js +1 -1
  126. package/dist/scores/index.cjs +9 -9
  127. package/dist/scores/index.js +2 -2
  128. package/dist/scores/run-experiment/index.d.ts +2 -2
  129. package/dist/scores/run-experiment/index.d.ts.map +1 -1
  130. package/dist/scores/scoreTraces/index.cjs +8 -8
  131. package/dist/scores/scoreTraces/index.js +3 -3
  132. package/dist/scores/scoreTraces/scoreTracesWorkflow.d.ts +10 -2
  133. package/dist/scores/scoreTraces/scoreTracesWorkflow.d.ts.map +1 -1
  134. package/dist/storage/domains/operations/base.d.ts +6 -0
  135. package/dist/storage/domains/operations/base.d.ts.map +1 -1
  136. package/dist/storage/index.cjs +11 -3
  137. package/dist/storage/index.cjs.map +1 -1
  138. package/dist/storage/index.js +9 -1
  139. package/dist/storage/index.js.map +1 -1
  140. package/dist/stream/MastraAgentNetworkStream.d.ts +5 -1
  141. package/dist/stream/MastraAgentNetworkStream.d.ts.map +1 -1
  142. package/dist/stream/MastraWorkflowStream.d.ts +3 -3
  143. package/dist/stream/MastraWorkflowStream.d.ts.map +1 -1
  144. package/dist/stream/index.cjs +4 -4
  145. package/dist/stream/index.js +1 -1
  146. package/dist/test-utils/llm-mock.cjs +2 -2
  147. package/dist/test-utils/llm-mock.js +1 -1
  148. package/dist/tools/index.cjs +4 -4
  149. package/dist/tools/index.js +1 -1
  150. package/dist/tools/is-vercel-tool.cjs +2 -2
  151. package/dist/tools/is-vercel-tool.js +1 -1
  152. package/dist/tools/tool.d.ts +163 -0
  153. package/dist/tools/tool.d.ts.map +1 -1
  154. package/dist/utils.cjs +17 -17
  155. package/dist/utils.d.ts +1 -1
  156. package/dist/utils.d.ts.map +1 -1
  157. package/dist/utils.js +1 -1
  158. package/dist/workflows/default.d.ts +13 -7
  159. package/dist/workflows/default.d.ts.map +1 -1
  160. package/dist/workflows/evented/index.cjs +10 -10
  161. package/dist/workflows/evented/index.js +1 -1
  162. package/dist/workflows/evented/step-executor.d.ts +7 -3
  163. package/dist/workflows/evented/step-executor.d.ts.map +1 -1
  164. package/dist/workflows/evented/workflow-event-processor/index.d.ts.map +1 -1
  165. package/dist/workflows/evented/workflow-event-processor/loop.d.ts.map +1 -1
  166. package/dist/workflows/evented/workflow-event-processor/parallel.d.ts.map +1 -1
  167. package/dist/workflows/evented/workflow-event-processor/utils.d.ts +1 -1
  168. package/dist/workflows/evented/workflow.d.ts +23 -19
  169. package/dist/workflows/evented/workflow.d.ts.map +1 -1
  170. package/dist/workflows/execution-engine.d.ts +5 -1
  171. package/dist/workflows/execution-engine.d.ts.map +1 -1
  172. package/dist/workflows/index.cjs +12 -12
  173. package/dist/workflows/index.js +1 -1
  174. package/dist/workflows/legacy/index.cjs +22 -22
  175. package/dist/workflows/legacy/index.js +1 -1
  176. package/dist/workflows/step.d.ts +11 -4
  177. package/dist/workflows/step.d.ts.map +1 -1
  178. package/dist/workflows/types.d.ts +33 -9
  179. package/dist/workflows/types.d.ts.map +1 -1
  180. package/dist/workflows/workflow.d.ts +85 -56
  181. package/dist/workflows/workflow.d.ts.map +1 -1
  182. package/dist/workflows/workflow.warning.d.ts +2 -2
  183. package/dist/workflows/workflow.warning.d.ts.map +1 -1
  184. package/package.json +9 -4
  185. package/dist/chunk-2SH5WPUA.cjs.map +0 -1
  186. package/dist/chunk-45CV4JYJ.cjs +0 -4
  187. package/dist/chunk-45CV4JYJ.cjs.map +0 -1
  188. package/dist/chunk-6R46VE63.js.map +0 -1
  189. package/dist/chunk-7EUC32F3.cjs.map +0 -1
  190. package/dist/chunk-A4RAEU6X.cjs.map +0 -1
  191. package/dist/chunk-AND6J5LG.js.map +0 -1
  192. package/dist/chunk-COYTVUIL.js.map +0 -1
  193. package/dist/chunk-DQISKQDE.js.map +0 -1
  194. package/dist/chunk-FV4QVXO4.js.map +0 -1
  195. package/dist/chunk-I6TOPBP6.cjs.map +0 -1
  196. package/dist/chunk-RFGQ3EQV.js +0 -3
  197. package/dist/chunk-RFGQ3EQV.js.map +0 -1
  198. package/dist/chunk-T4H33PBR.cjs.map +0 -1
  199. package/dist/llm/model/openai-compatible.d.ts +0 -37
  200. package/dist/llm/model/openai-compatible.d.ts.map +0 -1
@@ -2,6 +2,352 @@
2
2
 
3
3
  var chunkUU5L5GDY_cjs = require('./chunk-UU5L5GDY.cjs');
4
4
  var chunkWM4VQWOZ_cjs = require('./chunk-WM4VQWOZ.cjs');
5
+ var crypto = require('crypto');
6
+ var anthropicV5 = require('@ai-sdk/anthropic-v5');
7
+ var googleV5 = require('@ai-sdk/google-v5');
8
+ var openaiCompatibleV5 = require('@ai-sdk/openai-compatible-v5');
9
+ var openaiV5 = require('@ai-sdk/openai-v5');
10
+ var xaiV5 = require('@ai-sdk/xai-v5');
11
+ var aiSdkProviderV5 = require('@openrouter/ai-sdk-provider-v5');
12
+
13
+ // src/llm/model/gateway-resolver.ts
14
+ function parseModelRouterId(routerId, gatewayPrefix) {
15
+ if (gatewayPrefix && !routerId.startsWith(`${gatewayPrefix}/`)) {
16
+ throw new Error(`Expected ${gatewayPrefix}/ in model router ID ${routerId}`);
17
+ }
18
+ const idParts = routerId.split("/");
19
+ if (gatewayPrefix && idParts.length < 3) {
20
+ throw new Error(
21
+ `Expected atleast 3 id parts ${gatewayPrefix}/provider/model, but only saw ${idParts.length} in ${routerId}`
22
+ );
23
+ }
24
+ const providerId = idParts.at(gatewayPrefix ? 1 : 0);
25
+ const modelId = idParts.slice(gatewayPrefix ? 2 : 1).join(`/`);
26
+ if (!routerId.includes(`/`) || !providerId || !modelId) {
27
+ throw new Error(
28
+ `Attempted to parse provider/model from ${routerId} but this ID doesn't appear to contain a provider`
29
+ );
30
+ }
31
+ return {
32
+ providerId,
33
+ modelId
34
+ };
35
+ }
36
+
37
+ // src/llm/model/gateways/base.ts
38
+ var MastraModelGateway = class {
39
+ };
40
+
41
+ // src/llm/model/gateways/constants.ts
42
+ var PROVIDERS_WITH_INSTALLED_PACKAGES = ["anthropic", "google", "openai", "openrouter", "xai"];
43
+ var EXCLUDED_PROVIDERS = ["github-copilot"];
44
+
45
+ // src/llm/model/gateways/models-dev.ts
46
+ var OPENAI_COMPATIBLE_OVERRIDES = {
47
+ cerebras: {
48
+ url: "https://api.cerebras.ai/v1/chat/completions"
49
+ },
50
+ xai: {
51
+ url: "https://api.x.ai/v1/chat/completions"
52
+ },
53
+ mistral: {
54
+ url: "https://api.mistral.ai/v1/chat/completions"
55
+ },
56
+ groq: {
57
+ url: "https://api.groq.com/openai/v1/chat/completions"
58
+ },
59
+ togetherai: {
60
+ url: "https://api.together.xyz/v1/chat/completions"
61
+ },
62
+ deepinfra: {
63
+ url: "https://api.deepinfra.com/v1/openai/chat/completions"
64
+ },
65
+ perplexity: {
66
+ url: "https://api.perplexity.ai/chat/completions"
67
+ },
68
+ vercel: {
69
+ url: "https://ai-gateway.vercel.sh/v1/chat/completions",
70
+ apiKeyEnvVar: "AI_GATEWAY_API_KEY"
71
+ }
72
+ };
73
+ var ModelsDevGateway = class extends MastraModelGateway {
74
+ name = "models.dev";
75
+ prefix = void 0;
76
+ // No prefix for registry gateway
77
+ providerConfigs = {};
78
+ constructor(providerConfigs) {
79
+ super();
80
+ if (providerConfigs) this.providerConfigs = providerConfigs;
81
+ }
82
+ async fetchProviders() {
83
+ console.info("Fetching providers from models.dev API...");
84
+ const response = await fetch("https://models.dev/api.json");
85
+ if (!response.ok) {
86
+ throw new Error(`Failed to fetch from models.dev: ${response.statusText}`);
87
+ }
88
+ const data = await response.json();
89
+ const providerConfigs = {};
90
+ for (const [providerId, providerInfo] of Object.entries(data)) {
91
+ if (EXCLUDED_PROVIDERS.includes(providerId)) continue;
92
+ if (!providerInfo || typeof providerInfo !== "object" || !providerInfo.models) continue;
93
+ const normalizedId = providerId;
94
+ const isOpenAICompatible = providerInfo.npm === "@ai-sdk/openai-compatible" || providerInfo.npm === "@ai-sdk/gateway" || // Vercel AI Gateway is OpenAI-compatible
95
+ normalizedId in OPENAI_COMPATIBLE_OVERRIDES;
96
+ const hasInstalledPackage = PROVIDERS_WITH_INSTALLED_PACKAGES.includes(providerId);
97
+ const hasApiAndEnv = providerInfo.api && providerInfo.env && providerInfo.env.length > 0;
98
+ if (isOpenAICompatible || hasInstalledPackage || hasApiAndEnv) {
99
+ const modelIds = Object.keys(providerInfo.models).sort();
100
+ let url = providerInfo.api || OPENAI_COMPATIBLE_OVERRIDES[normalizedId]?.url;
101
+ if (!hasInstalledPackage && url && !url.includes("/chat/completions") && !url.includes("/messages")) {
102
+ url = url.replace(/\/$/, "") + "/chat/completions";
103
+ }
104
+ if (!hasInstalledPackage && !url) {
105
+ console.info(`Skipping ${normalizedId}: No API URL available`);
106
+ continue;
107
+ }
108
+ const apiKeyEnvVar = providerInfo.env?.[0] || `${normalizedId.toUpperCase().replace(/-/g, "_")}_API_KEY`;
109
+ const apiKeyHeader = !hasInstalledPackage ? OPENAI_COMPATIBLE_OVERRIDES[normalizedId]?.apiKeyHeader || "Authorization" : void 0;
110
+ providerConfigs[normalizedId] = {
111
+ url,
112
+ apiKeyEnvVar,
113
+ apiKeyHeader,
114
+ name: providerInfo.name || providerId.charAt(0).toUpperCase() + providerId.slice(1),
115
+ models: modelIds,
116
+ docUrl: providerInfo.doc,
117
+ // Include documentation URL if available
118
+ gateway: `models.dev`
119
+ };
120
+ } else {
121
+ console.info(`Skipped provider ${providerInfo.name}`);
122
+ }
123
+ }
124
+ this.providerConfigs = providerConfigs;
125
+ console.info(`Found ${Object.keys(providerConfigs).length} OpenAI-compatible providers`);
126
+ console.info("Providers:", Object.keys(providerConfigs).sort());
127
+ return providerConfigs;
128
+ }
129
+ buildUrl(routerId, envVars) {
130
+ const { providerId } = parseModelRouterId(routerId);
131
+ const config = this.providerConfigs[providerId];
132
+ if (!config?.url) {
133
+ return;
134
+ }
135
+ const baseUrlEnvVar = `${providerId.toUpperCase().replace(/-/g, "_")}_BASE_URL`;
136
+ const customBaseUrl = envVars?.[baseUrlEnvVar] || process.env[baseUrlEnvVar];
137
+ return customBaseUrl || config.url;
138
+ }
139
+ getApiKey(modelId) {
140
+ const [provider, model] = modelId.split("/");
141
+ if (!provider || !model) {
142
+ throw new Error(`Could not identify provider from model id ${modelId}`);
143
+ }
144
+ const config = this.providerConfigs[provider];
145
+ if (!config) {
146
+ throw new Error(`Could not find config for provider ${provider} with model id ${modelId}`);
147
+ }
148
+ const apiKey = typeof config.apiKeyEnvVar === `string` ? process.env[config.apiKeyEnvVar] : void 0;
149
+ if (!apiKey) {
150
+ throw new Error(`Could not find API key process.env.${config.apiKeyEnvVar} for model id ${modelId}`);
151
+ }
152
+ return Promise.resolve(apiKey);
153
+ }
154
+ async resolveLanguageModel({
155
+ modelId,
156
+ providerId,
157
+ apiKey
158
+ }) {
159
+ const baseURL = this.buildUrl(`${providerId}/${modelId}`);
160
+ switch (providerId) {
161
+ case "openai":
162
+ return openaiV5.createOpenAI({ apiKey }).responses(modelId);
163
+ case "gemini":
164
+ case "google":
165
+ return googleV5.createGoogleGenerativeAI({
166
+ apiKey
167
+ }).chat(modelId);
168
+ case "anthropic":
169
+ return anthropicV5.createAnthropic({ apiKey })(modelId);
170
+ case "openrouter":
171
+ return aiSdkProviderV5.createOpenRouter({ apiKey })(modelId);
172
+ case "xai":
173
+ return xaiV5.createXai({
174
+ apiKey
175
+ })(modelId);
176
+ default:
177
+ if (!baseURL) throw new Error(`No API URL found for ${providerId}/${modelId}`);
178
+ return openaiCompatibleV5.createOpenAICompatible({ name: providerId, apiKey, baseURL }).chatModel(modelId);
179
+ }
180
+ }
181
+ };
182
+ var NetlifyGateway = class extends MastraModelGateway {
183
+ name = "netlify";
184
+ prefix = "netlify";
185
+ // All providers will be prefixed with "netlify/"
186
+ tokenCache = new chunkUU5L5GDY_cjs.InMemoryServerCache();
187
+ async fetchProviders() {
188
+ console.info("Fetching providers from Netlify AI Gateway...");
189
+ const response = await fetch("https://api.netlify.com/api/v1/ai-gateway/providers");
190
+ if (!response.ok) {
191
+ throw new Error(`Failed to fetch from Netlify: ${response.statusText}`);
192
+ }
193
+ const data = await response.json();
194
+ const netlify = {
195
+ apiKeyEnvVar: ["NETLIFY_TOKEN", "NETLIFY_SITE_ID"],
196
+ apiKeyHeader: "Authorization",
197
+ // Netlify uses standard Bearer auth
198
+ name: `Netlify`,
199
+ gateway: `netlify`,
200
+ models: [],
201
+ docUrl: "https://docs.netlify.com/build/ai-gateway/overview/"
202
+ };
203
+ for (const [providerId, provider] of Object.entries(data.providers)) {
204
+ for (const model of provider.models) {
205
+ netlify.models.push(`${providerId}/${model}`);
206
+ }
207
+ }
208
+ console.info(`Found ${Object.keys(data.providers).length} models via Netlify Gateway`);
209
+ return { netlify };
210
+ }
211
+ async buildUrl(routerId, envVars) {
212
+ const siteId = envVars?.["NETLIFY_SITE_ID"] || process.env["NETLIFY_SITE_ID"];
213
+ const netlifyToken = envVars?.["NETLIFY_TOKEN"] || process.env["NETLIFY_TOKEN"];
214
+ if (!netlifyToken) {
215
+ throw new chunkWM4VQWOZ_cjs.MastraError({
216
+ id: "NETLIFY_GATEWAY_NO_TOKEN",
217
+ domain: "LLM",
218
+ category: "UNKNOWN",
219
+ text: `Missing NETLIFY_TOKEN environment variable required for model: ${routerId}`
220
+ });
221
+ }
222
+ if (!siteId) {
223
+ throw new chunkWM4VQWOZ_cjs.MastraError({
224
+ id: "NETLIFY_GATEWAY_NO_SITE_ID",
225
+ domain: "LLM",
226
+ category: "UNKNOWN",
227
+ text: `Missing NETLIFY_SITE_ID environment variable required for model: ${routerId}`
228
+ });
229
+ }
230
+ try {
231
+ const tokenData = await this.getOrFetchToken(siteId, netlifyToken);
232
+ return tokenData.url.endsWith(`/`) ? tokenData.url.substring(0, tokenData.url.length - 1) : tokenData.url;
233
+ } catch (error) {
234
+ throw new chunkWM4VQWOZ_cjs.MastraError({
235
+ id: "NETLIFY_GATEWAY_TOKEN_ERROR",
236
+ domain: "LLM",
237
+ category: "UNKNOWN",
238
+ text: `Failed to get Netlify AI Gateway token for model ${routerId}: ${error instanceof Error ? error.message : String(error)}`
239
+ });
240
+ }
241
+ }
242
+ /**
243
+ * Get cached token or fetch a new site-specific AI Gateway token from Netlify
244
+ */
245
+ async getOrFetchToken(siteId, netlifyToken) {
246
+ const cacheKey = `netlify-token:${siteId}:${netlifyToken}`;
247
+ const cached = await this.tokenCache.get(cacheKey);
248
+ if (cached && cached.expiresAt > Date.now() / 1e3 + 60) {
249
+ return { token: cached.token, url: cached.url };
250
+ }
251
+ const response = await fetch(`https://api.netlify.com/api/v1/sites/${siteId}/ai-gateway/token`, {
252
+ method: "GET",
253
+ headers: {
254
+ Authorization: `Bearer ${netlifyToken}`
255
+ }
256
+ });
257
+ if (!response.ok) {
258
+ const error = await response.text();
259
+ throw new Error(`Failed to get Netlify AI Gateway token: ${response.status} ${error}`);
260
+ }
261
+ const tokenResponse = await response.json();
262
+ await this.tokenCache.set(cacheKey, {
263
+ token: tokenResponse.token,
264
+ url: tokenResponse.url,
265
+ expiresAt: tokenResponse.expires_at
266
+ });
267
+ return { token: tokenResponse.token, url: tokenResponse.url };
268
+ }
269
+ /**
270
+ * Get cached token or fetch a new site-specific AI Gateway token from Netlify
271
+ */
272
+ async getApiKey(modelId) {
273
+ const siteId = process.env["NETLIFY_SITE_ID"];
274
+ const netlifyToken = process.env["NETLIFY_TOKEN"];
275
+ if (!netlifyToken) {
276
+ throw new chunkWM4VQWOZ_cjs.MastraError({
277
+ id: "NETLIFY_GATEWAY_NO_TOKEN",
278
+ domain: "LLM",
279
+ category: "UNKNOWN",
280
+ text: `Missing NETLIFY_TOKEN environment variable required for model: ${modelId}`
281
+ });
282
+ }
283
+ if (!siteId) {
284
+ throw new chunkWM4VQWOZ_cjs.MastraError({
285
+ id: "NETLIFY_GATEWAY_NO_SITE_ID",
286
+ domain: "LLM",
287
+ category: "UNKNOWN",
288
+ text: `Missing NETLIFY_SITE_ID environment variable required for model: ${modelId}`
289
+ });
290
+ }
291
+ try {
292
+ return (await this.getOrFetchToken(siteId, netlifyToken)).token;
293
+ } catch (error) {
294
+ throw new chunkWM4VQWOZ_cjs.MastraError({
295
+ id: "NETLIFY_GATEWAY_TOKEN_ERROR",
296
+ domain: "LLM",
297
+ category: "UNKNOWN",
298
+ text: `Failed to get Netlify AI Gateway token for model ${modelId}: ${error instanceof Error ? error.message : String(error)}`
299
+ });
300
+ }
301
+ }
302
+ async resolveLanguageModel({
303
+ modelId,
304
+ providerId,
305
+ apiKey
306
+ }) {
307
+ const baseURL = await this.buildUrl(`${providerId}/${modelId}`);
308
+ switch (providerId) {
309
+ case "openai":
310
+ return openaiV5.createOpenAI({ apiKey, baseURL }).responses(modelId);
311
+ case "gemini":
312
+ return googleV5.createGoogleGenerativeAI({
313
+ baseURL: `${baseURL}/v1beta/`,
314
+ apiKey,
315
+ headers: {
316
+ "user-agent": "google-genai-sdk/"
317
+ }
318
+ }).chat(modelId);
319
+ case "anthropic":
320
+ return anthropicV5.createAnthropic({
321
+ apiKey,
322
+ baseURL: `${baseURL}/v1/`,
323
+ headers: {
324
+ "anthropic-version": "2023-06-01",
325
+ "user-agent": "anthropic/"
326
+ }
327
+ })(modelId);
328
+ default:
329
+ return openaiCompatibleV5.createOpenAICompatible({ name: providerId, apiKey, baseURL }).chatModel(modelId);
330
+ }
331
+ }
332
+ };
333
+
334
+ // src/llm/model/gateways/index.ts
335
+ function findGatewayForModel(gatewayId, gateways2) {
336
+ const prefixedGateway = gateways2.find((g) => g.prefix && gatewayId.startsWith(`${g.prefix}/`));
337
+ if (prefixedGateway) {
338
+ return prefixedGateway;
339
+ }
340
+ const unprefixedGateways = gateways2.filter((g) => !g.prefix);
341
+ for (const gateway of unprefixedGateways) {
342
+ return gateway;
343
+ }
344
+ throw new chunkWM4VQWOZ_cjs.MastraError({
345
+ id: "MODEL_ROUTER_NO_GATEWAY_FOUND",
346
+ category: "USER",
347
+ domain: "MODEL_ROUTER",
348
+ text: `No Mastra model router gateway found for model id ${gatewayId}`
349
+ });
350
+ }
5
351
 
6
352
  // src/llm/model/provider-registry.generated.ts
7
353
  var PROVIDER_REGISTRY = {
@@ -53,7 +399,6 @@ var PROVIDER_REGISTRY = {
53
399
  xai: {
54
400
  url: "https://api.x.ai/v1/chat/completions",
55
401
  apiKeyEnvVar: "XAI_API_KEY",
56
- apiKeyHeader: "Authorization",
57
402
  name: "xAI",
58
403
  models: [
59
404
  "grok-2",
@@ -139,33 +484,6 @@ var PROVIDER_REGISTRY = {
139
484
  docUrl: "https://console.groq.com/docs/models",
140
485
  gateway: "models.dev"
141
486
  },
142
- "github-copilot": {
143
- url: "https://api.githubcopilot.com/chat/completions",
144
- apiKeyEnvVar: "GITHUB_TOKEN",
145
- apiKeyHeader: "Authorization",
146
- name: "GitHub Copilot",
147
- models: [
148
- "claude-3.5-sonnet",
149
- "claude-3.7-sonnet",
150
- "claude-3.7-sonnet-thought",
151
- "claude-opus-4",
152
- "claude-opus-41",
153
- "claude-sonnet-4",
154
- "claude-sonnet-4.5",
155
- "gemini-2.0-flash-001",
156
- "gemini-2.5-pro",
157
- "gpt-4.1",
158
- "gpt-4o",
159
- "gpt-5",
160
- "gpt-5-mini",
161
- "grok-code-fast-1",
162
- "o3",
163
- "o3-mini",
164
- "o4-mini"
165
- ],
166
- docUrl: "https://docs.github.com/en/copilot",
167
- gateway: "models.dev"
168
- },
169
487
  mistral: {
170
488
  url: "https://api.mistral.ai/v1/chat/completions",
171
489
  apiKeyEnvVar: "MISTRAL_API_KEY",
@@ -243,6 +561,7 @@ var PROVIDER_REGISTRY = {
243
561
  "openai/gpt-4o",
244
562
  "openai/gpt-4o-mini",
245
563
  "openai/gpt-5",
564
+ "openai/gpt-5-codex",
246
565
  "openai/gpt-5-mini",
247
566
  "openai/gpt-5-nano",
248
567
  "openai/gpt-oss-120b",
@@ -484,20 +803,22 @@ var PROVIDER_REGISTRY = {
484
803
  url: "https://opencode.ai/zen/v1/chat/completions",
485
804
  apiKeyEnvVar: "OPENCODE_API_KEY",
486
805
  apiKeyHeader: "Authorization",
487
- name: "opencode zen",
806
+ name: "OpenCode Zen",
488
807
  models: [
489
808
  "claude-3-5-haiku",
490
809
  "claude-opus-4-1",
491
810
  "claude-sonnet-4",
492
811
  "claude-sonnet-4-5",
493
812
  "code-supernova",
813
+ "glm-4.6",
494
814
  "gpt-5",
815
+ "gpt-5-codex",
495
816
  "grok-code",
496
817
  "kimi-k2",
497
818
  "qwen3-coder",
498
819
  "qwen3-max"
499
820
  ],
500
- docUrl: "https://opencode.ai/docs",
821
+ docUrl: "https://opencode.ai/docs/zen",
501
822
  gateway: "models.dev"
502
823
  },
503
824
  fastrouter: {
@@ -525,9 +846,7 @@ var PROVIDER_REGISTRY = {
525
846
  gateway: "models.dev"
526
847
  },
527
848
  google: {
528
- url: "https://generativelanguage.googleapis.com/v1beta/chat/completions",
529
849
  apiKeyEnvVar: "GOOGLE_GENERATIVE_AI_API_KEY",
530
- apiKeyHeader: "Authorization",
531
850
  name: "Google",
532
851
  models: [
533
852
  "gemini-1.5-flash",
@@ -582,11 +901,10 @@ var PROVIDER_REGISTRY = {
582
901
  gateway: "models.dev"
583
902
  },
584
903
  openai: {
585
- url: "https://api.openai.com/v1/chat/completions",
586
904
  apiKeyEnvVar: "OPENAI_API_KEY",
587
- apiKeyHeader: "Authorization",
588
905
  name: "OpenAI",
589
906
  models: [
907
+ "codex-mini-latest",
590
908
  "gpt-3.5-turbo",
591
909
  "gpt-4",
592
910
  "gpt-4-turbo",
@@ -600,6 +918,7 @@ var PROVIDER_REGISTRY = {
600
918
  "gpt-4o-mini",
601
919
  "gpt-5",
602
920
  "gpt-5-chat-latest",
921
+ "gpt-5-codex",
603
922
  "gpt-5-mini",
604
923
  "gpt-5-nano",
605
924
  "o1",
@@ -635,9 +954,8 @@ var PROVIDER_REGISTRY = {
635
954
  gateway: "models.dev"
636
955
  },
637
956
  openrouter: {
638
- url: "https://openrouter.ai/api/v1/chat/completions",
957
+ url: "https://openrouter.ai/api/v1",
639
958
  apiKeyEnvVar: "OPENROUTER_API_KEY",
640
- apiKeyHeader: "Authorization",
641
959
  name: "OpenRouter",
642
960
  models: [
643
961
  "anthropic/claude-3.5-haiku",
@@ -697,6 +1015,7 @@ var PROVIDER_REGISTRY = {
697
1015
  "openai/gpt-4o-mini",
698
1016
  "openai/gpt-5",
699
1017
  "openai/gpt-5-chat",
1018
+ "openai/gpt-5-codex",
700
1019
  "openai/gpt-5-mini",
701
1020
  "openai/gpt-5-nano",
702
1021
  "openai/gpt-oss-120b",
@@ -771,7 +1090,8 @@ var PROVIDER_REGISTRY = {
771
1090
  "hf:moonshotai/Kimi-K2-Instruct",
772
1091
  "hf:moonshotai/Kimi-K2-Instruct-0905",
773
1092
  "hf:openai/gpt-oss-120b",
774
- "hf:zai-org/GLM-4.5"
1093
+ "hf:zai-org/GLM-4.5",
1094
+ "hf:zai-org/GLM-4.6"
775
1095
  ],
776
1096
  docUrl: "https://synthetic.new/pricing",
777
1097
  gateway: "models.dev"
@@ -888,9 +1208,7 @@ var PROVIDER_REGISTRY = {
888
1208
  gateway: "models.dev"
889
1209
  },
890
1210
  anthropic: {
891
- url: "https://api.anthropic.com/v1/chat/completions",
892
1211
  apiKeyEnvVar: "ANTHROPIC_API_KEY",
893
- apiKeyHeader: "x-api-key",
894
1212
  name: "Anthropic",
895
1213
  models: [
896
1214
  "claude-3-5-haiku-20241022",
@@ -977,38 +1295,39 @@ var PROVIDER_REGISTRY = {
977
1295
  name: "Netlify",
978
1296
  gateway: "netlify",
979
1297
  models: [
980
- "anthropic/claude-3-5-haiku-20241022",
981
1298
  "anthropic/claude-opus-4-20250514",
1299
+ "anthropic/claude-sonnet-4-5-20250929",
982
1300
  "anthropic/claude-sonnet-4-20250514",
983
1301
  "anthropic/claude-3-7-sonnet-20250219",
1302
+ "anthropic/claude-3-7-sonnet-latest",
1303
+ "anthropic/claude-3-5-haiku-20241022",
984
1304
  "anthropic/claude-3-5-haiku-latest",
985
1305
  "anthropic/claude-3-haiku-20240307",
986
1306
  "anthropic/claude-opus-4-1-20250805",
987
- "anthropic/claude-sonnet-4-5-20250929",
988
- "anthropic/claude-3-7-sonnet-latest",
989
1307
  "gemini/gemini-2.5-pro",
990
- "gemini/gemini-2.5-flash",
991
- "gemini/gemini-flash-lite-latest",
992
- "gemini/gemini-2.0-flash-lite",
993
- "gemini/gemini-2.5-flash-image-preview",
994
1308
  "gemini/gemini-flash-latest",
995
- "gemini/gemini-2.5-flash-preview-09-2025",
1309
+ "gemini/gemini-2.5-flash",
996
1310
  "gemini/gemini-2.5-flash-lite-preview-09-2025",
997
1311
  "gemini/gemini-2.5-flash-lite",
1312
+ "gemini/gemini-2.5-flash-preview-09-2025",
1313
+ "gemini/gemini-flash-lite-latest",
998
1314
  "gemini/gemini-2.0-flash",
1315
+ "gemini/gemini-2.0-flash-lite",
1316
+ "gemini/gemini-2.5-flash-image-preview",
1317
+ "openai/gpt-4.1-mini",
1318
+ "openai/gpt-4.1-nano",
1319
+ "openai/gpt-4o",
1320
+ "openai/gpt-5-pro",
1321
+ "openai/gpt-4o-mini",
999
1322
  "openai/o4-mini",
1000
1323
  "openai/o3",
1001
1324
  "openai/o3-mini",
1002
1325
  "openai/codex-mini-latest",
1326
+ "openai/gpt-5",
1003
1327
  "openai/gpt-5-codex",
1004
1328
  "openai/gpt-5-mini",
1005
1329
  "openai/gpt-5-nano",
1006
- "openai/gpt-4.1",
1007
- "openai/gpt-4.1-mini",
1008
- "openai/gpt-4.1-nano",
1009
- "openai/gpt-4o",
1010
- "openai/gpt-4o-mini",
1011
- "openai/gpt-5"
1330
+ "openai/gpt-4.1"
1012
1331
  ],
1013
1332
  docUrl: "https://docs.netlify.com/build/ai-gateway/overview/"
1014
1333
  }
@@ -1034,331 +1353,12 @@ function parseModelString(modelString) {
1034
1353
  };
1035
1354
  }
1036
1355
 
1037
- // src/llm/model/gateways/base.ts
1038
- var MastraModelGateway = class {
1039
- };
1040
-
1041
- // src/llm/model/gateways/models-dev.ts
1042
- var OPENAI_COMPATIBLE_OVERRIDES = {
1043
- openai: {
1044
- url: "https://api.openai.com/v1/chat/completions"
1045
- },
1046
- anthropic: {
1047
- url: "https://api.anthropic.com/v1/chat/completions",
1048
- apiKeyHeader: "x-api-key"
1049
- },
1050
- cerebras: {
1051
- url: "https://api.cerebras.ai/v1/chat/completions"
1052
- },
1053
- xai: {
1054
- url: "https://api.x.ai/v1/chat/completions"
1055
- },
1056
- mistral: {
1057
- url: "https://api.mistral.ai/v1/chat/completions"
1058
- },
1059
- google: {
1060
- url: "https://generativelanguage.googleapis.com/v1beta/chat/completions"
1061
- },
1062
- groq: {
1063
- url: "https://api.groq.com/openai/v1/chat/completions"
1064
- },
1065
- togetherai: {
1066
- url: "https://api.together.xyz/v1/chat/completions"
1067
- },
1068
- deepinfra: {
1069
- url: "https://api.deepinfra.com/v1/openai/chat/completions"
1070
- },
1071
- perplexity: {
1072
- url: "https://api.perplexity.ai/chat/completions"
1073
- },
1074
- vercel: {
1075
- url: "https://ai-gateway.vercel.sh/v1/chat/completions",
1076
- apiKeyEnvVar: "AI_GATEWAY_API_KEY"
1077
- }
1078
- };
1079
- var ModelsDevGateway = class extends MastraModelGateway {
1080
- name = "models.dev";
1081
- prefix = void 0;
1082
- // No prefix for registry gateway
1083
- providerConfigs = {};
1084
- constructor(providerConfigs) {
1085
- super();
1086
- if (providerConfigs) this.providerConfigs = providerConfigs;
1087
- }
1088
- async fetchProviders() {
1089
- console.info("Fetching providers from models.dev API...");
1090
- const response = await fetch("https://models.dev/api.json");
1091
- if (!response.ok) {
1092
- throw new Error(`Failed to fetch from models.dev: ${response.statusText}`);
1093
- }
1094
- const data = await response.json();
1095
- const providerConfigs = {};
1096
- for (const [providerId, providerInfo] of Object.entries(data)) {
1097
- if (!providerInfo || typeof providerInfo !== "object" || !providerInfo.models) continue;
1098
- const normalizedId = providerId;
1099
- const isOpenAICompatible = providerInfo.npm === "@ai-sdk/openai-compatible" || providerInfo.npm === "@ai-sdk/gateway" || // Vercel AI Gateway is OpenAI-compatible
1100
- normalizedId in OPENAI_COMPATIBLE_OVERRIDES;
1101
- const hasApiAndEnv = providerInfo.api && providerInfo.env && providerInfo.env.length > 0;
1102
- if (isOpenAICompatible || hasApiAndEnv) {
1103
- const modelIds = Object.keys(providerInfo.models).sort();
1104
- let url = providerInfo.api || OPENAI_COMPATIBLE_OVERRIDES[normalizedId]?.url;
1105
- if (url && !url.includes("/chat/completions") && !url.includes("/messages")) {
1106
- url = url.replace(/\/$/, "") + "/chat/completions";
1107
- }
1108
- if (!url) {
1109
- console.info(`Skipping ${normalizedId}: No API URL available`);
1110
- continue;
1111
- }
1112
- const apiKeyEnvVar = providerInfo.env?.[0] || `${normalizedId.toUpperCase().replace(/-/g, "_")}_API_KEY`;
1113
- const apiKeyHeader = OPENAI_COMPATIBLE_OVERRIDES[normalizedId]?.apiKeyHeader || "Authorization";
1114
- providerConfigs[normalizedId] = {
1115
- url,
1116
- apiKeyEnvVar,
1117
- apiKeyHeader,
1118
- name: providerInfo.name || providerId.charAt(0).toUpperCase() + providerId.slice(1),
1119
- models: modelIds.filter((id) => !id.includes(`codex`)),
1120
- // codex requires responses api
1121
- docUrl: providerInfo.doc,
1122
- // Include documentation URL if available
1123
- gateway: `models.dev`
1124
- };
1125
- } else {
1126
- console.info(`Skipped provider ${providerInfo.name}`);
1127
- }
1128
- }
1129
- this.providerConfigs = providerConfigs;
1130
- console.info(`Found ${Object.keys(providerConfigs).length} OpenAI-compatible providers`);
1131
- console.info("Providers:", Object.keys(providerConfigs).sort());
1132
- return providerConfigs;
1133
- }
1134
- buildUrl(modelId, envVars) {
1135
- const [provider, ...modelParts] = modelId.split("/");
1136
- if (!provider || !modelParts.length) {
1137
- return false;
1138
- }
1139
- const config = this.providerConfigs[provider];
1140
- if (!config?.url) {
1141
- return false;
1142
- }
1143
- const baseUrlEnvVar = `${provider.toUpperCase().replace(/-/g, "_")}_BASE_URL`;
1144
- const customBaseUrl = envVars[baseUrlEnvVar];
1145
- return customBaseUrl || config.url;
1146
- }
1147
- buildHeaders(modelId, envVars) {
1148
- const [provider] = modelId.split("/");
1149
- if (!provider) {
1150
- return {};
1151
- }
1152
- const config = this.providerConfigs[provider];
1153
- if (!config) {
1154
- return {};
1155
- }
1156
- const apiKey = typeof config.apiKeyEnvVar === `string` ? envVars[config.apiKeyEnvVar] : void 0;
1157
- if (!apiKey) {
1158
- return {};
1159
- }
1160
- const headers = {};
1161
- if (config.apiKeyHeader === "Authorization" || !config.apiKeyHeader) {
1162
- headers["Authorization"] = `Bearer ${apiKey}`;
1163
- } else {
1164
- headers[config.apiKeyHeader] = apiKey;
1165
- }
1166
- if (provider === "anthropic") {
1167
- headers["anthropic-version"] = "2023-06-01";
1168
- }
1169
- return headers;
1170
- }
1171
- };
1172
-
1173
- // src/llm/model/gateways/netlify.ts
1174
- var NetlifyGateway = class extends MastraModelGateway {
1175
- name = "netlify";
1176
- prefix = "netlify";
1177
- // All providers will be prefixed with "netlify/"
1178
- tokenCache = new chunkUU5L5GDY_cjs.InMemoryServerCache();
1179
- async fetchProviders() {
1180
- console.info("Fetching providers from Netlify AI Gateway...");
1181
- const response = await fetch("https://api.netlify.com/api/v1/ai-gateway/providers");
1182
- if (!response.ok) {
1183
- throw new Error(`Failed to fetch from Netlify: ${response.statusText}`);
1184
- }
1185
- const data = await response.json();
1186
- const netlify = {
1187
- apiKeyEnvVar: ["NETLIFY_TOKEN", "NETLIFY_SITE_ID"],
1188
- apiKeyHeader: "Authorization",
1189
- // Netlify uses standard Bearer auth
1190
- name: `Netlify`,
1191
- gateway: `netlify`,
1192
- models: [],
1193
- docUrl: "https://docs.netlify.com/build/ai-gateway/overview/"
1194
- };
1195
- for (const [providerId, provider] of Object.entries(data.providers)) {
1196
- for (const model of provider.models) {
1197
- netlify.models.push(`${providerId}/${model}`);
1198
- }
1199
- }
1200
- console.info(`Found ${Object.keys(data.providers).length} models via Netlify Gateway`);
1201
- return { netlify };
1202
- }
1203
- async buildUrl(modelId, envVars) {
1204
- if (!modelId.startsWith(`${this.prefix}/`)) {
1205
- return false;
1206
- }
1207
- const parts = modelId.split("/");
1208
- if (parts.length < 3) {
1209
- return false;
1210
- }
1211
- const provider = parts[1];
1212
- if (!provider) {
1213
- return false;
1214
- }
1215
- const siteId = envVars["NETLIFY_SITE_ID"];
1216
- const netlifyToken = envVars["NETLIFY_TOKEN"];
1217
- if (!netlifyToken) {
1218
- throw new chunkWM4VQWOZ_cjs.MastraError({
1219
- id: "NETLIFY_GATEWAY_NO_TOKEN",
1220
- domain: "LLM",
1221
- category: "UNKNOWN",
1222
- text: `Missing NETLIFY_TOKEN environment variable required for model: ${modelId}`
1223
- });
1224
- }
1225
- if (!siteId) {
1226
- throw new chunkWM4VQWOZ_cjs.MastraError({
1227
- id: "NETLIFY_GATEWAY_NO_SITE_ID",
1228
- domain: "LLM",
1229
- category: "UNKNOWN",
1230
- text: `Missing NETLIFY_SITE_ID environment variable required for model: ${modelId}`
1231
- });
1232
- }
1233
- try {
1234
- const tokenData = await this.getOrFetchToken(siteId, netlifyToken);
1235
- return `${tokenData.url}chat/completions`;
1236
- } catch (error) {
1237
- throw new chunkWM4VQWOZ_cjs.MastraError({
1238
- id: "NETLIFY_GATEWAY_TOKEN_ERROR",
1239
- domain: "LLM",
1240
- category: "UNKNOWN",
1241
- text: `Failed to get Netlify AI Gateway token for model ${modelId}: ${error instanceof Error ? error.message : String(error)}`
1242
- });
1243
- }
1244
- }
1245
- /**
1246
- * Get cached token or fetch a new site-specific AI Gateway token from Netlify
1247
- */
1248
- async getOrFetchToken(siteId, netlifyToken) {
1249
- const cacheKey = `netlify-token:${siteId}:${netlifyToken}`;
1250
- const cached = await this.tokenCache.get(cacheKey);
1251
- if (cached && cached.expiresAt > Date.now() / 1e3 + 60) {
1252
- return { token: cached.token, url: cached.url };
1253
- }
1254
- const response = await fetch(`https://api.netlify.com/api/v1/sites/${siteId}/ai-gateway/token`, {
1255
- method: "GET",
1256
- headers: {
1257
- Authorization: `Bearer ${netlifyToken}`
1258
- }
1259
- });
1260
- if (!response.ok) {
1261
- const error = await response.text();
1262
- throw new Error(`Failed to get Netlify AI Gateway token: ${response.status} ${error}`);
1263
- }
1264
- const tokenResponse = await response.json();
1265
- await this.tokenCache.set(cacheKey, {
1266
- token: tokenResponse.token,
1267
- url: tokenResponse.url,
1268
- expiresAt: tokenResponse.expires_at
1269
- });
1270
- return { token: tokenResponse.token, url: tokenResponse.url };
1271
- }
1272
- async buildHeaders(modelId, envVars) {
1273
- const siteId = envVars["NETLIFY_SITE_ID"];
1274
- const netlifyToken = envVars["NETLIFY_TOKEN"];
1275
- if (!netlifyToken) {
1276
- throw new chunkWM4VQWOZ_cjs.MastraError({
1277
- id: "NETLIFY_GATEWAY_NO_TOKEN",
1278
- domain: "LLM",
1279
- category: "UNKNOWN",
1280
- text: `Missing NETLIFY_TOKEN environment variable required for model: ${modelId}`
1281
- });
1282
- }
1283
- if (!siteId) {
1284
- throw new chunkWM4VQWOZ_cjs.MastraError({
1285
- id: "NETLIFY_GATEWAY_NO_SITE_ID",
1286
- domain: "LLM",
1287
- category: "UNKNOWN",
1288
- text: `Missing NETLIFY_SITE_ID environment variable required for model: ${modelId}`
1289
- });
1290
- }
1291
- try {
1292
- const tokenData = await this.getOrFetchToken(siteId, netlifyToken);
1293
- return {
1294
- Authorization: `Bearer ${tokenData.token}`
1295
- };
1296
- } catch (error) {
1297
- throw new chunkWM4VQWOZ_cjs.MastraError({
1298
- id: "NETLIFY_GATEWAY_TOKEN_ERROR",
1299
- domain: "LLM",
1300
- category: "UNKNOWN",
1301
- text: `Failed to get Netlify AI Gateway token for model ${modelId}: ${error instanceof Error ? error.message : String(error)}`
1302
- });
1303
- }
1304
- }
1305
- };
1306
-
1307
- // src/llm/model/gateway-resolver.ts
1356
+ // src/llm/model/router.ts
1308
1357
  function getStaticProvidersByGateway(name) {
1309
1358
  return Object.fromEntries(Object.entries(PROVIDER_REGISTRY).filter(([_provider, config]) => config.gateway === name));
1310
1359
  }
1311
1360
  var gateways = [new NetlifyGateway(), new ModelsDevGateway(getStaticProvidersByGateway(`models.dev`))];
1312
- function findGatewayForModel(modelId) {
1313
- const prefixedGateway = gateways.find((g) => g.prefix && modelId.startsWith(`${g.prefix}/`));
1314
- if (prefixedGateway) {
1315
- return prefixedGateway;
1316
- }
1317
- const unprefixedGateways = gateways.filter((g) => !g.prefix);
1318
- for (const gateway of unprefixedGateways) {
1319
- return gateway;
1320
- }
1321
- return null;
1322
- }
1323
- async function resolveModelConfig(modelId, envVars = process.env) {
1324
- const gateway = findGatewayForModel(modelId);
1325
- if (!gateway) {
1326
- return { url: false, headers: {}, resolvedModelId: modelId };
1327
- }
1328
- const url = await gateway.buildUrl(modelId, envVars);
1329
- if (url === false) {
1330
- return { url: false, headers: {}, resolvedModelId: modelId };
1331
- }
1332
- const headers = gateway.buildHeaders ? await gateway.buildHeaders(modelId, envVars) : {};
1333
- let resolvedModelId = modelId;
1334
- const prefix = gateway.prefix ? `${gateway.prefix}/` : null;
1335
- if (prefix && resolvedModelId.startsWith(prefix)) {
1336
- resolvedModelId = resolvedModelId.substring(prefix.length);
1337
- }
1338
- const firstSlashIndex = resolvedModelId.indexOf("/");
1339
- if (firstSlashIndex !== -1) {
1340
- resolvedModelId = resolvedModelId.substring(firstSlashIndex + 1);
1341
- }
1342
- return { url, headers, resolvedModelId };
1343
- }
1344
-
1345
- // src/llm/model/openai-compatible.ts
1346
- function resolveApiKey({ provider, apiKey }) {
1347
- if (apiKey) return apiKey;
1348
- if (provider) {
1349
- const config = getProviderConfig(provider);
1350
- if (typeof config?.apiKeyEnvVar === `string`) {
1351
- return process.env[config.apiKeyEnvVar];
1352
- }
1353
- if (Array.isArray(config?.apiKeyEnvVar)) {
1354
- for (const key of config.apiKeyEnvVar) {
1355
- if (process.env[key]) return process.env[key];
1356
- }
1357
- }
1358
- }
1359
- return void 0;
1360
- }
1361
- var OpenAICompatibleModel = class {
1361
+ var ModelRouterLanguageModel = class _ModelRouterLanguageModel {
1362
1362
  specificationVersion = "v2";
1363
1363
  defaultObjectGenerationMode = "json";
1364
1364
  supportsStructuredOutputs = true;
@@ -1367,215 +1367,29 @@ var OpenAICompatibleModel = class {
1367
1367
  modelId;
1368
1368
  provider;
1369
1369
  config;
1370
- fullModelId;
1371
- // Store the full model ID for gateway resolution
1370
+ gateway;
1372
1371
  constructor(config) {
1373
- let parsedConfig;
1374
- if (typeof config === "string") {
1375
- let isUrl = false;
1376
- try {
1377
- new URL(config);
1378
- isUrl = true;
1379
- } catch {
1380
- }
1381
- if (isUrl) {
1382
- parsedConfig = {
1383
- id: "unknown",
1384
- url: config
1385
- };
1386
- this.provider = "openai-compatible";
1387
- this.fullModelId = "unknown";
1388
- this.config = { id: "unknown", url: config };
1389
- } else {
1390
- this.fullModelId = config;
1391
- const firstSlashIndex = config.indexOf("/");
1392
- if (firstSlashIndex !== -1) {
1393
- const provider = config.substring(0, firstSlashIndex);
1394
- const modelId = config.substring(firstSlashIndex + 1);
1395
- parsedConfig = {
1396
- id: modelId,
1397
- apiKey: resolveApiKey({ provider })
1398
- };
1399
- this.provider = provider;
1400
- } else {
1401
- throw new Error(`Invalid model string: "${config}". Use "provider/model" format or a direct URL.`);
1402
- }
1403
- }
1404
- } else {
1405
- parsedConfig = config;
1406
- this.fullModelId = config.id;
1407
- const parsed = parseModelString(config.id);
1408
- this.provider = parsed.provider || "openai-compatible";
1409
- if (parsed.provider && parsed.modelId !== config.id) {
1410
- parsedConfig.id = parsed.modelId;
1411
- }
1412
- if (!parsedConfig.apiKey) {
1413
- parsedConfig.apiKey = resolveApiKey({ provider: parsed.provider || void 0 });
1414
- }
1372
+ if (typeof config === `string`) config = { id: config };
1373
+ const parsedConfig = { ...config, routerId: config.id };
1374
+ this.gateway = findGatewayForModel(config.id, gateways);
1375
+ const parsed = parseModelRouterId(config.id, this.gateway.prefix);
1376
+ this.provider = parsed.providerId || "openai-compatible";
1377
+ if (parsed.providerId && parsed.modelId !== config.id) {
1378
+ parsedConfig.id = parsed.modelId;
1415
1379
  }
1416
1380
  this.modelId = parsedConfig.id;
1417
1381
  this.config = parsedConfig;
1418
- }
1419
- convertMessagesToOpenAI(messages) {
1420
- return messages.map((msg) => {
1421
- if (msg.role === "system") {
1422
- return {
1423
- role: "system",
1424
- content: msg.content
1425
- };
1426
- }
1427
- if (msg.role === "user") {
1428
- const contentParts = msg.content.map((part) => {
1429
- if (part.type === "text") {
1430
- return { type: "text", text: part.text };
1431
- }
1432
- if (part.type === "file") {
1433
- return {
1434
- type: "image_url",
1435
- image_url: { url: part.data }
1436
- };
1437
- }
1438
- return null;
1439
- }).filter(Boolean);
1440
- if (contentParts.every((p) => p?.type === "text")) {
1441
- return {
1442
- role: "user",
1443
- content: contentParts.map((p) => p?.text || "").join("")
1444
- };
1445
- }
1446
- return {
1447
- role: "user",
1448
- content: contentParts
1449
- };
1450
- }
1451
- if (msg.role === "assistant") {
1452
- const textContent = msg.content.filter((part) => part.type === "text").map((part) => part.text).join("");
1453
- const toolCalls = msg.content.filter((part) => part.type === "tool-call").map((part) => ({
1454
- id: part.toolCallId,
1455
- type: "function",
1456
- function: {
1457
- name: part.toolName,
1458
- arguments: JSON.stringify(part.input || {})
1459
- }
1460
- }));
1461
- return {
1462
- role: "assistant",
1463
- content: textContent || null,
1464
- ...toolCalls.length > 0 && { tool_calls: toolCalls }
1465
- };
1466
- }
1467
- if (msg.role === "tool") {
1468
- return msg.content.map((toolResponse) => ({
1469
- role: "tool",
1470
- tool_call_id: toolResponse.toolCallId,
1471
- content: JSON.stringify(toolResponse.output)
1472
- }));
1473
- }
1474
- return msg;
1475
- }).flat();
1476
- }
1477
- convertToolsToOpenAI(tools) {
1478
- if (!tools || Object.keys(tools).length === 0) return void 0;
1479
- return Object.entries(tools).map(([name, tool]) => {
1480
- if (tool.type === "function") {
1481
- return {
1482
- type: "function",
1483
- function: {
1484
- name: tool.name,
1485
- description: tool.description,
1486
- parameters: tool.inputSchema || {}
1487
- }
1488
- };
1489
- }
1490
- return {
1491
- type: "function",
1492
- function: {
1493
- name,
1494
- description: `Provider tool: ${name}`,
1495
- parameters: {}
1496
- }
1497
- };
1498
- });
1499
- }
1500
- mapFinishReason(reason) {
1501
- switch (reason) {
1502
- case "stop":
1503
- return "stop";
1504
- case "length":
1505
- case "max_tokens":
1506
- return "length";
1507
- case "tool_calls":
1508
- case "function_call":
1509
- return "tool-calls";
1510
- case "content_filter":
1511
- return "content-filter";
1512
- default:
1513
- return "unknown";
1514
- }
1515
- }
1516
- /**
1517
- * Resolve URL and headers for the request
1518
- * This is called fresh for each request to ensure we get the latest values
1519
- * (e.g., Netlify tokens can expire and need to be refreshed)
1520
- */
1521
- async resolveRequestConfig() {
1522
- const shouldUseGateway = !this.config.url;
1523
- if (shouldUseGateway) {
1524
- const { url, headers, resolvedModelId } = await resolveModelConfig(this.fullModelId);
1525
- if (url === false) {
1526
- throw new Error(`No gateway can handle model: ${this.fullModelId}`);
1527
- }
1528
- const finalHeaders = {
1529
- "Content-Type": "application/json",
1530
- ...headers,
1531
- ...this.config.headers
1532
- };
1533
- return { url, headers: finalHeaders, modelId: resolvedModelId };
1534
- } else {
1535
- if (!this.config.url) {
1536
- throw new Error("URL is required for OpenAI-compatible model");
1537
- }
1538
- const headers = {
1539
- "Content-Type": "application/json",
1540
- ...this.config.headers
1541
- };
1542
- if (this.config.apiKey) {
1543
- const providerConfig = this.provider !== "openai-compatible" ? getProviderConfig(this.provider) : void 0;
1544
- if (providerConfig?.apiKeyHeader === "x-api-key") {
1545
- headers["x-api-key"] = this.config.apiKey;
1546
- } else {
1547
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
1548
- }
1549
- }
1550
- return { url: this.config.url, headers, modelId: this.modelId };
1551
- }
1552
- }
1553
- validateApiKey() {
1554
- const willUseGateway = !this.config.url;
1555
- if (willUseGateway) {
1556
- return;
1557
- }
1558
- if (!this.config.apiKey && this.provider !== "openai-compatible") {
1559
- const providerConfig = getProviderConfig(this.provider);
1560
- if (providerConfig?.apiKeyEnvVar) {
1561
- throw new Error(
1562
- `API key not found for provider "${this.provider}". Please set the ${providerConfig.apiKeyEnvVar} environment variable.`
1563
- );
1564
- } else {
1565
- throw new Error(
1566
- `API key not found for provider "${this.provider}". Please provide an API key in the configuration.`
1567
- );
1568
- }
1569
- }
1382
+ this.gateway = findGatewayForModel(parsedConfig.routerId, gateways);
1570
1383
  }
1571
1384
  async doGenerate() {
1572
1385
  throw new Error(
1573
- "doGenerate is not supported by OpenAICompatibleModel. Mastra only uses streaming (doStream) for all LLM calls."
1386
+ "doGenerate is not supported by Mastra model router. Mastra only uses streaming (doStream) for all LLM calls."
1574
1387
  );
1575
1388
  }
1576
1389
  async doStream(options) {
1390
+ let apiKey;
1577
1391
  try {
1578
- this.validateApiKey();
1392
+ apiKey = await this.gateway.getApiKey(this.config.routerId);
1579
1393
  } catch (error) {
1580
1394
  return {
1581
1395
  stream: new ReadableStream({
@@ -1585,242 +1399,32 @@ var OpenAICompatibleModel = class {
1585
1399
  error: error instanceof Error ? error.message : String(error)
1586
1400
  });
1587
1401
  }
1588
- }),
1589
- warnings: []
1590
- };
1591
- }
1592
- try {
1593
- const { url, headers, modelId: resolvedModelId } = await this.resolveRequestConfig();
1594
- const { prompt, tools, toolChoice, providerOptions } = options;
1595
- const body = {
1596
- messages: this.convertMessagesToOpenAI(prompt),
1597
- model: resolvedModelId,
1598
- stream: true,
1599
- ...providerOptions
1600
- };
1601
- const openAITools = this.convertToolsToOpenAI(tools);
1602
- if (openAITools) {
1603
- body.tools = openAITools;
1604
- if (toolChoice) {
1605
- body.tool_choice = toolChoice.type === "none" ? "none" : toolChoice.type === "required" ? "required" : toolChoice.type === "auto" ? "auto" : toolChoice.type === "tool" ? { type: "function", function: { name: toolChoice.toolName } } : "auto";
1606
- }
1607
- }
1608
- if (options.responseFormat?.type === "json") {
1609
- body.response_format = {
1610
- type: "json_schema",
1611
- json_schema: {
1612
- name: "response",
1613
- strict: true,
1614
- schema: options.responseFormat.schema
1615
- }
1616
- };
1617
- }
1618
- const fetchArgs = {
1619
- method: "POST",
1620
- headers,
1621
- body: JSON.stringify(body),
1622
- signal: options.abortSignal
1623
- };
1624
- const response = await fetch(url, fetchArgs);
1625
- if (!response.ok) {
1626
- const error = await response.text();
1627
- if (response.status === 401 || response.status === 403) {
1628
- const providerConfig = getProviderConfig(this.provider);
1629
- if (providerConfig?.apiKeyEnvVar) {
1630
- throw new Error(
1631
- `Authentication failed for provider "${this.provider}". Please ensure the ${providerConfig.apiKeyEnvVar} environment variable is set with a valid API key.`
1632
- );
1633
- }
1634
- }
1635
- throw new Error(`OpenAI-compatible API error: ${response.status} - ${error}`);
1636
- }
1637
- const reader = response.body?.getReader();
1638
- if (!reader) {
1639
- throw new Error("Response body is not readable");
1640
- }
1641
- const decoder = new TextDecoder();
1642
- let buffer = "";
1643
- let sentStart = false;
1644
- const toolCallBuffers = /* @__PURE__ */ new Map();
1645
- const mapFinishReason = this.mapFinishReason.bind(this);
1646
- const modelId = this.modelId;
1647
- let isActiveText = false;
1648
- const stream = new ReadableStream({
1649
- async start(controller) {
1650
- try {
1651
- controller.enqueue({
1652
- type: "stream-start",
1653
- warnings: []
1654
- });
1655
- while (true) {
1656
- const { done, value } = await reader.read();
1657
- if (done) {
1658
- for (const [_, toolCall] of toolCallBuffers) {
1659
- if (!toolCall.sent && toolCall.id && toolCall.name && toolCall.args) {
1660
- controller.enqueue({
1661
- type: "tool-call",
1662
- toolCallId: toolCall.id,
1663
- toolName: toolCall.name,
1664
- input: toolCall.args || "{}"
1665
- });
1666
- }
1667
- }
1668
- controller.close();
1669
- break;
1670
- }
1671
- buffer += decoder.decode(value, { stream: true });
1672
- const lines = buffer.split("\n");
1673
- buffer = lines.pop() || "";
1674
- for (const line of lines) {
1675
- if (line.trim() === "" || line.trim() === "data: [DONE]") {
1676
- continue;
1677
- }
1678
- if (line.startsWith("data: ")) {
1679
- try {
1680
- const data = JSON.parse(line.slice(6));
1681
- if (!sentStart && data.id) {
1682
- controller.enqueue({
1683
- type: "response-metadata",
1684
- id: data.id,
1685
- modelId: data.model || modelId,
1686
- timestamp: new Date(data.created ? data.created * 1e3 : Date.now())
1687
- });
1688
- sentStart = true;
1689
- }
1690
- const choice = data.choices?.[0];
1691
- if (!choice) continue;
1692
- if (choice.delta?.content) {
1693
- if (!isActiveText) {
1694
- controller.enqueue({ type: "text-start", id: "text-1" });
1695
- isActiveText = true;
1696
- }
1697
- controller.enqueue({
1698
- type: "text-delta",
1699
- id: "text-1",
1700
- delta: choice.delta.content
1701
- });
1702
- } else if (isActiveText) {
1703
- controller.enqueue({ type: "text-end", id: "text-1" });
1704
- isActiveText = false;
1705
- }
1706
- if (choice.delta?.tool_calls) {
1707
- for (const toolCall of choice.delta.tool_calls) {
1708
- const index = toolCall.index;
1709
- if (!toolCallBuffers.has(index)) {
1710
- if (toolCall.id && toolCall.function?.name) {
1711
- controller.enqueue({
1712
- type: "tool-input-start",
1713
- id: toolCall.id,
1714
- toolName: toolCall.function.name
1715
- });
1716
- }
1717
- toolCallBuffers.set(index, {
1718
- id: toolCall.id || "",
1719
- name: toolCall.function?.name || "",
1720
- args: ""
1721
- });
1722
- }
1723
- const buffer2 = toolCallBuffers.get(index);
1724
- if (toolCall.id) {
1725
- buffer2.id = toolCall.id;
1726
- }
1727
- if (toolCall.function?.name) {
1728
- buffer2.name = toolCall.function.name;
1729
- }
1730
- if (toolCall.function?.arguments) {
1731
- buffer2.args += toolCall.function.arguments;
1732
- controller.enqueue({
1733
- type: "tool-input-delta",
1734
- id: buffer2.id,
1735
- delta: toolCall.function.arguments
1736
- });
1737
- try {
1738
- JSON.parse(buffer2.args);
1739
- if (buffer2.id && buffer2.name) {
1740
- controller.enqueue({
1741
- type: "tool-input-end",
1742
- id: buffer2.id
1743
- });
1744
- controller.enqueue({
1745
- type: "tool-call",
1746
- toolCallId: buffer2.id,
1747
- toolName: buffer2.name,
1748
- input: buffer2.args
1749
- });
1750
- toolCallBuffers.set(index, {
1751
- id: buffer2.id,
1752
- name: buffer2.name,
1753
- args: buffer2.args,
1754
- sent: true
1755
- });
1756
- }
1757
- } catch {
1758
- }
1759
- }
1760
- }
1761
- }
1762
- if (choice.finish_reason) {
1763
- toolCallBuffers.clear();
1764
- controller.enqueue({
1765
- type: "finish",
1766
- finishReason: mapFinishReason(choice.finish_reason),
1767
- usage: data.usage ? {
1768
- inputTokens: data.usage.prompt_tokens || 0,
1769
- outputTokens: data.usage.completion_tokens || 0,
1770
- totalTokens: data.usage.total_tokens || 0
1771
- } : {
1772
- inputTokens: 0,
1773
- outputTokens: 0,
1774
- totalTokens: 0
1775
- }
1776
- });
1777
- }
1778
- } catch (e) {
1779
- console.error("Error parsing SSE data:", e);
1780
- }
1781
- }
1782
- }
1783
- }
1784
- } catch (error) {
1785
- return {
1786
- stream: new ReadableStream({
1787
- start(controller2) {
1788
- controller2.enqueue({
1789
- type: "error",
1790
- error: error instanceof Error ? error.message : String(error)
1791
- });
1792
- }
1793
- }),
1794
- warnings: []
1795
- };
1796
- }
1797
- }
1798
- });
1799
- return {
1800
- stream,
1801
- request: { body: JSON.stringify(body) },
1802
- response: { headers: Object.fromEntries(response.headers.entries()) },
1803
- warnings: []
1804
- };
1805
- } catch (error) {
1806
- return {
1807
- stream: new ReadableStream({
1808
- start(controller) {
1809
- controller.enqueue({
1810
- type: "error",
1811
- error: error instanceof Error ? error.message : String(error)
1812
- });
1813
- }
1814
- }),
1815
- warnings: []
1402
+ })
1816
1403
  };
1817
1404
  }
1405
+ const model = await this.resolveLanguageModel({
1406
+ apiKey,
1407
+ ...parseModelRouterId(this.config.routerId, this.gateway.prefix)
1408
+ });
1409
+ return model.doStream(options);
1410
+ }
1411
+ async resolveLanguageModel({
1412
+ modelId,
1413
+ providerId,
1414
+ apiKey
1415
+ }) {
1416
+ const key = crypto.createHash("sha256").update(this.gateway.name + modelId + providerId + apiKey).digest("hex");
1417
+ if (_ModelRouterLanguageModel.modelInstances.has(key)) return _ModelRouterLanguageModel.modelInstances.get(key);
1418
+ const modelInstance = await this.gateway.resolveLanguageModel({ modelId, providerId, apiKey });
1419
+ _ModelRouterLanguageModel.modelInstances.set(key, modelInstance);
1420
+ return modelInstance;
1818
1421
  }
1422
+ static modelInstances = /* @__PURE__ */ new Map();
1819
1423
  };
1820
1424
 
1821
- exports.OpenAICompatibleModel = OpenAICompatibleModel;
1425
+ exports.ModelRouterLanguageModel = ModelRouterLanguageModel;
1822
1426
  exports.PROVIDER_REGISTRY = PROVIDER_REGISTRY;
1823
1427
  exports.getProviderConfig = getProviderConfig;
1824
1428
  exports.parseModelString = parseModelString;
1825
- //# sourceMappingURL=chunk-2SH5WPUA.cjs.map
1826
- //# sourceMappingURL=chunk-2SH5WPUA.cjs.map
1429
+ //# sourceMappingURL=chunk-BG5FC6ZZ.cjs.map
1430
+ //# sourceMappingURL=chunk-BG5FC6ZZ.cjs.map