mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-30 19:33:31 +00:00
refactor(providers): drop unused model defaults helpers
This commit is contained in:
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 } : {}),
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user