Merge PR #7865: fix(catalog): update Devin reasoning family routing (@will-bogusz)

This commit is contained in:
can1357
2026-08-07 13:37:55 +02:00
3 changed files with 167 additions and 10 deletions
+1
View File
@@ -5,6 +5,7 @@
### Fixed
- Widened the Amazon Bedrock stream idle-timeout floor for reasoning models (600s, matching the GLM coding-plan floor) and for adaptive-thinking Claude — Opus 4.7+, Sonnet/Opus 5, and Fable/Mythos 5, where stalls were most frequent — to 900s, matching the tolerance direct Anthropic gets from ping keepalives. Bedrock ConverseStream sends no keepalive events, so long quiet reasoning stretches previously tripped the generic 300s watchdog with `Provider stream stalled while waiting for the next event` during plan writing and todo execution. Explicit `compat.streamIdleTimeoutMs` overrides still win (`0` disables the watchdog) ([#7892](https://github.com/can1357/oh-my-pi/pull/7892) by [@voonfoo](https://github.com/voonfoo)).
- Fixed current Devin model families, including SWE-1.7, Claude 5, Gemini 3.6 Flash, Kimi K3, Grok 4.5, and Inkling, appearing as separate wire variants instead of logical models with reasoning-effort routing.
## [17.2.10] - 2026-08-06
+105 -4
View File
@@ -115,7 +115,7 @@ type DevinTierRoutes = Partial<Record<"off" | "minimal" | "low" | "medium" | "hi
/** Devin families with a `-max` sibling: five wire tiers, `low` floor. */
const DEVIN_FIVE_TIER_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh, Effort.Max];
/** Devin families topping out at `-xhigh` (pre-5.6 GPT, 5.6 fast lanes). */
/** Pre-5.6 Devin GPT families top out at `-xhigh`: four wire tiers, `low` floor. */
const DEVIN_FOUR_TIER_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh];
function devinTierFamily(
@@ -172,8 +172,7 @@ function devinTierFamily(
/**
* GPT-5.6 (Luna/Sol/Terra) serves per-tier siblings for the full five-tier
* `low..max` wire scale; user efforts route 1:1 onto them. Devin serves no
* `-max-priority` sibling, so the fast family tops out at `xhigh`.
* `low..max` wire scale in both standard and fast lanes.
*/
function devinGpt56Families(variant: "luna" | "sol" | "terra", name: string): readonly EffortVariantFamily[] {
const base = `gpt-5-6-${variant}`;
@@ -200,8 +199,9 @@ function devinGpt56Families(variant: "luna" | "sol" | "terra", name: string): re
medium: `${base}-medium-priority`,
high: `${base}-high-priority`,
xhigh: `${base}-xhigh-priority`,
max: `${base}-max-priority`,
},
DEVIN_FOUR_TIER_EFFORTS,
DEVIN_FIVE_TIER_EFFORTS,
),
];
}
@@ -378,6 +378,54 @@ export const GEMINI_CLI_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
};
export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
families: [
devinTierFamily(
"claude-opus-5",
"Claude Opus 5",
{
low: "claude-opus-5-low",
medium: "claude-opus-5-medium",
high: "claude-opus-5-high",
xhigh: "claude-opus-5-xhigh",
max: "claude-opus-5-max",
},
DEVIN_FIVE_TIER_EFFORTS,
),
devinTierFamily(
"claude-opus-5-fast",
"Claude Opus 5 Fast",
{
low: "claude-opus-5-low-fast",
medium: "claude-opus-5-medium-fast",
high: "claude-opus-5-high-fast",
xhigh: "claude-opus-5-xhigh-fast",
max: "claude-opus-5-max-fast",
},
DEVIN_FIVE_TIER_EFFORTS,
),
devinTierFamily(
"claude-fable-5",
"Claude Fable 5",
{
low: "claude-5-fable-low",
medium: "claude-5-fable-medium",
high: "claude-5-fable-high",
xhigh: "claude-5-fable-xhigh",
max: "claude-5-fable-max",
},
DEVIN_FIVE_TIER_EFFORTS,
),
devinTierFamily(
"claude-sonnet-5",
"Claude Sonnet 5",
{
low: "claude-sonnet-5-low",
medium: "claude-sonnet-5-medium",
high: "claude-sonnet-5-high",
xhigh: "claude-sonnet-5-xhigh",
max: "claude-sonnet-5-max",
},
DEVIN_FIVE_TIER_EFFORTS,
),
devinTierFamily(
"claude-opus-4-7",
"Claude Opus 4.7",
@@ -522,6 +570,48 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
...devinGpt56Families("luna", "GPT-5.6 Luna"),
...devinGpt56Families("sol", "GPT-5.6 Sol"),
...devinGpt56Families("terra", "GPT-5.6 Terra"),
devinTierFamily(
"kimi-k3",
"Kimi K3",
{
low: "kimi-k3-low",
high: "kimi-k3-high",
max: "kimi-k3-max",
},
[Effort.Low, Effort.High, Effort.Max],
),
devinTierFamily(
"swe-1-7",
"SWE-1.7",
{
medium: "swe-1-7-medium",
max: "swe-1-7",
},
[Effort.Medium, Effort.Max],
),
devinTierFamily(
"grok-4-5",
"Grok 4.5",
{
low: "grok-4-5-low",
medium: "grok-4-5-medium",
high: "grok-4-5-high",
},
[Effort.Low, Effort.Medium, Effort.High],
),
devinTierFamily(
"inkling",
"Inkling",
{
off: "inkling-none",
low: "inkling-low",
medium: "inkling-medium",
high: "inkling-high",
xhigh: "inkling-xhigh",
max: "inkling-max",
},
DEVIN_FIVE_TIER_EFFORTS,
),
devinTierFamily(
"gemini-3-1-pro",
"Gemini 3.1 Pro",
@@ -542,6 +632,17 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
},
[Effort.Minimal, Effort.Low, Effort.Medium, Effort.High],
),
devinTierFamily(
"gemini-3-6-flash",
"Gemini 3.6 Flash",
{
minimal: "gemini-3-6-flash-minimal",
low: "gemini-3-6-flash-low",
medium: "gemini-3-6-flash-medium",
high: "gemini-3-6-flash-high",
},
[Effort.Minimal, Effort.Low, Effort.Medium, Effort.High],
),
devinTierFamily(
"gemini-3-flash",
"Gemini 3 Flash",
+61 -6
View File
@@ -586,19 +586,74 @@ describe("Devin tier routing", () => {
expect(sol.routing[Effort.Low]).toBe("gpt-5-6-sol-low");
expect(sol.routing.off).toBe("gpt-5-6-sol-none");
expect(sol.routing[Effort.Minimal]).toBeUndefined();
const solFast = family("gpt-5-6-sol-fast");
expect(solFast.routing[Effort.Max]).toBe("gpt-5-6-sol-max-priority");
expect(solFast.thinking.efforts).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.XHigh, Effort.Max]);
});
it("keeps families without a -max sibling on the xhigh ceiling", () => {
const solFast = family("gpt-5-6-sol-fast");
expect(solFast.thinking.efforts).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.XHigh]);
expect(solFast.routing[Effort.Max]).toBeUndefined();
expect(solFast.routing[Effort.XHigh]).toBe("gpt-5-6-sol-xhigh-priority");
it("keeps pre-5.6 families without a -max sibling on the xhigh ceiling", () => {
const gpt55 = family("gpt-5-5");
expect(gpt55.thinking.efforts).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.XHigh]);
expect(gpt55.routing[Effort.Minimal]).toBeUndefined();
expect(gpt55.routing[Effort.Max]).toBeUndefined();
});
it("routes current Devin families onto their account-visible wire variants", () => {
const fable = family("claude-fable-5");
expect(fable.routing[Effort.Low]).toBe("claude-5-fable-low");
expect(fable.routing[Effort.Max]).toBe("claude-5-fable-max");
const swe = family("swe-1-7");
expect(swe.thinking.efforts).toEqual([Effort.Medium, Effort.Max]);
expect(swe.routing[Effort.Medium]).toBe("swe-1-7-medium");
expect(swe.routing[Effort.Max]).toBe("swe-1-7");
const gemini = family("gemini-3-6-flash");
expect(gemini.routing[Effort.Minimal]).toBe("gemini-3-6-flash-minimal");
expect(gemini.routing[Effort.High]).toBe("gemini-3-6-flash-high");
const inkling = family("inkling");
expect(inkling.routing.off).toBe("inkling-none");
expect(inkling.routing[Effort.Max]).toBe("inkling-max");
});
it("collapses entitled current variants and resolves the selected effort to the wire UID", () => {
const rawIds = [
"claude-5-fable-low",
"claude-5-fable-medium",
"claude-5-fable-high",
"claude-5-fable-xhigh",
"claude-5-fable-max",
"swe-1-7-medium",
"swe-1-7",
];
const specs = rawIds.map(
(id): ModelSpec<"devin-agent"> => ({
id,
name: id,
api: "devin-agent",
provider: "devin",
baseUrl: "https://server.codeium.com",
reasoning: true,
input: ["text"],
supportsTools: true,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 200_000,
maxTokens: 64_000,
}),
);
const collapsed = collapseEffortVariants(specs, DEVIN_VARIANT_COLLAPSE_TABLE);
expect(collapsed.map(model => model.id).sort()).toEqual(["claude-fable-5", "swe-1-7"]);
const fable = collapsed.find(model => model.id === "claude-fable-5");
const swe = collapsed.find(model => model.id === "swe-1-7");
if (!fable || !swe) throw new Error("Current Devin families did not collapse");
expect(resolveWireModelId(buildModel(fable), Effort.XHigh)).toBe("claude-5-fable-xhigh");
expect(resolveWireModelId(buildModel(swe), Effort.Medium)).toBe("swe-1-7-medium");
expect(resolveWireModelId(buildModel(swe), Effort.Max)).toBe("swe-1-7");
});
});
describe("variant aliases", () => {