fix(github-copilot): honor live prompt token limits (#103275)

* fix(github-copilot): honor live prompt token limits

* fix(github-copilot): align prompt token budgets

* fix(github-copilot): align prompt token budgets

---------

Co-authored-by: saju01 <saju@coderedcorp.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
This commit is contained in:
saju01
2026-07-10 06:27:14 +01:00
committed by GitHub
co-authored by saju01 Peter Steinberger Peter Steinberger
parent 0e4c7cd155
commit f0534c5b71
5 changed files with 16 additions and 2 deletions
+2 -2
View File
@@ -375,8 +375,8 @@ export default definePluginEntry({
}
}
// Try to fetch the live model catalog from Copilot's /models endpoint so
// the runtime tracks per-account entitlements and accurate context
// windows (max_context_window_tokens) without manifest churn. On any
// the runtime tracks per-account entitlements and accurate token limits
// without manifest churn. On any
// failure we return an empty model list, which lets the static manifest
// catalog continue to be the visible fallback for users.
let discoveredModels: Awaited<ReturnType<typeof fetchCopilotModelCatalog>> = [];
@@ -47,6 +47,7 @@ const STATIC_MODEL_OVERRIDES = new Map<string, Partial<ModelDefinitionConfig>>([
name: "GPT-5.5",
reasoning: true,
contextWindow: 400_000,
contextTokens: 272_000,
maxTokens: 128_000,
},
],
+7
View File
@@ -126,6 +126,7 @@ describe("resolveCopilotForwardCompatModel", () => {
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 400_000,
contextTokens: 272_000,
maxTokens: 128_000,
});
});
@@ -570,6 +571,7 @@ describe("fetchCopilotModelCatalog", () => {
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 400000,
contextTokens: 272000,
maxTokens: 128000,
compat: { supportedReasoningEfforts: ["low", "medium", "high"] },
});
@@ -578,6 +580,7 @@ describe("fetchCopilotModelCatalog", () => {
expect(codex?.input).toEqual(["text"]);
expect(codex?.reasoning).toBe(true);
expect(codex?.contextWindow).toBe(400000);
expect(codex?.contextTokens).toBeUndefined();
const gemini = out.find((m) => m.id === "gemini-3.1-pro-preview");
expect(gemini?.api).toBe("openai-completions");
@@ -664,6 +667,7 @@ describe("fetchCopilotModelCatalog", () => {
type: "chat",
limits: {
max_context_window_tokens: -1,
max_prompt_tokens: -1,
max_output_tokens: 128000.5,
},
},
@@ -676,6 +680,7 @@ describe("fetchCopilotModelCatalog", () => {
type: "chat",
limits: {
max_context_window_tokens: Number.POSITIVE_INFINITY,
max_prompt_tokens: Number.POSITIVE_INFINITY,
max_output_tokens: 0,
},
},
@@ -696,11 +701,13 @@ describe("fetchCopilotModelCatalog", () => {
contextWindow: 128000,
maxTokens: 8192,
});
expect(out[0]).not.toHaveProperty("contextTokens");
expect(out[1]).toMatchObject({
id: "gpt-bad-output",
contextWindow: 128000,
maxTokens: 8192,
});
expect(out[1]).not.toHaveProperty("contextTokens");
});
it("throws on non-2xx HTTP responses so the caller can fall back to the static catalog", async () => {
+5
View File
@@ -80,6 +80,9 @@ export function resolveCopilotForwardCompatModel(
input: staticOverride.input ?? ["text", "image"],
cost: staticOverride.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: staticOverride.contextWindow ?? DEFAULT_CONTEXT_WINDOW,
...(staticOverride.contextTokens !== undefined
? { contextTokens: staticOverride.contextTokens }
: {}),
maxTokens: staticOverride.maxTokens ?? DEFAULT_MAX_TOKENS,
...(staticOverride.thinkingLevelMap
? { thinkingLevelMap: staticOverride.thinkingLevelMap }
@@ -218,6 +221,7 @@ function mapCopilotApiModelToDefinition(
const contextWindow =
asPositiveSafeInteger(limits?.max_context_window_tokens) ?? DEFAULT_CONTEXT_WINDOW;
const contextTokens = asPositiveSafeInteger(limits?.max_prompt_tokens);
const maxTokens = asPositiveSafeInteger(limits?.max_output_tokens) ?? DEFAULT_MAX_TOKENS;
const compat = mergeCopilotCompat(resolveCopilotModelCompat(id), supports?.reasoning_effort);
const api = resolveCopilotApiForVendor(entry.vendor, id);
@@ -231,6 +235,7 @@ function mapCopilotApiModelToDefinition(
input,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow,
...(contextTokens !== undefined ? { contextTokens } : {}),
maxTokens,
...(thinkingLevelMap ? { thinkingLevelMap } : {}),
...(compat ? { compat } : {}),
@@ -108,6 +108,7 @@
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"contextTokens": 272000,
"maxTokens": 128000,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
},