@dexto/core 1.5.7 → 1.5.8

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 (128) hide show
  1. package/dist/agent/DextoAgent.cjs +96 -5
  2. package/dist/agent/DextoAgent.d.ts +32 -7
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +96 -5
  5. package/dist/agent/schemas.cjs +5 -0
  6. package/dist/agent/schemas.d.ts +60 -21
  7. package/dist/agent/schemas.d.ts.map +1 -1
  8. package/dist/agent/schemas.js +5 -0
  9. package/dist/context/manager.cjs +1 -1
  10. package/dist/context/manager.js +1 -1
  11. package/dist/context/utils.cjs +69 -42
  12. package/dist/context/utils.d.ts.map +1 -1
  13. package/dist/context/utils.js +69 -42
  14. package/dist/events/index.cjs +4 -1
  15. package/dist/events/index.d.ts +37 -2
  16. package/dist/events/index.d.ts.map +1 -1
  17. package/dist/events/index.js +4 -1
  18. package/dist/index.browser.d.ts +1 -1
  19. package/dist/index.browser.d.ts.map +1 -1
  20. package/dist/llm/curation-config.cjs +82 -0
  21. package/dist/llm/curation-config.d.ts +13 -0
  22. package/dist/llm/curation-config.d.ts.map +1 -0
  23. package/dist/llm/curation-config.js +59 -0
  24. package/dist/llm/curation.cjs +57 -0
  25. package/dist/llm/curation.d.ts +16 -0
  26. package/dist/llm/curation.d.ts.map +1 -0
  27. package/dist/llm/curation.js +34 -0
  28. package/dist/llm/errors.cjs +1 -1
  29. package/dist/llm/errors.d.ts +8 -8
  30. package/dist/llm/errors.js +1 -1
  31. package/dist/llm/executor/provider-options.cjs +1 -1
  32. package/dist/llm/executor/provider-options.js +1 -1
  33. package/dist/llm/executor/turn-executor.cjs +8 -2
  34. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  35. package/dist/llm/executor/turn-executor.js +8 -2
  36. package/dist/llm/index.cjs +14 -3
  37. package/dist/llm/index.d.ts +3 -1
  38. package/dist/llm/index.d.ts.map +1 -1
  39. package/dist/llm/index.js +13 -2
  40. package/dist/llm/registry/auto-update.cjs +263 -0
  41. package/dist/llm/registry/auto-update.d.ts +27 -0
  42. package/dist/llm/registry/auto-update.d.ts.map +1 -0
  43. package/dist/llm/registry/auto-update.js +227 -0
  44. package/dist/llm/registry/index.cjs +806 -0
  45. package/dist/llm/{registry.d.ts → registry/index.d.ts} +19 -41
  46. package/dist/llm/registry/index.d.ts.map +1 -0
  47. package/dist/llm/registry/index.js +756 -0
  48. package/dist/llm/registry/models.generated.cjs +4861 -0
  49. package/dist/llm/registry/models.generated.d.ts +431 -0
  50. package/dist/llm/registry/models.generated.d.ts.map +1 -0
  51. package/dist/llm/registry/models.generated.js +4838 -0
  52. package/dist/llm/registry/models.manual.cjs +44 -0
  53. package/dist/llm/registry/models.manual.d.ts +22 -0
  54. package/dist/llm/registry/models.manual.d.ts.map +1 -0
  55. package/dist/llm/registry/models.manual.js +21 -0
  56. package/dist/llm/registry/sync.cjs +354 -0
  57. package/dist/llm/registry/sync.d.ts +41 -0
  58. package/dist/llm/registry/sync.d.ts.map +1 -0
  59. package/dist/llm/registry/sync.js +328 -0
  60. package/dist/llm/resolver.cjs +27 -18
  61. package/dist/llm/resolver.d.ts +1 -1
  62. package/dist/llm/resolver.d.ts.map +1 -1
  63. package/dist/llm/resolver.js +28 -20
  64. package/dist/llm/schemas.cjs +13 -1
  65. package/dist/llm/schemas.d.ts +23 -23
  66. package/dist/llm/schemas.d.ts.map +1 -1
  67. package/dist/llm/schemas.js +14 -1
  68. package/dist/llm/services/factory.cjs +4 -4
  69. package/dist/llm/services/factory.d.ts.map +1 -1
  70. package/dist/llm/services/factory.js +4 -4
  71. package/dist/llm/services/test-utils.integration.cjs +1 -1
  72. package/dist/llm/services/test-utils.integration.js +1 -1
  73. package/dist/llm/services/vercel.cjs +4 -1
  74. package/dist/llm/services/vercel.d.ts +1 -0
  75. package/dist/llm/services/vercel.d.ts.map +1 -1
  76. package/dist/llm/services/vercel.js +4 -1
  77. package/dist/llm/types.cjs +1 -1
  78. package/dist/llm/types.d.ts +1 -1
  79. package/dist/llm/types.d.ts.map +1 -1
  80. package/dist/llm/types.js +1 -1
  81. package/dist/llm/validation.cjs +1 -1
  82. package/dist/llm/validation.js +1 -1
  83. package/dist/resources/handlers/filesystem-handler.cjs +25 -0
  84. package/dist/resources/handlers/filesystem-handler.d.ts +1 -0
  85. package/dist/resources/handlers/filesystem-handler.d.ts.map +1 -1
  86. package/dist/resources/handlers/filesystem-handler.js +25 -0
  87. package/dist/session/chat-session.cjs +1 -1
  88. package/dist/session/chat-session.js +1 -1
  89. package/dist/session/message-queue.cjs +29 -5
  90. package/dist/session/message-queue.d.ts +3 -1
  91. package/dist/session/message-queue.d.ts.map +1 -1
  92. package/dist/session/message-queue.js +29 -5
  93. package/dist/session/session-manager.cjs +40 -3
  94. package/dist/session/session-manager.d.ts +3 -1
  95. package/dist/session/session-manager.d.ts.map +1 -1
  96. package/dist/session/session-manager.js +30 -3
  97. package/dist/session/types.d.ts +1 -0
  98. package/dist/session/types.d.ts.map +1 -1
  99. package/dist/tools/internal-tools/provider.d.ts +3 -1
  100. package/dist/tools/internal-tools/provider.d.ts.map +1 -1
  101. package/dist/tools/internal-tools/registry.d.ts +1 -1
  102. package/dist/tools/internal-tools/registry.d.ts.map +1 -1
  103. package/dist/tools/tool-call-metadata.cjs +75 -0
  104. package/dist/tools/tool-call-metadata.d.ts +16 -0
  105. package/dist/tools/tool-call-metadata.d.ts.map +1 -0
  106. package/dist/tools/tool-call-metadata.js +51 -0
  107. package/dist/tools/tool-manager.cjs +257 -30
  108. package/dist/tools/tool-manager.d.ts +43 -2
  109. package/dist/tools/tool-manager.d.ts.map +1 -1
  110. package/dist/tools/tool-manager.js +257 -30
  111. package/dist/utils/api-key-resolver.cjs +1 -1
  112. package/dist/utils/api-key-resolver.js +1 -1
  113. package/dist/utils/env.cjs +49 -0
  114. package/dist/utils/env.d.ts +4 -0
  115. package/dist/utils/env.d.ts.map +1 -0
  116. package/dist/utils/env.js +24 -0
  117. package/dist/utils/index.cjs +3 -1
  118. package/dist/utils/index.d.ts +1 -0
  119. package/dist/utils/index.d.ts.map +1 -1
  120. package/dist/utils/index.js +1 -0
  121. package/dist/utils/service-initializer.cjs +17 -5
  122. package/dist/utils/service-initializer.d.ts +23 -4
  123. package/dist/utils/service-initializer.d.ts.map +1 -1
  124. package/dist/utils/service-initializer.js +17 -5
  125. package/package.json +6 -2
  126. package/dist/llm/registry.cjs +0 -2075
  127. package/dist/llm/registry.d.ts.map +0 -1
  128. package/dist/llm/registry.js +0 -2025
@@ -0,0 +1,328 @@
1
+ import "../../chunk-PTJYTZNU.js";
2
+ import { DextoValidationError } from "../../errors/DextoValidationError.js";
3
+ import { DextoRuntimeError } from "../../errors/DextoRuntimeError.js";
4
+ import { ErrorScope, ErrorType } from "../../errors/types.js";
5
+ const MODELS_DEV_URL = "https://models.dev/api.json";
6
+ function isRecord(value) {
7
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8
+ }
9
+ function makeIssue(message, path) {
10
+ return {
11
+ code: "llm_registry_models_dev_parse",
12
+ message,
13
+ scope: ErrorScope.LLM,
14
+ type: ErrorType.USER,
15
+ severity: "error",
16
+ ...path ? { path } : {}
17
+ };
18
+ }
19
+ function requireRecord(value, label) {
20
+ if (!isRecord(value))
21
+ throw new DextoValidationError([makeIssue(`Expected ${label} to be an object`)]);
22
+ return value;
23
+ }
24
+ function requireString(value, label) {
25
+ if (typeof value !== "string")
26
+ throw new DextoValidationError([makeIssue(`Expected ${label} to be a string`)]);
27
+ return value;
28
+ }
29
+ function requireNumber(value, label) {
30
+ if (typeof value !== "number" || Number.isNaN(value)) {
31
+ throw new DextoValidationError([makeIssue(`Expected ${label} to be a number`)]);
32
+ }
33
+ return value;
34
+ }
35
+ function parseModelsDevApi(json) {
36
+ const root = requireRecord(json, "models.dev api.json root");
37
+ const api = {};
38
+ function parseModalitiesArray(value) {
39
+ if (!Array.isArray(value)) return [];
40
+ const result = [];
41
+ for (const item of value) {
42
+ if (item === "text" || item === "audio" || item === "image" || item === "video" || item === "pdf") {
43
+ result.push(item);
44
+ }
45
+ }
46
+ return result;
47
+ }
48
+ for (const [providerId, providerValue] of Object.entries(root)) {
49
+ if (!isRecord(providerValue)) continue;
50
+ const provider = providerValue;
51
+ const models = requireRecord(provider.models, `models.dev provider '${providerId}'.models`);
52
+ const parsedProvider = {
53
+ id: requireString(provider.id ?? providerId, `models.dev provider '${providerId}'.id`),
54
+ name: requireString(
55
+ provider.name ?? providerId,
56
+ `models.dev provider '${providerId}'.name`
57
+ ),
58
+ models: {}
59
+ };
60
+ for (const [modelId, modelValue] of Object.entries(models)) {
61
+ if (!isRecord(modelValue)) continue;
62
+ const m = modelValue;
63
+ const limit = requireRecord(
64
+ m.limit,
65
+ `models.dev model '${providerId}/${modelId}'.limit`
66
+ );
67
+ const parsedModel = {
68
+ id: requireString(
69
+ m.id ?? modelId,
70
+ `models.dev model '${providerId}/${modelId}'.id`
71
+ ),
72
+ name: requireString(
73
+ m.name ?? modelId,
74
+ `models.dev model '${providerId}/${modelId}'.name`
75
+ ),
76
+ attachment: Boolean(m.attachment),
77
+ limit: {
78
+ context: requireNumber(
79
+ limit.context,
80
+ `models.dev model '${providerId}/${modelId}'.limit.context`
81
+ ),
82
+ ...typeof limit.input === "number" ? { input: limit.input } : {},
83
+ ...typeof limit.output === "number" ? { output: limit.output } : {}
84
+ },
85
+ modalities: isRecord(m.modalities) ? {
86
+ input: parseModalitiesArray(m.modalities.input),
87
+ output: parseModalitiesArray(m.modalities.output)
88
+ } : void 0,
89
+ cost: isRecord(m.cost) && typeof m.cost.input === "number" && typeof m.cost.output === "number" ? {
90
+ input: m.cost.input,
91
+ output: m.cost.output,
92
+ ...typeof m.cost.cache_read === "number" ? { cache_read: m.cost.cache_read } : {},
93
+ ...typeof m.cost.cache_write === "number" ? { cache_write: m.cost.cache_write } : {},
94
+ ...m.cost.context_over_200k != null ? { context_over_200k: m.cost.context_over_200k } : {}
95
+ } : void 0
96
+ };
97
+ parsedProvider.models[modelId] = parsedModel;
98
+ }
99
+ api[providerId] = parsedProvider;
100
+ }
101
+ return api;
102
+ }
103
+ function getSupportedFileTypesFromModel(provider, model) {
104
+ const inputModalities = model.modalities?.input ?? [];
105
+ const fileTypes = [];
106
+ if (inputModalities.includes("pdf")) fileTypes.push("pdf");
107
+ if (inputModalities.includes("image")) fileTypes.push("image");
108
+ if (inputModalities.includes("audio")) fileTypes.push("audio");
109
+ if (provider === "openai" && model.attachment === true && inputModalities.includes("image")) {
110
+ if (!fileTypes.includes("pdf")) fileTypes.unshift("pdf");
111
+ }
112
+ return fileTypes;
113
+ }
114
+ function getPricing(model) {
115
+ if (!model.cost) return void 0;
116
+ return {
117
+ inputPerM: model.cost.input,
118
+ outputPerM: model.cost.output,
119
+ ...typeof model.cost.cache_read === "number" ? { cacheReadPerM: model.cost.cache_read } : {},
120
+ ...typeof model.cost.cache_write === "number" ? { cacheWritePerM: model.cost.cache_write } : {},
121
+ currency: "USD",
122
+ unit: "per_million_tokens"
123
+ };
124
+ }
125
+ function modelToModelInfo(provider, model, options) {
126
+ const pricing = getPricing(model);
127
+ return {
128
+ name: model.id,
129
+ displayName: model.name,
130
+ maxInputTokens: model.limit.input ?? model.limit.context,
131
+ supportedFileTypes: getSupportedFileTypesFromModel(provider, model),
132
+ ...pricing ? { pricing } : {},
133
+ ...options.defaultModelId === model.id ? { default: true } : {}
134
+ };
135
+ }
136
+ function buildModelsFromModelsDevProvider(params) {
137
+ const { spec, modelsDevApi } = params;
138
+ const modelsDevProvider = modelsDevApi[spec.modelsDevProviderId];
139
+ if (!modelsDevProvider) {
140
+ throw new DextoRuntimeError(
141
+ "llm_registry_models_dev_provider_missing",
142
+ ErrorScope.LLM,
143
+ ErrorType.THIRD_PARTY,
144
+ `models.dev provider '${spec.modelsDevProviderId}' not found (needed for dexto-nova provider '${spec.provider}')`,
145
+ { modelsDevProviderId: spec.modelsDevProviderId, provider: spec.provider }
146
+ );
147
+ }
148
+ const results = [];
149
+ for (const [modelId, model] of Object.entries(modelsDevProvider.models)) {
150
+ if (!spec.includeModelId(modelId)) continue;
151
+ const options = {
152
+ ...spec.defaultModelId ? { defaultModelId: spec.defaultModelId } : {}
153
+ };
154
+ results.push(modelToModelInfo(spec.provider, model, options));
155
+ }
156
+ results.sort((a, b) => a.name.localeCompare(b.name));
157
+ return results;
158
+ }
159
+ function buildModelsByProviderFromParsedSources(params) {
160
+ const { modelsDevApi } = params;
161
+ const defaults = {
162
+ openai: "gpt-5-mini",
163
+ anthropic: "claude-haiku-4-5-20251001",
164
+ google: "gemini-3-flash-preview",
165
+ groq: "llama-3.3-70b-versatile",
166
+ xai: "grok-4",
167
+ cohere: "command-a-03-2025",
168
+ minimax: "MiniMax-M2.1",
169
+ glm: "glm-4.7",
170
+ vertex: "gemini-3-flash-preview",
171
+ bedrock: "anthropic.claude-sonnet-4-5-20250929-v1:0"
172
+ };
173
+ const include = {
174
+ openai: (id) => id.startsWith("gpt-") || id.startsWith("o"),
175
+ anthropic: (id) => id.startsWith("claude-"),
176
+ google: (id) => id.startsWith("gemini-"),
177
+ groq: (_id) => true,
178
+ xai: (id) => id.startsWith("grok-"),
179
+ cohere: (id) => id.startsWith("command-"),
180
+ minimax: (_id) => true,
181
+ glm: (id) => id.startsWith("glm-"),
182
+ vertex: (_id) => true,
183
+ bedrock: (_id) => true,
184
+ openrouter: (_id) => true
185
+ };
186
+ const modelsByProvider = {
187
+ openai: buildModelsFromModelsDevProvider({
188
+ spec: {
189
+ provider: "openai",
190
+ modelsDevProviderId: "openai",
191
+ ...defaults.openai ? { defaultModelId: defaults.openai } : {},
192
+ includeModelId: include.openai
193
+ },
194
+ modelsDevApi
195
+ }),
196
+ "openai-compatible": [],
197
+ anthropic: buildModelsFromModelsDevProvider({
198
+ spec: {
199
+ provider: "anthropic",
200
+ modelsDevProviderId: "anthropic",
201
+ ...defaults.anthropic ? { defaultModelId: defaults.anthropic } : {},
202
+ includeModelId: include.anthropic
203
+ },
204
+ modelsDevApi
205
+ }),
206
+ google: buildModelsFromModelsDevProvider({
207
+ spec: {
208
+ provider: "google",
209
+ modelsDevProviderId: "google",
210
+ ...defaults.google ? { defaultModelId: defaults.google } : {},
211
+ includeModelId: include.google
212
+ },
213
+ modelsDevApi
214
+ }),
215
+ groq: buildModelsFromModelsDevProvider({
216
+ spec: {
217
+ provider: "groq",
218
+ modelsDevProviderId: "groq",
219
+ ...defaults.groq ? { defaultModelId: defaults.groq } : {},
220
+ includeModelId: include.groq
221
+ },
222
+ modelsDevApi
223
+ }),
224
+ xai: buildModelsFromModelsDevProvider({
225
+ spec: {
226
+ provider: "xai",
227
+ modelsDevProviderId: "xai",
228
+ ...defaults.xai ? { defaultModelId: defaults.xai } : {},
229
+ includeModelId: include.xai
230
+ },
231
+ modelsDevApi
232
+ }),
233
+ cohere: buildModelsFromModelsDevProvider({
234
+ spec: {
235
+ provider: "cohere",
236
+ modelsDevProviderId: "cohere",
237
+ ...defaults.cohere ? { defaultModelId: defaults.cohere } : {},
238
+ includeModelId: include.cohere
239
+ },
240
+ modelsDevApi
241
+ }),
242
+ minimax: buildModelsFromModelsDevProvider({
243
+ spec: {
244
+ provider: "minimax",
245
+ modelsDevProviderId: "minimax",
246
+ ...defaults.minimax ? { defaultModelId: defaults.minimax } : {},
247
+ includeModelId: include.minimax
248
+ },
249
+ modelsDevApi
250
+ }),
251
+ glm: buildModelsFromModelsDevProvider({
252
+ spec: {
253
+ provider: "glm",
254
+ modelsDevProviderId: "zhipuai",
255
+ ...defaults.glm ? { defaultModelId: defaults.glm } : {},
256
+ includeModelId: include.glm
257
+ },
258
+ modelsDevApi
259
+ }),
260
+ openrouter: buildModelsFromModelsDevProvider({
261
+ spec: {
262
+ provider: "openrouter",
263
+ modelsDevProviderId: "openrouter",
264
+ includeModelId: include.openrouter
265
+ },
266
+ modelsDevApi
267
+ }),
268
+ litellm: [],
269
+ glama: [],
270
+ vertex: [
271
+ ...buildModelsFromModelsDevProvider({
272
+ spec: {
273
+ provider: "vertex",
274
+ modelsDevProviderId: "google-vertex",
275
+ ...defaults.vertex ? { defaultModelId: defaults.vertex } : {},
276
+ includeModelId: include.vertex
277
+ },
278
+ modelsDevApi
279
+ }),
280
+ ...buildModelsFromModelsDevProvider({
281
+ spec: {
282
+ provider: "vertex",
283
+ modelsDevProviderId: "google-vertex-anthropic",
284
+ includeModelId: include.vertex
285
+ },
286
+ modelsDevApi
287
+ })
288
+ ].sort((a, b) => a.name.localeCompare(b.name)),
289
+ bedrock: buildModelsFromModelsDevProvider({
290
+ spec: {
291
+ provider: "bedrock",
292
+ modelsDevProviderId: "amazon-bedrock",
293
+ ...defaults.bedrock ? { defaultModelId: defaults.bedrock } : {},
294
+ includeModelId: include.bedrock
295
+ },
296
+ modelsDevApi
297
+ }).map((m) => ({ ...m, name: m.name.replace(/^(eu\.|us\.|global\.)/i, "") })).filter((m, idx, arr) => arr.findIndex((x) => x.name === m.name) === idx).sort((a, b) => a.name.localeCompare(b.name)),
298
+ local: [],
299
+ ollama: [],
300
+ "dexto-nova": []
301
+ };
302
+ return modelsByProvider;
303
+ }
304
+ async function buildModelsByProviderFromRemote(options) {
305
+ const timeoutMs = options?.timeoutMs ?? 3e4;
306
+ const userAgent = options?.userAgent ?? "dexto-llm-registry";
307
+ const modelsDevRes = await fetch(options?.modelsDevUrl ?? MODELS_DEV_URL, {
308
+ headers: { "User-Agent": userAgent },
309
+ signal: AbortSignal.timeout(timeoutMs)
310
+ });
311
+ if (!modelsDevRes.ok) {
312
+ throw new DextoRuntimeError(
313
+ "llm_registry_models_dev_fetch_failed",
314
+ ErrorScope.LLM,
315
+ ErrorType.THIRD_PARTY,
316
+ `Failed to fetch models.dev (${modelsDevRes.status} ${modelsDevRes.statusText})`,
317
+ { status: modelsDevRes.status, statusText: modelsDevRes.statusText }
318
+ );
319
+ }
320
+ const modelsDevApi = parseModelsDevApi(await modelsDevRes.json());
321
+ return buildModelsByProviderFromParsedSources({ modelsDevApi });
322
+ }
323
+ export {
324
+ MODELS_DEV_URL,
325
+ buildModelsByProviderFromParsedSources,
326
+ buildModelsByProviderFromRemote,
327
+ parseModelsDevApi
328
+ };
@@ -27,7 +27,7 @@ var import_result = require("../utils/result.js");
27
27
  var import_types = require("../errors/types.cjs");
28
28
  var import_error_codes = require("./error-codes.js");
29
29
  var import_schemas2 = require("./schemas.js");
30
- var import_registry = require("./registry.js");
30
+ var import_registry = require("./registry/index.js");
31
31
  var import_openrouter_model_registry = require("./providers/openrouter-model-registry.js");
32
32
  var import_api_key_resolver = require("../utils/api-key-resolver.cjs");
33
33
  async function resolveAndValidateLLMConfig(previous, updates, logger) {
@@ -36,12 +36,12 @@ async function resolveAndValidateLLMConfig(previous, updates, logger) {
36
36
  const { errors } = (0, import_result.splitIssues)(warnings);
37
37
  return (0, import_result.fail)(errors);
38
38
  }
39
- const result = validateLLMConfig(candidate, warnings);
39
+ const result = validateLLMConfig(candidate, warnings, logger);
40
40
  return result;
41
41
  }
42
42
  async function resolveLLMConfig(previous, updates, logger) {
43
43
  const warnings = [];
44
- const provider = updates.provider ?? (updates.model ? (() => {
44
+ const provider = updates.provider ?? (updates.model && !updates.model.includes("/") ? (() => {
45
45
  try {
46
46
  return (0, import_registry.getProviderFromModel)(updates.model);
47
47
  } catch {
@@ -81,20 +81,20 @@ async function resolveLLMConfig(previous, updates, logger) {
81
81
  context: { provider, model }
82
82
  });
83
83
  }
84
- if ((0, import_registry.hasAllRegistryModelsSupport)(provider) && !model.includes("/")) {
85
- try {
86
- const originalProvider = (0, import_registry.getProviderFromModel)(model);
87
- model = (0, import_registry.transformModelNameForProvider)(model, originalProvider, provider);
88
- logger.debug(
89
- `Transformed model for ${provider}: ${updates.model ?? previous.model} -> ${model}`
90
- );
91
- } catch {
92
- logger.debug(
93
- `Model '${model}' not in registry, passing through to ${provider} without transformation`
94
- );
84
+ if (provider !== previous.provider && updates.model == null && (0, import_registry.hasAllRegistryModelsSupport)(provider) && !model.includes("/")) {
85
+ const defaultGatewayModel = (0, import_registry.getDefaultModelForProvider)(provider);
86
+ if (defaultGatewayModel) {
87
+ model = defaultGatewayModel;
88
+ warnings.push({
89
+ code: import_error_codes.LLMErrorCode.MODEL_INCOMPATIBLE,
90
+ message: `Model set to default '${model}' for provider '${provider}'`,
91
+ severity: "warning",
92
+ scope: import_types.ErrorScope.LLM,
93
+ type: import_types.ErrorType.USER,
94
+ context: { provider, model }
95
+ });
95
96
  }
96
97
  }
97
- const maxInputTokens = updates.maxInputTokens ?? (0, import_registry.getEffectiveMaxInputTokens)({ provider, model, apiKey: apiKey || previous.apiKey }, logger);
98
98
  let baseURL;
99
99
  if (updates.baseURL) {
100
100
  baseURL = updates.baseURL;
@@ -159,18 +159,27 @@ async function resolveLLMConfig(previous, updates, logger) {
159
159
  apiKey,
160
160
  baseURL,
161
161
  maxIterations: updates.maxIterations ?? previous.maxIterations,
162
- maxInputTokens,
162
+ maxInputTokens: updates.maxInputTokens,
163
163
  maxOutputTokens: updates.maxOutputTokens ?? previous.maxOutputTokens,
164
164
  temperature: updates.temperature ?? previous.temperature
165
165
  },
166
166
  warnings
167
167
  };
168
168
  }
169
- function validateLLMConfig(candidate, warnings) {
169
+ function validateLLMConfig(candidate, warnings, logger) {
170
170
  const parsed = import_schemas2.LLMConfigSchema.safeParse(candidate);
171
171
  if (!parsed.success) {
172
172
  return (0, import_result.fail)((0, import_result.zodToIssues)(parsed.error, "error"));
173
173
  }
174
+ const maxInputTokens = parsed.data.maxInputTokens ?? (0, import_registry.getEffectiveMaxInputTokens)(
175
+ {
176
+ provider: parsed.data.provider,
177
+ model: parsed.data.model,
178
+ apiKey: parsed.data.apiKey ?? candidate.apiKey ?? "",
179
+ baseURL: parsed.data.baseURL
180
+ },
181
+ logger
182
+ );
174
183
  if (parsed.data.apiKey && parsed.data.apiKey.length < 10) {
175
184
  warnings.push({
176
185
  code: import_error_codes.LLMErrorCode.API_KEY_INVALID,
@@ -185,7 +194,7 @@ function validateLLMConfig(candidate, warnings) {
185
194
  }
186
195
  });
187
196
  }
188
- return (0, import_result.ok)(parsed.data, warnings);
197
+ return (0, import_result.ok)({ ...parsed.data, maxInputTokens }, warnings);
189
198
  }
190
199
  // Annotate the CommonJS export names for ESM import in node:
191
200
  0 && (module.exports = {
@@ -17,5 +17,5 @@ export declare function resolveLLMConfig(previous: ValidatedLLMConfig, updates:
17
17
  candidate: LLMConfig;
18
18
  warnings: Issue<LLMUpdateContext>[];
19
19
  }>;
20
- export declare function validateLLMConfig(candidate: LLMConfig, warnings: Issue<LLMUpdateContext>[]): Result<ValidatedLLMConfig, LLMUpdateContext>;
20
+ export declare function validateLLMConfig(candidate: LLMConfig, warnings: Issue<LLMUpdateContext>[], logger: IDextoLogger): Result<ValidatedLLMConfig, LLMUpdateContext>;
21
21
  //# sourceMappingURL=resolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/llm/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAiD,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,KAAK,EAAyB,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAiBxF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAM7D;;GAEG;AACH,wBAAsB,2BAA2B,CAC7C,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,YAAY,GACrB,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC,CAUvD;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAClC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,YAAY,GACrB,OAAO,CAAC;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAA;CAAE,CAAC,CAoLxE;AAGD,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE,GACpC,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CA0B9C"}
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/llm/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAiD,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,KAAK,EAAyB,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAgBxF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAM7D;;GAEG;AACH,wBAAsB,2BAA2B,CAC7C,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,YAAY,GACrB,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC,CAUvD;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAClC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,YAAY,GACrB,OAAO,CAAC;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAA;CAAE,CAAC,CAoLxE;AAGD,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE,EACnC,MAAM,EAAE,YAAY,GACrB,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAuC9C"}
@@ -11,9 +11,8 @@ import {
11
11
  getEffectiveMaxInputTokens,
12
12
  supportsBaseURL,
13
13
  supportsCustomModels,
14
- hasAllRegistryModelsSupport,
15
- transformModelNameForProvider
16
- } from "./registry.js";
14
+ hasAllRegistryModelsSupport
15
+ } from "./registry/index.js";
17
16
  import {
18
17
  lookupOpenRouterModel,
19
18
  refreshOpenRouterModelCache
@@ -25,12 +24,12 @@ async function resolveAndValidateLLMConfig(previous, updates, logger) {
25
24
  const { errors } = splitIssues(warnings);
26
25
  return fail(errors);
27
26
  }
28
- const result = validateLLMConfig(candidate, warnings);
27
+ const result = validateLLMConfig(candidate, warnings, logger);
29
28
  return result;
30
29
  }
31
30
  async function resolveLLMConfig(previous, updates, logger) {
32
31
  const warnings = [];
33
- const provider = updates.provider ?? (updates.model ? (() => {
32
+ const provider = updates.provider ?? (updates.model && !updates.model.includes("/") ? (() => {
34
33
  try {
35
34
  return getProviderFromModel(updates.model);
36
35
  } catch {
@@ -70,20 +69,20 @@ async function resolveLLMConfig(previous, updates, logger) {
70
69
  context: { provider, model }
71
70
  });
72
71
  }
73
- if (hasAllRegistryModelsSupport(provider) && !model.includes("/")) {
74
- try {
75
- const originalProvider = getProviderFromModel(model);
76
- model = transformModelNameForProvider(model, originalProvider, provider);
77
- logger.debug(
78
- `Transformed model for ${provider}: ${updates.model ?? previous.model} -> ${model}`
79
- );
80
- } catch {
81
- logger.debug(
82
- `Model '${model}' not in registry, passing through to ${provider} without transformation`
83
- );
72
+ if (provider !== previous.provider && updates.model == null && hasAllRegistryModelsSupport(provider) && !model.includes("/")) {
73
+ const defaultGatewayModel = getDefaultModelForProvider(provider);
74
+ if (defaultGatewayModel) {
75
+ model = defaultGatewayModel;
76
+ warnings.push({
77
+ code: LLMErrorCode.MODEL_INCOMPATIBLE,
78
+ message: `Model set to default '${model}' for provider '${provider}'`,
79
+ severity: "warning",
80
+ scope: ErrorScope.LLM,
81
+ type: ErrorType.USER,
82
+ context: { provider, model }
83
+ });
84
84
  }
85
85
  }
86
- const maxInputTokens = updates.maxInputTokens ?? getEffectiveMaxInputTokens({ provider, model, apiKey: apiKey || previous.apiKey }, logger);
87
86
  let baseURL;
88
87
  if (updates.baseURL) {
89
88
  baseURL = updates.baseURL;
@@ -148,18 +147,27 @@ async function resolveLLMConfig(previous, updates, logger) {
148
147
  apiKey,
149
148
  baseURL,
150
149
  maxIterations: updates.maxIterations ?? previous.maxIterations,
151
- maxInputTokens,
150
+ maxInputTokens: updates.maxInputTokens,
152
151
  maxOutputTokens: updates.maxOutputTokens ?? previous.maxOutputTokens,
153
152
  temperature: updates.temperature ?? previous.temperature
154
153
  },
155
154
  warnings
156
155
  };
157
156
  }
158
- function validateLLMConfig(candidate, warnings) {
157
+ function validateLLMConfig(candidate, warnings, logger) {
159
158
  const parsed = LLMConfigSchema.safeParse(candidate);
160
159
  if (!parsed.success) {
161
160
  return fail(zodToIssues(parsed.error, "error"));
162
161
  }
162
+ const maxInputTokens = parsed.data.maxInputTokens ?? getEffectiveMaxInputTokens(
163
+ {
164
+ provider: parsed.data.provider,
165
+ model: parsed.data.model,
166
+ apiKey: parsed.data.apiKey ?? candidate.apiKey ?? "",
167
+ baseURL: parsed.data.baseURL
168
+ },
169
+ logger
170
+ );
163
171
  if (parsed.data.apiKey && parsed.data.apiKey.length < 10) {
164
172
  warnings.push({
165
173
  code: LLMErrorCode.API_KEY_INVALID,
@@ -174,7 +182,7 @@ function validateLLMConfig(candidate, warnings) {
174
182
  }
175
183
  });
176
184
  }
177
- return ok(parsed.data, warnings);
185
+ return ok({ ...parsed.data, maxInputTokens }, warnings);
178
186
  }
179
187
  export {
180
188
  resolveAndValidateLLMConfig,
@@ -31,7 +31,7 @@ var import_errors = require("../errors/index.cjs");
31
31
  var import_result = require("../utils/result.cjs");
32
32
  var import_api_key_resolver = require("../utils/api-key-resolver.cjs");
33
33
  var import_zod = require("zod");
34
- var import_registry = require("./registry.js");
34
+ var import_registry = require("./registry/index.js");
35
35
  var import_types2 = require("./types.js");
36
36
  const LLMConfigFields = {
37
37
  provider: import_zod.z.enum(import_types2.LLM_PROVIDERS).describe("LLM provider (e.g., 'openai', 'anthropic', 'google', 'groq')"),
@@ -84,6 +84,18 @@ function createLLMConfigSchema(options = {}) {
84
84
  return LLMConfigBaseSchema.superRefine((data, ctx) => {
85
85
  const baseURLIsSet = data.baseURL != null && data.baseURL.trim() !== "";
86
86
  const maxInputTokensIsSet = data.maxInputTokens != null;
87
+ if ((0, import_registry.hasAllRegistryModelsSupport)(data.provider) && !data.model.includes("/")) {
88
+ ctx.addIssue({
89
+ code: import_zod.z.ZodIssueCode.custom,
90
+ path: ["model"],
91
+ message: `Provider '${data.provider}' requires OpenRouter-format model IDs (e.g. 'openai/gpt-5-mini' or 'anthropic/claude-sonnet-4.5'). You provided '${data.model}'.`,
92
+ params: {
93
+ code: import_error_codes.LLMErrorCode.MODEL_INCOMPATIBLE,
94
+ scope: import_types.ErrorScope.LLM,
95
+ type: import_types.ErrorType.USER
96
+ }
97
+ });
98
+ }
87
99
  if (strict && (0, import_registry.requiresApiKey)(data.provider) && !data.apiKey?.trim()) {
88
100
  const primaryVar = (0, import_api_key_resolver.getPrimaryApiKeyEnvVar)(data.provider);
89
101
  ctx.addIssue({