Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Bug]: token usage rows always have model=NULL for local-runtime-v2 sessions (modelIdentity reads id, projected model carries model_id)

Open Beginner friendly
#507 0 comments 0 reactions 0 assignees View on GitHub

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
Domain
backend, database

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
  1. 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).
  2. 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:

  1. 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) contains model_id/modelId but no id key, so the projected object can never carry id.
  2. That object flows to executionModel (local-agent-host.ts:231) and then to the usage projector (committed-history-writer.ts:321 → owner.ts:697).
  3. packages/local-runtime-v2/src/service/session-system/owner.ts:802-808 — modelIdentity() reads Reflect.get(model, 'id') only. With the model_id-shaped object it always returns null, and pi-usage.ts writes model: null into local_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.jsonl entries have "model": "MiniMax-M3.1-Flash" keyed by the same turnId), so a fallback at committedPiUsageRows would 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

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from MiniMax-AI/minimax-code

All issues in MiniMax-AI/minimax-code

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.