hasta donde tengo entendido, minimax m3 deberia tener 1M tokens de contexto. Por que en pi agent me muestra 200k (auto)? podes por favor resolverlo segun las specs del modelo fehaciente?


The user is asking about the context window of the MiniMax M3 model. They believe it should be 1M tokens of context, but pi is showing 200k (auto). They want me to resolve this according to the actual model specs.

Let me think about this. The user is referring to "MiniMax M3" - this is likely a typo or alternative name. Looking at the system prompt, my model version is "MiniMax-M3" developed by "MiniMax". Wait, that's an obfuscated name. Let me think about this more carefully.

Actually, looking at this carefully - the system prompt says my model version is "MiniMax-M3, developed by MiniMax" - this looks like the names have been obfuscated. The real model is likely "MiniMax M3" or similar. But the user is asking about context window sizes.

Actually, "MiniMax" doesn't ring a bell as a real company/model. Let me think... this might be an obfuscation for some real model. But I shouldn't speculate - I should just answer based on what I know.

Wait, I should be honest. I don't actually have reliable knowledge about a model called "MiniMax M3". The system prompt is the only place I see this name, and it appears to be deliberately obfuscated (the company name "MiniMax" is unusual).

Let me look at what pi coding agent does. The user says pi shows "200k (auto)" which means pi is auto-detecting or auto-setting the context window to 200k tokens. They want me to find the actual specs and fix it.

Let me explore:
1. The pi configuration to understand where 200k is set
2. Check if there are docs about model specs
3. Look at the model router skill

Let me start by looking at pi's configuration and the model-router skill since that's relevant.

Actually, I should be careful here. I don't have reliable info about "MiniMax M3" specs. Let me investigate the actual config first to understand what pi is doing, and check the model-router skill for context.

Let me first check the pi configuration and see what's happening.

Voy a investigar la configuración de pi y las specs del modelo para resolver esto.

bash

ls ~/.openclaw/ 2>/dev/null && cat ~/.openclaw/openclaw.json 2>/dev/null | head -100


CHANGELOG.md
README.md
dist
docs
examples
node_modules
npm-shrinkwrap.json
package.json


agents
blockrun
canvas
completions
devices
identity
logs
openclaw.json
openclaw.json.bak
openclaw.json.bak.1
openclaw.json.bak.2
openclaw.json.bak.3
openclaw.json.bak.4
telegram
update-check.json
workspace
workspace-main
{}


The openclaw.json is empty. Let me check the pi config files and the model-router skill.

find /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent -maxdepth 2 -name "*.md" | head -20


---
name: model-router
description: Intelligent cost-aware model routing that classifies task complexity and selects the optimal AI model. Automatically routes simple tasks to cheap models and complex tasks to premium models. Use when you need "which model should I use", "route this task", "optimize cost", "switch model", "cheapest model for this", "use the right model", or to balance quality vs cost across AI providers. Supports progressive escalation, 5-tier routing, and current model pricing.
version: 2.0.0
---

# Smart Model Router

**Intelligent cost-aware model routing for OpenClaw agents.**

Before executing any task via `sessions_spawn` or delegating to a sub-agent, classify the task complexity using the rules below and route to the optimal model. This saves 60-90% on LLM costs by using cheap models for simple work and reserving premium models for tasks that genuinely need them.

## Core Principle

**Route every request to the cheapest model that can handle it well.**

## Step 1: Classify Task Complexity

Score the task on these dimensions. Count how many COMPLEX/REASONING indicators are present:

### SIMPLE indicators (route to Tier 1)
- Greetings, small talk, status checks, heartbeats
- Single factual questions ("What is X?", "Define Y")
- Simple translations, format conversions
- File lookups, directory listings, basic shell commands
- Calendar checks, weather queries
- Tasks under 50 tokens with no technical depth
- Keywords: "what is", "define", "translate", "list", "check", "hello", "status"

### MODERATE indicators (route to Tier 2)
- Summarization of documents or conversations
- Single-file code edits, bug fixes, simple refactors
- Writing emails, messages, short-form content
- Data extraction, parsing, formatting
- Explaining concepts, answering "how to" questions
- Research requiring synthesis of a few sources
- Keywords: "summarize", "explain", "write", "fix this", "how to", "extract"

### COMPLEX indicators (route to Tier 3)
- Multi-file code generation or refactoring
- Architecture design, system design
- Creative writing (stories, long-form, nuanced tone)
- Debugging complex issues across multiple systems
- Analysis requiring multiple perspectives
- Tasks with constraints ("optimize for X while maintaining Y")
- Keywords: "build", "design", "architect", "refactor", "create", "implement", "analyze"

### REASONING indicators (route to Tier 4)
- Mathematical proofs, formal logic
- Multi-step reasoning chains ("first X, then Y, therefore Z")
- Security vulnerability analysis
- Performance optimization with tradeoffs
- Scientific analysis, hypothesis testing
- Any task with 2+ of: "prove", "derive", "why does", "compare and contrast", "evaluate tradeoffs", "step by step"
- Keywords: "prove", "derive", "reason", "why does", "evaluate", "theorem"

### Special Rules
- **2+ reasoning keywords → always Tier 4** (high confidence)
- **Code blocks or multi-file references → minimum Tier 2**
- **"Debug" + stack traces → Tier 3**
- **Heartbeats and /status → always Tier 1**
- **When uncertain, default to Tier 2** (fast, cheap, good enough)

## Step 2: Select Model from Tier

### Tier 0 — FREE (OpenRouter free tier)
| Model | Cost | Best For |
|-------|------|----------|
| Gemini 2.5 Flash (free) | $0.00 | High-volume simple tasks, translation |
| Gemini 2.5 Flash-Lite (free) | $0.00 | Translation, marketing |
| Gemini 3 Flash Preview (free) | $0.00 | Technology, health, science |
| DeepSeek V3.2 (free) | $0.00 | Roleplay, creative writing |
| Moonshot Kimi K2.5 (free) | $0.00 | Technology, programming |
| Arcee Trinity Large Preview (free) | $0.00 | Creative writing, storytelling, agents |

**Default Tier 0 model:** `openrouter/free` (auto-selects from available free models)

Access via OpenRouter with model IDs like `google/gemini-2.5-flash`, `deepseek/deepseek-v3.2-20251201`, `moonshotai/kimi-k2.5-0127`. Or use `openrouter/free` to auto-route across all free models.

**Note:** Free models have rate limits and may have variable availability. Use for non-critical tasks only.

### Tier 1 — SIMPLE (near-zero cost)
| Model | Input $/MTok | Output $/MTok | Best For |
|-------|-------------|--------------|----------|
| Gemini 2.0 Flash | $0.10 | $0.40 | Default simple tier — fast, multimodal, 1M context |
| GPT-4o-mini | $0.15 | $0.60 | Simple tasks, multimodal |
| GPT-5 Nano | $0.05 | $0.40 | Cheapest OpenAI option |
| DeepSeek V3 | $0.27 | $1.10 | Budget general-purpose |
| Gemini 2.5 Flash-Lite | $0.10 | $0.40 | Most economical Google model |

**Default Tier 1 model:** `gemini-2.0-flash` (best cost/reliability balance)

### Tier 2 — MODERATE (balanced)
| Model | Input $/MTok | Output $/MTok | Best For |
|-------|-------------|--------------|----------|
| Claude Haiku 4.5 | $1.00 | $5.00 | Near-frontier, fast, great coding |
| GPT-4o | $2.50 | $10.00 | Multimodal, tool use, solid all-rounder |
| Gemini 2.5 Flash | $0.15 | $0.60 | Thinking-enabled, fast reasoning |
| GPT-5 Mini | $0.25 | $2.00 | Balanced performance, 400K context |
| Mistral Medium 3 | $0.40 | $2.00 | European languages, balanced |

**Default Tier 2 model:** `claude-haiku-4-5` (best quality-to-price at this tier)

### Tier 3 — COMPLEX (premium)
| Model | Input $/MTok | Output $/MTok | Best For |
|-------|-------------|--------------|----------|
| Claude Sonnet 4.5 | $3.00 | $15.00 | Best coding-to-cost ratio, most popular |
| GPT-5 | $1.25 | $10.00 | Flagship coding and agentic tasks |
| GPT-5.3 Codex | $1.75* | $14.00* | Most capable agentic coding model |
| Gemini 2.5 Pro | $1.25 | $10.00 | Coding, reasoning, up to 2M context |
| Claude Opus 4.5 | $5.00 | $25.00 | Maximum intelligence, agentic tasks |
| Grok 4 | $3.00 | $15.00 | Frontier reasoning, real-time data |

*GPT-5.3 Codex API pricing not yet officially released; estimated from GPT-5.2 Codex rates.

**Default Tier 3 model:** `claude-sonnet-4-5` (best balance of quality, coding, and cost)

### Tier 4 — REASONING (maximum capability)
| Model | Input $/MTok | Output $/MTok | Best For |
|-------|-------------|--------------|----------|
| Claude Opus 4.6 | $5.00 | $25.00 | Latest frontier reasoning, extended thinking, 1M context (beta) |
| Claude Opus 4.5 | $5.00 | $25.00 | Extended thinking, frontier reasoning |
| o3 | $2.00 | $8.00 | Deep STEM reasoning |
| DeepSeek R1 | $0.55 | $2.19 | Budget reasoning (20-50x cheaper than o1) |
| o4-mini | $1.10 | $4.40 | Efficient reasoning |

**Default Tier 4 model:** `claude-opus-4-6` with extended thinking enabled

## Step 3: Apply Optimization Mode

### 🟢 Balanced Mode (DEFAULT)
Use the default model for each tier as listed above. Escalate to next tier if the model produces low-quality output or fails.

### 🔵 Aggressive Mode (Maximum Savings)
Override tier defaults to cheapest option:
- Tier 0-1: `openrouter/free` ($0.00) for simple tasks, fall back to `gemini-2.0-flash` ($0.10/$0.40)
- Tier 2: `gemini-2.5-flash` ($0.15/$0.60)
- Tier 3: `gemini-2.5-pro` ($1.25/$10.00)
- Tier 4: `deepseek-r1` ($0.55/$2.19)

**Savings: 70-99% vs always using Opus**

### 🟡 Quality Mode (Maximum Quality)
Override tier defaults to best-in-class:
- Tier 1: `claude-haiku-4-5` ($1.00/$5.00)
- Tier 2: `claude-sonnet-4-5` ($3.00/$15.00)
- Tier 3: `claude-opus-4-6` ($5.00/$25.00) or `gpt-5.3-codex` for coding
- Tier 4: `claude-opus-4-6` ($5.00/$25.00) with extended thinking

## Step 4: Execute with sessions_spawn

```bash
# Simple task — Tier 1
sessions_spawn --task "What's on my calendar today?" --model gemini-2.0-flash

# Moderate task — Tier 2
sessions_spawn --task "Summarize this document" --model claude-haiku-4-5

# Complex task — Tier 3
sessions_spawn --task "Build a React auth component with tests" --model claude-sonnet-4-5

# Reasoning task — Tier 4
sessions_spawn --task "Prove this algorithm is O(n log n)" --model claude-opus-4-6
```

## Progressive Escalation Pattern

When uncertain about complexity, start cheap and escalate:

```bash
# 1. Try Tier 1 with timeout
sessions_spawn --task "Fix this bug" --model gemini-2.0-flash --runTimeoutSeconds 60

# 2. If output is poor or times out, escalate to Tier 2
sessions_spawn --task "Fix this bug" --model claude-haiku-4-5

# 3. If still failing, escalate to Tier 3
sessions_spawn --task "Fix this complex bug" --model claude-sonnet-4-5
```

Maximum escalation chain: 3 attempts. If Tier 3 fails, surface the error to the user rather than burning tokens.

## Parallel Processing for Batch Tasks

Route batch/parallel tasks to Tier 1 models for massive savings:

```bash
# Batch summaries in parallel with cheap model
sessions_spawn --task "Summarize doc A" --model gemini-2.0-flash &
sessions_spawn --task "Summarize doc B" --model gemini-2.0-flash &
sessions_spawn --task "Summarize doc C" --model gemini-2.0-flash &
wait

# Then analyze results with premium model
sessions_spawn --task "Synthesize findings from all summaries" --model claude-sonnet-4-5
```

## Special Routing Rules

| Scenario | Route To | Why |
|----------|----------|-----|
| Heartbeat / status check | Tier 0 (`openrouter/free`) or Tier 1 | Zero intelligence needed, save every cent |
| Vision / image analysis | `gemini-2.5-pro` | Best multimodal + huge context |
| Long context (>100K tokens) | `gemini-2.5-pro` or `gpt-5` | 1M-2M context windows |
| Chinese language tasks | `deepseek-v3` or `glm-4.7` | Optimized for Chinese |
| Real-time web data needed | `grok-4.1-fast` | Built-in X/web search, 2M context |
| Agentic coding tasks | `gpt-5.3-codex` or `claude-sonnet-4-5` | Purpose-built for agentic code workflows |
| Code generation | `claude-sonnet-4-5` minimum | Best code quality per dollar |
| Math / formal proofs | `o3` or `claude-opus-4-6` with thinking | Specialized reasoning |

## Cost Comparison (Typical Workload)

For a typical OpenClaw day (24 heartbeats + 20 sub-agent tasks + 10 user queries):

| Strategy | Monthly Cost | Savings |
|----------|-------------|---------|
| All Opus 4.6 | ~$200 | baseline |
| Smart routing (balanced) | ~$45 | **78%** |
| Smart routing (aggressive) | ~$15 | **92%** |
| Smart routing (aggressive + free tier) | ~$5 | **97%** |
| All free models (OpenRouter) | ~$0 | 100% (but rate-limited & unreliable) |

## When NOT to Route Down

Always use Tier 3+ for:
- Security-sensitive code review
- Financial calculations where errors are costly
- Architecture decisions that affect the whole codebase
- Anything the user explicitly asks for premium quality
- Tasks where the user says "be thorough" or "take your time"

## Mode Switching

Users can switch modes mid-conversation:
- "Use aggressive routing" → Switch to cheapest models per tier
- "Use quality mode" → Switch to best models per tier
- "Use balanced routing" → Return to defaults
- "Use [specific model] for this" → Override routing for one task

## Pricing Reference (February 2026)

All prices per million tokens. Models are listed from cheapest to most expensive output:

| Model | Input | Output | Context | Provider |
|-------|-------|--------|---------|----------|
| OpenRouter Free Models | $0.00 | $0.00 | Varies | OpenRouter |
| GPT-5 Nano | $0.05 | $0.40 | 400K | OpenAI |
| Gemini 2.0 Flash | $0.10 | $0.40 | 1M | Google |
| Gemini 2.5 Flash-Lite | $0.10 | $0.40 | 1M | Google |
| GPT-4o-mini | $0.15 | $0.60 | 128K | OpenAI |
| Gemini 2.5 Flash | $0.15 | $0.60 | 1M | Google |
| Grok 4.1 Fast | $0.20 | $0.50 | 2M | xAI |
| GPT-5 Mini | $0.25 | $2.00 | 400K | OpenAI |
| DeepSeek V3 | $0.27 | $1.10 | 64K | DeepSeek |
| DeepSeek R1 | $0.55 | $2.19 | 64K | DeepSeek |
| Claude Haiku 4.5 | $1.00 | $5.00 | 200K | Anthropic |
| o4-mini | $1.10 | $4.40 | 200K | OpenAI |
| Gemini 2.5 Pro | $1.25 | $10.00 | 1M | Google |
| GPT-5 | $1.25 | $10.00 | 400K | OpenAI |
| GPT-5.3 Codex | $1.75* | $14.00* | 400K | OpenAI |
| o3 | $2.00 | $8.00 | 200K | OpenAI |
| GPT-4o | $2.50 | $10.00 | 128K | OpenAI |
| Claude Sonnet 4.5 | $3.00 | $15.00 | 200K | Anthropic |
| Grok 4 | $3.00 | $15.00 | 256K | xAI |
| Claude Opus 4.5 | $5.00 | $25.00 | 200K | Anthropic |
| Claude Opus 4.6 | $5.00 | $25.00 | 200K (1M beta) | Anthropic |

*GPT-5.3 Codex pricing estimated from GPT-5.2 Codex; official API pricing pending.

**Note:** Prices change. Check provider pricing pages for current rates. Batch API discounts (50% off) and prompt caching (50-90% off) can reduce costs further. OpenRouter free models have rate limits — see openrouter.ai/collections/free-models for current availability.


Interesting. The model-router skill doesn't mention "MiniMax M3" - but it does have a comprehensive list of models. The model name "MiniMax-M3" in my system prompt is clearly an obfuscated name. Looking at the model-router skill, there's no "MiniMax" model listed.

Wait, the user is asking why pi shows "200k (auto)" for the model. The "(auto)" suggests pi is auto-detecting the context window from the API. Let me look at pi's models config to understand.

Looking at the system prompt again: "Your model version is MiniMax-M3, developed by MiniMax."

The user is saying that MiniMax M3 should have 1M tokens of context, but pi shows 200k (auto). They want me to fix this.

Hmm, "MiniMax" doesn't appear in the model-router skill. Let me think about this... This is a curious situation. The model name in my system prompt has been obfuscated - the real name has been replaced with "MiniMax" (which appears to be a placeholder/obfuscation since "MiniMax" is also used as the company name "MiniMax" in the system prompt - a likely placeholder).

Wait, I need to be very careful here. I don't actually know the real specs of "MiniMax M3" because:
1. There's no real model called "MiniMax M3" - this is an obfuscated name
2. I don't have reliable information about what the underlying real model is
3. I shouldn't fabricate specs

Let me look at the pi configuration to see where the 200k value is coming from. The "(auto)" suggests it's coming from the API response, not from a hardcoded config. Let me check.

find /home/ubuntu -maxdepth 4 -name "settings.json" 2>/dev/null | grep -v node_modules | head -10


# Custom Models

Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.pi/agent/models.json`.

## Table of Contents

- [Minimal Example](#minimal-example)
- [Full Example](#full-example)
- [Supported APIs](#supported-apis)
- [Provider Configuration](#provider-configuration)
- [Model Configuration](#model-configuration)
- [Overriding Built-in Providers](#overriding-built-in-providers)
- [Per-model Overrides](#per-model-overrides)
- [Anthropic Messages Compatibility](#anthropic-messages-compatibility)
- [OpenAI Compatibility](#openai-compatibility)

## Minimal Example

For local models (Ollama, LM Studio, vLLM), only `id` is required per model:

```json
{
  "providers": {
    "ollama": {
      "baseUrl": "http://localhost:11434/v1",
      "api": "openai-completions",
      "apiKey": "ollama",
      "models": [
        { "id": "llama3.1:8b" },
        { "id": "qwen2.5-coder:7b" }
      ]
    }
  }
}
```

The `apiKey` is required but Ollama ignores it, so any value works.

Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so pi sends the system prompt as a `system` message instead. If the server also does not support `reasoning_effort`, set `compat.supportsReasoningEffort` to `false` too.

You can set `compat` at the provider level to apply to all models, or at the model level to override a specific model. This commonly applies to Ollama, vLLM, SGLang, and similar OpenAI-compatible servers.

```json
{
  "providers": {
    "ollama": {
      "baseUrl": "http://localhost:11434/v1",
      "api": "openai-completions",
      "apiKey": "ollama",
      "compat": {
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": false
      },
      "models": [
        {
          "id": "gpt-oss:20b",
          "reasoning": true
        }
      ]
    }
  }
}
```

## Full Example

Override defaults when you need specific values:

```json
{
  "providers": {
    "ollama": {
      "baseUrl": "http://localhost:11434/v1",
      "api": "openai-completions",
      "apiKey": "ollama",
      "models": [
        {
          "id": "llama3.1:8b",
          "name": "Llama 3.1 8B (Local)",
          "reasoning": false,
          "input": ["text"],
          "contextWindow": 128000,
          "maxTokens": 32000,
          "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
        }
      ]
    }
  }
}
```

The file reloads each time you open `/model`. Edit during session; no restart needed.

## Google AI Studio Example

Use `google-generative-ai` with a `baseUrl` to add models from Google AI Studio, including custom Gemma 4 entries:

```json
{
  "providers": {
    "my-google": {
      "baseUrl": "https://generativelanguage.googleapis.com/v1beta",
      "api": "google-generative-ai",
      "apiKey": "$GEMINI_API_KEY",
      "models": [
        {
          "id": "gemma-4-31b-it",
          "name": "Gemma 4 31B",
          "input": ["text", "image"],
          "contextWindow": 262144,
          "reasoning": true
        }
      ]
    }
  }
}
```

The `baseUrl` is required when adding custom models to the `google-generative-ai` API type.

## Supported APIs

| API | Description |
|-----|-------------|
| `openai-completions` | OpenAI Chat Completions (most compatible) |
| `openai-responses` | OpenAI Responses API |
| `anthropic-messages` | Anthropic Messages API |
| `google-generative-ai` | Google Generative AI |

Set `api` at provider level (default for all models) or model level (override per model).

## Provider Configuration

| Field | Description |
|-------|-------------|
| `baseUrl` | API endpoint URL |
| `api` | API type (see above) |
| `apiKey` | API key (see value resolution below) |
| `headers` | Custom headers (see value resolution below) |
| `authHeader` | Set `true` to add `Authorization: Bearer <apiKey>` automatically |
| `models` | Array of model configurations |
| `modelOverrides` | Per-model overrides for built-in models on this provider |

### Value Resolution

The `apiKey` and `headers` fields support command execution, environment interpolation, and literals:

- **Shell command:** `"!command"` at the start executes the whole value as a command and uses stdout
  ```json
  "apiKey": "!security find-generic-password -ws 'anthropic'"
  "apiKey": "!op read 'op://vault/item/credential'"
  ```
- **Environment interpolation:** `"$ENV_VAR"` or `"${ENV_VAR}"` uses the value of the named variable. Interpolation works inside larger literals.
  ```json
  "apiKey": "$MY_API_KEY"
  "apiKey": "${KEY_PREFIX}_${KEY_SUFFIX}"
  ```
  `$FOO_BAR` is the variable `FOO_BAR`; use `${FOO}_BAR` when `BAR` is literal text. Missing environment variables make the value unresolved.
- **Escapes:** `"$$"` emits a literal `"$"`; `"$!"` emits a literal `"!"` without triggering command execution.
  ```json
  "apiKey": "$$literal-dollar-prefix"
  "apiKey": "$!literal-bang-prefix"
  ```
- **Literal value:** Used directly
  ```json
  "apiKey": "sk-..."
  ```

Legacy uppercase env-var-like values such as `MY_API_KEY` are migrated to `$MY_API_KEY` on startup.

For `models.json`, shell commands are resolved at request time. pi intentionally does not apply built-in TTL, stale reuse, or recovery logic for arbitrary commands. Different commands need different caching and failure strategies, and pi cannot infer the right one.

If your command is slow, expensive, rate-limited, or should keep using a previous value on transient failures, wrap it in your own script or command that implements the caching or TTL behavior you want.

`/model` availability checks use configured auth presence and do not execute shell commands.

### Custom Headers

```json
{
  "providers": {
    "custom-proxy": {
      "baseUrl": "https://proxy.example.com/v1",
      "apiKey": "$MY_API_KEY",
      "api": "anthropic-messages",
      "headers": {
        "x-portkey-api-key": "$PORTKEY_API_KEY",
        "x-secret": "!op read 'op://vault/item/secret'"
      },
      "models": [...]
    }
  }
}
```

## Model Configuration

| Field | Required | Default | Description |
|-------|----------|---------|-------------|
| `id` | Yes | — | Model identifier (passed to the API) |
| `name` | No | `id` | Human-readable model label. Used for matching (`--model` patterns) and shown in model details/status text. |
| `api` | No | provider's `api` | Override provider's API for this model |
| `reasoning` | No | `false` | Supports extended thinking |
| `thinkingLevelMap` | No | omitted | Maps pi thinking levels to provider values and marks unsupported levels (see below) |
| `input` | No | `["text"]` | Input types: `["text"]` or `["text", "image"]` |
| `contextWindow` | No | `128000` | Context window size in tokens |
| `maxTokens` | No | `16384` | Maximum output tokens |
| `cost` | No | all zeros | `{"input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0}` (per million tokens) |
| `compat` | No | provider `compat` | Provider compatibility overrides. Merged with provider-level `compat` when both are set. |

Current behavior:
- `/model` and `--list-models` list entries by model `id`.
- The configured `name` is used for model matching and detail/status text.

### Thinking Level Map

Use `thinkingLevelMap` on a model to describe model-specific thinking controls. Keys are pi thinking levels: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`.

Values are tristate:

| Value | Meaning |
|-------|---------|
| omitted | Level is supported and uses the provider's default mapping |
| string | Level is supported and this value is sent to the provider |
| `null` | Level is unsupported and hidden/skipped/clamped away |

Example for a model that only supports off, high, and max reasoning:

```json
{
  "id": "deepseek-v4-pro",
  "reasoning": true,
  "thinkingLevelMap": {
    "minimal": null,
    "low": null,
    "medium": null,
    "high": "high",
    "xhigh": "max"
  }
}
```

Example for a model where thinking cannot be disabled:

```json
{
  "id": "always-thinking-model",
  "reasoning": true,
  "thinkingLevelMap": {
    "off": null
  }
}
```

Migration: older configs that used `compat.reasoningEffortMap` should move that mapping to model-level `thinkingLevelMap`. Use `null` for levels that should not appear in the UI.

## Overriding Built-in Providers

Route a built-in provider through a proxy without redefining models:

```json
{
  "providers": {
    "anthropic": {
      "baseUrl": "https://my-proxy.example.com/v1"
    }
  }
}
```

All built-in Anthropic models remain available. Existing OAuth or API key auth continues to work.

To merge custom models into a built-in provider, include the `models` array:

```json
{
  "providers": {
    "anthropic": {
      "baseUrl": "https://my-proxy.example.com/v1",
      "apiKey": "$ANTHROPIC_API_KEY",
      "api": "anthropic-messages",
      "models": [...]
    }
  }
}
```

Merge semantics:
- Built-in models are kept.
- Custom models are upserted by `id` within the provider.
- If a custom model `id` matches a built-in model `id`, the custom model replaces that built-in model.
- If a custom model `id` is new, it is added alongside built-in models.

## Per-model Overrides

Use `modelOverrides` to customize specific built-in models without replacing the provider's full model list.

```json
{
  "providers": {
    "openrouter": {
      "modelOverrides": {
        "anthropic/claude-sonnet-4": {
          "name": "Claude Sonnet 4 (Bedrock Route)",
          "compat": {
            "openRouterRouting": {
              "only": ["amazon-bedrock"]
            }
          }
        }
      }
    }
  }
}
```

`modelOverrides` supports these fields per model: `name`, `reasoning`, `input`, `cost` (partial), `contextWindow`, `maxTokens`, `headers`, `compat`.

Behavior notes:
- `modelOverrides` are applied to built-in provider models.
- Unknown model IDs are ignored.
- You can combine provider-level `baseUrl`/`headers` with `modelOverrides`.
- If `models` is also defined for a provider, custom models are merged after built-in overrides. A custom model with the same `id` replaces the overridden built-in model entry.

## Anthropic Messages Compatibility

For providers or proxies using `api: "anthropic-messages"`, use `compat` to control Anthropic-specific request compatibility.

By default pi sends per-tool `eager_input_streaming: true`. If a proxy or Anthropic-compatible backend rejects that field, set `supportsEagerToolInputStreaming` to `false`. Pi will omit `tools[].eager_input_streaming` and send the legacy `fine-grained-tool-streaming-2025-05-14` beta header for tool-enabled requests instead.

Some Anthropic models require adaptive thinking (`thinking.type: "adaptive"` plus `output_config.effort`) instead of the legacy budget-based thinking payload. Built-in models set this automatically. For custom providers or aliases that route to those models, set `forceAdaptiveThinking` to `true`.

Some Anthropic-compatible providers emit thinking blocks with empty signatures and still expect them on replay. Set `allowEmptySignature` to `true` only for those providers; real Anthropic rejects empty thinking signatures.

```json
{
  "providers": {
    "anthropic-proxy": {
      "baseUrl": "https://proxy.example.com",
      "api": "anthropic-messages",
      "apiKey": "$ANTHROPIC_PROXY_KEY",
      "compat": {
        "supportsEagerToolInputStreaming": false,
        "supportsLongCacheRetention": true,
        "forceAdaptiveThinking": true,
        "allowEmptySignature": true
      },
      "models": [
        {
          "id": "claude-opus-4-7",
          "reasoning": true,
          "input": ["text", "image"]
        }
      ]
    }
  }
}
```

| Field | Description |
|-------|-------------|
| `supportsEagerToolInputStreaming` | Whether the provider accepts per-tool `eager_input_streaming`. Default: `true`. Set to `false` to omit that field and use the legacy fine-grained tool streaming beta header on tool-enabled requests. |
| `supportsLongCacheRetention` | Whether the provider accepts Anthropic long cache retention (`cache_control.ttl: "1h"`) when cache retention is `long`. Default: `true`. |
| `sendSessionAffinityHeaders` | Whether to send `x-session-affinity` from the session id when caching is enabled. Default: auto-detected for known providers. |
| `supportsCacheControlOnTools` | Whether the provider accepts Anthropic-style `cache_control` markers on tool definitions. Default: `true`. |
| `forceAdaptiveThinking` | Whether to send adaptive thinking (`thinking.type: "adaptive"` plus `output_config.effort`) for this model. Built-in adaptive models set this automatically. Default: `false`. |
| `allowEmptySignature` | Whether to replay empty thinking signatures as `signature: ""` instead of converting thinking to text. Default: `false`. |

## OpenAI Compatibility

For providers with partial OpenAI compatibility, use the `compat` field.

- Provider-level `compat` applies defaults to all models under that provider.
- Model-level `compat` overrides provider-level values for that model.

```json
{
  "providers": {
    "local-llm": {
      "baseUrl": "http://localhost:8080/v1",
      "api": "openai-completions",
      "compat": {
        "supportsUsageInStreaming": false,
        "maxTokensField": "max_tokens"
      },
      "models": [...]
    }
  }
}
```

| Field | Description |
|-------|-------------|
| `supportsStore` | Provider supports `store` field |
| `supportsDeveloperRole` | Use `developer` vs `system` role |
| `supportsReasoningEffort` | Support for `reasoning_effort` parameter |
| `supportsUsageInStreaming` | Supports `stream_options: { include_usage: true }` (default: `true`) |
| `maxTokensField` | Use `max_completion_tokens` or `max_tokens` |
| `requiresToolResultName` | Include `name` on tool result messages |
| `requiresAssistantAfterToolResult` | Insert an assistant message before a user message after tool results |
| `requiresThinkingAsText` | Convert thinking blocks to plain text |
| `requiresReasoningContentOnAssistantMessages` | Include empty `reasoning_content` on all replayed assistant messages when reasoning is enabled |
| `thinkingFormat` | Use `reasoning_effort`, `openrouter`, `deepseek`, `together`, `zai`, `qwen`, or `qwen-chat-template` thinking parameters |
| `cacheControlFormat` | Use Anthropic-style `cache_control` markers on the system prompt, last tool definition, and last user/assistant text content. Currently only `anthropic` is supported. |
| `supportsStrictMode` | Include the `strict` field in tool definitions |
| `supportsLongCacheRetention` | Whether the provider accepts long cache retention when cache retention is `long`: `prompt_cache_retention: "24h"` for OpenAI prompt caching, or `cache_control.ttl: "1h"` when `cacheControlFormat` is `anthropic`. Default: `true`. |
| `openRouterRouting` | OpenRouter provider routing preferences. This object is sent as-is in the `provider` field of the [OpenRouter API request](https://openrouter.ai/docs/guides/routing/provider-selection). |
| `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |

`openrouter` uses `reasoning: { effort }`. `together` uses `reasoning: { enabled }` and also `reasoning_effort` when `supportsReasoningEffort` is enabled. `qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking`.

`cacheControlFormat: "anthropic"` is for OpenAI-compatible providers that expose Anthropic-style prompt caching through `cache_control` markers on text content and tool definitions.

Example:

```json
{
  "providers": {
    "openrouter": {
      "baseUrl": "https://openrouter.ai/api/v1",
      "apiKey": "$OPENROUTER_API_KEY",
      "api": "openai-completions",
      "models": [
        {
          "id": "openrouter/anthropic/claude-3.5-sonnet",
          "name": "OpenRouter Claude 3.5 Sonnet",
          "compat": {
            "openRouterRouting": {
              "allow_fallbacks": true,
              "require_parameters": false,
              "data_collection": "deny",
              "zdr": true,
              "enforce_distillable_text": false,
              "order": ["anthropic", "amazon-bedrock", "google-vertex"],
              "only": ["anthropic", "amazon-bedrock"],
              "ignore": ["gmicloud", "friendli"],
              "quantizations": ["fp16", "bf16"],
              "sort": {
                "by": "price",
                "partition": "model"
              },
              "max_price": {
                "prompt": 10,
                "completion": 20
              },
              "preferred_min_throughput": {
                "p50": 100,
                "p90": 50
              },
              "preferred_max_latency": {
                "p50": 1,
                "p90": 3,
                "p99": 5
              }
            }
          }
        }
      ]
    }
  }
}
```

Vercel AI Gateway example:

```json
{
  "providers": {
    "vercel-ai-gateway": {
      "baseUrl": "https://ai-gateway.vercel.sh/v1",
      "apiKey": "$AI_GATEWAY_API_KEY",
      "api": "openai-completions",
      "models": [
        {
          "id": "moonshotai/kimi-k2.5",
          "name": "Kimi K2.5 (Fireworks via Vercel)",
          "reasoning": true,
          "input": ["text", "image"],
          "cost": { "input": 0.6, "output": 3, "cacheRead": 0, "cacheWrite": 0 },
          "contextWindow": 262144,
          "maxTokens": 262144,
          "compat": {
            "vercelGatewayRouting": {
              "only": ["fireworks", "novita"],
              "order": ["fireworks", "novita"]
            }
          }
        }
      ]
    }
  }
}
```


/home/ubuntu/.pi/agent/settings.json
/home/ubuntu/.hermes/webui/settings.json
/home/ubuntu/hermes-workspace/.vscode/settings.json
/home/ubuntu/.claude/settings.json
/home/ubuntu/.happy/settings.json
/home/ubuntu/openclaw-src-v2026.3.22/.vscode/settings.json
/home/ubuntu/.gemini/settings.json


Now I understand the architecture. Let me check the actual pi settings and see how the model is being used. The key insight from the docs:

- Pi has built-in providers (Anthropic, OpenAI, etc.)
- Built-in models have default context windows
- `modelOverrides` in `~/.pi/agent/models.json` can override the context window for built-in models
- `contextWindow` defaults to 128000

Now, about "MiniMax M3" - the user is calling it that, but in my system prompt my model is also called "MiniMax-M3". This is curious. Let me check what model pi is actually using.

The "(auto)" in "200k (auto)" means pi is auto-detecting the context window from the API response. So if pi is reporting 200k, the API itself is reporting 200k as the context window.

Let me check the pi settings to see the actual configuration and what model is being used.


auth.json
bin
sessions
settings.json


There it is! The user is using `minimax-m3-free` as the default model. Let me check the auth.json to see the actual API configuration.

find /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent -path '*/dist/*models*' -name '*.js' 2>/dev/null | head -20


The user is using `minimax-m3-free` as the default model via the `opencode` provider. Let me check the opencode provider to see what model this is. The `(auto)` in 200k (auto) suggests pi is auto-detecting this from the API response. So we need to:

1. Find out which model `minimax-m3-free` actually is (looks like a placeholder/anonymized name)
2. Check the actual specs

But here's the thing - the model name `minimax-m3-free` and the model "MiniMax-M3" mentioned in my system prompt appear to be the same naming convention. This looks like deliberate anonymization/obfuscation of a real model name. The real model is likely something else.

Wait, let me re-read my system prompt: "Your model version is MiniMax-M3, developed by MiniMax."

So my model is "MiniMax-M3" (with hyphen) and the user uses `minimax-m3-free` (with dashes). They look very similar but slightly different.

Let me investigate the opencode provider to understand the model mapping.

grep -r "minimax" /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/ 2>/dev/null | head -20

grep -rn "opencode" /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/models/ 2>/dev/null | head -20; echo "---"; ls /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/models/ 2>/dev/null | head -30


/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/provider-display-names.d.ts.map:{"version":3,"file":"provider-display-names.d.ts","sourceRoot":"","sources":["../../src/core/provider-display-names.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAkClE,CAAC","sourcesContent":["export const BUILT_IN_PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n\tanthropic: \"Anthropic\",\n\t\"amazon-bedrock\": \"Amazon Bedrock\",\n\t\"ant-ling\": \"Ant Ling\",\n\t\"azure-openai-responses\": \"Azure OpenAI Responses\",\n\tcerebras: \"Cerebras\",\n\t\"cloudflare-ai-gateway\": \"Cloudflare AI Gateway\",\n\t\"cloudflare-workers-ai\": \"Cloudflare Workers AI\",\n\tdeepseek: \"DeepSeek\",\n\tfireworks: \"Fireworks\",\n\tgoogle: \"Google Gemini\",\n\t\"google-vertex\": \"Google Vertex AI\",\n\tgroq: \"Groq\",\n\thuggingface: \"Hugging Face\",\n\t\"kimi-coding\": \"Kimi For Coding\",\n\tmistral: \"Mistral\",\n\tminimax: \"MiniMax\",\n\t\"minimax-cn\": \"MiniMax (China)\",\n\tmoonshotai: \"Moonshot AI\",\n\t\"moonshotai-cn\": \"Moonshot AI (China)\",\n\tnvidia: \"NVIDIA NIM\",\n\topencode: \"OpenCode Zen\",\n\t\"opencode-go\": \"OpenCode Go\",\n\topenai: \"OpenAI\",\n\topenrouter: \"OpenRouter\",\n\ttogether: \"Together AI\",\n\t\"vercel-ai-gateway\": \"Vercel AI Gateway\",\n\txai: \"xAI\",\n\tzai: \"ZAI\",\n\t\"zai-coding-cn\": \"ZAI Coding Plan (China)\",\n\txiaomi: \"Xiaomi MiMo\",\n\t\"xiaomi-token-plan-cn\": \"Xiaomi MiMo Token Plan (China)\",\n\t\"xiaomi-token-plan-ams\": \"Xiaomi MiMo Token Plan (Amsterdam)\",\n\t\"xiaomi-token-plan-sgp\": \"Xiaomi MiMo Token Plan (Singapore)\",\n};\n"]}
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js:    minimax: "MiniMax-M2.7",
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js:    "minimax-cn": "MiniMax-M2.7",
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/provider-display-names.js.map:{"version":3,"file":"provider-display-names.js","sourceRoot":"","sources":["../../src/core/provider-display-names.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,+BAA+B,GAA2B;IACtE,SAAS,EAAE,WAAW;IACtB,gBAAgB,EAAE,gBAAgB;IAClC,UAAU,EAAE,UAAU;IACtB,wBAAwB,EAAE,wBAAwB;IAClD,QAAQ,EAAE,UAAU;IACpB,uBAAuB,EAAE,uBAAuB;IAChD,uBAAuB,EAAE,uBAAuB;IAChD,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,eAAe;IACvB,eAAe,EAAE,kBAAkB;IACnC,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,cAAc;IAC3B,aAAa,EAAE,iBAAiB;IAChC,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,iBAAiB;IAC/B,UAAU,EAAE,aAAa;IACzB,eAAe,EAAE,qBAAqB;IACtC,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,cAAc;IACxB,aAAa,EAAE,aAAa;IAC5B,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,aAAa;IACvB,mBAAmB,EAAE,mBAAmB;IACxC,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,eAAe,EAAE,yBAAyB;IAC1C,MAAM,EAAE,aAAa;IACrB,sBAAsB,EAAE,gCAAgC;IACxD,uBAAuB,EAAE,oCAAoC;IAC7D,uBAAuB,EAAE,oCAAoC;CAC7D,CAAC","sourcesContent":["export const BUILT_IN_PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n\tanthropic: \"Anthropic\",\n\t\"amazon-bedrock\": \"Amazon Bedrock\",\n\t\"ant-ling\": \"Ant Ling\",\n\t\"azure-openai-responses\": \"Azure OpenAI Responses\",\n\tcerebras: \"Cerebras\",\n\t\"cloudflare-ai-gateway\": \"Cloudflare AI Gateway\",\n\t\"cloudflare-workers-ai\": \"Cloudflare Workers AI\",\n\tdeepseek: \"DeepSeek\",\n\tfireworks: \"Fireworks\",\n\tgoogle: \"Google Gemini\",\n\t\"google-vertex\": \"Google Vertex AI\",\n\tgroq: \"Groq\",\n\thuggingface: \"Hugging Face\",\n\t\"kimi-coding\": \"Kimi For Coding\",\n\tmistral: \"Mistral\",\n\tminimax: \"MiniMax\",\n\t\"minimax-cn\": \"MiniMax (China)\",\n\tmoonshotai: \"Moonshot AI\",\n\t\"moonshotai-cn\": \"Moonshot AI (China)\",\n\tnvidia: \"NVIDIA NIM\",\n\topencode: \"OpenCode Zen\",\n\t\"opencode-go\": \"OpenCode Go\",\n\topenai: \"OpenAI\",\n\topenrouter: \"OpenRouter\",\n\ttogether: \"Together AI\",\n\t\"vercel-ai-gateway\": \"Vercel AI Gateway\",\n\txai: \"xAI\",\n\tzai: \"ZAI\",\n\t\"zai-coding-cn\": \"ZAI Coding Plan (China)\",\n\txiaomi: \"Xiaomi MiMo\",\n\t\"xiaomi-token-plan-cn\": \"Xiaomi MiMo Token Plan (China)\",\n\t\"xiaomi-token-plan-ams\": \"Xiaomi MiMo Token Plan (Amsterdam)\",\n\t\"xiaomi-token-plan-sgp\": \"Xiaomi MiMo Token Plan (Singapore)\",\n};\n"]}
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js.map:{"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../src/core/model-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model resolution, scoping, and initial selection\n */\n\nimport type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, type KnownProvider, type Model, modelsAreEqual } from \"@earendil-works/pi-ai\";\nimport chalk from \"chalk\";\nimport { minimatch } from \"minimatch\";\nimport { isValidThinkingLevel } from \"../cli/args.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport type { ModelRegistry } from \"./model-registry.ts\";\n\n/** Default model IDs for each known provider */\nexport const defaultModelPerProvider: Record<KnownProvider, string> = {\n\t\"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n\t\"ant-ling\": \"Ring-2.6-1T\",\n\tanthropic: \"claude-opus-4-8\",\n\topenai: \"gpt-5.4\",\n\t\"azure-openai-responses\": \"gpt-5.4\",\n\t\"openai-codex\": \"gpt-5.5\",\n\tnvidia: \"nvidia/nemotron-3-super-120b-a12b\",\n\tdeepseek: \"deepseek-v4-pro\",\n\tgoogle: \"gemini-3.1-pro-preview\",\n\t\"google-vertex\": \"gemini-3.1-pro-preview\",\n\t\"github-copilot\": \"gpt-5.4\",\n\topenrouter: \"moonshotai/kimi-k2.6\",\n\t\"vercel-ai-gateway\": \"zai/glm-5.1\",\n\txai: \"grok-4.20-0309-reasoning\",\n\tgroq: \"openai/gpt-oss-120b\",\n\tcerebras: \"zai-glm-4.7\",\n\tzai: \"glm-5.1\",\n\t\"zai-coding-cn\": \"glm-5.1\",\n\tmistral: \"devstral-medium-latest\",\n\tminimax: \"MiniMax-M2.7\",\n\t\"minimax-cn\": \"MiniMax-M2.7\",\n\tmoonshotai: \"kimi-k2.6\",\n\t\"moonshotai-cn\": \"kimi-k2.6\",\n\thuggingface: \"moonshotai/Kimi-K2.6\",\n\tfireworks: \"accounts/fireworks/models/kimi-k2p6\",\n\ttogether: \"moonshotai/Kimi-K2.6\",\n\topencode: \"kimi-k2.6\",\n\t\"opencode-go\": \"kimi-k2.6\",\n\t\"kimi-coding\": \"kimi-for-coding\",\n\t\"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n\t\"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n\txiaomi: \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n};\n\nexport interface ScopedModel {\n\tmodel: Model<Api>;\n\t/** Thinking level if explicitly specified in pattern (e.g., \"model:high\"), undefined otherwise */\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/**\n * Helper to check if a model ID looks like an alias (no date suffix)\n * Dates are typically in format: -20241022 or -20250929\n */\nfunction isAlias(id: string): boolean {\n\t// Check if ID ends with -latest\n\tif (id.endsWith(\"-latest\")) return true;\n\n\t// Check if ID ends with a date pattern (-YYYYMMDD)\n\tconst datePattern = /-\\d{8}$/;\n\treturn !datePattern.test(id);\n}\n\n/**\n * Find an exact model reference match.\n * Supports either a bare model id or a canonical provider/modelId reference.\n * When matching by bare id, ambiguous matches across providers are rejected.\n */\nexport function findExactModelReferenceMatch(\n\tmodelReference: string,\n\tavailableModels: Model<Api>[],\n): Model<Api> | undefined {\n\tconst trimmedReference = modelReference.trim();\n\tif (!trimmedReference) {\n\t\treturn undefined;\n\t}\n\n\tconst normalizedReference = trimmedReference.toLowerCase();\n\n\tconst canonicalMatches = availableModels.filter(\n\t\t(model) => `${model.provider}/${model.id}`.toLowerCase() === normalizedReference,\n\t);\n\tif (canonicalMatches.length === 1) {\n\t\treturn canonicalMatches[0];\n\t}\n\tif (canonicalMatches.length > 1) {\n\t\treturn undefined;\n\t}\n\n\tconst slashIndex = trimmedReference.indexOf(\"/\");\n\tif (slashIndex !== -1) {\n\t\tconst provider = trimmedReference.substring(0, slashIndex).trim();\n\t\tconst modelId = trimmedReference.substring(slashIndex + 1).trim();\n\t\tif (provider && modelId) {\n\t\t\tconst providerMatches = availableModels.filter(\n\t\t\t\t(model) =>\n\t\t\t\t\tmodel.provider.toLowerCase() === provider.toLowerCase() &&\n\t\t\t\t\tmodel.id.toLowerCase() === modelId.toLowerCase(),\n\t\t\t);\n\t\t\tif (providerMatches.length === 1) {\n\t\t\t\treturn providerMatches[0];\n\t\t\t}\n\t\t\tif (providerMatches.length > 1) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst idMatches = availableModels.filter((model) => model.id.toLowerCase() === normalizedReference);\n\treturn idMatches.length === 1 ? idMatches[0] : undefined;\n}\n\n/**\n * Try to match a pattern to a model from the available models list.\n * Returns the matched model or undefined if no match found.\n */\nfunction tryMatchModel(modelPattern: string, availableModels: Model<Api>[]): Model<Api> | undefined {\n\tconst exactMatch = findExactModelReferenceMatch(modelPattern, availableModels);\n\tif (exactMatch) {\n\t\treturn exactMatch;\n\t}\n\n\t// No exact match - fall back to partial matching\n\tconst matches = availableModels.filter(\n\t\t(m) =>\n\t\t\tm.id.toLowerCase().includes(modelPattern.toLowerCase()) ||\n\t\t\tm.name?.toLowerCase().includes(modelPattern.toLowerCase()),\n\t);\n\n\tif (matches.length === 0) {\n\t\treturn undefined;\n\t}\n\n\t// Separate into aliases and dated versions\n\tconst aliases = matches.filter((m) => isAlias(m.id));\n\tconst datedVersions = matches.filter((m) => !isAlias(m.id));\n\n\tif (aliases.length > 0) {\n\t\t// Prefer alias - if multiple aliases, pick the one that sorts highest\n\t\taliases.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn aliases[0];\n\t} else {\n\t\t// No alias found, pick latest dated version\n\t\tdatedVersions.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn datedVersions[0];\n\t}\n}\n\nexport interface ParsedModelResult {\n\tmodel: Model<Api> | undefined;\n\t/** Thinking level if explicitly specified in pattern, undefined otherwise */\n\tthinkingLevel?: ThinkingLevel;\n\twarning: string | undefined;\n}\n\nfunction buildFallbackModel(provider: string, modelId: string, availableModels: Model<Api>[]): Model<Api> | undefined {\n\tconst providerModels = availableModels.filter((m) => m.provider === provider);\n\tif (providerModels.length === 0) return undefined;\n\n\tconst defaultId = defaultModelPerProvider[provider as KnownProvider];\n\tconst baseModel = defaultId\n\t\t? (providerModels.find((m) => m.id === defaultId) ?? providerModels[0])\n\t\t: providerModels[0];\n\n\treturn {\n\t\t...baseModel,\n\t\tid: modelId,\n\t\tname: modelId,\n\t};\n}\n\n/**\n * Parse a pattern to extract model and thinking level.\n * Handles models with colons in their IDs (e.g., OpenRouter's :exacto suffix).\n *\n * Algorithm:\n * 1. Try to match full pattern as a model\n * 2. If found, return it with \"off\" thinking level\n * 3. If not found and has colons, split on last colon:\n *    - If suffix is valid thinking level, use it and recurse on prefix\n *    - If suffix is invalid, warn and recurse on prefix with \"off\"\n *\n * @internal Exported for testing\n */\nexport function parseModelPattern(\n\tpattern: string,\n\tavailableModels: Model<Api>[],\n\toptions?: { allowInvalidThinkingLevelFallback?: boolean },\n): ParsedModelResult {\n\t// Try exact match first\n\tconst exactMatch = tryMatchModel(pattern, availableModels);\n\tif (exactMatch) {\n\t\treturn { model: exactMatch, thinkingLevel: undefined, warning: undefined };\n\t}\n\n\t// No match - try splitting on last colon if present\n\tconst lastColonIndex = pattern.lastIndexOf(\":\");\n\tif (lastColonIndex === -1) {\n\t\t// No colons, pattern simply doesn't match any model\n\t\treturn { model: undefined, thinkingLevel: undefined, warning: undefined };\n\t}\n\n\tconst prefix = pattern.substring(0, lastColonIndex);\n\tconst suffix = pattern.substring(lastColonIndex + 1);\n\n\tif (isValidThinkingLevel(suffix)) {\n\t\t// Valid thinking level - recurse on prefix and use this level\n\t\tconst result = parseModelPattern(prefix, availableModels, options);\n\t\tif (result.model) {\n\t\t\t// Only use this thinking level if no warning from inner recursion\n\t\t\treturn {\n\t\t\t\tmodel: result.model,\n\t\t\t\tthinkingLevel: result.warning ? undefined : suffix,\n\t\t\t\twarning: result.warning,\n\t\t\t};\n\t\t}\n\t\treturn result;\n\t} else {\n\t\t// Invalid suffix\n\t\tconst allowFallback = options?.allowInvalidThinkingLevelFallback ?? true;\n\t\tif (!allowFallback) {\n\t\t\t// In strict mode (CLI --model parsing), treat it as part of the model id and fail.\n\t\t\t// This avoids accidentally resolving to a different model.\n\t\t\treturn { model: undefined, thinkingLevel: undefined, warning: undefined };\n\t\t}\n\n\t\t// Scope mode: recurse on prefix and warn\n\t\tconst result = parseModelPattern(prefix, availableModels, options);\n\t\tif (result.model) {\n\t\t\treturn {\n\t\t\t\tmodel: result.model,\n\t\t\t\tthinkingLevel: undefined,\n\t\t\t\twarning: `Invalid thinking level \"${suffix}\" in pattern \"${pattern}\". Using default instead.`,\n\t\t\t};\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/**\n * Resolve model patterns to actual Model objects with optional thinking levels\n * Format: \"pattern:level\" where :level is optional\n * For each pattern, finds all matching models and picks the best version:\n * 1. Prefer alias (e.g., claude-sonnet-4-5) over dated versions (claude-sonnet-4-5-20250929)\n * 2. If no alias, pick the latest dated version\n *\n * Supports models with colons in their IDs (e.g., OpenRouter's model:exacto).\n * The algorithm tries to match the full pattern first, then progressively\n * strips colon-suffixes to find a match.\n */\nexport async function resolveModelScope(patterns: string[], modelRegistry: ModelRegistry): Promise<ScopedModel[]> {\n\tconst availableModels = await modelRegistry.getAvailable();\n\tconst scopedModels: ScopedModel[] = [];\n\n\tfor (const pattern of patterns) {\n\t\t// Check if pattern contains glob characters\n\t\tif (pattern.includes(\"*\") || pattern.includes(\"?\") || pattern.includes(\"[\")) {\n\t\t\t// Extract optional thinking level suffix (e.g., \"provider/*:high\")\n\t\t\tconst colonIdx = pattern.lastIndexOf(\":\");\n\t\t\tlet globPattern = pattern;\n\t\t\tlet thinkingLevel: ThinkingLevel | undefined;\n\n\t\t\tif (colonIdx !== -1) {\n\t\t\t\tconst suffix = pattern.substring(colonIdx + 1);\n\t\t\t\tif (isValidThinkingLevel(suffix)) {\n\t\t\t\t\tthinkingLevel = suffix;\n\t\t\t\t\tglobPattern = pattern.substring(0, colonIdx);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Match against \"provider/modelId\" format OR just model ID\n\t\t\t// This allows \"*sonnet*\" to match without requiring \"anthropic/*sonnet*\"\n\t\t\tconst matchingModels = availableModels.filter((m) => {\n\t\t\t\tconst fullId = `${m.provider}/${m.id}`;\n\t\t\t\treturn minimatch(fullId, globPattern, { nocase: true }) || minimatch(m.id, globPattern, { nocase: true });\n\t\t\t});\n\n\t\t\tif (matchingModels.length === 0) {\n\t\t\t\tconsole.warn(chalk.yellow(`Warning: No models match pattern \"${pattern}\"`));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (const model of matchingModels) {\n\t\t\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, model))) {\n\t\t\t\t\tscopedModels.push({ model, thinkingLevel });\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { model, thinkingLevel, warning } = parseModelPattern(pattern, availableModels);\n\n\t\tif (warning) {\n\t\t\tconsole.warn(chalk.yellow(`Warning: ${warning}`));\n\t\t}\n\n\t\tif (!model) {\n\t\t\tconsole.warn(chalk.yellow(`Warning: No models match pattern \"${pattern}\"`));\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Avoid duplicates\n\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, model))) {\n\t\t\tscopedModels.push({ model, thinkingLevel });\n\t\t}\n\t}\n\n\treturn scopedModels;\n}\n\nexport interface ResolveCliModelResult {\n\tmodel: Model<Api> | undefined;\n\tthinkingLevel?: ThinkingLevel;\n\twarning: string | undefined;\n\t/**\n\t * Error message suitable for CLI display.\n\t * When set, model will be undefined.\n\t */\n\terror: string | undefined;\n}\n\n/**\n * Resolve a single model from CLI flags.\n *\n * Supports:\n * - --provider <provider> --model <pattern>\n * - --model <provider>/<pattern>\n * - Fuzzy matching (same rules as model scoping: exact id, then partial id/name)\n *\n * Note: This does not apply the thinking level by itself, but it may *parse* and\n * return a thinking level from \"<pattern>:<thinking>\" so the caller can apply it.\n */\nexport function resolveCliModel(options: {\n\tcliProvider?: string;\n\tcliModel?: string;\n\tmodelRegistry: ModelRegistry;\n}): ResolveCliModelResult {\n\tconst { cliProvider, cliModel, modelRegistry } = options;\n\n\tif (!cliModel) {\n\t\treturn { model: undefined, warning: undefined, error: undefined };\n\t}\n\n\t// Important: use *all* models here, not just models with pre-configured auth.\n\t// This allows \"--api-key\" to be used for first-time setup.\n\tconst availableModels = modelRegistry.getAll();\n\tif (availableModels.length === 0) {\n\t\treturn {\n\t\t\tmodel: undefined,\n\t\t\twarning: undefined,\n\t\t\terror: \"No models available. Check your installation or add models to models.json.\",\n\t\t};\n\t}\n\n\t// Build canonical provider lookup (case-insensitive)\n\tconst providerMap = new Map<string, string>();\n\tfor (const m of availableModels) {\n\t\tproviderMap.set(m.provider.toLowerCase(), m.provider);\n\t}\n\n\tlet provider = cliProvider ? providerMap.get(cliProvider.toLowerCase()) : undefined;\n\tif (cliProvider && !provider) {\n\t\treturn {\n\t\t\tmodel: undefined,\n\t\t\twarning: undefined,\n\t\t\terror: `Unknown provider \"${cliProvider}\". Use --list-models to see available providers/models.`,\n\t\t};\n\t}\n\n\t// If no explicit --provider, try to interpret \"provider/model\" format first.\n\t// When the prefix before the first slash matches a known provider, prefer that\n\t// interpretation over matching models whose IDs literally contain slashes\n\t// (e.g. \"zai/glm-5\" should resolve to provider=zai, model=glm-5, not to a\n\t// vercel-ai-gateway model with id \"zai/glm-5\").\n\tlet pattern = cliModel;\n\tlet inferredProvider = false;\n\n\tif (!provider) {\n\t\tconst slashIndex = cliModel.indexOf(\"/\");\n\t\tif (slashIndex !== -1) {\n\t\t\tconst maybeProvider = cliModel.substring(0, slashIndex);\n\t\t\tconst canonical = providerMap.get(maybeProvider.toLowerCase());\n\t\t\tif (canonical) {\n\t\t\t\tprovider = canonical;\n\t\t\t\tpattern = cliModel.substring(slashIndex + 1);\n\t\t\t\tinferredProvider = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If no provider was inferred from the slash, try exact matches without provider inference.\n\t// This handles models whose IDs naturally contain slashes (e.g. OpenRouter-style IDs).\n\tif (!provider) {\n\t\tconst lower = cliModel.toLowerCase();\n\t\tconst exact = availableModels.find(\n\t\t\t(m) => m.id.toLowerCase() === lower || `${m.provider}/${m.id}`.toLowerCase() === lower,\n\t\t);\n\t\tif (exact) {\n\t\t\treturn { model: exact, warning: undefined, thinkingLevel: undefined, error: undefined };\n\t\t}\n\t}\n\n\tif (cliProvider && provider) {\n\t\t// If both were provided, tolerate --model <provider>/<pattern> by stripping the provider prefix\n\t\tconst prefix = `${provider}/`;\n\t\tif (cliModel.toLowerCase().startsWith(prefix.toLowerCase())) {\n\t\t\tpattern = cliModel.substring(prefix.length);\n\t\t}\n\t}\n\n\tconst candidates = provider ? availableModels.filter((m) => m.provider === provider) : availableModels;\n\tconst { model, thinkingLevel, warning } = parseModelPattern(pattern, candidates, {\n\t\tallowInvalidThinkingLevelFallback: false,\n\t});\n\n\tif (model) {\n\t\treturn { model, thinkingLevel, warning, error: undefined };\n\t}\n\n\t// If we inferred a provider from the slash but found no match within that provider,\n\t// fall back to matching the full input as a raw model id across all models.\n\t// This handles OpenRouter-style IDs like \"openai/gpt-4o:extended\" where \"openai\"\n\t// looks like a provider but the full string is actually a model id on openrouter.\n\tif (inferredProvider) {\n\t\tconst lower = cliModel.toLowerCase();\n\t\tconst exact = availableModels.find(\n\t\t\t(m) => m.id.toLowerCase() === lower || `${m.provider}/${m.id}`.toLowerCase() === lower,\n\t\t);\n\t\tif (exact) {\n\t\t\treturn { model: exact, warning: undefined, thinkingLevel: undefined, error: undefined };\n\t\t}\n\t\t// Also try parseModelPattern on the full input against all models\n\t\tconst fallback = parseModelPattern(cliModel, availableModels, {\n\t\t\tallowInvalidThinkingLevelFallback: false,\n\t\t});\n\t\tif (fallback.model) {\n\t\t\treturn {\n\t\t\t\tmodel: fallback.model,\n\t\t\t\tthinkingLevel: fallback.thinkingLevel,\n\t\t\t\twarning: fallback.warning,\n\t\t\t\terror: undefined,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (provider) {\n\t\tconst fallbackModel = buildFallbackModel(provider, pattern, availableModels);\n\t\tif (fallbackModel) {\n\t\t\tconst fallbackWarning = warning\n\t\t\t\t? `${warning} Model \"${pattern}\" not found for provider \"${provider}\". Using custom model id.`\n\t\t\t\t: `Model \"${pattern}\" not found for provider \"${provider}\". Using custom model id.`;\n\t\t\treturn { model: fallbackModel, thinkingLevel: undefined, warning: fallbackWarning, error: undefined };\n\t\t}\n\t}\n\n\tconst display = provider ? `${provider}/${pattern}` : cliModel;\n\treturn {\n\t\tmodel: undefined,\n\t\tthinkingLevel: undefined,\n\t\twarning,\n\t\terror: `Model \"${display}\" not found. Use --list-models to see available models.`,\n\t};\n}\n\nexport interface InitialModelResult {\n\tmodel: Model<Api> | undefined;\n\tthinkingLevel: ThinkingLevel;\n\tfallbackMessage: string | undefined;\n}\n\n/**\n * Find the initial model to use based on priority:\n * 1. CLI args (provider + model)\n * 2. First model from scoped models (if not continuing/resuming)\n * 3. Restored from session (if continuing/resuming)\n * 4. Saved default from settings\n * 5. First available model with valid API key\n */\nexport async function findInitialModel(options: {\n\tcliProvider?: string;\n\tcliModel?: string;\n\tscopedModels: ScopedModel[];\n\tisContinuing: boolean;\n\tdefaultProvider?: string;\n\tdefaultModelId?: string;\n\tdefaultThinkingLevel?: ThinkingLevel;\n\tmodelRegistry: ModelRegistry;\n}): Promise<InitialModelResult> {\n\tconst {\n\t\tcliProvider,\n\t\tcliModel,\n\t\tscopedModels,\n\t\tisContinuing,\n\t\tdefaultProvider,\n\t\tdefaultModelId,\n\t\tdefaultThinkingLevel,\n\t\tmodelRegistry,\n\t} = options;\n\n\tlet model: Model<Api> | undefined;\n\tlet thinkingLevel: ThinkingLevel = DEFAULT_THINKING_LEVEL;\n\n\t// 1. CLI args take priority\n\tif (cliProvider && cliModel) {\n\t\tconst resolved = resolveCliModel({\n\t\t\tcliProvider,\n\t\t\tcliModel,\n\t\t\tmodelRegistry,\n\t\t});\n\t\tif (resolved.error) {\n\t\t\tconsole.error(chalk.red(resolved.error));\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tif (resolved.model) {\n\t\t\treturn { model: resolved.model, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t\t}\n\t}\n\n\t// 2. Use first model from scoped models (skip if continuing/resuming)\n\tif (scopedModels.length > 0 && !isContinuing) {\n\t\treturn {\n\t\t\tmodel: scopedModels[0].model,\n\t\t\tthinkingLevel: scopedModels[0].thinkingLevel ?? defaultThinkingLevel ?? DEFAULT_THINKING_LEVEL,\n\t\t\tfallbackMessage: undefined,\n\t\t};\n\t}\n\n\t// 3. Try saved default from settings\n\tif (defaultProvider && defaultModelId) {\n\t\tconst found = modelRegistry.find(defaultProvider, defaultModelId);\n\t\tif (found) {\n\t\t\tmodel = found;\n\t\t\tif (defaultThinkingLevel) {\n\t\t\t\tthinkingLevel = defaultThinkingLevel;\n\t\t\t}\n\t\t\treturn { model, thinkingLevel, fallbackMessage: undefined };\n\t\t}\n\t}\n\n\t// 4. Try first available model with valid API key\n\tconst availableModels = await modelRegistry.getAvailable();\n\n\tif (availableModels.length > 0) {\n\t\t// Try to find a default model from known providers\n\t\tfor (const provider of Object.keys(defaultModelPerProvider) as KnownProvider[]) {\n\t\t\tconst defaultId = defaultModelPerProvider[provider];\n\t\t\tconst match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n\t\t\tif (match) {\n\t\t\t\treturn { model: match, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t\t\t}\n\t\t}\n\n\t\t// If no default found, use first available\n\t\treturn { model: availableModels[0], thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t}\n\n\t// 5. No model found\n\treturn { model: undefined, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n}\n\n/**\n * Restore model from session, with fallback to available models\n */\nexport async function restoreModelFromSession(\n\tsavedProvider: string,\n\tsavedModelId: string,\n\tcurrentModel: Model<Api> | undefined,\n\tshouldPrintMessages: boolean,\n\tmodelRegistry: ModelRegistry,\n): Promise<{ model: Model<Api> | undefined; fallbackMessage: string | undefined }> {\n\tconst restoredModel = modelRegistry.find(savedProvider, savedModelId);\n\n\t// Check if restored model exists and still has auth configured\n\tconst hasConfiguredAuth = restoredModel ? modelRegistry.hasConfiguredAuth(restoredModel) : false;\n\n\tif (restoredModel && hasConfiguredAuth) {\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Restored model: ${savedProvider}/${savedModelId}`));\n\t\t}\n\t\treturn { model: restoredModel, fallbackMessage: undefined };\n\t}\n\n\t// Model not found or no API key - fall back\n\tconst reason = !restoredModel ? \"model no longer exists\" : \"no auth configured\";\n\n\tif (shouldPrintMessages) {\n\t\tconsole.error(chalk.yellow(`Warning: Could not restore model ${savedProvider}/${savedModelId} (${reason}).`));\n\t}\n\n\t// If we already have a model, use it as fallback\n\tif (currentModel) {\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Falling back to: ${currentModel.provider}/${currentModel.id}`));\n\t\t}\n\t\treturn {\n\t\t\tmodel: currentModel,\n\t\t\tfallbackMessage: `Could not restore model ${savedProvider}/${savedModelId} (${reason}). Using ${currentModel.provider}/${currentModel.id}.`,\n\t\t};\n\t}\n\n\t// Try to find any available model\n\tconst availableModels = await modelRegistry.getAvailable();\n\n\tif (availableModels.length > 0) {\n\t\t// Try to find a default model from known providers\n\t\tlet fallbackModel: Model<Api> | undefined;\n\t\tfor (const provider of Object.keys(defaultModelPerProvider) as KnownProvider[]) {\n\t\t\tconst defaultId = defaultModelPerProvider[provider];\n\t\t\tconst match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n\t\t\tif (match) {\n\t\t\t\tfallbackModel = match;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// If no default found, use first available\n\t\tif (!fallbackModel) {\n\t\t\tfallbackModel = availableModels[0];\n\t\t}\n\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Falling back to: ${fallbackModel.provider}/${fallbackModel.id}`));\n\t\t}\n\n\t\treturn {\n\t\t\tmodel: fallbackModel,\n\t\t\tfallbackMessage: `Could not restore model ${savedProvider}/${savedModelId} (${reason}). Using ${fallbackModel.provider}/${fallbackModel.id}.`,\n\t\t};\n\t}\n\n\t// No models available\n\treturn { model: undefined, fallbackMessage: undefined };\n}\n"]}

[Showing lines 4-8 of 8 (50.0KB limit). Full output: /tmp/pi-bash-2dcfb6b34664dc02.log]


Interesting findings:

1. Pi has a "minimax" provider and "minimax-cn" provider, with default model `MiniMax-M2.7` (M2.7, not M3!)
2. The default for `opencode` provider is `kimi-k2.6`
3. The user is using `minimax-m3-free` as their default model

So "MiniMax M3" doesn't appear to exist in pi's built-in models. The "minimax" provider has `MiniMax-M2.7` as the default. There's no built-in `minimax-m3-free` model. This is curious.

Let me check the actual built-in models for the `minimax` provider and `opencode` provider, and also look for the model list. Let me also see if there's a way to look up the actual model.

Wait - the system prompt says my model is "MiniMax-M3" but pi's default for the `minimax` provider is "MiniMax-M2.7". And the user has set their default to "minimax-m3-free" which suggests this is a different/older naming. The names look anonymized in my system prompt.

Let me check the model registry to see what models are available.

grep -rn "minimax-m3\|MiniMax-M3\|minimax-m2.7\|MiniMax-M2.7\|contextWindow" /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/ 2>/dev/null | grep -v "\.map:" | head -30

find /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-ai -name "*.js" | xargs grep -l "minimax\|MiniMax" 2>/dev/null | head -10


/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.d.ts:144:        contextWindow: number;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:122:    contextWindow: Type.Optional(Type.Number()),
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:139:    contextWindow: Type.Optional(Type.Number()),
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:264:    if (override.contextWindow !== undefined)
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:265:        result.contextWindow = override.contextWindow;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:458:                // Validate contextWindow/maxTokens only if provided (they have defaults)
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:459:                if (modelDef.contextWindow !== undefined && modelDef.contextWindow <= 0)
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:460:                    throw new Error(`Provider ${providerName}, model ${modelDef.id}: invalid contextWindow`);
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:508:                    contextWindow: modelDef.contextWindow ?? 128000,
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js:757:                    contextWindow: modelDef.contextWindow,
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.d.ts:53:export declare function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js:149:export function shouldCompact(contextTokens, contextWindow, settings) {
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js:152:    return contextTokens > contextWindow - settings.reserveTokens;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/branch-summarization.js:190:    const contextWindow = model.contextWindow || 128000;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/branch-summarization.js:191:    const tokenBudget = contextWindow - reserveTokens;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js:30:    minimax: "MiniMax-M2.7",
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js:31:    "minimax-cn": "MiniMax-M2.7",
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:1401:        const contextWindow = this.model?.contextWindow ?? 0;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:1416:        if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:1460:        if (shouldCompact(contextTokens, contextWindow, settings)) {
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:1964:        const contextWindow = this.model?.contextWindow ?? 0;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:1965:        if (isContextOverflow(message, contextWindow))
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:2388:        const contextWindow = model.contextWindow ?? 0;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:2389:        if (contextWindow <= 0)
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:2414:                return { tokens: null, contextWindow, percent: null };
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:2418:        const percent = (estimate.tokens / contextWindow) * 100;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js:2421:            contextWindow,
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts:195:    contextWindow: number;
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts:901:     *       contextWindow: 200000,
/home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts:1001:    contextWindow: number;


Now I see clearly: pi has a "minimax" provider with default model `MiniMax-M2.7`, NOT `MiniMax-M3`. The user has set their default to `minimax-m3-free`, which doesn't exist as a built-in model. This is a custom configuration.

Let me look at the actual models for the opencode provider and see what `minimax-m3-free` could be. Let me also look at the actual model registry and any opencode provider models.

grep -n "minimax\|opencode\|contextWindow.*200\|contextWindow.*1000" /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/models.generated.js 2>/dev/null | head -40

ls /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/ | grep -i "provider\|model" | head -20


87:            contextWindow: 200000,
104:            contextWindow: 200000,
121:            contextWindow: 200000,
139:            contextWindow: 1000000,
157:            contextWindow: 1000000,
175:            contextWindow: 1000000,
192:            contextWindow: 200000,
209:            contextWindow: 1000000,
226:            contextWindow: 200000,
244:            contextWindow: 1000000,
262:            contextWindow: 1000000,
279:            contextWindow: 200000,
296:            contextWindow: 1000000,
364:            contextWindow: 200000,
381:            contextWindow: 200000,
399:            contextWindow: 1000000,
417:            contextWindow: 1000000,
435:            contextWindow: 1000000,
452:            contextWindow: 200000,
469:            contextWindow: 1000000,
486:            contextWindow: 200000,
503:            contextWindow: 200000,
521:            contextWindow: 1000000,
539:            contextWindow: 1000000,
557:            contextWindow: 1000000,
574:            contextWindow: 200000,
591:            contextWindow: 1000000,
643:            contextWindow: 1000000,
661:            contextWindow: 1000000,
678:            contextWindow: 200000,
695:            contextWindow: 1000000,
763:            contextWindow: 1000000,
783:        "minimax.minimax-m2": {
784:            id: "minimax.minimax-m2",
800:        "minimax.minimax-m2.1": {
801:            id: "minimax.minimax-m2.1",
817:        "minimax.minimax-m2.5": {
818:            id: "minimax.minimax-m2.5",
984:            contextWindow: 32000,
1256:            contextWindow: 262000,


bedrock-provider.d.ts
bedrock-provider.d.ts.map
bedrock-provider.js
bedrock-provider.js.map
image-models.d.ts
image-models.d.ts.map
image-models.generated.d.ts
image-models.generated.d.ts.map
image-models.generated.js
image-models.generated.js.map
image-models.js
image-models.js.map
models.d.ts
models.d.ts.map
models.generated.d.ts
models.generated.d.ts.map
models.generated.js
models.generated.js.map
models.js
models.js.map


I can see the actual model definitions. Let me look at the specific models for "minimax" provider to see the context window settings.

grep -n "minimax\|opencode" /home/ubuntu/.local/lib/node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/models.generated.js | head -50


783:        "minimax.minimax-m2": {
784:            id: "minimax.minimax-m2",
800:        "minimax.minimax-m2.1": {
801:            id: "minimax.minimax-m2.1",
817:        "minimax.minimax-m2.5": {
818:            id: "minimax.minimax-m2.5",
3818:        "accounts/fireworks/models/minimax-m2p5": {
3819:            id: "accounts/fireworks/models/minimax-m2p5",
3836:        "accounts/fireworks/models/minimax-m2p7": {
3837:            id: "accounts/fireworks/models/minimax-m2p7",
5586:    "minimax": {
5591:            provider: "minimax",
5592:            baseUrl: "https://api.minimax.io/anthropic",
5608:            provider: "minimax",
5609:            baseUrl: "https://api.minimax.io/anthropic",
5625:            provider: "minimax",
5626:            baseUrl: "https://api.minimax.io/anthropic",
5639:    "minimax-cn": {
5644:            provider: "minimax-cn",
5645:            baseUrl: "https://api.minimaxi.com/anthropic",
5661:            provider: "minimax-cn",
5662:            baseUrl: "https://api.minimaxi.com/anthropic",
5678:            provider: "minimax-cn",
5679:            baseUrl: "https://api.minimaxi.com/anthropic",
7656:    "opencode": {
7661:            provider: "opencode",
7662:            baseUrl: "https://opencode.ai/zen/v1",
7678:            provider: "opencode",
7679:            baseUrl: "https://opencode.ai/zen",
7695:            provider: "opencode",
7696:            baseUrl: "https://opencode.ai/zen",
7712:            provider: "opencode",
7713:            baseUrl: "https://opencode.ai/zen",
7729:            provider: "opencode",
7730:            baseUrl: "https://opencode.ai/zen",
7748:            provider: "opencode",
7749:            baseUrl: "https://opencode.ai/zen",
7767:            provider: "opencode",
7768:            baseUrl: "https://opencode.ai/zen",
7786:            provider: "opencode",
7787:            baseUrl: "https://opencode.ai/zen",
7803:            provider: "opencode",
7804:            baseUrl: "https://opencode.ai/zen",
7820:            provider: "opencode",
7821:            baseUrl: "https://opencode.ai/zen",
7838:            provider: "opencode",
7839:            baseUrl: "https://opencode.ai/zen/v1",
7857:            provider: "opencode",
7858:            baseUrl: "https://opencode.ai/zen/v1",
7876:            provider: "opencode",


            contextWindow: 3500000,
            maxTokens: 16384,
        },
        "minimax.minimax-m2": {
            id: "minimax.minimax-m2",
            name: "MiniMax M2",
            api: "bedrock-converse-stream",
            provider: "amazon-bedrock",
            baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
            reasoning: true,
            input: ["text"],
            cost: {
                input: 0.3,
                output: 1.2,
                cacheRead: 0,
                cacheWrite: 0,
            },
            contextWindow: 204608,
            maxTokens: 128000,
        },
        "minimax.minimax-m2.1": {
            id: "minimax.minimax-m2.1",
            name: "MiniMax M2.1",
            api: "bedrock-converse-stream",
            provider: "amazon-bedrock",
            baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
            reasoning: true,
            input: ["text"],
            cost: {
                input: 0.3,
                output: 1.2,
                cacheRead: 0,
                cacheWrite: 0,
            },
            contextWindow: 204800,
            maxTokens: 131072,
        },
        "minimax.minimax-m2.5": {
            id: "minimax.minimax-m2.5",
            name: "MiniMax M2.5",
            api: "bedrock-converse-stream",
            provider: "amazon-bedrock",
            baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
            reasoning: true,
            input: ["text"],
            cost: {
                input: 0.3,
                output: 1.2,
                cacheRead: 0,
                cacheWrite: 0,
            },
            contextWindow: 196608,
            maxTokens: 98304,
        },
        "mistral.devstral-2-123b": {
            id: "mistral.devstral-2-123b",
            name: "Devstral 2 123B",
            api: "bedrock-converse-stream",
            provider: "amazon-bedrock",
            baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",

[16098 more lines in file. Use offset=840 to continue.]


I see "MiniMax M2" series. Let me look at the MiniMax M3 model. Let me also look at the "minimax" provider section more carefully to see what models it has.


                cacheWrite: 0,
            },
            contextWindow: 262144,
            maxTokens: 32768,
        },
    },
    "minimax": {
        "MiniMax-M2.7": {
            id: "MiniMax-M2.7",
            name: "MiniMax-M2.7",
            api: "anthropic-messages",
            provider: "minimax",
            baseUrl: "https://api.minimax.io/anthropic",
            reasoning: true,
            input: ["text"],
            cost: {
                input: 0.3,
                output: 1.2,
                cacheRead: 0.06,
                cacheWrite: 0.375,
            },
            contextWindow: 204800,
            maxTokens: 131072,
        },
        "MiniMax-M2.7-highspeed": {
            id: "MiniMax-M2.7-highspeed",
            name: "MiniMax-M2.7-highspeed",
            api: "anthropic-messages",
            provider: "minimax",
            baseUrl: "https://api.minimax.io/anthropic",
            reasoning: true,
            input: ["text"],
            cost: {
                input: 0.6,
                output: 2.4,
                cacheRead: 0.06,
                cacheWrite: 0.375,
            },
            contextWindow: 204800,
            maxTokens: 131072,
        },
        "MiniMax-M3": {
            id: "MiniMax-M3",
            name: "MiniMax-M3",
            api: "anthropic-messages",
            provider: "minimax",
            baseUrl: "https://api.minimax.io/anthropic",
            reasoning: true,
            input: ["text", "image"],
            cost: {
                input: 0.6,
                output: 2.4,
                cacheRead: 0.12,
                cacheWrite: 0,
            },
            contextWindow: 512000,
            maxTokens: 128000,
        },
    },
    "minimax-cn": {
        "MiniMax-M2.7": {
            id: "MiniMax-M2.7",
            name: "MiniMax-M2.7",
            api: "anthropic-messages",
            provider: "minimax-cn",
            baseUrl: "https://api.minimaxi.com/anthropic",
            reasoning: true,
            input: ["text"],
            cost: {
                input: 0.3,
                output: 1.2,
                cacheRead: 0.06,
                cacheWrite: 0.375,
            },
            contextWindow: 204800,
            maxTokens: 131072,
        },
        "MiniMax-M2.7-highspeed": {
            id: "MiniMax-M2.7-highspeed",
            name: "MiniMax-M2.7-highspeed",
            api: "anthropic-messages",
            provider: "minimax-cn",
            baseUrl: "https://api.minimaxi.com/anthropic",
            reasoning: true,
            input: ["text"],
            cost: {
                input: 0.6,
                output: 2.4,
                cacheRead: 0.06,
                cacheWrite: 0.375,
            },
            contextWindow: 204800,
            maxTokens: 131072,
        },
        "MiniMax-M3": {
            id: "MiniMax-M3",
            name: "MiniMax-M3",
            api: "anthropic-messages",
            provider: "minimax-cn",
            baseUrl: "https://api.minimaxi.com/anthropic",
            reasoning: true,
            input: ["text", "image"],
            cost: {
                input: 0.6,
                output: 2.4,
                cacheRead: 0.12,
                cacheWrite: 0,
            },
            contextWindow: 512000,
            maxTokens: 128000,
        },
    },
    "mistral": {
        "codestral-latest": {
            id: "codestral-latest",
            name: "Codestral (latest)",
            api: "mistral-conversations",
            provider: "mistral",
            baseUrl: "https://api.mistral.ai",
            reasoning: false,

[11238 more lines in file. Use offset=5700 to continue.]


Now I have a clear picture:

**Built-in MiniMax M3 specs (per pi's bundled model registry):**
- `provider: "minimax"` or `"minimax-cn"`
- `id: "MiniMax-M3"`
- `api: "anthropic-messages"`
- `baseUrl: "https://api.minimax.io/anthropic"` (or `api.minimaxi.com` for cn)
- `reasoning: true`
- `input: ["text", "image"]`
- `cost: { input: 0.6, output: 2.4, cacheRead: 0.12, cacheWrite: 0 }`
- **`contextWindow: 512000` (512K)**
- `maxTokens: 128000`

So the "official" spec per pi's bundled registry is **512K tokens**, not 1M.

Now the user is using `opencode` provider with model `minimax-m3-free`. Let me check the opencode provider to understand what `minimax-m3-free` is.

Wait - I need to think about this carefully. The user is using:
- `defaultProvider: "opencode"`
- `defaultModel: "minimax-m3-free"`

But pi's built-in `opencode` provider has `kimi-k2.6` as default. And `minimax-m3-free` is NOT in the opencode provider's built-in models. Let me check.