@dreb/ai 2.25.3 → 2.25.4
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/README.md +25 -0
- package/dist/models.d.ts +5 -0
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +0 -102
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +23 -125
- package/dist/models.generated.js.map +1 -1
- package/dist/models.js +8 -0
- package/dist/models.js.map +1 -1
- package/dist/providers/amazon-bedrock.d.ts +3 -1
- package/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/dist/providers/amazon-bedrock.js +18 -15
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/anthropic.d.ts +6 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +12 -10
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -509,6 +509,31 @@ for await (const event of s) {
|
|
|
509
509
|
}
|
|
510
510
|
```
|
|
511
511
|
|
|
512
|
+
### Controlling Thinking Display (Anthropic adaptive models)
|
|
513
|
+
|
|
514
|
+
Adaptive-thinking Claude models (Opus 4.6+, Sonnet 4.6+) support a `thinkingDisplay`
|
|
515
|
+
option on `streamSimple`/`completeSimple`:
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
const s = streamSimple(model, context, {
|
|
519
|
+
reasoning: 'high',
|
|
520
|
+
thinkingDisplay: 'summarized', // 'summarized' | 'omitted'
|
|
521
|
+
});
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
- `'summarized'` — the provider returns summarized thinking text (visible via
|
|
525
|
+
`thinking_delta` events and `thinking` blocks).
|
|
526
|
+
- `'omitted'` — the provider returns thinking blocks with an empty `thinking` field
|
|
527
|
+
and only an encrypted signature. Lower time-to-first-text latency, nothing to display.
|
|
528
|
+
|
|
529
|
+
This maps to Anthropic's `thinking.display` field. **Opus 4.7+ default to `'omitted'`
|
|
530
|
+
at the API**, so set `thinkingDisplay: 'summarized'` to make thinking visible again.
|
|
531
|
+
The option is only honored by adaptive-thinking Anthropic and Bedrock Claude models;
|
|
532
|
+
it is silently ignored by other models and budget-based thinking. When unset, the
|
|
533
|
+
provider default applies.
|
|
534
|
+
|
|
535
|
+
Use `supportsAdaptiveThinking(model)` to check whether a model honors this option.
|
|
536
|
+
|
|
512
537
|
## Stop Reasons
|
|
513
538
|
|
|
514
539
|
Every `AssistantMessage` includes a `stopReason` field that indicates how the generation ended:
|
package/dist/models.d.ts
CHANGED
|
@@ -49,6 +49,11 @@ export declare function calculateCost<TApi extends Api>(model: Model<TApi>, usag
|
|
|
49
49
|
* - Opus 4.6+ models (xhigh maps to adaptive effort "max" on Anthropic-compatible providers)
|
|
50
50
|
*/
|
|
51
51
|
export declare function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a model uses adaptive thinking (Opus 4.6+, Sonnet 4.6+), where the
|
|
54
|
+
* `thinkingDisplay` option is honored. Mirrors the per-provider internal checks.
|
|
55
|
+
*/
|
|
56
|
+
export declare function supportsAdaptiveThinking<TApi extends Api>(model: Model<TApi>): boolean;
|
|
52
57
|
/**
|
|
53
58
|
* Check if two models are equal by comparing both their id and provider.
|
|
54
59
|
* Returns false if either model is null or undefined.
|
package/dist/models.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAanE,KAAK,QAAQ,CACZ,SAAS,SAAS,aAAa,EAC/B,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,IAC9C,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,CAAC,IAAI,SAAS,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEjH,wBAAgB,QAAQ,CAAC,SAAS,SAAS,aAAa,EAAE,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,EAC1G,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,QAAQ,GACf,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAGtC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAGhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CA8BnF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CA4B7F;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,aAAa,EACxD,QAAQ,EAAE,SAAS,GACjB,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAGhE;AAED,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAO/F;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAkB3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAS,GAAG,EAC9C,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,EACjC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,GAC/B,OAAO,CAGT","sourcesContent":["import { MODELS } from \"./models.generated.js\";\nimport type { Api, KnownProvider, Model, Usage } from \"./types.js\";\n\nconst modelRegistry: Map<string, Map<string, Model<Api>>> = new Map();\n\n// Initialize registry from MODELS on module load\nfor (const [provider, models] of Object.entries(MODELS)) {\n\tconst providerModels = new Map<string, Model<Api>>();\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tproviderModels.set(id, model as Model<Api>);\n\t}\n\tmodelRegistry.set(provider, providerModels);\n}\n\ntype ModelApi<\n\tTProvider extends KnownProvider,\n\tTModelId extends keyof (typeof MODELS)[TProvider],\n> = (typeof MODELS)[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never;\n\nexport function getModel<TProvider extends KnownProvider, TModelId extends keyof (typeof MODELS)[TProvider]>(\n\tprovider: TProvider,\n\tmodelId: TModelId,\n): Model<ModelApi<TProvider, TModelId>> {\n\tconst providerModels = modelRegistry.get(provider);\n\treturn providerModels?.get(modelId as string) as Model<ModelApi<TProvider, TModelId>>;\n}\n\n/**\n * Check if a model ID looks like an alias (no date suffix).\n * Aliases are preferred over dated versions when fuzzy matching.\n *\n * IDs ending with `-latest` are treated as aliases.\n * IDs ending with a date pattern (`-YYYYMMDD`) are treated as dated versions.\n */\nexport function isModelAlias(id: string): boolean {\n\tif (id.endsWith(\"-latest\")) return true;\n\treturn !/-\\d{8}$/.test(id);\n}\n\n/**\n * Find a model by fuzzy matching against the provider's registered models.\n *\n * Resolution order:\n * 1. Exact match by provider + model ID (via registry Map.get)\n * 2. Case-insensitive substring match against model ID and display name\n * 3. Among matches, prefer aliases (non-dated IDs) over dated versions\n * 4. Among ties, pick the lexicographically highest (latest) ID\n *\n * This is the same matching logic used by the CLI, subagent model resolution,\n * and interactive mode — centralised here so tests can exercise the real path.\n *\n * @example\n * findModel(\"anthropic\", \"sonnet\") // → latest claude-sonnet alias\n * findModel(\"anthropic\", \"haiku\") // → latest claude-haiku alias\n * findModel(\"openai\", \"gpt-5\") // → latest gpt-5 alias\n */\nexport function findModel(provider: string, pattern: string): Model<Api> | undefined {\n\tconst providerModels = modelRegistry.get(provider);\n\tif (!providerModels) return undefined;\n\n\t// Try exact match first\n\tconst exact = providerModels.get(pattern);\n\tif (exact) return exact;\n\n\t// Substring match (case-insensitive)\n\tconst normalizedPattern = pattern.toLowerCase();\n\tconst matches = Array.from(providerModels.values()).filter(\n\t\t(m) => m.id.toLowerCase().includes(normalizedPattern) || m.name?.toLowerCase().includes(normalizedPattern),\n\t);\n\n\tif (matches.length === 0) return undefined;\n\tif (matches.length === 1) return matches[0];\n\n\t// Multiple matches — separate into aliases and dated versions\n\tconst aliases = matches.filter((m) => isModelAlias(m.id));\n\tconst datedVersions = matches.filter((m) => !isModelAlias(m.id));\n\n\tif (aliases.length > 0) {\n\t\t// Prefer alias — if multiple, pick the lexicographically highest\n\t\taliases.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn aliases[0];\n\t}\n\n\t// All dated — prefer the latest\n\tdatedVersions.sort((a, b) => b.id.localeCompare(a.id));\n\treturn datedVersions[0];\n}\n\n/**\n * Find a model by fuzzy matching against a flat array of models.\n * Same algorithm as findModel() but operates on an arbitrary model list\n * instead of the built-in registry.\n *\n * Used by model-resolver.ts and other code that manages its own model lists.\n */\nexport function findModelInList(pattern: string, models: Model<Api>[]): Model<Api> | undefined {\n\tif (models.length === 0) return undefined;\n\n\tconst normalizedPattern = pattern.toLowerCase();\n\n\t// Exact ID match (case-insensitive)\n\tconst exactById = models.find((m) => m.id.toLowerCase() === normalizedPattern);\n\tif (exactById) return exactById;\n\n\t// Substring match (case-insensitive)\n\tconst matches = models.filter(\n\t\t(m) => m.id.toLowerCase().includes(normalizedPattern) || m.name?.toLowerCase().includes(normalizedPattern),\n\t);\n\n\tif (matches.length === 0) return undefined;\n\tif (matches.length === 1) return matches[0];\n\n\t// Multiple matches — separate into aliases and dated versions\n\tconst aliases = matches.filter((m) => isModelAlias(m.id));\n\tconst datedVersions = matches.filter((m) => !isModelAlias(m.id));\n\n\tif (aliases.length > 0) {\n\t\taliases.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn aliases[0];\n\t}\n\n\tdatedVersions.sort((a, b) => b.id.localeCompare(a.id));\n\treturn datedVersions[0];\n}\n\nexport function getProviders(): KnownProvider[] {\n\treturn Array.from(modelRegistry.keys()) as KnownProvider[];\n}\n\nexport function getModels<TProvider extends KnownProvider>(\n\tprovider: TProvider,\n): Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[] {\n\tconst models = modelRegistry.get(provider);\n\treturn models ? (Array.from(models.values()) as Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[]) : [];\n}\n\nexport function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage[\"cost\"] {\n\tusage.cost.input = (model.cost.input / 1000000) * usage.input;\n\tusage.cost.output = (model.cost.output / 1000000) * usage.output;\n\tusage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;\n\tusage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage.cost;\n}\n\n/**\n * Check if a model supports xhigh thinking level.\n *\n * Supported today:\n * - GPT-5.2 / GPT-5.3 / GPT-5.4 model families\n * - Opus 4.6+ models (xhigh maps to adaptive effort \"max\" on Anthropic-compatible providers)\n */\nexport function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean {\n\tif (\n\t\tmodel.id.includes(\"gpt-5.2\") ||\n\t\tmodel.id.includes(\"gpt-5.3\") ||\n\t\tmodel.id.includes(\"gpt-5.4\") ||\n\t\tmodel.id.includes(\"gpt-5.5\")\n\t) {\n\t\treturn true;\n\t}\n\n\t// Opus 4.6+ supports xhigh (adaptive effort \"max\").\n\t// Match any opus-4-N or opus-4.N where N >= 6 (1-2 digit minor version, not date suffixes).\n\tconst opusMatch = model.id.match(/opus-4[.-](\\d{1,2})(?!\\d)/);\n\tif (opusMatch && Number.parseInt(opusMatch[1], 10) >= 6) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Check if two models are equal by comparing both their id and provider.\n * Returns false if either model is null or undefined.\n */\nexport function modelsAreEqual<TApi extends Api>(\n\ta: Model<TApi> | null | undefined,\n\tb: Model<TApi> | null | undefined,\n): boolean {\n\tif (!a || !b) return false;\n\treturn a.id === b.id && a.provider === b.provider;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAanE,KAAK,QAAQ,CACZ,SAAS,SAAS,aAAa,EAC/B,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,IAC9C,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,CAAC,IAAI,SAAS,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEjH,wBAAgB,QAAQ,CAAC,SAAS,SAAS,aAAa,EAAE,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,EAC1G,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,QAAQ,GACf,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAGtC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAGhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CA8BnF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CA4B7F;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,aAAa,EACxD,QAAQ,EAAE,SAAS,GACjB,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAGhE;AAED,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAO/F;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAkB3E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAGtF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAS,GAAG,EAC9C,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,EACjC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,GAC/B,OAAO,CAGT","sourcesContent":["import { MODELS } from \"./models.generated.js\";\nimport type { Api, KnownProvider, Model, Usage } from \"./types.js\";\n\nconst modelRegistry: Map<string, Map<string, Model<Api>>> = new Map();\n\n// Initialize registry from MODELS on module load\nfor (const [provider, models] of Object.entries(MODELS)) {\n\tconst providerModels = new Map<string, Model<Api>>();\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tproviderModels.set(id, model as Model<Api>);\n\t}\n\tmodelRegistry.set(provider, providerModels);\n}\n\ntype ModelApi<\n\tTProvider extends KnownProvider,\n\tTModelId extends keyof (typeof MODELS)[TProvider],\n> = (typeof MODELS)[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never;\n\nexport function getModel<TProvider extends KnownProvider, TModelId extends keyof (typeof MODELS)[TProvider]>(\n\tprovider: TProvider,\n\tmodelId: TModelId,\n): Model<ModelApi<TProvider, TModelId>> {\n\tconst providerModels = modelRegistry.get(provider);\n\treturn providerModels?.get(modelId as string) as Model<ModelApi<TProvider, TModelId>>;\n}\n\n/**\n * Check if a model ID looks like an alias (no date suffix).\n * Aliases are preferred over dated versions when fuzzy matching.\n *\n * IDs ending with `-latest` are treated as aliases.\n * IDs ending with a date pattern (`-YYYYMMDD`) are treated as dated versions.\n */\nexport function isModelAlias(id: string): boolean {\n\tif (id.endsWith(\"-latest\")) return true;\n\treturn !/-\\d{8}$/.test(id);\n}\n\n/**\n * Find a model by fuzzy matching against the provider's registered models.\n *\n * Resolution order:\n * 1. Exact match by provider + model ID (via registry Map.get)\n * 2. Case-insensitive substring match against model ID and display name\n * 3. Among matches, prefer aliases (non-dated IDs) over dated versions\n * 4. Among ties, pick the lexicographically highest (latest) ID\n *\n * This is the same matching logic used by the CLI, subagent model resolution,\n * and interactive mode — centralised here so tests can exercise the real path.\n *\n * @example\n * findModel(\"anthropic\", \"sonnet\") // → latest claude-sonnet alias\n * findModel(\"anthropic\", \"haiku\") // → latest claude-haiku alias\n * findModel(\"openai\", \"gpt-5\") // → latest gpt-5 alias\n */\nexport function findModel(provider: string, pattern: string): Model<Api> | undefined {\n\tconst providerModels = modelRegistry.get(provider);\n\tif (!providerModels) return undefined;\n\n\t// Try exact match first\n\tconst exact = providerModels.get(pattern);\n\tif (exact) return exact;\n\n\t// Substring match (case-insensitive)\n\tconst normalizedPattern = pattern.toLowerCase();\n\tconst matches = Array.from(providerModels.values()).filter(\n\t\t(m) => m.id.toLowerCase().includes(normalizedPattern) || m.name?.toLowerCase().includes(normalizedPattern),\n\t);\n\n\tif (matches.length === 0) return undefined;\n\tif (matches.length === 1) return matches[0];\n\n\t// Multiple matches — separate into aliases and dated versions\n\tconst aliases = matches.filter((m) => isModelAlias(m.id));\n\tconst datedVersions = matches.filter((m) => !isModelAlias(m.id));\n\n\tif (aliases.length > 0) {\n\t\t// Prefer alias — if multiple, pick the lexicographically highest\n\t\taliases.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn aliases[0];\n\t}\n\n\t// All dated — prefer the latest\n\tdatedVersions.sort((a, b) => b.id.localeCompare(a.id));\n\treturn datedVersions[0];\n}\n\n/**\n * Find a model by fuzzy matching against a flat array of models.\n * Same algorithm as findModel() but operates on an arbitrary model list\n * instead of the built-in registry.\n *\n * Used by model-resolver.ts and other code that manages its own model lists.\n */\nexport function findModelInList(pattern: string, models: Model<Api>[]): Model<Api> | undefined {\n\tif (models.length === 0) return undefined;\n\n\tconst normalizedPattern = pattern.toLowerCase();\n\n\t// Exact ID match (case-insensitive)\n\tconst exactById = models.find((m) => m.id.toLowerCase() === normalizedPattern);\n\tif (exactById) return exactById;\n\n\t// Substring match (case-insensitive)\n\tconst matches = models.filter(\n\t\t(m) => m.id.toLowerCase().includes(normalizedPattern) || m.name?.toLowerCase().includes(normalizedPattern),\n\t);\n\n\tif (matches.length === 0) return undefined;\n\tif (matches.length === 1) return matches[0];\n\n\t// Multiple matches — separate into aliases and dated versions\n\tconst aliases = matches.filter((m) => isModelAlias(m.id));\n\tconst datedVersions = matches.filter((m) => !isModelAlias(m.id));\n\n\tif (aliases.length > 0) {\n\t\taliases.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn aliases[0];\n\t}\n\n\tdatedVersions.sort((a, b) => b.id.localeCompare(a.id));\n\treturn datedVersions[0];\n}\n\nexport function getProviders(): KnownProvider[] {\n\treturn Array.from(modelRegistry.keys()) as KnownProvider[];\n}\n\nexport function getModels<TProvider extends KnownProvider>(\n\tprovider: TProvider,\n): Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[] {\n\tconst models = modelRegistry.get(provider);\n\treturn models ? (Array.from(models.values()) as Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[]) : [];\n}\n\nexport function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage[\"cost\"] {\n\tusage.cost.input = (model.cost.input / 1000000) * usage.input;\n\tusage.cost.output = (model.cost.output / 1000000) * usage.output;\n\tusage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;\n\tusage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage.cost;\n}\n\n/**\n * Check if a model supports xhigh thinking level.\n *\n * Supported today:\n * - GPT-5.2 / GPT-5.3 / GPT-5.4 model families\n * - Opus 4.6+ models (xhigh maps to adaptive effort \"max\" on Anthropic-compatible providers)\n */\nexport function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean {\n\tif (\n\t\tmodel.id.includes(\"gpt-5.2\") ||\n\t\tmodel.id.includes(\"gpt-5.3\") ||\n\t\tmodel.id.includes(\"gpt-5.4\") ||\n\t\tmodel.id.includes(\"gpt-5.5\")\n\t) {\n\t\treturn true;\n\t}\n\n\t// Opus 4.6+ supports xhigh (adaptive effort \"max\").\n\t// Match any opus-4-N or opus-4.N where N >= 6 (1-2 digit minor version, not date suffixes).\n\tconst opusMatch = model.id.match(/opus-4[.-](\\d{1,2})(?!\\d)/);\n\tif (opusMatch && Number.parseInt(opusMatch[1], 10) >= 6) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Check if a model uses adaptive thinking (Opus 4.6+, Sonnet 4.6+), where the\n * `thinkingDisplay` option is honored. Mirrors the per-provider internal checks.\n */\nexport function supportsAdaptiveThinking<TApi extends Api>(model: Model<TApi>): boolean {\n\tconst m = model.id.match(/(opus|sonnet)-4[.-](\\d{1,2})(?!\\d)/);\n\treturn m != null && Number.parseInt(m[2], 10) >= 6;\n}\n\n/**\n * Check if two models are equal by comparing both their id and provider.\n * Returns false if either model is null or undefined.\n */\nexport function modelsAreEqual<TApi extends Api>(\n\ta: Model<TApi> | null | undefined,\n\tb: Model<TApi> | null | undefined,\n): boolean {\n\tif (!a || !b) return false;\n\treturn a.id === b.id && a.provider === b.provider;\n}\n"]}
|
|
@@ -6949,23 +6949,6 @@ export declare const MODELS: {
|
|
|
6949
6949
|
contextWindow: number;
|
|
6950
6950
|
maxTokens: number;
|
|
6951
6951
|
};
|
|
6952
|
-
readonly "minimax-m3-free": {
|
|
6953
|
-
id: string;
|
|
6954
|
-
name: string;
|
|
6955
|
-
api: "anthropic-messages";
|
|
6956
|
-
provider: string;
|
|
6957
|
-
baseUrl: string;
|
|
6958
|
-
reasoning: true;
|
|
6959
|
-
input: ("image" | "text")[];
|
|
6960
|
-
cost: {
|
|
6961
|
-
input: number;
|
|
6962
|
-
output: number;
|
|
6963
|
-
cacheRead: number;
|
|
6964
|
-
cacheWrite: number;
|
|
6965
|
-
};
|
|
6966
|
-
contextWindow: number;
|
|
6967
|
-
maxTokens: number;
|
|
6968
|
-
};
|
|
6969
6952
|
readonly "nemotron-3-ultra-free": {
|
|
6970
6953
|
id: string;
|
|
6971
6954
|
name: string;
|
|
@@ -7684,23 +7667,6 @@ export declare const MODELS: {
|
|
|
7684
7667
|
contextWindow: number;
|
|
7685
7668
|
maxTokens: number;
|
|
7686
7669
|
};
|
|
7687
|
-
readonly "baidu/ernie-4.5-vl-28b-a3b": {
|
|
7688
|
-
id: string;
|
|
7689
|
-
name: string;
|
|
7690
|
-
api: "openai-completions";
|
|
7691
|
-
provider: string;
|
|
7692
|
-
baseUrl: string;
|
|
7693
|
-
reasoning: true;
|
|
7694
|
-
input: ("image" | "text")[];
|
|
7695
|
-
cost: {
|
|
7696
|
-
input: number;
|
|
7697
|
-
output: number;
|
|
7698
|
-
cacheRead: number;
|
|
7699
|
-
cacheWrite: number;
|
|
7700
|
-
};
|
|
7701
|
-
contextWindow: number;
|
|
7702
|
-
maxTokens: number;
|
|
7703
|
-
};
|
|
7704
7670
|
readonly "bytedance-seed/seed-1.6": {
|
|
7705
7671
|
id: string;
|
|
7706
7672
|
name: string;
|
|
@@ -8993,23 +8959,6 @@ export declare const MODELS: {
|
|
|
8993
8959
|
contextWindow: number;
|
|
8994
8960
|
maxTokens: number;
|
|
8995
8961
|
};
|
|
8996
|
-
readonly "nex-agi/deepseek-v3.1-nex-n1": {
|
|
8997
|
-
id: string;
|
|
8998
|
-
name: string;
|
|
8999
|
-
api: "openai-completions";
|
|
9000
|
-
provider: string;
|
|
9001
|
-
baseUrl: string;
|
|
9002
|
-
reasoning: false;
|
|
9003
|
-
input: "text"[];
|
|
9004
|
-
cost: {
|
|
9005
|
-
input: number;
|
|
9006
|
-
output: number;
|
|
9007
|
-
cacheRead: number;
|
|
9008
|
-
cacheWrite: number;
|
|
9009
|
-
};
|
|
9010
|
-
contextWindow: number;
|
|
9011
|
-
maxTokens: number;
|
|
9012
|
-
};
|
|
9013
8962
|
readonly "nvidia/llama-3.3-nemotron-super-49b-v1.5": {
|
|
9014
8963
|
id: string;
|
|
9015
8964
|
name: string;
|
|
@@ -9265,23 +9214,6 @@ export declare const MODELS: {
|
|
|
9265
9214
|
contextWindow: number;
|
|
9266
9215
|
maxTokens: number;
|
|
9267
9216
|
};
|
|
9268
|
-
readonly "openai/gpt-4-1106-preview": {
|
|
9269
|
-
id: string;
|
|
9270
|
-
name: string;
|
|
9271
|
-
api: "openai-completions";
|
|
9272
|
-
provider: string;
|
|
9273
|
-
baseUrl: string;
|
|
9274
|
-
reasoning: false;
|
|
9275
|
-
input: "text"[];
|
|
9276
|
-
cost: {
|
|
9277
|
-
input: number;
|
|
9278
|
-
output: number;
|
|
9279
|
-
cacheRead: number;
|
|
9280
|
-
cacheWrite: number;
|
|
9281
|
-
};
|
|
9282
|
-
contextWindow: number;
|
|
9283
|
-
maxTokens: number;
|
|
9284
|
-
};
|
|
9285
9217
|
readonly "openai/gpt-4-turbo": {
|
|
9286
9218
|
id: string;
|
|
9287
9219
|
name: string;
|
|
@@ -12412,40 +12344,6 @@ export declare const MODELS: {
|
|
|
12412
12344
|
contextWindow: number;
|
|
12413
12345
|
maxTokens: number;
|
|
12414
12346
|
};
|
|
12415
|
-
readonly "google/gemini-2.0-flash": {
|
|
12416
|
-
id: string;
|
|
12417
|
-
name: string;
|
|
12418
|
-
api: "anthropic-messages";
|
|
12419
|
-
provider: string;
|
|
12420
|
-
baseUrl: string;
|
|
12421
|
-
reasoning: false;
|
|
12422
|
-
input: ("image" | "text")[];
|
|
12423
|
-
cost: {
|
|
12424
|
-
input: number;
|
|
12425
|
-
output: number;
|
|
12426
|
-
cacheRead: number;
|
|
12427
|
-
cacheWrite: number;
|
|
12428
|
-
};
|
|
12429
|
-
contextWindow: number;
|
|
12430
|
-
maxTokens: number;
|
|
12431
|
-
};
|
|
12432
|
-
readonly "google/gemini-2.0-flash-lite": {
|
|
12433
|
-
id: string;
|
|
12434
|
-
name: string;
|
|
12435
|
-
api: "anthropic-messages";
|
|
12436
|
-
provider: string;
|
|
12437
|
-
baseUrl: string;
|
|
12438
|
-
reasoning: false;
|
|
12439
|
-
input: ("image" | "text")[];
|
|
12440
|
-
cost: {
|
|
12441
|
-
input: number;
|
|
12442
|
-
output: number;
|
|
12443
|
-
cacheRead: number;
|
|
12444
|
-
cacheWrite: number;
|
|
12445
|
-
};
|
|
12446
|
-
contextWindow: number;
|
|
12447
|
-
maxTokens: number;
|
|
12448
|
-
};
|
|
12449
12347
|
readonly "google/gemini-2.5-flash": {
|
|
12450
12348
|
id: string;
|
|
12451
12349
|
name: string;
|