mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(deepinfra): preserve manifest reasoning during live discovery (#129998)
This commit is contained in:
committed by
GitHub
parent
de8a33a553
commit
772f6a3d5e
@@ -263,6 +263,89 @@ describe("discoverDeepInfraModels (chat-only shim)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves bundled reasoning and compat while keeping live model facts authoritative", async () => {
|
||||
const rows = [
|
||||
makeAgentModelEntry({
|
||||
id: "deepseek-ai/DeepSeek-V4-Pro",
|
||||
metadata: {
|
||||
context_length: 96000,
|
||||
max_tokens: 4096,
|
||||
pricing: { input_tokens: 4, output_tokens: 8, cache_read_tokens: 0.4 },
|
||||
tags: ["chat"],
|
||||
},
|
||||
}),
|
||||
makeAgentModelEntry({
|
||||
id: "stepfun-ai/Step-3.7-Flash",
|
||||
metadata: {
|
||||
context_length: 192000,
|
||||
max_tokens: 16384,
|
||||
pricing: { input_tokens: 0.2, output_tokens: 1.15 },
|
||||
tags: ["chat", "vlm", "vision"],
|
||||
},
|
||||
}),
|
||||
makeAgentModelEntry({
|
||||
id: "deepseek-ai/DeepSeek-V3.2",
|
||||
metadata: {
|
||||
context_length: 64000,
|
||||
max_tokens: 8192,
|
||||
pricing: { input_tokens: 1, output_tokens: 2 },
|
||||
tags: ["chat", "reasoning"],
|
||||
},
|
||||
}),
|
||||
makeAgentModelEntry({
|
||||
id: "unlisted/no-reasoning",
|
||||
metadata: { context_length: 32000, max_tokens: 2048, pricing: {}, tags: ["chat"] },
|
||||
}),
|
||||
makeAgentModelEntry({
|
||||
id: "unlisted/with-reasoning",
|
||||
metadata: {
|
||||
context_length: 48000,
|
||||
max_tokens: 4096,
|
||||
pricing: {},
|
||||
tags: ["chat", "reasoning_effort"],
|
||||
},
|
||||
}),
|
||||
];
|
||||
const mockFetch = vi.fn().mockResolvedValue(jsonResponse({ data: rows }));
|
||||
DEEPINFRA_MODEL_CATALOG.push(DEEPINFRA_MODEL_CATALOG[0]!);
|
||||
|
||||
try {
|
||||
await withFetchPathTest(mockFetch, { DEEPINFRA_API_KEY: "sk-test" }, async () => {
|
||||
const models = await discoverDeepInfraModels();
|
||||
|
||||
expect(models.slice(0, rows.length)).toMatchObject([
|
||||
{
|
||||
id: "deepseek-ai/DeepSeek-V4-Pro",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
contextWindow: 96000,
|
||||
maxTokens: 4096,
|
||||
cost: { input: 4, output: 8, cacheRead: 0.4, cacheWrite: 0 },
|
||||
compat: {
|
||||
codeMode: "capable",
|
||||
supportsUsageInStreaming: true,
|
||||
thinkingFormat: "deepseek",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "stepfun-ai/Step-3.7-Flash",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 192000,
|
||||
maxTokens: 16384,
|
||||
cost: { input: 0.2, output: 1.15, cacheRead: 0, cacheWrite: 0 },
|
||||
},
|
||||
{ id: "deepseek-ai/DeepSeek-V3.2", reasoning: false },
|
||||
{ id: "unlisted/no-reasoning", reasoning: false },
|
||||
{ id: "unlisted/with-reasoning", reasoning: true },
|
||||
]);
|
||||
expect(new Set(models.map((model) => model.id)).size).toBe(models.length);
|
||||
});
|
||||
} finally {
|
||||
DEEPINFRA_MODEL_CATALOG.pop();
|
||||
}
|
||||
});
|
||||
|
||||
it("skips entries with no metadata or no surface tag, and deduplicates ids", async () => {
|
||||
const mockFetch = vi.fn().mockResolvedValue(
|
||||
jsonResponse({
|
||||
|
||||
@@ -359,13 +359,15 @@ export function buildDeepInfraModelDefinition(model: ModelDefinitionConfig): Mod
|
||||
}
|
||||
|
||||
function chatSurfaceModelToModelDefinition(model: DeepInfraSurfaceModel): ModelDefinitionConfig {
|
||||
const manifestModel = DEEPINFRA_MODEL_CATALOG.find((entry) => entry.id === model.id);
|
||||
const input: Array<"text" | "image"> = model.tags.includes("vlm") ? ["text", "image"] : ["text"];
|
||||
const reasoning = model.tags.includes("reasoning") || model.tags.includes("reasoning_effort");
|
||||
return buildDeepInfraModelDefinition({
|
||||
id: model.id,
|
||||
name: model.name,
|
||||
reasoning,
|
||||
reasoning: manifestModel?.reasoning ?? reasoning,
|
||||
input,
|
||||
...(manifestModel?.compat ? { compat: manifestModel.compat } : {}),
|
||||
contextWindow: model.contextWindow ?? DEEPINFRA_DEFAULT_CONTEXT_WINDOW,
|
||||
maxTokens: model.maxTokens ?? DEEPINFRA_DEFAULT_MAX_TOKENS,
|
||||
cost: {
|
||||
@@ -480,14 +482,10 @@ export async function discoverDeepInfraModels(options?: {
|
||||
}
|
||||
const liveModels = chatModels.map(chatSurfaceModelToModelDefinition);
|
||||
const seen = new Set(liveModels.map((model) => model.id));
|
||||
const manifestModels = DEEPINFRA_MODEL_CATALOG.map(buildDeepInfraModelDefinition).filter(
|
||||
(model) => {
|
||||
if (seen.has(model.id)) {
|
||||
return false;
|
||||
}
|
||||
seen.add(model.id);
|
||||
return true;
|
||||
},
|
||||
);
|
||||
const manifestModels = DEEPINFRA_MODEL_CATALOG.filter((model) => {
|
||||
const unseen = !seen.has(model.id);
|
||||
seen.add(model.id);
|
||||
return unseen;
|
||||
}).map(buildDeepInfraModelDefinition);
|
||||
return [...liveModels, ...manifestModels];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user