Skip to content

Commit 880c094

Browse files
committed
fix: preserve copilot gpt-5.5 fallback metadata
1 parent 0a91152 commit 880c094

4 files changed

Lines changed: 81 additions & 16 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
2+
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
3+
4+
const STATIC_MODEL_OVERRIDES = new Map<string, Partial<ModelDefinitionConfig>>([
5+
[
6+
"gpt-5.5",
7+
{
8+
name: "GPT-5.5",
9+
reasoning: true,
10+
contextWindow: 400_000,
11+
maxTokens: 128_000,
12+
},
13+
],
14+
]);
15+
16+
export function resolveCopilotTransportApi(
17+
modelId: string,
18+
): "anthropic-messages" | "openai-responses" {
19+
return (normalizeOptionalLowercaseString(modelId) ?? "").includes("claude")
20+
? "anthropic-messages"
21+
: "openai-responses";
22+
}
23+
24+
export function resolveStaticCopilotModelOverride(
25+
modelId: string,
26+
): Partial<ModelDefinitionConfig> | undefined {
27+
return STATIC_MODEL_OVERRIDES.get(normalizeOptionalLowercaseString(modelId) ?? "");
28+
}

extensions/github-copilot/models-defaults.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
2-
import { resolveCopilotTransportApi } from "./models.js";
2+
import { resolveCopilotTransportApi, resolveStaticCopilotModelOverride } from "./model-metadata.js";
33

44
const DEFAULT_CONTEXT_WINDOW = 128_000;
55
const DEFAULT_MAX_TOKENS = 8192;
@@ -41,14 +41,16 @@ export function buildCopilotModelDefinition(modelId: string): ModelDefinitionCon
4141
if (!id) {
4242
throw new Error("Model id required");
4343
}
44+
const staticOverride = resolveStaticCopilotModelOverride(id);
4445
return {
4546
id,
46-
name: id,
47-
api: resolveCopilotTransportApi(id),
48-
reasoning: false,
49-
input: ["text", "image"],
50-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
51-
contextWindow: DEFAULT_CONTEXT_WINDOW,
52-
maxTokens: DEFAULT_MAX_TOKENS,
47+
name: staticOverride?.name ?? id,
48+
api: staticOverride?.api ?? resolveCopilotTransportApi(id),
49+
reasoning: staticOverride?.reasoning ?? false,
50+
input: staticOverride?.input ?? ["text", "image"],
51+
cost: staticOverride?.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
52+
contextWindow: staticOverride?.contextWindow ?? DEFAULT_CONTEXT_WINDOW,
53+
maxTokens: staticOverride?.maxTokens ?? DEFAULT_MAX_TOKENS,
54+
...(staticOverride?.compat ? { compat: staticOverride.compat } : {}),
5355
};
5456
}

extensions/github-copilot/models.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,19 @@ describe("github-copilot model defaults", () => {
103103
expect(def.api).toBe("anthropic-messages");
104104
});
105105

106+
it("uses static metadata overrides for gpt-5.5 fallback rows", () => {
107+
const def = buildCopilotModelDefinition("gpt-5.5");
108+
expect(def).toMatchObject({
109+
id: "gpt-5.5",
110+
name: "GPT-5.5",
111+
api: "openai-responses",
112+
reasoning: true,
113+
input: ["text", "image"],
114+
contextWindow: 400_000,
115+
maxTokens: 128_000,
116+
});
117+
});
118+
106119
it("trims whitespace from model id", () => {
107120
const def = buildCopilotModelDefinition(" gpt-4o ");
108121
expect(def.id).toBe("gpt-4o");
@@ -197,6 +210,19 @@ describe("resolveCopilotForwardCompatModel", () => {
197210
expect(result.id).toBe("gpt-5.4");
198211
});
199212

213+
it("uses static metadata for gpt-5.5 when live discovery rows are unavailable", () => {
214+
const result = requireResolvedModel(createMockCtx("gpt-5.5"));
215+
expect(result).toMatchObject({
216+
id: "gpt-5.5",
217+
name: "GPT-5.5",
218+
api: "openai-responses",
219+
reasoning: true,
220+
input: ["text", "image"],
221+
contextWindow: 400_000,
222+
maxTokens: 128_000,
223+
});
224+
});
225+
200226
it("creates synthetic model for arbitrary unknown model ID", () => {
201227
const ctx = createMockCtx("gpt-5.4-mini");
202228
const result = requireResolvedModel(ctx);

extensions/github-copilot/models.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {
55
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
66
import { normalizeModelCompat } from "openclaw/plugin-sdk/provider-model-shared";
77
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
8+
import { resolveCopilotTransportApi, resolveStaticCopilotModelOverride } from "./model-metadata.js";
89

910
export const PROVIDER_ID = "github-copilot";
1011
const CODEX_FORWARD_COMPAT_TARGET_IDS = new Set(["gpt-5.4", "gpt-5.3-codex"]);
@@ -19,14 +20,6 @@ function isCopilotCodexModelId(modelId: string): boolean {
1920
return /(?:^|[-_.])codex(?:$|[-_.])/.test(modelId);
2021
}
2122

22-
export function resolveCopilotTransportApi(
23-
modelId: string,
24-
): "anthropic-messages" | "openai-responses" {
25-
return (normalizeOptionalLowercaseString(modelId) ?? "").includes("claude")
26-
? "anthropic-messages"
27-
: "openai-responses";
28-
}
29-
3023
export function resolveCopilotForwardCompatModel(
3124
ctx: ProviderResolveDynamicModelContext,
3225
): ProviderRuntimeModel | undefined {
@@ -62,6 +55,22 @@ export function resolveCopilotForwardCompatModel(
6255
// Template not found — fall through to synthetic catch-all below.
6356
}
6457

58+
const staticOverride = resolveStaticCopilotModelOverride(lowerModelId);
59+
if (staticOverride) {
60+
return normalizeModelCompat({
61+
id: trimmedModelId,
62+
name: staticOverride.name ?? trimmedModelId,
63+
provider: PROVIDER_ID,
64+
api: staticOverride.api ?? resolveCopilotTransportApi(trimmedModelId),
65+
reasoning: staticOverride.reasoning ?? false,
66+
input: staticOverride.input ?? ["text", "image"],
67+
cost: staticOverride.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
68+
contextWindow: staticOverride.contextWindow ?? DEFAULT_CONTEXT_WINDOW,
69+
maxTokens: staticOverride.maxTokens ?? DEFAULT_MAX_TOKENS,
70+
...(staticOverride.compat ? { compat: staticOverride.compat } : {}),
71+
} as ProviderRuntimeModel);
72+
}
73+
6574
// Catch-all: create a synthetic model definition for any unknown model ID.
6675
// The Copilot API is OpenAI-compatible and will return its own error if the
6776
// model isn't available on the user's plan. This lets new models be used

0 commit comments

Comments
 (0)