1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
# 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.
|