From 4e8fa51616194fd6c73a35dfc852e9d9e346108f Mon Sep 17 00:00:00 2001 From: can1357 Date: Tue, 10 Feb 2026 22:17:29 +0100 Subject: [PATCH] feat(ai): added TypeScript types and simplified model function signatures - Added TypeScript type declarations for models.json to provide better IDE support and type safety. - Simplified type signatures for getModel() and getModels() functions by removing complex generic type inference in favor of simpler, more maintainable typing. - Updated google-antigravity provider model ordering and metadata, including renamed Gemini 2.5 Flash (Thinking) model and expanded input types for claude-opus-4-5-thinking. - Refactored test helper code in context-overflow.test.ts to improve code clarity and type safety. --- packages/ai/CHANGELOG.md | 7 ++ packages/ai/src/models.json | 136 +++++++++++----------- packages/ai/src/models.json.d.ts | 9 ++ packages/ai/src/models.ts | 18 +-- packages/ai/test/context-overflow.test.ts | 3 +- 5 files changed, 89 insertions(+), 84 deletions(-) create mode 100644 packages/ai/src/models.json.d.ts diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index e4c92c009..87101ded6 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,12 +1,19 @@ # Changelog ## [Unreleased] + ### Breaking Changes - Replaced `./models.generated` export with `./models.json` - update imports from `import { MODELS } from './models.generated'` to `import MODELS from './models.json' with { type: 'json' }` +### Added + +- Added TypeScript type declarations for `models.json` to enable proper type inference when importing the JSON file + ### Changed +- Updated available models in google-antigravity provider with new model variants and updated context window/token limits +- Simplified type signatures for `getModel()` and `getModels()` functions for improved usability - Changed models export from TypeScript module to JSON format for improved performance and reduced bundle size - Updated `@anthropic-ai/sdk` dependency from ^0.72.1 to ^0.74.0 diff --git a/packages/ai/src/models.json b/packages/ai/src/models.json index 694d09af0..ea71e38ab 100644 --- a/packages/ai/src/models.json +++ b/packages/ai/src/models.json @@ -12762,9 +12762,29 @@ } }, "google-antigravity": { - "claude-sonnet-4-5-thinking": { - "id": "claude-sonnet-4-5-thinking", - "name": "Claude Sonnet 4.5 (Thinking) (Antigravity)", + "gemini-3-flash": { + "id": "gemini-3-flash", + "name": "Gemini 3 Flash (Antigravity)", + "api": "google-gemini-cli", + "provider": "google-antigravity", + "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", + "reasoning": true, + "input": [ + "text", + "image" + ], + "cost": { + "input": 0, + "output": 0, + "cacheRead": 0, + "cacheWrite": 0 + }, + "contextWindow": 1048576, + "maxTokens": 65536 + }, + "claude-opus-4-6-thinking": { + "id": "claude-opus-4-6-thinking", + "name": "Claude Opus 4.6 (Thinking) (Antigravity)", "api": "google-gemini-cli", "provider": "google-antigravity", "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", @@ -12802,15 +12822,16 @@ "contextWindow": 200000, "maxTokens": 64000 }, - "gpt-oss-120b-medium": { - "id": "gpt-oss-120b-medium", - "name": "GPT-OSS 120B (Medium) (Antigravity)", + "gemini-2.5-flash-thinking": { + "id": "gemini-2.5-flash-thinking", + "name": "Gemini 2.5 Flash (Thinking) (Antigravity)", "api": "google-gemini-cli", "provider": "google-antigravity", "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", "reasoning": true, "input": [ - "text" + "text", + "image" ], "cost": { "input": 0, @@ -12818,8 +12839,28 @@ "cacheRead": 0, "cacheWrite": 0 }, - "contextWindow": 131072, - "maxTokens": 32768 + "contextWindow": 1048576, + "maxTokens": 65535 + }, + "claude-sonnet-4-5-thinking": { + "id": "claude-sonnet-4-5-thinking", + "name": "Claude Sonnet 4.5 (Thinking) (Antigravity)", + "api": "google-gemini-cli", + "provider": "google-antigravity", + "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", + "reasoning": true, + "input": [ + "text", + "image" + ], + "cost": { + "input": 0, + "output": 0, + "cacheRead": 0, + "cacheWrite": 0 + }, + "contextWindow": 200000, + "maxTokens": 64000 }, "gemini-2.5-flash": { "id": "gemini-2.5-flash", @@ -12841,13 +12882,13 @@ "contextWindow": 1048576, "maxTokens": 65535 }, - "gemini-3-pro-low": { - "id": "gemini-3-pro-low", - "name": "Gemini 3 Pro (Low) (Antigravity)", + "claude-sonnet-4-5": { + "id": "claude-sonnet-4-5", + "name": "Claude Sonnet 4.5 (Antigravity)", "api": "google-gemini-cli", "provider": "google-antigravity", "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", - "reasoning": true, + "reasoning": false, "input": [ "text", "image" @@ -12858,12 +12899,12 @@ "cacheRead": 0, "cacheWrite": 0 }, - "contextWindow": 1048576, - "maxTokens": 65535 + "contextWindow": 200000, + "maxTokens": 64000 }, - "gemini-3-pro-high": { - "id": "gemini-3-pro-high", - "name": "Gemini 3 Pro (High) (Antigravity)", + "gemini-3-pro-low": { + "id": "gemini-3-pro-low", + "name": "Gemini 3 Pro (Low) (Antigravity)", "api": "google-gemini-cli", "provider": "google-antigravity", "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", @@ -12901,49 +12942,9 @@ "contextWindow": 1048576, "maxTokens": 65535 }, - "claude-opus-4-6-thinking": { - "id": "claude-opus-4-6-thinking", - "name": "Claude Opus 4.6 (Thinking) (Antigravity)", - "api": "google-gemini-cli", - "provider": "google-antigravity", - "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", - "reasoning": true, - "input": [ - "text", - "image" - ], - "cost": { - "input": 0, - "output": 0, - "cacheRead": 0, - "cacheWrite": 0 - }, - "contextWindow": 200000, - "maxTokens": 64000 - }, - "claude-sonnet-4-5": { - "id": "claude-sonnet-4-5", - "name": "Claude Sonnet 4.5 (Antigravity)", - "api": "google-gemini-cli", - "provider": "google-antigravity", - "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", - "reasoning": false, - "input": [ - "text", - "image" - ], - "cost": { - "input": 0, - "output": 0, - "cacheRead": 0, - "cacheWrite": 0 - }, - "contextWindow": 200000, - "maxTokens": 64000 - }, - "gemini-2.5-flash-thinking": { - "id": "gemini-2.5-flash-thinking", - "name": "Gemini 2.5 Flash (Thinking) (Antigravity)", + "gemini-3-pro-high": { + "id": "gemini-3-pro-high", + "name": "Gemini 3 Pro (High) (Antigravity)", "api": "google-gemini-cli", "provider": "google-antigravity", "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", @@ -12961,16 +12962,15 @@ "contextWindow": 1048576, "maxTokens": 65535 }, - "gemini-3-flash": { - "id": "gemini-3-flash", - "name": "Gemini 3 Flash (Antigravity)", + "gpt-oss-120b-medium": { + "id": "gpt-oss-120b-medium", + "name": "GPT-OSS 120B (Medium) (Antigravity)", "api": "google-gemini-cli", "provider": "google-antigravity", "baseUrl": "https://daily-cloudcode-pa.sandbox.googleapis.com", "reasoning": true, "input": [ - "text", - "image" + "text" ], "cost": { "input": 0, @@ -12978,8 +12978,8 @@ "cacheRead": 0, "cacheWrite": 0 }, - "contextWindow": 1048576, - "maxTokens": 65536 + "contextWindow": 131072, + "maxTokens": 32768 } }, "google-vertex": { diff --git a/packages/ai/src/models.json.d.ts b/packages/ai/src/models.json.d.ts new file mode 100644 index 000000000..b1212116a --- /dev/null +++ b/packages/ai/src/models.json.d.ts @@ -0,0 +1,9 @@ +import type { Api } from "./types"; + +/** Typed declaration for the generated models.json — only the `api` field matters for type inference. */ +declare const models: { + [provider: string]: { + [modelId: string]: { readonly api: Api; [key: string]: unknown }; + }; +}; +export default models; diff --git a/packages/ai/src/models.ts b/packages/ai/src/models.ts index d2f3d2b51..1bc227912 100644 --- a/packages/ai/src/models.ts +++ b/packages/ai/src/models.ts @@ -14,28 +14,18 @@ for (const [provider, models] of Object.entries(MODELS)) { type GeneratedProvider = keyof typeof MODELS; -type ModelApi< - TProvider extends GeneratedProvider, - TModelId extends keyof (typeof MODELS)[TProvider], -> = (typeof MODELS)[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never; - -export function getModel( - provider: TProvider, - modelId: TModelId, -): Model> { +export function getModel(provider: GeneratedProvider, modelId: string): Model { const providerModels = modelRegistry.get(provider); - return providerModels?.get(modelId as string) as Model>; + return providerModels?.get(modelId) as Model; } export function getProviders(): KnownProvider[] { return Array.from(modelRegistry.keys()) as KnownProvider[]; } -export function getModels( - provider: TProvider, -): Model>[] { +export function getModels(provider: GeneratedProvider): Model[] { const models = modelRegistry.get(provider); - return models ? (Array.from(models.values()) as Model>[]) : []; + return models ? (Array.from(models.values()) as Model[]) : []; } export function calculateCost(model: Model, usage: Usage): Usage["cost"] { diff --git a/packages/ai/test/context-overflow.test.ts b/packages/ai/test/context-overflow.test.ts index de4c5ad6f..0e9a3c9d9 100644 --- a/packages/ai/test/context-overflow.test.ts +++ b/packages/ai/test/context-overflow.test.ts @@ -165,8 +165,7 @@ describe("Context overflow error handling", () => { describe.skipIf(!e2eApiKey("OPENAI_API_KEY"))("OpenAI Completions", () => { it("gpt-4o-mini - should detect overflow via isContextOverflow", async () => { - const model = { ...getModel("openai", "gpt-4o-mini") }; - model.api = "openai-completions" as any; + const model = { ...getModel("openai", "gpt-4o-mini"), api: "openai-completions" as const }; const result = await testContextOverflow(model, Bun.env.OPENAI_API_KEY!); logResult(result);