From 5b69636c3527993ca267cc74383bbcd8fc9a461c Mon Sep 17 00:00:00 2001 From: "itarun.p" Date: Sat, 22 Aug 2026 21:43:37 +0700 Subject: [PATCH] fix(pricing): resolve fable/mythos canary variants via fuzzy match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claude-auto-pilot-fable-v1-canary and claude-mythos-*-canary model ids wrap the pinned claude-fable-5/claude-mythos-5 names with extra prefix/suffix segments (auto-pilot-, -v1-canary), so "fable"/"mythos" is not a contiguous substring of the curated exact key. Every non-fuzzy resolution tier in matcher.js requires a contiguous substring match, so these ids fell through to miss and billed $0 — the dashboard hid the cost column entirely (formatCost() returns null for cost <= 0). Add curated fuzzy rules for "fable" and "mythos", matching the existing kiro/hy3/composer fuzzy pattern. Fixes #187 --- src/lib/pricing/curated-overrides.json | 2 ++ test/pricing.test.js | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/lib/pricing/curated-overrides.json b/src/lib/pricing/curated-overrides.json index b575bbdfc..076a58c22 100644 --- a/src/lib/pricing/curated-overrides.json +++ b/src/lib/pricing/curated-overrides.json @@ -68,6 +68,8 @@ { "match": "kiro", "ref": "kiro-cli-agent" }, { "match": "hy3", "ref": "hy3-preview-agent" }, { "match": "composer", "ref": "composer-1" }, + { "match": "fable", "ref": "claude-fable-5" }, + { "match": "mythos", "ref": "claude-mythos-5" }, { "match": "minimax-m2.7-highspeed", "ref": "MiniMax-M2.7-highspeed" }, { "match": "minimax-m2.7", "ref": "MiniMax-M2.7" }, { "match": "deepseek-v4-flash", "ref": "deepseek-v4-flash" }, diff --git a/test/pricing.test.js b/test/pricing.test.js index 72984b1ae..5884df39e 100644 --- a/test/pricing.test.js +++ b/test/pricing.test.js @@ -475,6 +475,16 @@ test("index: getModelPricing pins Claude Fable/Mythos 5 pricing from curated ove assert.equal(pinned.cache_write, 12.5); } + // Regression (issue #187): auto-pilot/canary variants wrap the pinned name + // with extra prefix/suffix segments (e.g. "claude-auto-pilot-fable-v1-canary"), + // so "fable"/"mythos" is not a contiguous substring of "claude-fable-5"/ + // "claude-mythos-5" — every non-fuzzy resolution tier misses on these ids. + for (const model of ["claude-auto-pilot-fable-v1-canary", "claude-mythos-v1-canary"]) { + const pinned = pricing.getModelPricing(model); + assert.equal(pinned.input, 10, `${model} should resolve to the Fable/Mythos pin`); + assert.equal(pinned.output, 50, `${model} should resolve to the Fable/Mythos pin`); + } + assert.equal( pricing.computeRowCost({ source: "claude",