# MiniMax Adapter Plan — Overview ## Goal Convert the forked Claude adapter at `reference/dispatch-adapter-minimax/` into a working `Dispatch::Adapter::MiniMax` adapter that talks to MiniMax's Anthropic-compatible endpoint at `https://api.minimax.io/anthropic`, using a single static API key (Token Plan). ## Working directory All file paths in these plans are RELATIVE to the gem root: ``` reference/dispatch-adapter-minimax/ ``` When `run_tests` is called, `project_path` MUST be that directory. ## Locked design decisions | # | Topic | Decision | |---|---|---| | 1 | Module name | `Dispatch::Adapter::MiniMax` (note CamelCase: `MiniMax`) | | 2 | Default model | `MiniMax-M2.7` | | 3 | `thinking` param | Keep, default `"high"`, plumb `thinking_delta` SSE through unchanged | | 4 | Pricing / `Usage#cost` | Keep field, always `0.0`; strip `PricingTable` populated rows | | 5 | `count_tokens` + `list_models` | Keep both (Python SDK uses both `/v1/messages/count_tokens` and `/v1/models`) | | 6 | `cache_control` blocks | Keep (SDK emits them; MiniMax must accept or ignore) | | 7 | Strict-tool-schema fallback | Keep harness, broaden matcher regex to also fire on MiniMax-shaped errors | | 8 | API key resolution | constructor `api_key:` → `ENV["MINIMAX_API_KEY"]` → `~/.config/dispatch/minimax_api_key` (0600 plain text) → raise | ## SDK-is-fair-game rule Whatever the Anthropic Python SDK does is *permitted* and considered safe. It is a permission, not a constraint. We may do MORE if it is better and safe; we don't have to emulate exactly. Reference clone: `reference/anthropic-sdk-python/` (already cloned). ## Hard rules for every phase 1. After every code change, call `run_tests` with `project_path=reference/dispatch-adapter-minimax`. The `Overall:` line in the results file MUST read `PASS` (rubocop AND rspec each exit 0) before calling `ask_for_next_plan`. 2. NEVER weaken or delete a test to make it pass. Fix the implementation. Tests that target removed code (OAuth, PKCE, cloaking, usage_client) should be DELETED in their dedicated retarget phase, not weakened earlier. 3. Do NOT add runtime gem dependencies. Stick to stdlib (`net/http`, `uri`, `json`, `fileutils`, `digest`, `securerandom`). 4. Do NOT make live network calls in specs. Stub with WebMock / fixtures. 5. After phase 17 is complete, the gem must `bundle install` cleanly, `bundle exec rubocop --autocorrect-all` must report no offenses, and `bundle exec rspec` must pass with no `.skip` or `pending` examples. 6. Each plan file is self-contained. Do not look ahead at other plan files. The system prompt + the current plan body is all you need. ## MiniMax-specific request constraints These must be enforced in the request builder: - `temperature` range is `(0.0, 1.0]` — MiniMax explicitly errors outside. - `image` and `document` content blocks are NOT supported — reject with `ArgumentError` at request-build time. - These input parameters get IGNORED by MiniMax (strip silently before send to keep the wire clean): `top_k`, `stop_sequences`, `service_tier`, `mcp_servers`, `context_management`, `container`. ## Supported MiniMax models (hardcoded catalog) All seven share a 204,800-token context window: - `MiniMax-M2.7` (default) - `MiniMax-M2.7-highspeed` - `MiniMax-M2.5` - `MiniMax-M2.5-highspeed` - `MiniMax-M2.1` - `MiniMax-M2.1-highspeed` - `MiniMax-M2` ## Steps | # | File | Phase | |---|------|-------| | 01 | `01-30-rename-namespace.md` | Rename files, modules, gemspec, requires | | 02 | `02-30-strip-oauth-and-anthropic-machinery.md` | Delete OAuth / PKCE / cloaking / usage / rate-limit-headers files and methods | | 03 | `03-15-keystore.md` | Replace `TokenStore` with simple `KeyStore` (env / file / explicit) | | 04 | `04-15-simplify-headers.md` | Collapse `Headers.build` to bearer + content-type + accept | | 05 | `05-10-config-swap.md` | `DEFAULT_BASE_URL` and `DEFAULT_MODEL` constants | | 06 | `06-15-pricing-zero.md` | Zero out `PricingTable` so `Usage#cost` is always 0.0 | | 07 | `07-15-model-catalog.md` | Hardcode the 7-model MiniMax catalog | | 08 | `08-15-strip-ignored-params-and-temp.md` | Strip ignored params; validate temperature `(0,1]` | | 09 | `09-15-reject-image-document.md` | Reject `image` / `document` content blocks at request build time | | 10 | `10-10-broaden-strict-regex.md` | Broaden `strict_grammar_error?` matcher | | 11 | `11-15-errors-module.md` | Rename `ClaudeErrors` → `MiniMaxErrors`, retarget mapping | | 12 | `12-25-update-fixtures.md` | Replace SSE + JSON fixtures with MiniMax-shaped data | | 13 | `13-25-retarget-headers-and-request-builder-specs.md` | Update headers_spec + request_builder_spec to new shapes | | 14 | `14-25-retarget-response-builder-and-streaming-internals-specs.md` | Update response_builder_spec + sse_parser_spec + stream_collector_spec | | 15 | `15-30-retarget-chat-and-counttokens-listmodels-specs.md` | Update chat_streaming + chat_non_streaming + chat_streaming_retry + count_tokens + list_models specs | | 16 | `16-20-retarget-misc-specs.md` | Update model_catalog + pricing_table + errors + strict_fallback + http_client + rate_limiter + main `minimax_spec.rb` | | 17 | `17-20-readme-changelog-examples.md` | Rewrite README, CHANGELOG, and examples | ## Out-of-scope reminders - Live API smoke testing is NOT in this plan series — it's a manual step after phase 17 and requires a real Token Plan API key. - Adding new public methods or features beyond what the SDK already exposes is out of scope. Stick to the parity surface.