@theokit/sdk 4.12.2 → 4.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -573,10 +573,10 @@ function buildToolPrompt(prompt) {
573
573
  Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
574
574
  }
575
575
  function setupStructuredOutput(schema, maxRetries) {
576
- const z12 = requireZod();
576
+ const z13 = requireZod();
577
577
  const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
578
578
  return {
579
- z: z12,
579
+ z: z13,
580
580
  jsonSchema,
581
581
  maxRetries: maxRetries ?? 1,
582
582
  initialUsage: { inputTokens: 0, outputTokens: 0 }
@@ -13083,6 +13083,192 @@ function applyToolResultGuard(parts, opts) {
13083
13083
  )
13084
13084
  );
13085
13085
  }
13086
+ var MODALITIES = ["text", "audio", "image", "video", "pdf"];
13087
+ var costSchema = z.object({
13088
+ /** USD per 1M tokens (models.dev convention). */
13089
+ input: z.number().nonnegative(),
13090
+ output: z.number().nonnegative(),
13091
+ cache_read: z.number().nonnegative().optional(),
13092
+ cache_write: z.number().nonnegative().optional()
13093
+ }).loose();
13094
+ var limitSchema = z.object({
13095
+ context: z.number().positive(),
13096
+ input: z.number().positive().optional(),
13097
+ output: z.number().positive().optional()
13098
+ }).loose();
13099
+ var modalitiesSchema = z.object({
13100
+ input: z.array(z.enum(MODALITIES)).optional(),
13101
+ output: z.array(z.enum(MODALITIES)).optional()
13102
+ }).loose();
13103
+ var catalogModelSchema = z.object({
13104
+ name: z.string().optional(),
13105
+ release_date: z.string().optional(),
13106
+ attachment: z.boolean().optional(),
13107
+ reasoning: z.boolean().optional(),
13108
+ temperature: z.boolean().optional(),
13109
+ tool_call: z.boolean().optional(),
13110
+ /** theokit extension — maps to ModelCapabilities.supportsStructuredOutput. */
13111
+ structured_output: z.boolean().optional(),
13112
+ /** theokit extension — maps to ModelCapabilities.supportsCacheControl. */
13113
+ cache_control: z.boolean().optional(),
13114
+ cost: costSchema.optional(),
13115
+ limit: limitSchema.optional(),
13116
+ modalities: modalitiesSchema.optional(),
13117
+ status: z.enum(["alpha", "beta", "deprecated"]).optional()
13118
+ }).loose();
13119
+
13120
+ // src/internal/providers/registry.ts
13121
+ function globalSingleton(key2, create) {
13122
+ const g = globalThis;
13123
+ const sym = Symbol.for(key2);
13124
+ if (g[sym] === void 0) g[sym] = create();
13125
+ return g[sym];
13126
+ }
13127
+ var REGISTRY = globalSingleton(
13128
+ "theokit-sdk.providers.registry",
13129
+ () => /* @__PURE__ */ new Map()
13130
+ );
13131
+ var ALIASES = globalSingleton("theokit-sdk.providers.aliases", () => /* @__PURE__ */ new Map());
13132
+ function registerProvider(profile) {
13133
+ if (REGISTRY.has(profile.name)) {
13134
+ process.stderr.write(`[theokit-sdk] Provider "${profile.name}" overridden by user plugin.
13135
+ `);
13136
+ }
13137
+ REGISTRY.set(profile.name, profile);
13138
+ for (const alias of profile.aliases ?? []) {
13139
+ const previous = ALIASES.get(alias);
13140
+ if (previous !== void 0 && previous !== profile.name) {
13141
+ process.stderr.write(
13142
+ `[theokit-sdk] Alias "${alias}" collision: was "${previous}", now "${profile.name}".
13143
+ `
13144
+ );
13145
+ }
13146
+ ALIASES.set(alias, profile.name);
13147
+ }
13148
+ }
13149
+ function getProviderProfile(name) {
13150
+ const canonical = ALIASES.get(name) ?? name;
13151
+ return REGISTRY.get(canonical);
13152
+ }
13153
+ function listProviders() {
13154
+ return Array.from(REGISTRY.values());
13155
+ }
13156
+
13157
+ // src/internal/providers/catalog-loader.ts
13158
+ var __dirname_resolved = dirname(fileURLToPath(import.meta.url));
13159
+ function globalSingleton2(key2, create) {
13160
+ const g = globalThis;
13161
+ const sym = Symbol.for(key2);
13162
+ if (g[sym] === void 0) g[sym] = create();
13163
+ return g[sym];
13164
+ }
13165
+ var modelInfoIndex = globalSingleton2(
13166
+ "theokit-sdk.providers.model-info-index",
13167
+ () => /* @__PURE__ */ new Map()
13168
+ );
13169
+ var patchedModelKeys = globalSingleton2(
13170
+ "theokit-sdk.providers.model-info-patched",
13171
+ () => /* @__PURE__ */ new Set()
13172
+ );
13173
+ var indexState = globalSingleton2("theokit-sdk.providers.model-info-loaded", () => ({
13174
+ loaded: false
13175
+ }));
13176
+ function getCatalogModelInfo(key2) {
13177
+ ensureModelIndexLoaded();
13178
+ return modelInfoIndex.get(key2);
13179
+ }
13180
+ function isPatchedModelKey(key2) {
13181
+ return patchedModelKeys.has(key2);
13182
+ }
13183
+ function ensureModelIndexLoaded() {
13184
+ if (indexState.loaded) return;
13185
+ indexState.loaded = true;
13186
+ try {
13187
+ const catalog = loadProviderCatalog();
13188
+ for (const entry of Object.values(catalog)) {
13189
+ indexEntryModels(entry);
13190
+ }
13191
+ } catch (err) {
13192
+ process.stderr.write(
13193
+ `[theokit-sdk] WARN: provider catalog unavailable (${err.message}) \u2014 per-model data disabled
13194
+ `
13195
+ );
13196
+ }
13197
+ }
13198
+ function indexEntryModels(entry) {
13199
+ if (entry.models === void 0 || typeof entry.models !== "object") return;
13200
+ for (const [modelId, raw] of Object.entries(entry.models)) {
13201
+ const parsed = catalogModelSchema.safeParse(raw);
13202
+ if (!parsed.success) {
13203
+ process.stderr.write(
13204
+ `[theokit-sdk] WARN: Skipping malformed catalog model "${entry.id}/${modelId}": ${parsed.error.issues[0]?.message ?? "invalid"}
13205
+ `
13206
+ );
13207
+ continue;
13208
+ }
13209
+ modelInfoIndex.set(`${entry.id}/${modelId}`, parsed.data);
13210
+ for (const alias of entry.aliases ?? []) {
13211
+ const key2 = `${alias}/${modelId}`;
13212
+ if (!modelInfoIndex.has(key2)) modelInfoIndex.set(key2, parsed.data);
13213
+ }
13214
+ }
13215
+ }
13216
+ function validateEntry(raw) {
13217
+ if (typeof raw.id !== "string" || typeof raw.displayName !== "string" || typeof raw.apiMode !== "string" || typeof raw.authType !== "string" || typeof raw.baseUrl !== "string" || !Array.isArray(raw.envVars) || !Array.isArray(raw.fallbackModels) || raw.capabilities == null || typeof raw.capabilities !== "object") {
13218
+ return null;
13219
+ }
13220
+ return raw;
13221
+ }
13222
+ function loadProviderCatalog(opts) {
13223
+ const catalogPath = join(__dirname_resolved, "provider-catalog.json");
13224
+ const rawText = readFileSync(catalogPath, "utf-8");
13225
+ let entries = JSON.parse(rawText);
13226
+ const result = {};
13227
+ for (const raw of entries) {
13228
+ const validated = validateEntry(raw);
13229
+ if (validated === null) {
13230
+ process.stderr.write(
13231
+ `[theokit-sdk] WARN: Skipping malformed catalog entry: ${JSON.stringify(raw).slice(0, 100)}
13232
+ `
13233
+ );
13234
+ continue;
13235
+ }
13236
+ result[validated.id] = validated;
13237
+ }
13238
+ return result;
13239
+ }
13240
+ var _capabilitiesCache = null;
13241
+ function getCatalogCapabilities(providerId) {
13242
+ if (_capabilitiesCache === null) {
13243
+ const catalog = loadProviderCatalog();
13244
+ _capabilitiesCache = {};
13245
+ for (const entry of Object.values(catalog)) {
13246
+ _capabilitiesCache[entry.id] = entry.capabilities;
13247
+ }
13248
+ }
13249
+ return _capabilitiesCache[providerId];
13250
+ }
13251
+ function registerCatalogProviders(opts) {
13252
+ const catalog = loadProviderCatalog();
13253
+ for (const entry of Object.values(catalog)) {
13254
+ if (getProviderProfile(entry.id) !== void 0) continue;
13255
+ if (entry.aliases?.some((a) => getProviderProfile(a) !== void 0)) continue;
13256
+ const profile = {
13257
+ name: entry.id,
13258
+ apiMode: entry.apiMode,
13259
+ authType: entry.authType,
13260
+ baseUrl: entry.baseUrl,
13261
+ envVars: entry.envVars,
13262
+ fallbackModels: entry.fallbackModels,
13263
+ displayName: entry.displayName,
13264
+ aliases: entry.aliases,
13265
+ modelsUrl: entry.modelsUrl,
13266
+ hostname: entry.hostname,
13267
+ extraHeaders: entry.extraHeaders
13268
+ };
13269
+ registerProvider(profile);
13270
+ }
13271
+ }
13086
13272
 
13087
13273
  // src/internal/budget/pricing-data.json
13088
13274
  var pricing_data_default = {
@@ -13175,9 +13361,9 @@ var pricing_data_default = {
13175
13361
  cacheRead: 0.025
13176
13362
  },
13177
13363
  "openai/o3": {
13178
- input: 10,
13179
- output: 40,
13180
- cacheRead: 2.5
13364
+ input: 2,
13365
+ output: 8,
13366
+ cacheRead: 0.5
13181
13367
  },
13182
13368
  "openai/o3-mini": {
13183
13369
  input: 1.1,
@@ -13265,6 +13451,30 @@ function getPricingEntry(opts) {
13265
13451
  if (found2 !== void 0) return buildEntry(stripped, found2);
13266
13452
  }
13267
13453
  }
13454
+ const catalogEntry = catalogCostFallback(opts.provider, cleaned);
13455
+ if (catalogEntry !== void 0) return catalogEntry;
13456
+ return void 0;
13457
+ }
13458
+ function catalogCostFallback(provider, cleanedModel) {
13459
+ const stripped = stripDateSuffix(cleanedModel);
13460
+ const candidates = [`${provider}/${cleanedModel}`, cleanedModel];
13461
+ if (stripped !== cleanedModel) candidates.push(`${provider}/${stripped}`, stripped);
13462
+ for (const key2 of candidates) {
13463
+ const info = getCatalogModelInfo(key2);
13464
+ const cost = info?.cost;
13465
+ if (cost === void 0) continue;
13466
+ const [prov, ...modelParts] = key2.split("/");
13467
+ return {
13468
+ provider: prov ?? provider,
13469
+ model: modelParts.join("/") || cleanedModel,
13470
+ inputCostPerMillion: cost.input,
13471
+ outputCostPerMillion: cost.output,
13472
+ ...cost.cache_read !== void 0 ? { cacheReadCostPerMillion: cost.cache_read } : {},
13473
+ ...cost.cache_write !== void 0 ? { cacheWriteCostPerMillion: cost.cache_write } : {},
13474
+ // M44 M5 fix — honest provenance: a key patched by the LIVE models-dev source is not "vendored".
13475
+ pricingVersion: isPatchedModelKey(key2) ? "catalog-models-dev" : "catalog-vendored"
13476
+ };
13477
+ }
13268
13478
  return void 0;
13269
13479
  }
13270
13480
 
@@ -13781,93 +13991,6 @@ function abortError(signal) {
13781
13991
  // src/internal/llm/router.ts
13782
13992
  init_errors();
13783
13993
 
13784
- // src/internal/providers/registry.ts
13785
- var REGISTRY = /* @__PURE__ */ new Map();
13786
- var ALIASES = /* @__PURE__ */ new Map();
13787
- function registerProvider(profile) {
13788
- if (REGISTRY.has(profile.name)) {
13789
- process.stderr.write(`[theokit-sdk] Provider "${profile.name}" overridden by user plugin.
13790
- `);
13791
- }
13792
- REGISTRY.set(profile.name, profile);
13793
- for (const alias of profile.aliases ?? []) {
13794
- const previous = ALIASES.get(alias);
13795
- if (previous !== void 0 && previous !== profile.name) {
13796
- process.stderr.write(
13797
- `[theokit-sdk] Alias "${alias}" collision: was "${previous}", now "${profile.name}".
13798
- `
13799
- );
13800
- }
13801
- ALIASES.set(alias, profile.name);
13802
- }
13803
- }
13804
- function getProviderProfile(name) {
13805
- const canonical = ALIASES.get(name) ?? name;
13806
- return REGISTRY.get(canonical);
13807
- }
13808
- function listProviders() {
13809
- return Array.from(REGISTRY.values());
13810
- }
13811
-
13812
- // src/internal/providers/catalog-loader.ts
13813
- var __dirname_resolved = dirname(fileURLToPath(import.meta.url));
13814
- function validateEntry(raw) {
13815
- if (typeof raw.id !== "string" || typeof raw.displayName !== "string" || typeof raw.apiMode !== "string" || typeof raw.authType !== "string" || typeof raw.baseUrl !== "string" || !Array.isArray(raw.envVars) || !Array.isArray(raw.fallbackModels) || raw.capabilities == null || typeof raw.capabilities !== "object") {
13816
- return null;
13817
- }
13818
- return raw;
13819
- }
13820
- function loadProviderCatalog(opts) {
13821
- const catalogPath = join(__dirname_resolved, "provider-catalog.json");
13822
- const rawText = readFileSync(catalogPath, "utf-8");
13823
- let entries = JSON.parse(rawText);
13824
- const result = {};
13825
- for (const raw of entries) {
13826
- const validated = validateEntry(raw);
13827
- if (validated === null) {
13828
- process.stderr.write(
13829
- `[theokit-sdk] WARN: Skipping malformed catalog entry: ${JSON.stringify(raw).slice(0, 100)}
13830
- `
13831
- );
13832
- continue;
13833
- }
13834
- result[validated.id] = validated;
13835
- }
13836
- return result;
13837
- }
13838
- var _capabilitiesCache = null;
13839
- function getCatalogCapabilities(providerId) {
13840
- if (_capabilitiesCache === null) {
13841
- const catalog = loadProviderCatalog();
13842
- _capabilitiesCache = {};
13843
- for (const entry of Object.values(catalog)) {
13844
- _capabilitiesCache[entry.id] = entry.capabilities;
13845
- }
13846
- }
13847
- return _capabilitiesCache[providerId];
13848
- }
13849
- function registerCatalogProviders(opts) {
13850
- const catalog = loadProviderCatalog();
13851
- for (const entry of Object.values(catalog)) {
13852
- if (getProviderProfile(entry.id) !== void 0) continue;
13853
- if (entry.aliases?.some((a) => getProviderProfile(a) !== void 0)) continue;
13854
- const profile = {
13855
- name: entry.id,
13856
- apiMode: entry.apiMode,
13857
- authType: entry.authType,
13858
- baseUrl: entry.baseUrl,
13859
- envVars: entry.envVars,
13860
- fallbackModels: entry.fallbackModels,
13861
- displayName: entry.displayName,
13862
- aliases: entry.aliases,
13863
- modelsUrl: entry.modelsUrl,
13864
- hostname: entry.hostname,
13865
- extraHeaders: entry.extraHeaders
13866
- };
13867
- registerProvider(profile);
13868
- }
13869
- }
13870
-
13871
13994
  // src/internal/providers/builtin/anthropic.ts
13872
13995
  var ANTHROPIC = {
13873
13996
  name: "anthropic",