Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions crates/agent-gateway/test/webui/web-settings.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const loader = createWebModuleLoader();
const webSettings = loader.loadModule("src/lib/webSettings.ts");
const settings = loader.loadModule("@/lib/settings/index.ts");
const settingsSync = loader.loadModule("@liveagent/ui/lib/settings/sync.ts");
const catalog = loader.loadModule("@liveagent/ui/lib/models/modelCatalog.ts");
const chatHelpers = loader.loadModule("@/lib/chat/chatPageHelpers.ts");
const adminApi = loader.loadModule("@/lib/adminApi.ts");
const RIGHT_DOCK_TAB_IDS = settings.RIGHT_DOCK_SINGLETON_TAB_IDS;
Expand Down Expand Up @@ -1879,21 +1880,32 @@ test("xai model limits use the generated catalog without changing thinking detec
});

test("xai thinking levels come from the catalog per model, thinking always on", () => {
// 档位按型号差异化(目录真值):grok-4.5 只有 low/medium/high;
// grok-4.20-multi-agent-0309 声明到 xhigh。xai 思考一律恒开
//(wire 无法表达 off),目录的 off 声明对 xai 供应商不生效。
assert.deepEqual(settings.getKnownModelThinkingLevels("xai", "grok-4.5"), [
"low",
"medium",
"high",
]);
assert.equal(settings.isThinkingAlwaysOnForModel("xai", "grok-4.5"), true);
const multiAgent = settings.getKnownModelThinkingLevels("xai", "grok-4.20-multi-agent-0309");
assert.ok(multiAgent.includes("xhigh"));
assert.equal(settings.isThinkingAlwaysOnForModel("xai", "grok-4.3"), true);
// 钳制路径:xhigh 超出 grok-4.5 档位表时压回默认 high。
// 档位按型号取目录真值:逐条对照快照里每个 xai 条目,不写死档位表(目录每日
// 自动刷新)。单点对照分不出"按型号读目录"和"整个供应商一张固定表",逐条
// 对照可以(快照里有档位为空的条目)。xai 思考一律恒开(wire 无法表达 off),
// 目录里 off: true 的条目对 xai 供应商同样不生效。
const entries = catalog.MODEL_CATALOG.xai.filter((model) => model.thinking);
assert.ok(entries.length >= 2, "xai thinking entries missing from the catalog snapshot");
for (const entry of entries) {
assert.deepEqual(
settings.getKnownModelThinkingLevels("xai", entry.id),
[...entry.thinking.levels],
`${entry.id} levels`,
);
assert.equal(
settings.isThinkingAlwaysOnForModel("xai", entry.id),
true,
`${entry.id} always on`,
);
}
// 钳制路径:表外档位(取档位阶梯里最高的表外档)压回默认 high。
const grok45Levels = settings.getKnownModelThinkingLevels("xai", "grok-4.5");
const outside = ["minimal", "low", "medium", "high", "xhigh", "max"]
.filter((level) => !grok45Levels.includes(level))
.at(-1);
assert.ok(outside, "grok-4.5 covers the whole level ladder; clamp needs another model");
const clamped = settings.normalizeChatRuntimeControlsForProvider(
{ reasoning: "xhigh", reasoningByProvider: { xai: "xhigh" } },
{ reasoning: outside, reasoningByProvider: { xai: outside } },
{ providerId: "xai", modelId: "grok-4.5" },
);
assert.equal(clamped.reasoning, "high");
Expand Down
6 changes: 5 additions & 1 deletion crates/agent-gui/test/models/model-catalog.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,11 @@ test("normalizeModelIdCandidates strips a month-day date suffix only when no ful
test("a dated relay id resolves to the catalog entry, an exact dated id keeps its own entry", () => {
const relayed = catalog.findCatalogModelAcrossProviders("deepseek-ai/deepseek-v4-pro-0813");
assert.equal(relayed?.id, "deepseek-v4-pro");
assert.equal(relayed?.contextWindow, 1000000);
// 限额对照目录快照本身,不写死数值:目录每日自动刷新会改动上游限额。
assert.deepEqual(
relayed,
catalog.MODEL_CATALOG.deepseek.find((model) => model.id === "deepseek-v4-pro"),
);
assert.equal(catalog.findCatalogModelAcrossProviders("deepseek-r1-0528")?.id, "deepseek-r1-0528");
assert.equal(catalog.findCatalogModelAcrossProviders("deepseek-r1-0601")?.id, "deepseek-r1");
});
Expand Down
30 changes: 26 additions & 4 deletions crates/agent-gui/test/settings/normalization.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,21 @@ const loader = createTsModuleLoader();
const settings = loader.loadModule("src/lib/settings/index.ts");
const normalize = loader.loadModule("@liveagent/ui/lib/settings/normalize.ts");
const sync = loader.loadModule("@liveagent/ui/lib/settings/sync.ts");
const modelCatalog = loader.loadModule("@liveagent/ui/lib/models/modelCatalog.ts");
const RIGHT_DOCK_TAB_IDS = settings.RIGHT_DOCK_SINGLETON_TAB_IDS;

// 目录每日自动刷新会改动上游限额:断言"取到目录真值"的用例对照快照条目,
// 不写死数值。
function catalogLimits(section, modelId) {
const entry = modelCatalog.MODEL_CATALOG[section].find((model) => model.id === modelId);
assert.ok(entry, `${section}/${modelId} missing from the catalog snapshot`);
return { contextWindow: entry.contextWindow, maxOutputToken: entry.maxOutputToken };
}

function pickLimits(limits) {
return { contextWindow: limits.contextWindow, maxOutputToken: limits.maxOutputToken };
}

async function withNavigator(value, task) {
const previous = Object.getOwnPropertyDescriptor(globalThis, "navigator");
Object.defineProperty(globalThis, "navigator", {
Expand Down Expand Up @@ -315,8 +328,11 @@ test("DeepSeek provider normalization keeps native routing and native search", (
assert.equal(provider.promptCachingEnabled, false);
assert.equal(provider.promptCacheHintMode, undefined);
assert.equal(provider.nativeWebSearchEnabled, true);
assert.equal(provider.models[0].contextWindow, 1_000_000);
assert.equal(provider.models[0].maxOutputToken, 393_216);
assert.deepEqual(pickLimits(provider.models[0]), catalogLimits("deepseek", "deepseek-v4-flash"));
assert.notDeepEqual(
pickLimits(provider.models[0]),
modelCatalog.PROVIDER_FALLBACK_LIMITS.deepseek,
);
});

test("legacy Codex-group DeepSeek configs stay untouched — migration is user-driven", () => {
Expand Down Expand Up @@ -3044,8 +3060,14 @@ test("cross-provider models resolve real catalog limits instead of provider fall
"claude_code",
"deepseek-v4-flash",
);
assert.equal(deepseekUnderClaude.contextWindow, 1_000_000);
assert.equal(deepseekUnderClaude.maxOutputToken, 393_216);
assert.deepEqual(
pickLimits(deepseekUnderClaude),
catalogLimits("deepseek", "deepseek-v4-flash"),
);
assert.notDeepEqual(
pickLimits(deepseekUnderClaude),
modelCatalog.PROVIDER_FALLBACK_LIMITS.claude_code,
);
const glmUnderCodex = settings.getProviderModelDefaults("codex", "glm-4.7");
assert.equal(glmUnderCodex.contextWindow, 204_800);
assert.equal(glmUnderCodex.maxOutputToken, 131_072);
Expand Down
Loading
Loading