fix(session): port upstream malformed model cost guard (anomalyco/opencode#43248)

DE
17d ago
+22-5

Issue for this PR

Closes #1573

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Session.getUsage multiplies token counts by the model's cost fields with decimal.js. When a provider or models.dev entry carries a malformed cost (an object, a string or NaN), new Decimal(...).mul(...) throws DecimalError and the whole turn fails after the model already answered.

Ported from upstream anomalyco/opencode#43248: each cost field goes through a finite() guard, so a non-finite value counts as 0 instead of throwing. Valid fields are still billed. Wrapped in altimate_change markers tagged upstream_fix:.

Note: session/session.ts has a second getUsage copy that nothing imports (callers use session/index.ts), so it is left untouched.

How did you verify your code works?

New test in test/session/session-getusage.test.ts sets input: {}, cache.read: NaN, cache.write: "x" and checks the output cost is still billed (1.5). It throws on main and passes on this branch. bun typecheck and bun run script/upstream/analyze.ts --markers --base origin/main --strict are clean.

Cost side effects

None. No new model calls, queries or resources. Malformed cost fields now count as 0 in the usage total instead of failing the turn.

Screenshots / recordings

N/A, no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR
  • I checked for cost side effects (model calls, queries or cloud resources that grow with user data) and described them, or wrote "none"

Written by Devin


Summary by cubic

Fixes Session.getUsage so malformed model cost fields (objects, strings, or NaN) are treated as 0 instead of throwing DecimalError and failing the turn. Valid cost fields are still billed. Adds a test covering malformed cost input.