feat(command-code): expose reasoning effort suffixes (#10884)

Validado no worktree combinado do lote (`.claude/worktrees/batch-round2-0821`): typecheck:core, lint, changelog-integrity, file-size, complexity e cognitive-complexity todos verdes; testes focados (71 casos citados na PR + suíte combo-builder-effort-variants/model-discovery-reasoning-levels) passando. CI vermelho neste PR é o base-red já rastreado em #9985. Obrigado!
This commit is contained in:
Jonathan Bailey
2026-08-20 22:12:49 -07:00
committed by GitHub
parent 7fa65288aa
commit 24f31cf4e0
5 changed files with 89 additions and 3 deletions

View File

@@ -0,0 +1 @@
- feat(command-code): advertise low/medium/high/xhigh/max reasoning-effort suffixes for reasoning-capable models in the catalog and Combo Builder, with request-time resolution to reasoning_effort

View File

@@ -1,5 +1,7 @@
import type { RegistryEntry } from "../../shared.ts";
const COMMAND_CODE_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"] as const;
export const command_codeProvider: RegistryEntry = {
id: "command-code",
alias: "cmd",
@@ -20,6 +22,7 @@ export const command_codeProvider: RegistryEntry = {
id: "claude-opus-4-7",
name: "Claude Opus 4.7 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 200000,
maxOutputTokens: 32000,
@@ -28,6 +31,7 @@ export const command_codeProvider: RegistryEntry = {
id: "claude-opus-4-6",
name: "Claude Opus 4.6 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 200000,
maxOutputTokens: 32000,
@@ -36,6 +40,7 @@ export const command_codeProvider: RegistryEntry = {
id: "claude-sonnet-4-6",
name: "Claude Sonnet 4.6 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 200000,
maxOutputTokens: 16384,
@@ -44,6 +49,7 @@ export const command_codeProvider: RegistryEntry = {
id: "claude-haiku-4-5-20251001",
name: "Claude Haiku 4.5 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 200000,
maxOutputTokens: 8192,
@@ -52,6 +58,7 @@ export const command_codeProvider: RegistryEntry = {
id: "gpt-5.5",
name: "GPT-5.5 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 256000,
maxOutputTokens: 128000,
@@ -60,6 +67,7 @@ export const command_codeProvider: RegistryEntry = {
id: "gpt-5.4",
name: "GPT-5.4 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 256000,
maxOutputTokens: 128000,
@@ -68,6 +76,7 @@ export const command_codeProvider: RegistryEntry = {
id: "gpt-5.3-codex",
name: "GPT-5.3 Codex (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 256000,
maxOutputTokens: 128000,
@@ -75,7 +84,8 @@ export const command_codeProvider: RegistryEntry = {
{
id: "gpt-5.4-mini",
name: "GPT-5.4 Mini (CC)",
supportsReasoning: false,
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 256000,
maxOutputTokens: 128000,
@@ -84,6 +94,7 @@ export const command_codeProvider: RegistryEntry = {
id: "deepseek/deepseek-v4-pro",
name: "DeepSeek V4 Pro (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
contextLength: 1000000,
maxOutputTokens: 131072,
},
@@ -91,6 +102,7 @@ export const command_codeProvider: RegistryEntry = {
id: "deepseek/deepseek-v4-flash",
name: "DeepSeek V4 Flash (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
contextLength: 1000000,
maxOutputTokens: 131072,
},
@@ -98,6 +110,7 @@ export const command_codeProvider: RegistryEntry = {
id: "moonshotai/Kimi-K2.6",
name: "Kimi K2.6 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 262144,
maxOutputTokens: 65536,
@@ -106,6 +119,7 @@ export const command_codeProvider: RegistryEntry = {
id: "moonshotai/Kimi-K2.5",
name: "Kimi K2.5 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 262144,
maxOutputTokens: 65536,
@@ -114,6 +128,7 @@ export const command_codeProvider: RegistryEntry = {
id: "zai-org/GLM-5.1",
name: "GLM-5.1 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
contextLength: 200000,
maxOutputTokens: 32768,
},
@@ -121,6 +136,7 @@ export const command_codeProvider: RegistryEntry = {
id: "zai-org/GLM-5",
name: "GLM-5 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
contextLength: 200000,
maxOutputTokens: 32768,
},
@@ -128,6 +144,7 @@ export const command_codeProvider: RegistryEntry = {
id: "MiniMaxAI/MiniMax-M2.7",
name: "MiniMax M2.7 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
contextLength: 1048576,
maxOutputTokens: 65536,
},
@@ -135,6 +152,7 @@ export const command_codeProvider: RegistryEntry = {
id: "MiniMaxAI/MiniMax-M2.5",
name: "MiniMax M2.5 (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
contextLength: 1048576,
maxOutputTokens: 65536,
},
@@ -142,6 +160,7 @@ export const command_codeProvider: RegistryEntry = {
id: "Qwen/Qwen3.6-Max-Preview",
name: "Qwen 3.6 Max (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
contextLength: 1000000,
maxOutputTokens: 32768,
},
@@ -149,6 +168,7 @@ export const command_codeProvider: RegistryEntry = {
id: "Qwen/Qwen3.6-Plus",
name: "Qwen 3.6 Plus (CC)",
supportsReasoning: true,
supportedThinkingEfforts: COMMAND_CODE_REASONING_EFFORTS,
supportsVision: true,
contextLength: 1000000,
maxOutputTokens: 32768,

View File

@@ -98,6 +98,11 @@ const EFFORT_SYNONYMS: Record<string, string> = { max: "xhigh" };
// Live request testing confirms Crof accepts `max` as a distinct top tier.
const CROF_REASONING_EFFORTS = ["none", "low", "medium", "high", "max"] as const;
// Command Code's provider API accepts the documented low/medium/high/xhigh/max
// reasoning_effort values for its reasoning-capable model catalog, but its
// /models response does not declare them. Keep this fallback provider-scoped.
const COMMAND_CODE_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"] as const;
function normalizeSupportedEffort(effort: string): string {
if ((CANONICAL_EFFORT_VALUES as readonly string[]).includes(effort)) return effort;
return EFFORT_SYNONYMS[effort.toLowerCase()] || effort;
@@ -232,6 +237,7 @@ export function normalizeDiscoveredModels(
if (!id) continue;
const isCrofReasoningModel = providerId === "crof" && record.reasoning_effort === true;
const isCommandCodeModel = providerId === "command-code";
const supportedThinkingEfforts = (() => {
// The flat import field and every recognized upstream tier array remain
// authoritative over the provider fallback, including an explicit empty list.
@@ -242,7 +248,8 @@ export function normalizeDiscoveredModels(
}
const detected = detectSupportedThinkingEfforts(record);
if (detected || hasDeclaredEffortList(record)) return detected;
return isCrofReasoningModel ? [...CROF_REASONING_EFFORTS] : undefined;
if (isCrofReasoningModel) return [...CROF_REASONING_EFFORTS];
return isCommandCodeModel ? [...COMMAND_CODE_REASONING_EFFORTS] : undefined;
})();
const name =
@@ -308,7 +315,7 @@ export function normalizeDiscoveredModels(
...(typeof record.description === "string" ? { description: record.description } : {}),
...(typeof record.supportsThinking === "boolean"
? { supportsThinking: record.supportsThinking }
: isCrofReasoningModel
: isCrofReasoningModel || isCommandCodeModel
? { supportsThinking: true }
: {}),
...(record.alwaysThinking === true ? { alwaysThinking: true } : {}),

View File

@@ -199,3 +199,52 @@ test("#9485 Crof synced effort aliases appear exactly in the Combo Builder picke
);
assert.deepEqual(actualAliases, expectedAliases);
});
test("Command Code static reasoning models expose all documented effort suffixes", async () => {
const connection = await providersDb.createProviderConnection({
provider: "command-code",
authType: "apikey",
name: "command-code-efforts",
apiKey: "command-code-key",
isActive: true,
testStatus: "active",
});
assert.ok(connection);
const payload = await getComboBuilderOptions();
const provider = payload.providers.find((entry) => entry.providerId === "command-code");
assert.ok(provider, "command-code provider must appear in the combo builder output");
const reasoningModels = [
"claude-opus-4-7",
"claude-opus-4-6",
"claude-sonnet-4-6",
"claude-haiku-4-5-20251001",
"gpt-5.5",
"gpt-5.4",
"gpt-5.4-mini",
"gpt-5.3-codex",
"deepseek/deepseek-v4-pro",
"deepseek/deepseek-v4-flash",
"moonshotai/Kimi-K2.6",
"moonshotai/Kimi-K2.5",
"zai-org/GLM-5.1",
"zai-org/GLM-5",
"MiniMaxAI/MiniMax-M2.7",
"MiniMaxAI/MiniMax-M2.5",
"Qwen/Qwen3.6-Max-Preview",
"Qwen/Qwen3.6-Plus",
];
const effortTiers = ["low", "medium", "high", "xhigh", "max"];
for (const baseId of reasoningModels) {
const base = provider!.models.find((model) => model.id === baseId);
assert.ok(base, `${baseId} base model must appear in the model picker`);
for (const effort of effortTiers) {
const alias = provider!.models.find((model) => model.id === `${baseId}-${effort}`);
assert.ok(alias, `${baseId}-${effort} must appear in the model picker`);
assert.equal(alias!.contextLength, base!.contextLength);
assert.equal(alias!.outputTokenLimit, base!.outputTokenLimit);
assert.equal(alias!.supportsThinking, true);
}
}
});

View File

@@ -113,6 +113,15 @@ test("CrofAI reasoning_effort true maps to the supported effort tiers", () => {
assert.deepEqual(model.supportedThinkingEfforts, ["none", "low", "medium", "high", "max"]);
});
test("Command Code discovery supplies provider-wide effort tiers when /models omits them", () => {
const [model] = normalizeDiscoveredModels(
[{ id: "command-code-live-model", name: "Command Code Live Model" }],
"command-code"
);
assert.equal(model.supportsThinking, true);
assert.deepEqual(model.supportedThinkingEfforts, ["low", "medium", "high", "xhigh", "max"]);
});
test("CrofAI false or absent reasoning_effort adds no reasoning metadata", () => {
const models = normalizeDiscoveredModels(
[{ id: "crof-no-reasoning", reasoning_effort: false }, { id: "crof-unknown-reasoning" }],