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.
This commit is contained in:
can1357
2026-02-10 22:17:29 +01:00
parent 148f9e883d
commit 4e8fa51616
5 changed files with 89 additions and 84 deletions
+7
View File
@@ -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
+68 -68
View File
@@ -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": {
+9
View File
@@ -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;
+4 -14
View File
@@ -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<TProvider extends GeneratedProvider, TModelId extends keyof (typeof MODELS)[TProvider]>(
provider: TProvider,
modelId: TModelId,
): Model<ModelApi<TProvider, TModelId>> {
export function getModel(provider: GeneratedProvider, modelId: string): Model<Api> {
const providerModels = modelRegistry.get(provider);
return providerModels?.get(modelId as string) as Model<ModelApi<TProvider, TModelId>>;
return providerModels?.get(modelId) as Model<Api>;
}
export function getProviders(): KnownProvider[] {
return Array.from(modelRegistry.keys()) as KnownProvider[];
}
export function getModels<TProvider extends GeneratedProvider>(
provider: TProvider,
): Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[] {
export function getModels(provider: GeneratedProvider): Model<Api>[] {
const models = modelRegistry.get(provider);
return models ? (Array.from(models.values()) as Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[]) : [];
return models ? (Array.from(models.values()) as Model<Api>[]) : [];
}
export function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage["cost"] {
+1 -2
View File
@@ -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);