[Bug]: token usage rows always have model=NULL for local-runtime-v2 sessions (modelIdentity reads id, projected model carries model_id)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- sqlite, typescript
Research direction
Read packages/local-runtime-v2/src/service/session-system/owner.ts around modelIdentity() and trace how its result reaches the usage rows in pi-usage.ts. Check the projected model shape in packages/local-runtime-v2/src/service/turn-system/agent-host/assembly-context.ts; the issue identifies the model_id field mismatch. Confirm the fix by exercising the v2 usage recording path and verifying new local_runtime_token_usage rows contain the model.
Written by the indexing model from the issue text.
Description
Product or interface
Desktop app (also affects CLI TUI / headless / ACP — all paths that record usage through local-runtime-v2)
Version
Desktop 3.1.3 (macOS); source analysis at main 9a93560 (v0.6.5)
Platform
macOS
OS version and architecture
macOS 26 arm64
Issue area
Other (local usage ledger / local_runtime_token_usage)
Steps to reproduce
- Use MiniMax Code desktop 3.1.3 (or any build recording usage via
local-runtime-v2) for a normal coding session with a MiniMax model (e.g.minimax/MiniMax-M3.1-Flash). - Inspect
~/.minimax/v2/sqlite/runtime-state.sqlite:
SELECT model, count(*) FROM local_runtime_token_usage GROUP BY model;
-- after upgrading to 3.1.3: every new row has model = NULL
On my machine: 1314 rows written by the previous version all have model = 'minimax/MiniMax-M3'; all 7 rows written after the 3.1.3 upgrade have model = NULL (session layout v2-final-dated-session, so they went through the v2 runtime).
Expected and actual behavior
Expected: the model column records the model used for each turn (as the v1 runtime path did, and as the model column, the idx_local_runtime_token_usage_model_ts index, and the group=model query path in usage/repo/drizzle.ts all imply).
Actual: rows written by local-runtime-v2 always have model = NULL.
Downstream impact: every tool that reads this table for statistics (including the built-in summarizeGroupBy('model') API, which falls back to coalesce(model, 'unknown')) can only show "unknown" for new sessions. See also cc-switch #7705 where a third-party importer hits the same thing ("mcode session 用量导入模型恒为 unknown").
Root cause analysis (source at main 9a93560)
The v2 write chain feeds modelIdentity() a model object whose keys can never match:
packages/local-runtime-v2/src/service/turn-system/agent-host/assembly-context.ts—projectResolvedModel()returns{ provider, model_id: resolved.id, context_window, max_tokens, … }.MODEL_ALLOWLIST(lines 42–58) containsmodel_id/modelIdbut noidkey, so the projected object can never carryid.- That object flows to
executionModel(local-agent-host.ts:231) and then to the usage projector (committed-history-writer.ts:321→owner.ts:697). packages/local-runtime-v2/src/service/session-system/owner.ts:802-808—modelIdentity()readsReflect.get(model, 'id')only. With themodel_id-shaped object it always returnsnull, andpi-usage.tswritesmodel: nullintolocal_runtime_token_usage.
modelIdentity() matches the pi framework's Model shape ({ id, provider, … }, third_party/pi-mono/packages/ai/src/types.ts:593), which is why the compat layer's modelIdentity(turn.model) calls still produce correct provider/id strings. Only the v2 projected shape is broken — the same function consumes two shapes and one of them silently degrades to null.
Additional notes:
- Both files are unchanged since the initial import commit (c59cf53, 2026-09-18), so this is not a recent regression in the public history — it has been there since the first snapshot.
- The assistant messages themselves carry the model (e.g.
messages.jsonlentries have"model": "MiniMax-M3.1-Flash"keyed by the sameturnId), so a fallback atcommittedPiUsageRowswould also work.
Suggested fix (either or both)
// owner.ts
function modelIdentity(model: unknown): string | null {
if (!model || typeof model !== 'object') return null;
const provider = Reflect.get(model, 'provider');
const id = Reflect.get(model, 'id') ?? Reflect.get(model, 'model_id') ?? Reflect.get(model, 'modelId');
if (typeof provider === 'string' && typeof id === 'string') return `${provider}/${id}`;
return typeof id === 'string' ? id : null;
}
or in pi-usage.ts committedPiUsageRows: fall back to the assistant message's own model field when input.model is null.
Before submitting
- I have searched existing issues.
- I have included my version and removed sensitive information.
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 259
- Avg merge
- 7h 56m
- Merged PRs (30d)
- 126
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from MiniMax-AI/minimax-code
-
bug needs-triage tui
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
MiniMax-AI/minimax-code#481 · 1 comment ·
Maintainers usually reply within 1 day
-
bug cli documentation needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
MiniMax-AI/minimax-code#299 · 3 comments ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 15/100
MiniMax-AI/minimax-code#514 ·
Maintainers usually reply within 1 day
-
desktop
Difficulty 5/5 Over a week Newbie friendliness 35/100
MiniMax-AI/minimax-code#513 · 3 comments ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
MiniMax-AI/minimax-code#512 ·
Maintainers usually reply within 1 day
All issues in MiniMax-AI/minimax-code
Similar issues
-
engine-rs P3 review-deferral wasm
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
maniator/verticopolis#1154 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
telerik/kendo-react#3861 ·
Maintainers usually reply within 1 day
-
[bug]: use-mobile.ts uses pixel logic, causing UI state de-sync with Tailwind CSS rem breakpointsOpenbug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
task
Difficulty 2/5 1-3 hours Newbie friendliness 72/100