mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-28 20:46:57 +02:00
fix(agents): validate thinking with model catalog
This commit is contained in:
@@ -813,17 +813,27 @@ async function agentCommandInternal(
|
||||
catalog: catalogForThinking.length > 0 ? catalogForThinking : undefined,
|
||||
});
|
||||
}
|
||||
if (!isThinkingLevelSupported({ provider, model, level: resolvedThinkLevel })) {
|
||||
const catalogForThinking = modelCatalog ?? allowedModelCatalog;
|
||||
const thinkingCatalog = catalogForThinking.length > 0 ? catalogForThinking : undefined;
|
||||
if (
|
||||
!isThinkingLevelSupported({
|
||||
provider,
|
||||
model,
|
||||
level: resolvedThinkLevel,
|
||||
catalog: thinkingCatalog,
|
||||
})
|
||||
) {
|
||||
const explicitThink = Boolean(thinkOnce || thinkOverride);
|
||||
if (explicitThink) {
|
||||
throw new Error(
|
||||
`Thinking level "${resolvedThinkLevel}" is not supported for ${provider}/${model}. Use one of: ${formatThinkingLevels(provider, model)}.`,
|
||||
`Thinking level "${resolvedThinkLevel}" is not supported for ${provider}/${model}. Use one of: ${formatThinkingLevels(provider, model, ", ", thinkingCatalog)}.`,
|
||||
);
|
||||
}
|
||||
const fallbackThinkLevel = resolveSupportedThinkingLevel({
|
||||
provider,
|
||||
model,
|
||||
level: resolvedThinkLevel,
|
||||
catalog: thinkingCatalog,
|
||||
});
|
||||
if (fallbackThinkLevel !== resolvedThinkLevel) {
|
||||
const previousThinkLevel = resolvedThinkLevel;
|
||||
|
||||
@@ -12,6 +12,8 @@ let listThinkingLevelOptions: typeof import("./thinking.js").listThinkingLevelOp
|
||||
let listThinkingLevels: typeof import("./thinking.js").listThinkingLevels;
|
||||
let normalizeReasoningLevel: typeof import("./thinking.js").normalizeReasoningLevel;
|
||||
let normalizeThinkLevel: typeof import("./thinking.js").normalizeThinkLevel;
|
||||
let isThinkingLevelSupported: typeof import("./thinking.js").isThinkingLevelSupported;
|
||||
let formatThinkingLevels: typeof import("./thinking.js").formatThinkingLevels;
|
||||
let resolveSupportedThinkingLevel: typeof import("./thinking.js").resolveSupportedThinkingLevel;
|
||||
let resolveThinkingDefaultForModel: typeof import("./thinking.js").resolveThinkingDefaultForModel;
|
||||
|
||||
@@ -42,6 +44,8 @@ beforeEach(async () => {
|
||||
listThinkingLevels,
|
||||
normalizeReasoningLevel,
|
||||
normalizeThinkLevel,
|
||||
isThinkingLevelSupported,
|
||||
formatThinkingLevels,
|
||||
resolveSupportedThinkingLevel,
|
||||
resolveThinkingDefaultForModel,
|
||||
} = await loadFreshThinkingModuleForTest());
|
||||
@@ -170,6 +174,37 @@ describe("listThinkingLevels", () => {
|
||||
expect(listThinkingLevelLabels("demo", "demo-model")).toEqual(["off", "on"]);
|
||||
});
|
||||
|
||||
it("passes catalog reasoning into provider thinking profiles for support checks", () => {
|
||||
providerRuntimeMocks.resolveProviderThinkingProfile.mockImplementation(({ context }) => ({
|
||||
levels:
|
||||
context.reasoning === true
|
||||
? [{ id: "off" }, { id: "low" }, { id: "medium" }, { id: "high" }, { id: "max" }]
|
||||
: [{ id: "off" }],
|
||||
defaultLevel: "off",
|
||||
}));
|
||||
const catalog = [{ provider: "ollama", id: "gpt-oss:20b", name: "gpt-oss", reasoning: true }];
|
||||
|
||||
expect(
|
||||
isThinkingLevelSupported({
|
||||
provider: "ollama",
|
||||
model: "gpt-oss:20b",
|
||||
level: "max",
|
||||
catalog,
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(formatThinkingLevels("ollama", "gpt-oss:20b", ", ", catalog)).toBe(
|
||||
"off, low, medium, high, max",
|
||||
);
|
||||
expect(
|
||||
resolveSupportedThinkingLevel({
|
||||
provider: "ollama",
|
||||
model: "gpt-oss:20b",
|
||||
level: "max",
|
||||
catalog,
|
||||
}),
|
||||
).toBe("max");
|
||||
});
|
||||
|
||||
it("maps stale unsupported levels to the largest profile level", () => {
|
||||
providerRuntimeMocks.resolveProviderThinkingProfile.mockReturnValue({
|
||||
levels: [{ id: "off" }, { id: "high" }],
|
||||
|
||||
@@ -194,8 +194,11 @@ function supportsThinkingLevel(
|
||||
provider: string | null | undefined,
|
||||
model: string | null | undefined,
|
||||
level: ThinkLevel,
|
||||
catalog?: ThinkingCatalogEntry[],
|
||||
): boolean {
|
||||
return resolveThinkingProfile({ provider, model }).levels.some((entry) => entry.id === level);
|
||||
return resolveThinkingProfile({ provider, model, catalog }).levels.some(
|
||||
(entry) => entry.id === level,
|
||||
);
|
||||
}
|
||||
|
||||
export function supportsXHighThinking(provider?: string | null, model?: string | null): boolean {
|
||||
@@ -223,8 +226,10 @@ export function formatThinkingLevels(
|
||||
provider?: string | null,
|
||||
model?: string | null,
|
||||
separator = ", ",
|
||||
catalog?: ThinkingCatalogEntry[],
|
||||
): string {
|
||||
return listThinkingLevelLabels(provider, model).join(separator);
|
||||
const profile = resolveThinkingProfile({ provider, model, catalog });
|
||||
return profile.levels.map(({ label }) => label).join(separator);
|
||||
}
|
||||
|
||||
export function resolveThinkingDefaultForModel(params: {
|
||||
@@ -262,8 +267,9 @@ export function isThinkingLevelSupported(params: {
|
||||
provider?: string | null;
|
||||
model?: string | null;
|
||||
level: ThinkLevel;
|
||||
catalog?: ThinkingCatalogEntry[];
|
||||
}): boolean {
|
||||
return supportsThinkingLevel(params.provider, params.model, params.level);
|
||||
return supportsThinkingLevel(params.provider, params.model, params.level, params.catalog);
|
||||
}
|
||||
|
||||
function resolveSupportedThinkingLevelFromProfile(
|
||||
@@ -286,7 +292,12 @@ export function resolveSupportedThinkingLevel(params: {
|
||||
provider?: string | null;
|
||||
model?: string | null;
|
||||
level: ThinkLevel;
|
||||
catalog?: ThinkingCatalogEntry[];
|
||||
}): ThinkLevel {
|
||||
const profile = resolveThinkingProfile({ provider: params.provider, model: params.model });
|
||||
const profile = resolveThinkingProfile({
|
||||
provider: params.provider,
|
||||
model: params.model,
|
||||
catalog: params.catalog,
|
||||
});
|
||||
return resolveSupportedThinkingLevelFromProfile(profile, params.level);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user