Skip to content

Free mode: wrong context window/max-output everywhere (catalog hardcode, footer fallback, compact heuristic) — real registry values never consulted #393

Description

@7jrxt42BxFZo4iAnN4CX

Environment

  • Claurst master @ 595b0eb (built as 0.1.7.r85.g595b0eb); the same code paths exist in v0.1.7
  • OS: Arch Linux, kitty/tmux
  • Provider/model: Free Mode, pinned opencode-zen/x-preview-f-free
    (real limits per models.dev opencode/x-preview-f-free: context 1,000,000 / output 131,072)

Summary

In Free mode the effective context window ends up wrong in three independent
places, because none of them consult ModelRegistry/models.dev for the actual
(upstream, model) pair, and models.dev has no opencode-zen entry at all:

Consumer Source of the window Value seen
Footer / token warnings — App::refresh_context_window_size() (crates/tui/src/app.rs:1921) registry miss → hardcoded fallback table 128_000
Auto-compact sizing — compact::resolve_context_window() (crates/query/src/compact.rs:851) registry miss → Claude-only name heuristic 100_000
/model picker — Free provider catalog() (crates/api/src/providers/free.rs:374,389) constants for every upstream model 128_000 / max_output 8_192

So for a 1M-context model the footer claims 128k, auto-compact was sized from a
~100k heuristic, and the picker lists every free upstream model as 128k/8k —
including e.g. google/gemini-2.5-flash (real: 1M) or the Zen default
minimax-m2.5-free (real: 204,800).

Root cause

  1. free.rs catalog() passes literal 128_000 / 8_192 for all chained
    upstream models instead of resolving them per (upstream_id, model) from the
    registry.
  2. refresh_context_window_size() only strips the active provider prefix and
    then does registry.get("free", "<model-id>"). It does not try the embedded
    "provider/model" split the way resolve_context_window() does
    (compact.rs:867-873), so the two consumers derive different registry keys
    for the same model.
  3. models.dev has no opencode-zen provider entry; Zen gateway models are
    listed under provider id opencode. Registry lookups keyed by
    opencode-zen/<model> therefore always miss.

Steps to reproduce

  1. /connect → Free Mode, add a Zen-capable key, pin opencode-zen/x-preview-f-free
  2. Footer shows Nk/128000; before any override, compaction sizing came from the
    100k heuristic
  3. /model lists the entry as 128k / 8k output
  4. Cross-check models.dev: opencode/x-preview-f-free = 1,000,000 / 131,072

Workaround (verified working)

Duplicate the metadata override under both key schemas in settings.json
(the registry synthesizes entries for unknown keys):

{
  "modelOverrides": {
    "opencode-zen/x-preview-f-free": { "contextWindow": 1000000, "maxOutputTokens": 131072 },
    "free/opencode-zen/x-preview-f-free": { "contextWindow": 1000000, "maxOutputTokens": 131072 }
  }
}

##Suggested fix

  • In the Free catalog, resolve context_window / max_output_tokens per
    (upstream_id, default_model) from ModelRegistry, keeping the current
    constants only as last-resort defaults (reuse the existing
    MIN_PLAUSIBLE_REGISTRY_WINDOW plausibility guard).
  • Make App::refresh_context_window_size() delegate to
    compact::resolve_context_window() so both consumers share one key-derivation
    path instead of maintaining parallel lookup logic.
  • (Upstream data) file against models.dev: missing opencode-zen entry.

Happy to test a patch.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions