Skip to content
33 changes: 33 additions & 0 deletions packages/types/src/__tests__/vscode-llm.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { describe, it, expect } from "vitest"
import { vscodeLlmModels, vscodeLlmDefaultModelId } from "../providers/vscode-llm.js"

describe("vscodeLlmModels", () => {
it("exposes the opus-4.8 row with its measured maxInputTokens and contextWindow", () => {
// claude-opus-4.8 intentionally diverges: maxInputTokens (197897) is the enforced ceiling the
// UI reads, contextWindow (679560) the advertised window. Assert the on-disk literals as a tripwire.
expect(vscodeLlmModels).toHaveProperty("claude-opus-4.8")
expect(vscodeLlmModels["claude-opus-4.8"].contextWindow).toBe(679560)
expect(vscodeLlmModels["claude-opus-4.8"].maxInputTokens).toBe(197897)
})
it("preserves the real window for models captured with a smaller maxInputTokens", () => {
expect(vscodeLlmModels["gpt-4o-mini"].maxInputTokens).toBe(12078)
expect(vscodeLlmModels["gpt-4o-mini"].contextWindow).toBe(12078)
expect(vscodeLlmModels["gemini-2.5-pro"].contextWindow).toBe(108594)
expect(vscodeLlmModels["gemini-2.5-pro"].maxInputTokens).toBe(108594)
})
it("keeps both window fields populated and positive for every row", () => {
for (const [family, model] of Object.entries(vscodeLlmModels)) {
expect(model.contextWindow, `${family}: contextWindow must be a positive integer`).toBeGreaterThan(0)
expect(model.maxInputTokens, `${family}: maxInputTokens must be a positive integer`).toBeGreaterThan(0)
}
})
it("excludes fabricated/internal/alias families and the dropped legacy rows", () => {
expect(vscodeLlmModels).not.toHaveProperty("claude-opus-4.7-high")
expect(vscodeLlmModels).not.toHaveProperty("claude-3.5-sonnet")
expect(vscodeLlmModels).not.toHaveProperty("claude-4-sonnet")
})
it("defaults to a model id that exists in the table", () => {
expect(vscodeLlmDefaultModelId).toBe("claude-sonnet-4.5")
expect(vscodeLlmModels).toHaveProperty(vscodeLlmDefaultModelId)
})
})
224 changes: 125 additions & 99 deletions packages/types/src/providers/vscode-llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,189 +2,215 @@ import type { ModelInfo } from "../model.js"

export type VscodeLlmModelId = keyof typeof vscodeLlmModels

export const vscodeLlmDefaultModelId: VscodeLlmModelId = "claude-3.5-sonnet"
export const vscodeLlmDefaultModelId: VscodeLlmModelId = "claude-sonnet-4.5"

// https://docs.cline.bot/provider-config/vscode-language-model-api
// Curated VS Code LM (GitHub Copilot) model catalog.
// The API exposes only `maxInputTokens`; the UI and condense gate read that. `contextWindow` is
// the advertised window, kept for rows where it diverges from the ceiling (e.g. claude-opus-4.8).
export const vscodeLlmModels = {
"gpt-3.5-turbo": {
contextWindow: 12114,
supportsImages: false,
"claude-opus-4.8": {
contextWindow: 679560,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-3.5-turbo",
version: "gpt-3.5-turbo-0613",
name: "GPT 3.5 Turbo",
family: "claude-opus-4.8",
version: "claude-opus-4.8",
name: "Claude Opus 4.8",
supportsToolCalling: true,
maxInputTokens: 12114,
maxInputTokens: 197897,
},
"gpt-4o-mini": {
contextWindow: 12115,
supportsImages: false,
"claude-opus-4.7": {
contextWindow: 197897,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-4o-mini",
version: "gpt-4o-mini-2024-07-18",
name: "GPT-4o mini",
family: "claude-opus-4.7",
version: "claude-opus-4.7",
name: "Claude Opus 4.7",
supportsToolCalling: true,
maxInputTokens: 12115,
maxInputTokens: 197897,
},
"gpt-4": {
contextWindow: 28501,
supportsImages: false,
"claude-opus-4.6": {
contextWindow: 197897,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-4",
version: "gpt-4-0613",
name: "GPT 4",
family: "claude-opus-4.6",
version: "claude-opus-4.6",
name: "Claude Opus 4.6",
supportsToolCalling: true,
maxInputTokens: 28501,
maxInputTokens: 197897,
},
"gpt-4-0125-preview": {
contextWindow: 63826,
supportsImages: false,
"claude-opus-4.5": {
contextWindow: 167790,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-4-turbo",
version: "gpt-4-0125-preview",
name: "GPT 4 Turbo",
family: "claude-opus-4.5",
version: "claude-opus-4.5",
name: "Claude Opus 4.5",
supportsToolCalling: true,
maxInputTokens: 63826,
maxInputTokens: 167790,
},
"gpt-4o": {
contextWindow: 63827,
"claude-sonnet-4.6": {
contextWindow: 197896,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-4o",
version: "gpt-4o-2024-11-20",
name: "GPT-4o",
family: "claude-sonnet-4.6",
version: "claude-sonnet-4.6",
name: "Claude Sonnet 4.6",
supportsToolCalling: true,
maxInputTokens: 63827,
maxInputTokens: 197896,
},
o1: {
contextWindow: 19827,
supportsImages: false,
"claude-sonnet-4.5": {
contextWindow: 167790,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "o1-ga",
version: "o1-2024-12-17",
name: "o1 (Preview)",
family: "claude-sonnet-4.5",
version: "claude-sonnet-4.5",
name: "Claude Sonnet 4.5",
supportsToolCalling: true,
maxInputTokens: 19827,
maxInputTokens: 167790,
},
"o3-mini": {
contextWindow: 63827,
supportsImages: false,
"claude-haiku-4.5": {
contextWindow: 135790,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "o3-mini",
version: "o3-mini-2025-01-31",
name: "o3-mini",
family: "claude-haiku-4.5",
version: "claude-haiku-4.5",
name: "Claude Haiku 4.5",
supportsToolCalling: true,
maxInputTokens: 63827,
maxInputTokens: 135790,
},
"claude-3.5-sonnet": {
contextWindow: 81638,
"gpt-5.5": {
contextWindow: 268426,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "claude-3.5-sonnet",
version: "claude-3.5-sonnet",
name: "Claude 3.5 Sonnet",
family: "gpt-5.5",
version: "gpt-5.5",
name: "GPT-5.5",
supportsToolCalling: true,
maxInputTokens: 81638,
maxInputTokens: 268426,
},
"claude-4-sonnet": {
contextWindow: 128000,
"gpt-5.4": {
contextWindow: 268424,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "claude-sonnet-4",
version: "claude-sonnet-4",
name: "Claude Sonnet 4",
family: "gpt-5.4",
version: "gpt-5.4",
name: "GPT-5.4",
supportsToolCalling: true,
maxInputTokens: 111836,
maxInputTokens: 268424,
},
"gemini-2.0-flash-001": {
contextWindow: 127827,
"gpt-5.4-mini": {
contextWindow: 271790,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gemini-2.0-flash",
version: "gemini-2.0-flash-001",
name: "Gemini 2.0 Flash",
supportsToolCalling: false,
maxInputTokens: 127827,
family: "gpt-5.4-mini",
version: "gpt-5.4-mini",
name: "GPT-5.4 mini",
supportsToolCalling: true,
maxInputTokens: 271790,
},
"gemini-2.5-pro": {
contextWindow: 128000,
"gpt-5.3-codex": {
contextWindow: 271790,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gemini-2.5-pro",
version: "gemini-2.5-pro-preview-03-25",
name: "Gemini 2.5 Pro (Preview)",
family: "gpt-5.3-codex",
version: "gpt-5.3-codex",
name: "GPT-5.3-Codex",
supportsToolCalling: true,
maxInputTokens: 108637,
maxInputTokens: 271790,
},
"o4-mini": {
contextWindow: 128000,
"gpt-5-mini": {
contextWindow: 127790,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-5-mini",
version: "gpt-5-mini",
name: "GPT-5 mini",
supportsToolCalling: true,
maxInputTokens: 127790,
},
"gpt-4o-mini": {
contextWindow: 12078,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "o4-mini",
version: "o4-mini-2025-04-16",
name: "o4-mini (Preview)",
family: "gpt-4o-mini",
version: "gpt-4o-mini-2024-07-18",
name: "GPT-4o mini",
supportsToolCalling: true,
maxInputTokens: 111452,
maxInputTokens: 12078,
},
"gpt-4.1": {
contextWindow: 128000,
"gemini-3.1-pro-preview": {
contextWindow: 197897,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-4.1",
version: "gpt-4.1-2025-04-14",
name: "GPT-4.1 (Preview)",
family: "gemini-3.1-pro-preview",
version: "gemini-3.1-pro-preview",
name: "Gemini 3.1 Pro (Preview)",
supportsToolCalling: true,
maxInputTokens: 111452,
maxInputTokens: 197897,
},
"gpt-5-mini": {
contextWindow: 128000,
"gemini-3.5-flash": {
contextWindow: 197895,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-5-mini",
version: "gpt-5-mini",
name: "GPT-5 mini (Preview)",
family: "gemini-3.5-flash",
version: "gemini-3.5-flash",
name: "Gemini 3.5 Flash",
supportsToolCalling: true,
maxInputTokens: 197895,
},
"gemini-3-flash": {
contextWindow: 108594,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gemini-3-flash",
version: "gemini-3-flash-preview",
name: "Gemini 3 Flash (Preview)",
supportsToolCalling: true,
maxInputTokens: 108637,
maxInputTokens: 108594,
},
"gpt-5": {
contextWindow: 128000,
"gemini-2.5-pro": {
contextWindow: 108594,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
family: "gpt-5",
version: "gpt-5",
name: "GPT-5 (Preview)",
family: "gemini-2.5-pro",
version: "gemini-2.5-pro",
name: "Gemini 2.5 Pro",
supportsToolCalling: true,
maxInputTokens: 108637,
maxInputTokens: 108594,
},
} as const satisfies Record<
string,
Expand Down
7 changes: 7 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ export interface ApiHandler {

getModel(): { id: string; info: ModelInfo }

/**
* Optional context window for context-management / auto-condense when it must differ from
* getModel().info.contextWindow. Only VS Code LM overrides it (static `maxInputTokens` vs its
* inflated live window); others leave it undefined and callers fall back.
*/
getCondenseContextWindow?(): number

/**
* Counts tokens for content blocks
* All providers extend BaseProvider which provides a default tiktoken implementation,
Expand Down
Loading
Loading