@stll/ai-catalog 0.7.1 → 0.8.0

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.
@@ -1,3 +1,4 @@
1
+ import { MODEL_DEFAULTS_LEDGER, MODEL_TASK_OVERRIDE_GROUP, resolveDefaultModel } from "./model-defaults-ledger.js";
1
2
  import * as v from "valibot";
2
3
  //#region src/capabilities.gen.ts
3
4
  /**
@@ -2061,21 +2062,6 @@ const DOCUMENT_INPUT_OVERRIDES = {
2061
2062
  * ID here against live provider/aggregator listings so a retired model
2062
2063
  * fails CI instead of 400-ing a user at runtime.
2063
2064
  */
2064
- /**
2065
- * Logical model roles. Call sites declare *what* they need, not
2066
- * *which* model to use.
2067
- *
2068
- * - fast: classification, extraction, short generation
2069
- * - chat: conversational with tool use and streaming
2070
- * - reasoning: complex multi-step legal analysis
2071
- * - pdf: native PDF/image understanding
2072
- */
2073
- const MODEL_ROLES = [
2074
- "fast",
2075
- "chat",
2076
- "reasoning",
2077
- "pdf"
2078
- ];
2079
2065
  const TEMPERATURE_POLICIES = ["emit", "omit"];
2080
2066
  const IMAGE_INPUT_CAPABILITIES = [
2081
2067
  "supported",
@@ -2173,176 +2159,48 @@ const GPT_56_MODEL_IDS = {
2173
2159
  };
2174
2160
  const GPT_56_OPENAI_MODEL_IDS = Object.values(GPT_56_MODEL_IDS).map(({ openai }) => openai);
2175
2161
  const GPT_56_OPENROUTER_MODEL_IDS = Object.values(GPT_56_MODEL_IDS).map(({ openrouter }) => openrouter);
2162
+ const defaultPresentation = (entry) => ({
2163
+ kind: "default",
2164
+ modelId: entry.candidate.modelId,
2165
+ rationaleKey: entry.rationale.rationaleKey
2166
+ });
2167
+ /** Default labels in the override editor derive from the task ledger. */
2176
2168
  const BYOK_DEFAULT_MODELS = {
2177
2169
  google: {
2178
- fast: {
2179
- kind: "default",
2180
- modelId: "gemini-3.8-flash",
2181
- rationaleKey: "organization.aiConfig.defaultRationale.fast"
2182
- },
2183
- chat: {
2184
- kind: "default",
2185
- modelId: "gemini-3.8-flash",
2186
- rationaleKey: "organization.aiConfig.defaultRationale.chat"
2187
- },
2188
- reasoning: {
2189
- kind: "default",
2190
- modelId: "gemini-3.8-flash",
2191
- rationaleKey: "organization.aiConfig.defaultRationale.reasoning"
2192
- },
2193
- pdf: {
2194
- kind: "default",
2195
- modelId: "gemini-3.8-flash",
2196
- rationaleKey: "organization.aiConfig.defaultRationale.pdf"
2197
- }
2170
+ fast: defaultPresentation(MODEL_DEFAULTS_LEDGER["short-text"].google),
2171
+ chat: defaultPresentation(MODEL_DEFAULTS_LEDGER.chat.google),
2172
+ reasoning: defaultPresentation(MODEL_DEFAULTS_LEDGER.reasoning.google),
2173
+ pdf: defaultPresentation(MODEL_DEFAULTS_LEDGER.pdf.google)
2198
2174
  },
2199
2175
  openrouter: {
2200
- fast: {
2201
- kind: "default",
2202
- modelId: GPT_6_MODEL_IDS.luna.openrouter,
2203
- rationaleKey: "organization.aiConfig.defaultRationale.fast"
2204
- },
2205
- chat: {
2206
- kind: "default",
2207
- modelId: GPT_6_MODEL_IDS.sol.openrouter,
2208
- rationaleKey: "organization.aiConfig.defaultRationale.chat"
2209
- },
2210
- reasoning: {
2211
- kind: "default",
2212
- modelId: GPT_6_MODEL_IDS.sol.openrouter,
2213
- rationaleKey: "organization.aiConfig.defaultRationale.reasoning"
2214
- },
2215
- pdf: {
2216
- kind: "default",
2217
- modelId: GPT_6_MODEL_IDS.sol.openrouter,
2218
- rationaleKey: "organization.aiConfig.defaultRationale.pdf"
2219
- }
2176
+ fast: defaultPresentation(MODEL_DEFAULTS_LEDGER["short-text"].openrouter),
2177
+ chat: defaultPresentation(MODEL_DEFAULTS_LEDGER.chat.openrouter),
2178
+ reasoning: defaultPresentation(MODEL_DEFAULTS_LEDGER.reasoning.openrouter),
2179
+ pdf: defaultPresentation(MODEL_DEFAULTS_LEDGER.pdf.openrouter)
2220
2180
  },
2221
2181
  openai: {
2222
- fast: {
2223
- kind: "default",
2224
- modelId: GPT_6_MODEL_IDS.luna.openai,
2225
- rationaleKey: "organization.aiConfig.defaultRationale.fast"
2226
- },
2227
- chat: {
2228
- kind: "default",
2229
- modelId: GPT_6_MODEL_IDS.sol.openai,
2230
- rationaleKey: "organization.aiConfig.defaultRationale.chat"
2231
- },
2232
- reasoning: {
2233
- kind: "default",
2234
- modelId: GPT_6_MODEL_IDS.sol.openai,
2235
- rationaleKey: "organization.aiConfig.defaultRationale.reasoning"
2236
- },
2237
- pdf: {
2238
- kind: "default",
2239
- modelId: GPT_6_MODEL_IDS.sol.openai,
2240
- rationaleKey: "organization.aiConfig.defaultRationale.pdf"
2241
- }
2182
+ fast: defaultPresentation(MODEL_DEFAULTS_LEDGER["short-text"].openai),
2183
+ chat: defaultPresentation(MODEL_DEFAULTS_LEDGER.chat.openai),
2184
+ reasoning: defaultPresentation(MODEL_DEFAULTS_LEDGER.reasoning.openai),
2185
+ pdf: defaultPresentation(MODEL_DEFAULTS_LEDGER.pdf.openai)
2242
2186
  },
2243
2187
  anthropic: {
2244
- fast: {
2245
- kind: "default",
2246
- modelId: "claude-opus-5-5",
2247
- rationaleKey: "organization.aiConfig.defaultRationale.fast"
2248
- },
2249
- chat: {
2250
- kind: "default",
2251
- modelId: "claude-opus-5-5",
2252
- rationaleKey: "organization.aiConfig.defaultRationale.chat"
2253
- },
2254
- reasoning: {
2255
- kind: "default",
2256
- modelId: "claude-opus-5-5",
2257
- rationaleKey: "organization.aiConfig.defaultRationale.reasoning"
2258
- },
2259
- pdf: {
2260
- kind: "default",
2261
- modelId: "claude-opus-5-5",
2262
- rationaleKey: "organization.aiConfig.defaultRationale.pdf"
2263
- }
2188
+ fast: defaultPresentation(MODEL_DEFAULTS_LEDGER["short-text"].anthropic),
2189
+ chat: defaultPresentation(MODEL_DEFAULTS_LEDGER.chat.anthropic),
2190
+ reasoning: defaultPresentation(MODEL_DEFAULTS_LEDGER.reasoning.anthropic),
2191
+ pdf: defaultPresentation(MODEL_DEFAULTS_LEDGER.pdf.anthropic)
2264
2192
  },
2265
2193
  bedrock: {
2266
- fast: {
2267
- kind: "default",
2268
- modelId: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
2269
- rationaleKey: "organization.aiConfig.defaultRationale.fast"
2270
- },
2271
- chat: {
2272
- kind: "default",
2273
- modelId: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
2274
- rationaleKey: "organization.aiConfig.defaultRationale.chat"
2275
- },
2276
- reasoning: {
2277
- kind: "default",
2278
- modelId: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
2279
- rationaleKey: "organization.aiConfig.defaultRationale.reasoning"
2280
- },
2281
- pdf: {
2282
- kind: "default",
2283
- modelId: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
2284
- rationaleKey: "organization.aiConfig.defaultRationale.pdf"
2285
- }
2194
+ fast: defaultPresentation(MODEL_DEFAULTS_LEDGER["short-text"].bedrock),
2195
+ chat: defaultPresentation(MODEL_DEFAULTS_LEDGER.chat.bedrock),
2196
+ reasoning: defaultPresentation(MODEL_DEFAULTS_LEDGER.reasoning.bedrock),
2197
+ pdf: defaultPresentation(MODEL_DEFAULTS_LEDGER.pdf.bedrock)
2286
2198
  },
2287
2199
  mistral: {
2288
- fast: {
2289
- kind: "default",
2290
- modelId: "mistral-small-latest",
2291
- rationaleKey: "organization.aiConfig.defaultRationale.fast"
2292
- },
2293
- chat: {
2294
- kind: "default",
2295
- modelId: "mistral-medium-latest",
2296
- rationaleKey: "organization.aiConfig.defaultRationale.chat"
2297
- },
2298
- reasoning: {
2299
- kind: "default",
2300
- modelId: "mistral-medium-latest",
2301
- rationaleKey: "organization.aiConfig.defaultRationale.reasoning"
2302
- },
2303
- pdf: { kind: "unsupported" }
2304
- }
2305
- };
2306
- const defaultModelIds = (defaults) => ({
2307
- fast: defaults.fast.modelId,
2308
- chat: defaults.chat.modelId,
2309
- reasoning: defaults.reasoning.modelId,
2310
- pdf: defaults.pdf.modelId
2311
- });
2312
- /**
2313
- * Instance-level default model IDs per provider. Extends the BYOK
2314
- * defaults with the providers that only the instance path uses
2315
- * (custom deployments and OpenAI-compatible endpoints).
2316
- */
2317
- const DEFAULT_MODELS = {
2318
- google: defaultModelIds(BYOK_DEFAULT_MODELS.google),
2319
- openrouter: defaultModelIds(BYOK_DEFAULT_MODELS.openrouter),
2320
- openai: defaultModelIds(BYOK_DEFAULT_MODELS.openai),
2321
- anthropic: defaultModelIds(BYOK_DEFAULT_MODELS.anthropic),
2322
- bedrock: defaultModelIds(BYOK_DEFAULT_MODELS.bedrock),
2323
- mistral: {
2324
- fast: BYOK_DEFAULT_MODELS.mistral.fast.modelId,
2325
- chat: BYOK_DEFAULT_MODELS.mistral.chat.modelId,
2326
- reasoning: BYOK_DEFAULT_MODELS.mistral.reasoning.modelId,
2327
- pdf: null
2328
- },
2329
- azure_foundry: {
2330
- fast: GPT_56_MODEL_IDS.luna.openai,
2331
- chat: GPT_56_MODEL_IDS.terra.openai,
2332
- reasoning: GPT_56_MODEL_IDS.terra.openai,
2333
- pdf: GPT_56_MODEL_IDS.terra.openai
2334
- },
2335
- openai_compatible: {
2336
- fast: "default",
2337
- chat: "default",
2338
- reasoning: "default",
2339
- pdf: "default"
2340
- },
2341
- huggingface: {
2342
- fast: "speakleash/Bielik-1.5B-v3.0-Instruct",
2343
- chat: "speakleash/Bielik-11B-v2.3-Instruct",
2344
- reasoning: "speakleash/Bielik-11B-v2.3-Instruct",
2345
- pdf: "speakleash/Bielik-11B-v2.3-Instruct"
2200
+ fast: defaultPresentation(MODEL_DEFAULTS_LEDGER["short-text"].mistral),
2201
+ chat: defaultPresentation(MODEL_DEFAULTS_LEDGER.chat.mistral),
2202
+ reasoning: defaultPresentation(MODEL_DEFAULTS_LEDGER.reasoning.mistral),
2203
+ pdf: { kind: MODEL_DEFAULTS_LEDGER.pdf.mistral.kind }
2346
2204
  }
2347
2205
  };
2348
2206
  /**
@@ -2801,34 +2659,18 @@ const isOfferedBYOKModelForRole = ({ provider, modelId, role }) => {
2801
2659
  role
2802
2660
  });
2803
2661
  };
2804
- /**
2805
- * Resolve a model id that will actually work for this provider+role,
2806
- * keeping the SAME provider. Returns the caller's model unchanged when
2807
- * it is still offered; otherwise falls back to the provider's per-role
2808
- * default (`BYOK_DEFAULT_MODELS`). Returns `null` only when the
2809
- * provider has no valid model for the role at all — the sole case
2810
- * today is `mistral` + `pdf`, because the TanStack Mistral adapter
2811
- * exposes no `document` input modality, so no Mistral model (not even
2812
- * the default) can serve the PDF role.
2813
- *
2814
- * Used to auto-heal org AI configs whose pinned model was removed by a
2815
- * catalog bump, so generation resolves to a supported model instead of
2816
- * 400-ing (or forwarding a retired id to the provider).
2817
- */
2818
- const resolveWorkingBYOKModelForRole = ({ provider, modelId, role }) => {
2662
+ /** Keep a supported override, otherwise use that provider's task default. */
2663
+ const resolveWorkingBYOKModelForTask = ({ provider, modelId, task }) => {
2664
+ const role = MODEL_TASK_OVERRIDE_GROUP[task];
2819
2665
  if (isOfferedBYOKModelForRole({
2820
2666
  provider,
2821
2667
  modelId,
2822
2668
  role
2823
2669
  })) return modelId;
2824
- const entry = BYOK_DEFAULT_MODELS[provider][role];
2825
- if (entry.kind === "unsupported") return null;
2826
- const fallback = entry.modelId;
2827
- return isOfferedBYOKModelForRole({
2828
- provider,
2829
- modelId: fallback,
2830
- role
2831
- }) ? fallback : null;
2670
+ return resolveDefaultModel({
2671
+ task,
2672
+ orgProviders: [provider]
2673
+ })?.modelId ?? null;
2832
2674
  };
2833
2675
  /** Native Anthropic adaptive-thinking models, derived from replay capabilities. */
2834
2676
  const ANTHROPIC_ADAPTIVE_THINKING_MODELS = BYOK_MODEL_OPTIONS.anthropic.filter((model) => MODEL_REASONING_CAPABILITIES[model].anthropicThinking === "adaptive");
@@ -2849,24 +2691,6 @@ const REASONING_EFFORTS = [
2849
2691
  ];
2850
2692
  const resolvedReasoningEffortSchema = v.pipe(v.picklist(REASONING_EFFORTS), v.brand("ResolvedReasoningEffort"));
2851
2693
  /**
2852
- * Per-provider model served when a user's included budget is exhausted
2853
- * and no explicit selection overrides it. Falls back to each
2854
- * provider's fast-role default; providers without a first-class
2855
- * adapter path cannot serve the lane. Total over providers so a new
2856
- * provider lands with an explicit decision.
2857
- */
2858
- const FALLBACK_CHAT_MODEL_BY_PROVIDER = {
2859
- google: DEFAULT_MODELS.google.fast,
2860
- openrouter: DEFAULT_MODELS.openrouter.fast,
2861
- openai: DEFAULT_MODELS.openai.fast,
2862
- anthropic: DEFAULT_MODELS.anthropic.fast,
2863
- bedrock: DEFAULT_MODELS.bedrock.fast,
2864
- mistral: DEFAULT_MODELS.mistral.fast,
2865
- azure_foundry: null,
2866
- openai_compatible: null,
2867
- huggingface: null
2868
- };
2869
- /**
2870
2694
  * Provider-native IDs that are exact aliases of an offered catalog ID.
2871
2695
  * Every metadata lookup normalizes here, so instance/dev overrides cannot
2872
2696
  * bypass rates or capabilities and duplicated alias rows cannot drift apart.
@@ -3054,7 +2878,7 @@ const getModelRate = (modelId) => {
3054
2878
  *
3055
2879
  * Keys are the canonical model IDs stella resolves for the provider
3056
2880
  * adapters (the same forms used in `MODEL_RATES`, `BYOK_MODEL_OPTIONS`,
3057
- * and `DEFAULT_MODELS`, including OpenRouter provider-prefixed slugs and
2881
+ * and the task defaults ledger, including OpenRouter provider-prefixed slugs and
3058
2882
  * AWS Bedrock IDs). Values are the providers' publicly documented input
3059
2883
  * windows; where a provider offers a larger beta window we intentionally
3060
2884
  * take the conservative default (e.g. Claude's standard 200K rather than
@@ -3172,4 +2996,4 @@ const getModelReasoningCapabilities = (modelId) => {
3172
2996
  return Object.hasOwn(MODEL_REASONING_CAPABILITIES_BY_ID, normalized) ? MODEL_REASONING_CAPABILITIES_BY_ID[normalized] ?? null : null;
3173
2997
  };
3174
2998
  //#endregion
3175
- export { MODEL_RATES as $, getModelReasoningCapabilities as A, supportsStreamingToolUse as B, TANSTACK_AI_PROVIDERS as C, getModelDisplayMetadata as D, getModelDefaultReasoningEffort as E, isChatPdfAttachmentModelSupported as F, MODELS_DEV_RATE_PROVIDER_BY_CATALOG_PROVIDER as G, CAPABILITY_OVERRIDES as H, normalizeModelCatalogId as I, MODEL_RATE_UNITS_PER_USD as J, MODELS_DEV_RATE_SOURCE_ALIASES as K, resolveReasoningEffort as L, getOutputTokenLimit as M, isBYOKModelRoleSupported as N, getModelImageInputCapability as O, isBYOKProviderRoleSupported as P, REASONING_REPLAY_FORMATS as Q, resolveWorkingBYOKModelForRole as R, STREAMING_TOOL_USE_SUPPORTS as S, getContextWindowTokens as T, IMAGE_INPUT_OVERRIDES as U, DOCUMENT_INPUT_OVERRIDES as V, MODELS_DEV_RATE_CORRECTIONS as W, resolveModelRate as X, getStandardModelRate as Y, MODEL_REASONING_CAPABILITIES as Z, MODEL_DISPLAY_METADATA as _, BYOK_MODEL_OPTIONS as a, REASONING_EFFORTS as b, DECISION_MODEL_CATALOG as c, DEFAULT_MODELS as d, MODEL_DEFAULT_REASONING_EFFORTS as et, FALLBACK_CHAT_MODEL_BY_PROVIDER as f, MODEL_CATALOG_PROVIDER_KIND as g, MODEL_CATALOG_ID_ALIASES as h, BYOK_DOCUMENT_INPUT_MODEL_OPTIONS as i, MODEL_TEMPERATURE_POLICIES as it, getModelReasoningEfforts as j, getModelRate as k, DECISION_MODEL_PROVIDERS as l, IMAGE_INPUT_CAPABILITIES as m, ANTHROPIC_ADAPTIVE_THINKING_MODELS as n, MODEL_OUTPUT_TOKEN_LIMITS as nt, CHAT_PDF_ATTACHMENT_MODEL_OPTIONS as o, FIRST_PARTY_MODEL_PROVIDERS as p, RETAINED_MODELS_DEV_RATE_ENTRIES as q, BYOK_DEFAULT_MODELS as r, MODEL_REASONING_EFFORTS as rt, CONTEXT_WINDOW_TOKENS as s, AI_PROVIDERS as t, MODEL_IMAGE_INPUT_CAPABILITIES as tt, DEFAULT_CONTEXT_WINDOW_TOKENS as u, MODEL_ROLES as v, TEMPERATURE_POLICIES as w, RECOMMENDED_CHAT_MODELS as x, MODEL_STREAMING_TOOL_USE as y, shouldEmitTemperature as z };
2999
+ export { MODEL_OUTPUT_TOKEN_LIMITS as $, isBYOKModelRoleSupported as A, IMAGE_INPUT_OVERRIDES as B, getModelDefaultReasoningEffort as C, getModelReasoningCapabilities as D, getModelRate as E, resolveWorkingBYOKModelForTask as F, MODEL_RATE_UNITS_PER_USD as G, MODELS_DEV_RATE_PROVIDER_BY_CATALOG_PROVIDER as H, shouldEmitTemperature as I, MODEL_REASONING_CAPABILITIES as J, getStandardModelRate as K, supportsStreamingToolUse as L, isChatPdfAttachmentModelSupported as M, normalizeModelCatalogId as N, getModelReasoningEfforts as O, resolveReasoningEffort as P, MODEL_IMAGE_INPUT_CAPABILITIES as Q, DOCUMENT_INPUT_OVERRIDES as R, getContextWindowTokens as S, getModelImageInputCapability as T, MODELS_DEV_RATE_SOURCE_ALIASES as U, MODELS_DEV_RATE_CORRECTIONS as V, RETAINED_MODELS_DEV_RATE_ENTRIES as W, MODEL_RATES as X, REASONING_REPLAY_FORMATS as Y, MODEL_DEFAULT_REASONING_EFFORTS as Z, REASONING_EFFORTS as _, BYOK_MODEL_OPTIONS as a, TANSTACK_AI_PROVIDERS as b, DECISION_MODEL_CATALOG as c, FIRST_PARTY_MODEL_PROVIDERS as d, MODEL_REASONING_EFFORTS as et, IMAGE_INPUT_CAPABILITIES as f, MODEL_STREAMING_TOOL_USE as g, MODEL_DISPLAY_METADATA as h, BYOK_DOCUMENT_INPUT_MODEL_OPTIONS as i, isBYOKProviderRoleSupported as j, getOutputTokenLimit as k, DECISION_MODEL_PROVIDERS as l, MODEL_CATALOG_PROVIDER_KIND as m, ANTHROPIC_ADAPTIVE_THINKING_MODELS as n, CHAT_PDF_ATTACHMENT_MODEL_OPTIONS as o, MODEL_CATALOG_ID_ALIASES as p, resolveModelRate as q, BYOK_DEFAULT_MODELS as r, CONTEXT_WINDOW_TOKENS as s, AI_PROVIDERS as t, MODEL_TEMPERATURE_POLICIES as tt, DEFAULT_CONTEXT_WINDOW_TOKENS as u, RECOMMENDED_CHAT_MODELS as v, getModelDisplayMetadata as w, TEMPERATURE_POLICIES as x, STREAMING_TOOL_USE_SUPPORTS as y, CAPABILITY_OVERRIDES as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/ai-catalog",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Provider-neutral AI model roles, capabilities, and curated model metadata.",
5
5
  "keywords": [
6
6
  "ai",
@@ -36,6 +36,10 @@
36
36
  "./benchmarks": {
37
37
  "types": "./dist/benchmarks.d.ts",
38
38
  "import": "./dist/benchmarks.js"
39
+ },
40
+ "./model-defaults-ledger": {
41
+ "types": "./dist/model-defaults-ledger.d.ts",
42
+ "import": "./dist/model-defaults-ledger.js"
39
43
  }
40
44
  },
41
45
  "publishConfig": {
@@ -47,9 +51,11 @@
47
51
  "gen:benchmarks": "bun ../scripts/src/model-catalog-benchmarks-gen.ts",
48
52
  "gen:capabilities": "bun --preload ../../scripts/offline-network-preload.ts ../scripts/src/model-catalog-capabilities-gen.ts",
49
53
  "check:generations": "bun --preload ../../scripts/offline-network-preload.ts ../scripts/src/model-catalog-generation-check.ts",
54
+ "check:defaults": "bun ../../scripts/check-model-defaults-ledger.ts",
50
55
  "gen:rates": "bun --preload ../../scripts/offline-network-preload.ts ../scripts/src/model-catalog-rates-gen.ts",
51
56
  "pack:dry-run": "bun pm pack --dry-run",
52
57
  "test": "bun test src",
58
+ "test:defaults": "bun test src/model-defaults-ledger.test.ts",
53
59
  "test:property": "bun test --preload @stll/property-testing/preload $(grep -rlE 'fc\\.assert|assertProperty' src --include='*.test.ts')",
54
60
  "typecheck": "bun check --no-pretty --all --project=tsconfig.json",
55
61
  "lint": "cd ../.. && bun --bun oxlint -c oxlint.config.ts --report-unused-disable-directives-severity=error --type-aware --type-check packages/ai-catalog",