diff --git a/changelog.d/fixes/command-code-effort-capabilities.md b/changelog.d/fixes/command-code-effort-capabilities.md
new file mode 100644
index 0000000000..38057107ef
--- /dev/null
+++ b/changelog.d/fixes/command-code-effort-capabilities.md
@@ -0,0 +1 @@
+- fix(combo): resolve effort-suffixed command-code variants (e.g. `deepseek-v4-flash-max`) to their base model for capability lookups, so tool-bearing combo requests keep the declared priority order instead of reordering behind models with confirmed capabilities
diff --git a/src/lib/modelCapabilities.ts b/src/lib/modelCapabilities.ts
index 727122d204..9d9572a7b1 100644
--- a/src/lib/modelCapabilities.ts
+++ b/src/lib/modelCapabilities.ts
@@ -254,6 +254,39 @@ function leafModelId(modelId: string | null | undefined): string | null {
return leaf && leaf !== modelId ? leaf : null;
}
+/**
+ * Effort suffixes the catalog synthesizes as `-` variant ids from a
+ * base model's `supportedThinkingEfforts` (mirrors REGISTERED_EFFORT_SUFFIXES
+ * in open-sse/utils/registeredEffortVariants.ts, plus `minimal` for muse).
+ */
+const EFFORT_VARIANT_SUFFIXES = [
+ "none",
+ "minimal",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max",
+] as const;
+
+/**
+ * Strip a trailing effort-tier suffix off a model id (e.g.
+ * `deepseek-v4-flash-max` → `deepseek-v4-flash`). Longest token first so
+ * `xhigh` is matched before `high`. Returns null when no known suffix matches
+ * or the id would be left empty.
+ */
+function stripKnownEffortSuffix(modelId: string): string | null {
+ const normalized = String(modelId || "").trim();
+ if (!normalized) return null;
+ for (const suffix of EFFORT_VARIANT_SUFFIXES) {
+ const token = `-${suffix}`;
+ if (normalized.length > token.length && normalized.endsWith(token)) {
+ return normalized.slice(0, -token.length);
+ }
+ }
+ return null;
+}
+
function getStaticSpec(modelId: string | null, rawModel: string | null): ModelSpec | undefined {
if (modelId) {
const byCanonical = getModelSpec(modelId);
@@ -704,15 +737,38 @@ export function getResolvedModelCapabilities(
// persisted override never feeds back into the comparison that (re)writes it.
const usePersistedOverrides = options?.persistedOverrides !== false;
const resolved = resolveCapabilityInput(input);
- const spec = getStaticSpec(resolved.model, resolved.rawModel);
- const registryModel = getRegistryModel(resolved.provider, resolved.model);
- const synced = getSyncedCapabilityForResolved(
+ let spec = getStaticSpec(resolved.model, resolved.rawModel);
+ let registryModel = getRegistryModel(resolved.provider, resolved.model);
+ let synced = getSyncedCapabilityForResolved(
resolved.provider,
resolved.model,
resolved.rawModel,
snapshot
);
+ // Effort-suffixed variants (e.g. command-code `deepseek-v4-flash-max`,
+ // `meta/muse-spark-1.2-contributor-xhigh`) are synthesized in the catalog
+ // from the base model's `supportedThinkingEfforts`; they have no registry
+ // row, synced row, or static spec of their own. Without a base-model
+ // fallback the variant resolves with NULL tool/vision/context capabilities,
+ // so a tool-bearing combo request treats the target as incompatible and
+ // silently reorders it behind models with confirmed capabilities. Resolve
+ // the variant's capabilities from its base model when every direct source
+ // misses.
+ if (!spec && !registryModel && !synced && resolved.provider && resolved.model) {
+ const baseModelId = stripKnownEffortSuffix(resolved.model);
+ if (baseModelId && baseModelId !== resolved.model) {
+ spec = getStaticSpec(baseModelId, resolved.rawModel);
+ registryModel = getRegistryModel(resolved.provider, baseModelId);
+ synced = getSyncedCapabilityForResolved(
+ resolved.provider,
+ baseModelId,
+ resolved.rawModel,
+ snapshot
+ );
+ }
+ }
+
const modalitiesInput = parseModalities(synced?.modalities_input);
const modalitiesOutput = parseModalities(synced?.modalities_output);
const lookupKey =
diff --git a/tests/unit/command-code-registry-vision.test.ts b/tests/unit/command-code-registry-vision.test.ts
index ab7f193876..c86b7b5baa 100644
--- a/tests/unit/command-code-registry-vision.test.ts
+++ b/tests/unit/command-code-registry-vision.test.ts
@@ -74,3 +74,53 @@ test("MiniMax M3 via command-code keeps existing vision capability (no regressio
const caps = getResolvedModelCapabilities("command-code/MiniMaxAI/MiniMax-M3");
assert.equal(caps.supportsVision, true);
});
+
+test("command-code effort-suffixed variants resolve capabilities from their base model", async () => {
+ // Effort variants (e.g. `-max`, `-xhigh`) are synthesized from the base's
+ // supportedThinkingEfforts and have no registry/synced row of their own.
+ // Without the base-model fallback they resolve NULL tool/vision/context,
+ // which makes a tool-bearing combo request drop them behind confirmed
+ // targets (observed: orchestrator tried opencode-go/mimo-v2.5-max at
+ // position 2 while command-code deepseek sat unused at its declared
+ // priority position 2).
+ //
+ // Seed the models.dev capability store (the source getResolvedModelCapabilities
+ // reads for tool/vision/context) with the base models, then verify the
+ // effort-suffixed variants inherit those capabilities via the base fallback.
+ const modelsDevSync = await import("../../src/lib/modelsDevSync.ts");
+ modelsDevSync.saveModelsDevCapabilities({
+ "command-code": {
+ "deepseek/deepseek-v4-flash": {
+ tool_call: true,
+ reasoning: true,
+ attachment: false,
+ limit_context: 1000000,
+ limit_input: 1000000,
+ limit_output: 131072,
+ },
+ "meta/muse-spark-1.2-contributor": {
+ tool_call: true,
+ reasoning: true,
+ attachment: true,
+ limit_context: 1048576,
+ limit_input: 1048576,
+ limit_output: 1048576,
+ },
+ },
+ });
+
+ const cases: Array<[string, boolean]> = [
+ ["command-code/deepseek/deepseek-v4-flash-max", false], // text-only base
+ ["command-code/deepseek/deepseek-v4-flash-high", false],
+ ["command-code/meta/muse-spark-1.2-contributor-xhigh", true], // vision base
+ ["command-code/meta/muse-spark-1.2-contributor-high", true],
+ ];
+ for (const [modelId, vision] of cases) {
+ const caps = getResolvedModelCapabilities(modelId);
+ assert.equal(caps.provider, "command-code", `${modelId} provider`);
+ assert.equal(caps.supportsTools, true, `${modelId} must inherit tool support from base`);
+ assert.equal(caps.supportsVision, vision, `${modelId} must inherit vision from base`);
+ assert.equal(typeof caps.contextWindow, "number", `${modelId} must inherit a context window`);
+ assert.equal(caps.supportsThinking, true, `${modelId} must inherit reasoning from base`);
+ }
+});