Skip to content

fix(commandcode): char-safe model canonicalize, MiniMax pricing, per-turn input - #750

Merged
junhoyeo merged 1 commit into
mainfrom
fix/commandcode-717
Jun 22, 2026
Merged

fix(commandcode): char-safe model canonicalize, MiniMax pricing, per-turn input#750
junhoyeo merged 1 commit into
mainfrom
fix/commandcode-717

Conversation

@junhoyeo

@junhoyeo junhoyeo commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Problem

Three confirmed bugs in crates/tokscale-core/src/sessions/commandcode.rs (PR #717):

  • (a) PANIC (high): canonicalize_model byte-sliced base[base.len() - PROMO_SUFFIX.len()..] guarded only by a length check, not a char boundary. A non-ASCII model id from the untrusted ~/.commandcode/config.json could place that byte index mid-codepoint and panic the parse.
  • (b) PRICING (low): Stripping the org prefix turned MiniMaxAI/MiniMax-M3-Free into bare MiniMax-M3, but the client's own command-code provider is not a pricing provider, so the resolver never reached the minimax/... pricing key and cost resolved to 0.
  • (c) O(N^2) INPUT (low): Per-assistant-turn input was estimated from context_chars, a cumulative running sum of all prior messages that grows across the session, inflating reported input versus other clients.

Fix

  • (a) Char-safe, case-insensitive -free strip via str::get(..), which returns None (instead of panicking) when the tail is not on a char boundary.
  • (b) Recover the real provider from the gateway id with provider_identity::inferred_provider_from_model (e.g. minimax) and use it as the message provider_id, matching the claudecode convention. Falls back to command-code when no provider is inferred.
  • (c) Estimate each turn's input from only the new context introduced since the previous response (user prompt + tool results), not the cumulative total. Summed over the session this charges each message's content exactly once.

Tests

  • test_canonicalize_model_does_not_panic_on_non_ascii — non-ASCII/emoji model ids do not panic (fails before fix a).
  • test_minimax_model_resolves_nonzero_pricing — a MiniMax session resolves non-zero pricing against a minimax/... key (fails before fix b).
  • test_input_is_per_turn_delta_not_cumulative + rewritten pinning test test_commandcode_input_is_per_turn_delta — per-turn input does not accumulate (fails before fix c).
  • Updated the module doc-comment to describe per-turn (not cumulative) input estimation.

cargo test -p tokscale-core (985 lib + integration tests) and cargo clippy -p tokscale-core --tests both pass clean.

Residual concern

provider_id for MiniMax sessions is now minimax rather than command-code (intentional, so pricing resolves and matches how claudecode attributes multi-provider models). Gateway ids that infer no known provider keep the prior command-code provider unchanged.

🤖 Generated with Claude Code


Summary by cubic

Fixes three issues in the Command Code session parser: safe model canonicalization to prevent panics, correct MiniMax pricing via provider inference, and per-turn input accounting to stop inflated usage. Improves stability, pricing accuracy, and consistent usage metrics.

  • Bug Fixes
    • Model id: safely strip -free with char-boundary checks; non-ASCII ids no longer panic.
    • Pricing: infer the real provider from gateway ids (e.g., MiniMaxAI/MiniMax-M3-Free -> provider minimax, model MiniMax-M3), falling back to command-code, so pricing hits minimax/....
    • Input: estimate each assistant turn’s input from only new context (user prompt + tool results) and reset after the response; avoids O(N^2) growth and over-reporting.

Written for commit 2bdbd61. Summary will update on new commits.

Review in cubic

…turn input

Three confirmed bugs in the Command Code session parser (PR #717):

(a) PANIC: canonicalize_model byte-sliced `base[base.len()-N..]` guarded only
    by a length check. A non-ASCII model id from the untrusted
    ~/.commandcode/config.json could place that byte index mid-codepoint and
    panic. Switch to a boundary-safe `str::get(..)` slice that returns None
    (instead of panicking) when the tail is not on a char boundary, preserving
    the case-insensitive `-free` strip.

(b) PRICING: dropping the org prefix turned `MiniMaxAI/MiniMax-M3-Free` into
    bare `MiniMax-M3`, but the client's own `command-code` provider is not a
    pricing provider, so the resolver never reached a `minimax/...` key and
    pricing was lost. Recover the real provider from the gateway id via
    `provider_identity::inferred_provider_from_model` and use it as the
    message provider_id (matching the claudecode convention), falling back to
    `command-code` when nothing is inferred.

(c) O(N^2) INPUT: per-assistant-turn input was estimated from `context_chars`,
    a running cumulative sum of ALL prior messages, inflating input across the
    session versus other clients. Estimate per-turn input from only the new
    context introduced since the previous response (user prompt + tool
    results). Summed over the session this charges each message's content once.

Regression tests added: non-ASCII / emoji model ids do not panic; a MiniMax
model resolves non-zero pricing; per-turn input does not accumulate. Updated
the module doc-comment and renamed the pinning test to match the new model.

Confidence: high
Scope-risk: moderate
Directive: provider_id for MiniMax sessions is now `minimax`, not
`command-code`; this is intentional so pricing resolves. Do not revert without
restoring a pricing path for the gateway provider.
Not-tested: real-world non-MiniMax gateway ids that infer no provider (fall
back to `command-code`, unchanged behavior)
@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
tokscale Ignored Ignored Jun 22, 2026 7:30am

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Re-trigger cubic

@junhoyeo
junhoyeo merged commit db88138 into main Jun 22, 2026
15 checks passed
makoMakoGo added a commit to makoMakoGo/tokscale that referenced this pull request Jun 23, 2026
ported from upstream junhoyeo#735
ported from upstream junhoyeo#737
ported from upstream junhoyeo#747
ported from upstream junhoyeo#750
ported from upstream junhoyeo#752
ported from upstream junhoyeo#760
ported from upstream junhoyeo#766
t1000040 pushed a commit to tmobi-internal/tokscale that referenced this pull request Jun 30, 2026
…turn input (junhoyeo#750)

Three confirmed bugs in the Command Code session parser (PR junhoyeo#717):

(a) PANIC: canonicalize_model byte-sliced `base[base.len()-N..]` guarded only
    by a length check. A non-ASCII model id from the untrusted
    ~/.commandcode/config.json could place that byte index mid-codepoint and
    panic. Switch to a boundary-safe `str::get(..)` slice that returns None
    (instead of panicking) when the tail is not on a char boundary, preserving
    the case-insensitive `-free` strip.

(b) PRICING: dropping the org prefix turned `MiniMaxAI/MiniMax-M3-Free` into
    bare `MiniMax-M3`, but the client's own `command-code` provider is not a
    pricing provider, so the resolver never reached a `minimax/...` key and
    pricing was lost. Recover the real provider from the gateway id via
    `provider_identity::inferred_provider_from_model` and use it as the
    message provider_id (matching the claudecode convention), falling back to
    `command-code` when nothing is inferred.

(c) O(N^2) INPUT: per-assistant-turn input was estimated from `context_chars`,
    a running cumulative sum of ALL prior messages, inflating input across the
    session versus other clients. Estimate per-turn input from only the new
    context introduced since the previous response (user prompt + tool
    results). Summed over the session this charges each message's content once.

Regression tests added: non-ASCII / emoji model ids do not panic; a MiniMax
model resolves non-zero pricing; per-turn input does not accumulate. Updated
the module doc-comment and renamed the pinning test to match the new model.

Confidence: high
Scope-risk: moderate
Directive: provider_id for MiniMax sessions is now `minimax`, not
`command-code`; this is intentional so pricing resolves. Do not revert without
restoring a pricing path for the gateway provider.
Not-tested: real-world non-MiniMax gateway ids that infer no provider (fall
back to `command-code`, unchanged behavior)
@junhoyeo
junhoyeo deleted the fix/commandcode-717 branch July 13, 2026 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant