refactor(providers): drop unused model defaults helpers

This commit is contained in:
Vincent Koc
2026-06-19 13:05:46 +08:00
parent 3a82bf5766
commit 46c42d4a0d
6 changed files with 8 additions and 176 deletions

View File

@@ -6,7 +6,7 @@ import {
isLiveTestEnabled,
} from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { BYTEPLUS_CODING_BASE_URL, BYTEPLUS_DEFAULT_COST } from "./models.js";
import { BYTEPLUS_CODING_BASE_URL } from "./models.js";
const BYTEPLUS_KEY = process.env.BYTEPLUS_API_KEY ?? "";
const BYTEPLUS_CODING_MODEL = process.env.BYTEPLUS_CODING_MODEL?.trim() || "ark-code-latest";
@@ -33,7 +33,7 @@ describeLive("byteplus coding plan live", () => {
baseUrl: BYTEPLUS_CODING_BASE_URL,
reasoning: false,
input: ["text"],
cost: BYTEPLUS_DEFAULT_COST,
cost: { input: 0.0001, output: 0.0002, cacheRead: 0, cacheWrite: 0 },
contextWindow: 256000,
maxTokens: 4096,
};

View File

@@ -20,14 +20,6 @@ export const BYTEPLUS_BASE_URL = BYTEPLUS_MANIFEST_PROVIDER.baseUrl;
/** Base URL for BytePlus Plan coding APIs from the manifest catalog. */
export const BYTEPLUS_CODING_BASE_URL = BYTEPLUS_CODING_MANIFEST_PROVIDER.baseUrl;
/** Fallback cost shape retained for callers that need BytePlus defaults. */
export const BYTEPLUS_DEFAULT_COST = {
input: 0.0001,
output: 0.0002,
cacheRead: 0,
cacheWrite: 0,
};
/** BytePlus general model catalog entries. */
export const BYTEPLUS_MODEL_CATALOG: ModelDefinitionConfig[] = BYTEPLUS_MANIFEST_PROVIDER.models;
/** BytePlus coding/planning model catalog entries. */

View File

@@ -15,10 +15,11 @@ import {
FIREWORKS_DEFAULT_CONTEXT_WINDOW,
FIREWORKS_DEFAULT_MAX_TOKENS,
FIREWORKS_DEFAULT_MODEL_ID,
FIREWORKS_K2_6_MODEL_ID,
} from "./provider-catalog.js";
import { resolveThinkingProfile } from "./provider-policy-api.js";
const FIREWORKS_KIMI_K2_6_MODEL_ID = "accounts/fireworks/models/kimi-k2p6";
function createFireworksDefaultRuntimeModel(params: { reasoning: boolean }): ProviderRuntimeModel {
return {
id: FIREWORKS_DEFAULT_MODEL_ID,
@@ -65,7 +66,7 @@ describe("fireworks provider plugin", () => {
throw new Error("expected Fireworks catalog models");
}
expect(models.map((model) => model.id)).toEqual([
FIREWORKS_K2_6_MODEL_ID,
FIREWORKS_KIMI_K2_6_MODEL_ID,
FIREWORKS_DEFAULT_MODEL_ID,
]);
expect(models[0]?.reasoning).toBe(false);
@@ -144,7 +145,7 @@ describe("fireworks provider plugin", () => {
it("defers manifest catalog models to core static-catalog resolution", async () => {
const provider = await registerSingleProviderPlugin(fireworksPlugin);
for (const modelId of [FIREWORKS_K2_6_MODEL_ID, FIREWORKS_DEFAULT_MODEL_ID]) {
for (const modelId of [FIREWORKS_KIMI_K2_6_MODEL_ID, FIREWORKS_DEFAULT_MODEL_ID]) {
const resolved = provider.resolveDynamicModel?.(
createProviderDynamicModelContext({
provider: "fireworks",
@@ -172,7 +173,7 @@ describe("fireworks provider plugin", () => {
expect(
provider.resolveThinkingProfile?.({
provider: "fireworks",
modelId: FIREWORKS_K2_6_MODEL_ID,
modelId: FIREWORKS_KIMI_K2_6_MODEL_ID,
}),
).toEqual({
levels: [{ id: "off" }],
@@ -184,7 +185,7 @@ describe("fireworks provider plugin", () => {
modelId: "accounts/fireworks/models/qwen3.6-plus",
}),
).toBeUndefined();
expect(resolveThinkingProfile({ modelId: FIREWORKS_K2_6_MODEL_ID })).toEqual({
expect(resolveThinkingProfile({ modelId: FIREWORKS_KIMI_K2_6_MODEL_ID })).toEqual({
levels: [{ id: "off" }],
defaultLevel: "off",
});

View File

@@ -13,7 +13,6 @@ const FIREWORKS_MANIFEST_PROVIDER = buildManifestModelProviderConfig({
export const FIREWORKS_BASE_URL = FIREWORKS_MANIFEST_PROVIDER.baseUrl;
export const FIREWORKS_DEFAULT_MODEL_ID = "accounts/fireworks/routers/kimi-k2p5-turbo";
export const FIREWORKS_K2_6_MODEL_ID = "accounts/fireworks/models/kimi-k2p6";
function requireFireworksManifestModel(id: string): ModelDefinitionConfig {
const model = FIREWORKS_MANIFEST_PROVIDER.models.find((entry) => entry.id === id);

View File

@@ -1,57 +0,0 @@
// Github Copilot plugin module implements models defaults behavior.
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
import {
resolveCopilotModelCompat,
resolveCopilotTransportApi,
resolveStaticCopilotModelOverride,
} from "./model-metadata.js";
const DEFAULT_CONTEXT_WINDOW = 128_000;
const DEFAULT_MAX_TOKENS = 8192;
// Copilot model ids vary by plan/org and can change.
// We keep this list intentionally broad; if a model isn't available Copilot will
// return an error and users can remove it from their config.
const DEFAULT_MODEL_IDS = [
"claude-opus-4.6",
"claude-opus-4.7",
"claude-opus-4.8",
"claude-sonnet-4.6",
"gemini-2.5-pro",
"gemini-3-flash",
"gemini-3.1-pro",
"gpt-5.3-codex",
"gpt-5.4",
"gpt-5.4-mini",
"gpt-5.4-nano",
"gpt-5.5",
"raptor-mini",
"goldeneye",
] as const;
export function getDefaultCopilotModelIds(): string[] {
return [...DEFAULT_MODEL_IDS];
}
export function buildCopilotModelDefinition(modelId: string): ModelDefinitionConfig {
const id = modelId.trim();
if (!id) {
throw new Error("Model id required");
}
const staticOverride = resolveStaticCopilotModelOverride(id);
const compat = staticOverride?.compat ?? resolveCopilotModelCompat(id);
return {
id,
name: staticOverride?.name ?? id,
api: staticOverride?.api ?? resolveCopilotTransportApi(id),
reasoning: staticOverride?.reasoning ?? false,
input: staticOverride?.input ?? ["text", "image"],
cost: staticOverride?.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: staticOverride?.contextWindow ?? DEFAULT_CONTEXT_WINDOW,
maxTokens: staticOverride?.maxTokens ?? DEFAULT_MAX_TOKENS,
...(staticOverride?.thinkingLevelMap
? { thinkingLevelMap: staticOverride.thinkingLevelMap }
: {}),
...(compat ? { compat } : {}),
};
}

View File

@@ -1,7 +1,6 @@
// Github Copilot tests cover models plugin behavior.
import { createProviderUsageFetch, makeResponse } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { buildCopilotModelDefinition, getDefaultCopilotModelIds } from "./models-defaults.js";
import { deriveCopilotApiBaseUrlFromToken, resolveCopilotApiToken } from "./token.js";
import { fetchCopilotUsage } from "./usage.js";
@@ -54,108 +53,6 @@ function requireResolvedModel(ctx: ProviderResolveDynamicModelContext) {
return result;
}
describe("github-copilot model defaults", () => {
describe("getDefaultCopilotModelIds", () => {
it("includes claude-opus-4.7", () => {
expect(getDefaultCopilotModelIds()).toContain("claude-opus-4.7");
expect(getDefaultCopilotModelIds()).toContain("claude-opus-4.6");
});
it("includes claude-opus-4.8", () => {
expect(getDefaultCopilotModelIds()).toContain("claude-opus-4.8");
});
it("includes claude-sonnet-4.6", () => {
expect(getDefaultCopilotModelIds()).toContain("claude-sonnet-4.6");
});
it("excludes retired and old Claude fallback rows", () => {
expect(getDefaultCopilotModelIds()).not.toContain("claude-sonnet-4");
expect(getDefaultCopilotModelIds()).not.toContain("claude-sonnet-4.5");
expect(getDefaultCopilotModelIds()).not.toContain("claude-opus-4.5");
expect(getDefaultCopilotModelIds()).not.toContain("claude-haiku-4.5");
expect(getDefaultCopilotModelIds()).not.toContain("grok-code-fast-1");
});
it("returns a mutable copy", () => {
const a = getDefaultCopilotModelIds();
const b = getDefaultCopilotModelIds();
expect(a).not.toBe(b);
expect(a).toEqual(b);
});
});
describe("buildCopilotModelDefinition", () => {
it("builds a valid definition for claude-sonnet-4.6", () => {
const def = buildCopilotModelDefinition("claude-sonnet-4.6");
expect(def.id).toBe("claude-sonnet-4.6");
expect(def.api).toBe("anthropic-messages");
expect(def.compat).toBeUndefined();
});
it.each(["claude-haiku-4.5", "claude-sonnet-4-5"])(
"disables eager tool streaming for Copilot Claude 4.5 model %s",
(modelId) => {
expect(buildCopilotModelDefinition(modelId).compat).toEqual({
supportsEagerToolInputStreaming: false,
});
},
);
it("uses static metadata overrides for gpt-5.5 fallback rows", () => {
const def = buildCopilotModelDefinition("gpt-5.5");
expect(def).toEqual({
id: "gpt-5.5",
name: "GPT-5.5",
api: "openai-responses",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 400_000,
maxTokens: 128_000,
});
});
it("uses static metadata overrides for Claude Opus 1M fallback rows", () => {
const def = buildCopilotModelDefinition("claude-opus-4.7-1m-internal");
expect(def).toEqual({
id: "claude-opus-4.7-1m-internal",
name: "Claude Opus 4.7 (1M context)",
api: "anthropic-messages",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 1_000_000,
maxTokens: 64_000,
thinkingLevelMap: { xhigh: "xhigh", max: null },
compat: { supportedReasoningEfforts: ["low", "medium", "high", "xhigh"] },
});
});
it("trims whitespace from model id", () => {
const def = buildCopilotModelDefinition(" gpt-4o ");
expect(def.id).toBe("gpt-4o");
expect(def.api).toBe("openai-responses");
});
it("routes Gemini models through Chat Completions with Copilot compat flags", () => {
const def = buildCopilotModelDefinition("gemini-3.1-pro-preview");
expect(def.api).toBe("openai-completions");
expect(def.compat).toEqual({
supportsStore: false,
supportsDeveloperRole: false,
supportsUsageInStreaming: false,
maxTokensField: "max_tokens",
});
});
it("throws on empty model id", () => {
expect(() => buildCopilotModelDefinition("")).toThrow("Model id required");
expect(() => buildCopilotModelDefinition(" ")).toThrow("Model id required");
});
});
});
describe("resolveCopilotForwardCompatModel", () => {
it("returns undefined for empty modelId", () => {
expect(resolveCopilotForwardCompatModel(createMockCtx(""))).toBeUndefined();