@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/eval.js CHANGED
@@ -566,10 +566,10 @@ function buildToolPrompt(prompt) {
566
566
  Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
567
567
  }
568
568
  function setupStructuredOutput(schema, maxRetries) {
569
- const z10 = requireZod();
569
+ const z11 = requireZod();
570
570
  const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
571
571
  return {
572
- z: z10,
572
+ z: z11,
573
573
  jsonSchema,
574
574
  maxRetries: maxRetries ?? 1,
575
575
  initialUsage: { inputTokens: 0, outputTokens: 0 }
@@ -10496,6 +10496,178 @@ function applyToolResultGuard(parts, opts) {
10496
10496
  )
10497
10497
  );
10498
10498
  }
10499
+ var MODALITIES = ["text", "audio", "image", "video", "pdf"];
10500
+ var costSchema = z.object({
10501
+ /** USD per 1M tokens (models.dev convention). */
10502
+ input: z.number().nonnegative(),
10503
+ output: z.number().nonnegative(),
10504
+ cache_read: z.number().nonnegative().optional(),
10505
+ cache_write: z.number().nonnegative().optional()
10506
+ }).loose();
10507
+ var limitSchema = z.object({
10508
+ context: z.number().positive(),
10509
+ input: z.number().positive().optional(),
10510
+ output: z.number().positive().optional()
10511
+ }).loose();
10512
+ var modalitiesSchema = z.object({
10513
+ input: z.array(z.enum(MODALITIES)).optional(),
10514
+ output: z.array(z.enum(MODALITIES)).optional()
10515
+ }).loose();
10516
+ var catalogModelSchema = z.object({
10517
+ name: z.string().optional(),
10518
+ release_date: z.string().optional(),
10519
+ attachment: z.boolean().optional(),
10520
+ reasoning: z.boolean().optional(),
10521
+ temperature: z.boolean().optional(),
10522
+ tool_call: z.boolean().optional(),
10523
+ /** theokit extension — maps to ModelCapabilities.supportsStructuredOutput. */
10524
+ structured_output: z.boolean().optional(),
10525
+ /** theokit extension — maps to ModelCapabilities.supportsCacheControl. */
10526
+ cache_control: z.boolean().optional(),
10527
+ cost: costSchema.optional(),
10528
+ limit: limitSchema.optional(),
10529
+ modalities: modalitiesSchema.optional(),
10530
+ status: z.enum(["alpha", "beta", "deprecated"]).optional()
10531
+ }).loose();
10532
+
10533
+ // src/internal/providers/registry.ts
10534
+ function globalSingleton(key, create) {
10535
+ const g = globalThis;
10536
+ const sym = Symbol.for(key);
10537
+ if (g[sym] === void 0) g[sym] = create();
10538
+ return g[sym];
10539
+ }
10540
+ var REGISTRY = globalSingleton(
10541
+ "theokit-sdk.providers.registry",
10542
+ () => /* @__PURE__ */ new Map()
10543
+ );
10544
+ var ALIASES = globalSingleton("theokit-sdk.providers.aliases", () => /* @__PURE__ */ new Map());
10545
+ function registerProvider(profile) {
10546
+ if (REGISTRY.has(profile.name)) {
10547
+ process.stderr.write(`[theokit-sdk] Provider "${profile.name}" overridden by user plugin.
10548
+ `);
10549
+ }
10550
+ REGISTRY.set(profile.name, profile);
10551
+ for (const alias of profile.aliases ?? []) {
10552
+ const previous = ALIASES.get(alias);
10553
+ if (previous !== void 0 && previous !== profile.name) {
10554
+ process.stderr.write(
10555
+ `[theokit-sdk] Alias "${alias}" collision: was "${previous}", now "${profile.name}".
10556
+ `
10557
+ );
10558
+ }
10559
+ ALIASES.set(alias, profile.name);
10560
+ }
10561
+ }
10562
+ function getProviderProfile(name) {
10563
+ const canonical = ALIASES.get(name) ?? name;
10564
+ return REGISTRY.get(canonical);
10565
+ }
10566
+
10567
+ // src/internal/providers/catalog-loader.ts
10568
+ var __dirname_resolved = dirname(fileURLToPath(import.meta.url));
10569
+ function globalSingleton2(key, create) {
10570
+ const g = globalThis;
10571
+ const sym = Symbol.for(key);
10572
+ if (g[sym] === void 0) g[sym] = create();
10573
+ return g[sym];
10574
+ }
10575
+ var modelInfoIndex = globalSingleton2(
10576
+ "theokit-sdk.providers.model-info-index",
10577
+ () => /* @__PURE__ */ new Map()
10578
+ );
10579
+ var patchedModelKeys = globalSingleton2(
10580
+ "theokit-sdk.providers.model-info-patched",
10581
+ () => /* @__PURE__ */ new Set()
10582
+ );
10583
+ var indexState = globalSingleton2("theokit-sdk.providers.model-info-loaded", () => ({
10584
+ loaded: false
10585
+ }));
10586
+ function getCatalogModelInfo(key) {
10587
+ ensureModelIndexLoaded();
10588
+ return modelInfoIndex.get(key);
10589
+ }
10590
+ function isPatchedModelKey(key) {
10591
+ return patchedModelKeys.has(key);
10592
+ }
10593
+ function ensureModelIndexLoaded() {
10594
+ if (indexState.loaded) return;
10595
+ indexState.loaded = true;
10596
+ try {
10597
+ const catalog = loadProviderCatalog();
10598
+ for (const entry of Object.values(catalog)) {
10599
+ indexEntryModels(entry);
10600
+ }
10601
+ } catch (err) {
10602
+ process.stderr.write(
10603
+ `[theokit-sdk] WARN: provider catalog unavailable (${err.message}) \u2014 per-model data disabled
10604
+ `
10605
+ );
10606
+ }
10607
+ }
10608
+ function indexEntryModels(entry) {
10609
+ if (entry.models === void 0 || typeof entry.models !== "object") return;
10610
+ for (const [modelId, raw] of Object.entries(entry.models)) {
10611
+ const parsed = catalogModelSchema.safeParse(raw);
10612
+ if (!parsed.success) {
10613
+ process.stderr.write(
10614
+ `[theokit-sdk] WARN: Skipping malformed catalog model "${entry.id}/${modelId}": ${parsed.error.issues[0]?.message ?? "invalid"}
10615
+ `
10616
+ );
10617
+ continue;
10618
+ }
10619
+ modelInfoIndex.set(`${entry.id}/${modelId}`, parsed.data);
10620
+ for (const alias of entry.aliases ?? []) {
10621
+ const key = `${alias}/${modelId}`;
10622
+ if (!modelInfoIndex.has(key)) modelInfoIndex.set(key, parsed.data);
10623
+ }
10624
+ }
10625
+ }
10626
+ function validateEntry(raw) {
10627
+ 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") {
10628
+ return null;
10629
+ }
10630
+ return raw;
10631
+ }
10632
+ function loadProviderCatalog(opts) {
10633
+ const catalogPath = join(__dirname_resolved, "provider-catalog.json");
10634
+ const rawText = readFileSync(catalogPath, "utf-8");
10635
+ let entries = JSON.parse(rawText);
10636
+ const result = {};
10637
+ for (const raw of entries) {
10638
+ const validated = validateEntry(raw);
10639
+ if (validated === null) {
10640
+ process.stderr.write(
10641
+ `[theokit-sdk] WARN: Skipping malformed catalog entry: ${JSON.stringify(raw).slice(0, 100)}
10642
+ `
10643
+ );
10644
+ continue;
10645
+ }
10646
+ result[validated.id] = validated;
10647
+ }
10648
+ return result;
10649
+ }
10650
+ function registerCatalogProviders(opts) {
10651
+ const catalog = loadProviderCatalog();
10652
+ for (const entry of Object.values(catalog)) {
10653
+ if (getProviderProfile(entry.id) !== void 0) continue;
10654
+ if (entry.aliases?.some((a) => getProviderProfile(a) !== void 0)) continue;
10655
+ const profile = {
10656
+ name: entry.id,
10657
+ apiMode: entry.apiMode,
10658
+ authType: entry.authType,
10659
+ baseUrl: entry.baseUrl,
10660
+ envVars: entry.envVars,
10661
+ fallbackModels: entry.fallbackModels,
10662
+ displayName: entry.displayName,
10663
+ aliases: entry.aliases,
10664
+ modelsUrl: entry.modelsUrl,
10665
+ hostname: entry.hostname,
10666
+ extraHeaders: entry.extraHeaders
10667
+ };
10668
+ registerProvider(profile);
10669
+ }
10670
+ }
10499
10671
 
10500
10672
  // src/internal/budget/pricing-data.json
10501
10673
  var pricing_data_default = {
@@ -10588,9 +10760,9 @@ var pricing_data_default = {
10588
10760
  cacheRead: 0.025
10589
10761
  },
10590
10762
  "openai/o3": {
10591
- input: 10,
10592
- output: 40,
10593
- cacheRead: 2.5
10763
+ input: 2,
10764
+ output: 8,
10765
+ cacheRead: 0.5
10594
10766
  },
10595
10767
  "openai/o3-mini": {
10596
10768
  input: 1.1,
@@ -10678,6 +10850,30 @@ function getPricingEntry(opts) {
10678
10850
  if (found2 !== void 0) return buildEntry(stripped, found2);
10679
10851
  }
10680
10852
  }
10853
+ const catalogEntry = catalogCostFallback(opts.provider, cleaned);
10854
+ if (catalogEntry !== void 0) return catalogEntry;
10855
+ return void 0;
10856
+ }
10857
+ function catalogCostFallback(provider, cleanedModel) {
10858
+ const stripped = stripDateSuffix(cleanedModel);
10859
+ const candidates = [`${provider}/${cleanedModel}`, cleanedModel];
10860
+ if (stripped !== cleanedModel) candidates.push(`${provider}/${stripped}`, stripped);
10861
+ for (const key of candidates) {
10862
+ const info = getCatalogModelInfo(key);
10863
+ const cost = info?.cost;
10864
+ if (cost === void 0) continue;
10865
+ const [prov, ...modelParts] = key.split("/");
10866
+ return {
10867
+ provider: prov ?? provider,
10868
+ model: modelParts.join("/") || cleanedModel,
10869
+ inputCostPerMillion: cost.input,
10870
+ outputCostPerMillion: cost.output,
10871
+ ...cost.cache_read !== void 0 ? { cacheReadCostPerMillion: cost.cache_read } : {},
10872
+ ...cost.cache_write !== void 0 ? { cacheWriteCostPerMillion: cost.cache_write } : {},
10873
+ // M44 M5 fix — honest provenance: a key patched by the LIVE models-dev source is not "vendored".
10874
+ pricingVersion: isPatchedModelKey(key) ? "catalog-models-dev" : "catalog-vendored"
10875
+ };
10876
+ }
10681
10877
  return void 0;
10682
10878
  }
10683
10879
 
@@ -11194,79 +11390,6 @@ function abortError(signal) {
11194
11390
  // src/internal/llm/router.ts
11195
11391
  init_errors();
11196
11392
 
11197
- // src/internal/providers/registry.ts
11198
- var REGISTRY = /* @__PURE__ */ new Map();
11199
- var ALIASES = /* @__PURE__ */ new Map();
11200
- function registerProvider(profile) {
11201
- if (REGISTRY.has(profile.name)) {
11202
- process.stderr.write(`[theokit-sdk] Provider "${profile.name}" overridden by user plugin.
11203
- `);
11204
- }
11205
- REGISTRY.set(profile.name, profile);
11206
- for (const alias of profile.aliases ?? []) {
11207
- const previous = ALIASES.get(alias);
11208
- if (previous !== void 0 && previous !== profile.name) {
11209
- process.stderr.write(
11210
- `[theokit-sdk] Alias "${alias}" collision: was "${previous}", now "${profile.name}".
11211
- `
11212
- );
11213
- }
11214
- ALIASES.set(alias, profile.name);
11215
- }
11216
- }
11217
- function getProviderProfile(name) {
11218
- const canonical = ALIASES.get(name) ?? name;
11219
- return REGISTRY.get(canonical);
11220
- }
11221
-
11222
- // src/internal/providers/catalog-loader.ts
11223
- var __dirname_resolved = dirname(fileURLToPath(import.meta.url));
11224
- function validateEntry(raw) {
11225
- 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") {
11226
- return null;
11227
- }
11228
- return raw;
11229
- }
11230
- function loadProviderCatalog(opts) {
11231
- const catalogPath = join(__dirname_resolved, "provider-catalog.json");
11232
- const rawText = readFileSync(catalogPath, "utf-8");
11233
- let entries = JSON.parse(rawText);
11234
- const result = {};
11235
- for (const raw of entries) {
11236
- const validated = validateEntry(raw);
11237
- if (validated === null) {
11238
- process.stderr.write(
11239
- `[theokit-sdk] WARN: Skipping malformed catalog entry: ${JSON.stringify(raw).slice(0, 100)}
11240
- `
11241
- );
11242
- continue;
11243
- }
11244
- result[validated.id] = validated;
11245
- }
11246
- return result;
11247
- }
11248
- function registerCatalogProviders(opts) {
11249
- const catalog = loadProviderCatalog();
11250
- for (const entry of Object.values(catalog)) {
11251
- if (getProviderProfile(entry.id) !== void 0) continue;
11252
- if (entry.aliases?.some((a) => getProviderProfile(a) !== void 0)) continue;
11253
- const profile = {
11254
- name: entry.id,
11255
- apiMode: entry.apiMode,
11256
- authType: entry.authType,
11257
- baseUrl: entry.baseUrl,
11258
- envVars: entry.envVars,
11259
- fallbackModels: entry.fallbackModels,
11260
- displayName: entry.displayName,
11261
- aliases: entry.aliases,
11262
- modelsUrl: entry.modelsUrl,
11263
- hostname: entry.hostname,
11264
- extraHeaders: entry.extraHeaders
11265
- };
11266
- registerProvider(profile);
11267
- }
11268
- }
11269
-
11270
11393
  // src/internal/providers/builtin/anthropic.ts
11271
11394
  var ANTHROPIC = {
11272
11395
  name: "anthropic",