From decb944e422ec1c8d22f38fa60f3663629aca12a Mon Sep 17 00:00:00 2001 From: Shujakuinkuraudo Date: Tue, 6 Oct 2026 22:12:28 -0400 Subject: [PATCH] fix(pi-devin): parse Devin CLI 1M cost_summary correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Devin catalog emits '$4 / 1M Input · $0.2 / 1M Cached input · $20 / 1M Output' but the vendored parseCost only matched '/MTok In/Out', leaving output and cached prices at 0 so session cost totals for devin models were wrong. Accept 1M Input/Output/Cached input labels and use the real cached-input price for cacheRead instead of the 10% input heuristic. --- src/models.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/models.ts b/src/models.ts index ac3137f..7865cf0 100644 --- a/src/models.ts +++ b/src/models.ts @@ -30,14 +30,18 @@ const THINKING_ORDER = ["off", "minimal", "low", "medium", "high", "xhigh", "max function parseCost(summary?: string): ProviderModelConfig["cost"] { const empty = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }; if (!summary) return empty; - const input = summary.match(/\$([0-9.]+)\s*\/\s*MTok In/i); - const output = summary.match(/\$([0-9.]+)\s*\/\s*MTok Out/i); + // Devin CLI emits e.g. "$10 / 1M Input · $0.25 / 1M Cached input · $50 / 1M Output"; + // older catalogs used "/MTok In" style labels. Match the unit token loosely. + const input = summary.match(/\$([0-9.]+)\s*\/\s*1?M(?:Tok)?\s+In(?:put)?/i); + const output = summary.match(/\$([0-9.]+)\s*\/\s*1?M(?:Tok)?\s+Out(?:put)?/i); + const cached = summary.match(/\$([0-9.]+)\s*\/\s*1?M(?:Tok)?\s+Cached\s+in(?:put)?/i); const inCost = input ? Number(input[1]) : 0; const outCost = output ? Number(output[1]) : 0; + const cacheRead = cached ? Number(cached[1]) : Number((inCost * 0.1).toFixed(4)); return { input: inCost, output: outCost, - cacheRead: Number((inCost * 0.1).toFixed(4)), + cacheRead, cacheWrite: Number((inCost * 1.25).toFixed(4)), }; }