fix(model): 支持不设置推理强度

This commit is contained in:
上玄
2026-08-11 21:18:10 +08:00
parent da5fa34a4d
commit edd59dc684
20 changed files with 575 additions and 277 deletions
+13 -8
View File
@@ -18,11 +18,14 @@ import {
testModelAdapter,
fetchModelAdapterModels,
} from "@/services/clientApi";
import {
normalizeReasoningEffort,
SUPPORTED_REASONING_EFFORTS,
} from "@/state/modelAdapterReasoning";
const APP_STATE_STORAGE_KEY = "cursor-client:runtime-state:v2";
const GENERIC_SERVICE_ERROR = "服务错误";
const SUPPORTED_MODEL_ADAPTER_TYPES = new Set(["openai", "anthropic"]);
const SUPPORTED_REASONING_EFFORTS = new Set(["low", "medium", "high", "xhigh", "max"]);
const SUPPORTED_ANTHROPIC_THINKING_EFFORTS = new Set(["low", "medium", "high", "xhigh", "max"]);
export const ANTHROPIC_THINKING_EFFORT_DEFAULT = "xhigh";
export const OPENAI_ENDPOINT_RESPONSES = "/v1/responses";
@@ -165,7 +168,7 @@ export function buildModelAdapterTestRequestHash(source) {
normalizeBaseURL(adapter.baseURL),
asString(adapter.apiKey),
asString(adapter.modelID),
adapter.type === "openai" ? asString(adapter.reasoningEffort || "medium") : "",
adapter.type === "openai" ? asString(adapter.reasoningEffort) : "",
adapter.type === "openai" ? normalizeOpenAIEndpoint(adapter.openAIEndpoint) : "",
adapter.type === "openai" ? String(Boolean(adapter.openAIExtraParamsEnabled)) : "false",
adapter.type === "openai" && adapter.openAIExtraParamsEnabled ? asString(adapter.openAIExtraParamsJSON) : "",
@@ -254,7 +257,7 @@ export function createEmptyModelAdapter() {
apiKey: "",
tooltipData: "备注",
modelID: "",
reasoningEffort: "medium",
reasoningEffort: "",
openAIEndpoint: OPENAI_ENDPOINT_RESPONSES,
openAIExtraParamsEnabled: false,
openAIExtraParamsJSON: OPENAI_EXTRA_PARAMS_DEFAULT_JSON,
@@ -329,7 +332,7 @@ function validateAnthropicExtraParamsJSON(value) {
export function normalizeModelAdapter(source) {
const raw = source && typeof source === "object" ? source : {};
const normalizedType = asString(raw.type).toLowerCase();
const normalizedReasoningEffort = asString(raw.reasoningEffort || raw.reasoning_effort).toLowerCase();
const normalizedReasoningEffort = normalizeReasoningEffort(raw.reasoningEffort ?? raw.reasoning_effort);
const normalizedAnthropicThinkingEffort = asString(
raw.anthropicThinkingEffort
?? raw.anthropic_thinking_effort
@@ -362,9 +365,7 @@ export function normalizeModelAdapter(source) {
apiKey: asString(raw.apiKey || raw.key),
tooltipData: asString(raw.tooltipData),
modelID: asString(raw.modelID),
reasoningEffort: SUPPORTED_REASONING_EFFORTS.has(normalizedReasoningEffort)
? normalizedReasoningEffort
: "medium",
reasoningEffort: normalizedReasoningEffort,
openAIEndpoint: normalizedType === "openai" ? normalizedOpenAIEndpoint : "",
openAIExtraParamsEnabled,
openAIExtraParamsJSON,
@@ -442,7 +443,7 @@ export function validateModelAdapters(source) {
return `${prefix} 的上下文窗口必须为正整数`;
}
if (adapter.type === "openai" && !SUPPORTED_REASONING_EFFORTS.has(adapter.reasoningEffort)) {
return `${prefix} 的推理强度仅支持 low、medium、high、xhigh、max`;
return `${prefix} 的推理强度仅支持不设置、low、medium、high、xhigh、max`;
}
if (adapter.type === "anthropic" && adapter.anthropicMaxTokens && (!Number.isInteger(adapter.anthropicMaxTokens) || adapter.anthropicMaxTokens <= 0)) {
return `${prefix} 的最大输出 Token 必须为正整数`;
@@ -1086,6 +1087,10 @@ export async function refreshModelAdapterTestResults() {
export function startModelAdapterTest(adapter) {
const normalized = normalizeModelAdapter(adapter);
const validationError = validateModelAdapters([normalized]);
if (validationError) {
return Promise.reject(new Error(validationError));
}
return testModelAdapter(normalized).then((rawResult) => {
const result = normalizeModelAdapterTestResult(rawResult);
if (result.adapterID) {
@@ -0,0 +1,14 @@
export const SUPPORTED_REASONING_EFFORTS = new Set(["", "low", "medium", "high", "xhigh", "max"]);
export function normalizeReasoningEffort(value) {
if (typeof value === "string") {
return value.trim().toLowerCase();
}
if (value instanceof String) {
return value.toString().trim().toLowerCase();
}
if (typeof value === "number" || typeof value === "boolean") {
return String(value).trim().toLowerCase();
}
return "";
}
@@ -0,0 +1,20 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
normalizeReasoningEffort,
SUPPORTED_REASONING_EFFORTS,
} from "./modelAdapterReasoning.js";
test("normalizeReasoningEffort preserves blank and supported values", () => {
assert.equal(normalizeReasoningEffort(""), "");
assert.equal(normalizeReasoningEffort(" HIGH "), "high");
assert.equal(SUPPORTED_REASONING_EFFORTS.has(normalizeReasoningEffort("max")), true);
});
test("normalizeReasoningEffort preserves unknown values for validation", () => {
const normalized = normalizeReasoningEffort(" Unsupported ");
assert.equal(normalized, "unsupported");
assert.equal(SUPPORTED_REASONING_EFFORTS.has(normalized), false);
});