summaryrefslogtreecommitdiffhomepage
path: root/.rules/plan/02-30-strip-oauth-and-anthropic-machinery.md
blob: a4a278d2b6f1f23d6b8f21430fde59dfaaa32897 (plain)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# Phase 02 — Strip OAuth and Anthropic-specific machinery

**Estimated time:** ~30 minutes
**Touches:** `lib/dispatch/adapter/minimax.rb` and 7 sub-files (deletions).

## Goal

Delete all code and methods that exist solely to support Anthropic's OAuth
flow, Stainless SDK fingerprinting, Claude Code cloaking, the
`/api/oauth/usage` endpoint, and Anthropic's unified rate-limit header
format. After this phase the gem will be missing some required pieces
(`Headers.build` will be partially broken until phase 03) — that's OK,
phase 03 reconstructs the simplified replacements.

MiniMax uses a single static API key (Token Plan) — no OAuth, no PKCE,
no token refresh, no usage endpoint, no Stainless headers.

## Files to DELETE entirely

```text
lib/dispatch/adapter/minimax/oauth.rb
lib/dispatch/adapter/minimax/oauth/                 (the whole directory and callback_server.rb)
lib/dispatch/adapter/minimax/pkce.rb
lib/dispatch/adapter/minimax/cloaking.rb
lib/dispatch/adapter/minimax/usage_client.rb
lib/dispatch/adapter/minimax/rate_limit_headers.rb
spec/dispatch/adapter/minimax/oauth_spec.rb
spec/dispatch/adapter/minimax/pkce_spec.rb
spec/dispatch/adapter/minimax/cloaking_spec.rb
spec/dispatch/adapter/minimax/usage_report_fixtures_spec.rb
spec/dispatch/adapter/minimax/auth_lifecycle_spec.rb
spec/fixtures/responses/oauth-profile.json
spec/fixtures/responses/oauth-usage-full.json
spec/fixtures/responses/oauth-usage-partial.json
```

(The `token_store.rb` file is renamed in phase 03, not deleted here.)

## Edits in `lib/dispatch/adapter/minimax.rb`

### 1. Remove the now-stale `require_relative` lines

Delete these from the top of `lib/dispatch/adapter/minimax.rb`:

```ruby
require_relative "minimax/pkce"
require_relative "minimax/oauth"
require_relative "minimax/cloaking"
require_relative "minimax/usage_client"
require_relative "minimax/rate_limit_headers"
```

Also delete the corresponding stdlib requires that ONLY OAuth needed:

```ruby
require "securerandom"   # only used by PKCE / OAuth state
require "digest"         # only used by PKCE
require "base64"         # only used by OAuth.CLIENT_ID decode
```

### 2. Delete the following methods from the `MiniMax` class

- `authenticate!`
- `authenticated?`
- `logout!`
- `usage_report`
- `with_auth_recovery` (private)
- `rotate_token_for_usage` (private)
- `ensure_token!` (private)
- `expired?` (private)
- `resolve_is_oauth` (private)
- `explicit_api_key_present?` (private)
- `capture_rate_limit_headers` (private)
- `log_rate_limit_info` (private)
- `http_client_claude_code` (private)

### 3. Delete the following ivars / state

Remove all assignment to and reading of:

- `@is_oauth`
- `@is_oauth_override`
- `@token_store` (will be replaced by `@key_store` in phase 03; for this
  phase, you may leave the variable name alone but DO simplify the
  assignment so it no longer takes a `token_path:` parameter — see below)
- `@explicit_api_key`
- `@strict_disabled` (KEEP — phase 06 retargets the strict-fallback)
- `@rate_limit_info`
- `@last_all_headers`
- `@rate_limit_log_path`
- `@models_cache`, `@models_cache_at` (KEEP — list_models is staying)

### 4. Simplify `initialize`

Replace the constructor signature and body with a minimal version that
accepts just `api_key:` (and the existing `model:`, `base_url:`,
`max_tokens:`, `thinking:`, `cache_retention:`, `min_request_interval:`,
`rate_limit:`, `extra_betas:`). Remove these constructor parameters:

- `token_path:`
- `is_oauth:`
- `token_store:`
- `user_agent_override:`

Inside the body, remove all the `resolve_api_key` / `resolve_is_oauth` /
TokenStore wiring. Phase 03 will introduce a `KeyStore` to load the API
key from disk; for this phase, just accept `api_key:` as a keyword
argument and require it (raise `ArgumentError` if it's nil/empty for
now — phase 03 makes it optional and falls back to env / file).

```ruby
def initialize(
  model: DEFAULT_MODEL,
  api_key: nil,
  base_url: DEFAULT_BASE_URL,
  max_tokens: nil,
  thinking: "high",
  cache_retention: nil,
  min_request_interval: DEFAULT_MIN_REQUEST_INTERVAL,
  rate_limit: nil,
  extra_betas: []
)
  super()
  @model           = model.to_s
  @base_url        = base_url.to_s.chomp("/")
  @max_tokens      = max_tokens
  @thinking        = thinking
  @cache_retention = cache_retention
  @extra_betas     = Array(extra_betas)
  @api_key         = api_key.to_s
  raise ArgumentError, "api_key required" if @api_key.empty?
  @strict_disabled = false

  rate_limit_path = File.join(Dir.home, ".config", "dispatch", "minimax_rate_limit")
  @rate_limiter = RateLimiter.new(
    rate_limit_path: rate_limit_path,
    min_request_interval: min_request_interval,
    rate_limit: rate_limit
  )
end
```

### 5. Simplify `chat` and `count_tokens`

Inside both `#chat` and `#count_tokens`, remove the `with_auth_recovery`
wrapper and the `ensure_token!` call. Keep `with_rate_limit`. Example:

```ruby
def chat(messages, system: nil, tools: [], stream: false, ...)
  with_rate_limit do
    # body unchanged
  end
end
```

### 6. Simplify `RequestBuilder` calls

In every place `RequestBuilder.build(...)` is called, remove the
`is_oauth: @is_oauth` keyword argument. The `RequestBuilder` itself is
edited in phase 06 to drop the parameter from its signature.

### 7. Simplify `ResponseBuilder.build` calls

Remove the `is_oauth: @is_oauth` keyword argument from
`ResponseBuilder.build(json, model_info: model_info, is_oauth: @is_oauth)`.
The `ResponseBuilder` itself drops the parameter in phase 08.

### 8. Simplify `StreamCollector.new` calls

Remove the `is_oauth: @is_oauth` keyword. The `StreamCollector` itself
drops the parameter in phase 08.

### 9. Simplify `Headers.build` callsite

In `build_headers_proc`, remove `claude_code_only:` (delete the parameter
on the lambda and the `cc_only` capture). Phase 03 deletes the entire
`claude_code_only` branch inside `Headers.build`. For now, just stop
threading the parameter through.

### 10. Update or delete `RequestBuilder` references to cloaking

If `request_builder.rb` requires or calls `Cloaking.cloak!` or
`Cloaking.something`, REMOVE those calls. The system prompt and message
shaping should remain identical to a non-OAuth Anthropic call. (Cloaking
exists only because OAuth tokens require Claude-Code-style behavior;
without OAuth, no cloaking is needed.)

## Acceptance criteria

After completing this phase:

- `grep -rn 'OAuth\|PKCE\|Cloaking\|UsageClient\|RateLimitHeaders' lib/`
  returns ZERO matches.
- `grep -rn '@is_oauth\|claude_code_only\|sk-ant-oat\|usage_report\|token_path' lib/`
  returns ZERO matches.
- `grep -rn '/api/oauth' lib/` returns ZERO matches.
- All deleted files are gone from the working tree.
- All deleted spec files are gone from the working tree.
- `bundle exec rubocop --autocorrect-all` exits 0 (run via `run_tests`).
- `bundle exec rspec` may have failures from specs that target the
  rate-limit-header parser or strict-fallback (phase 06/07 hooks), but
  must NOT have any `LoadError` or `NameError` referring to the deleted
  modules. If you see one, the corresponding `require_relative` line was
  missed in step 1.

## Verification

Run `run_tests` with `project_path=reference/dispatch-adapter-minimax`.

Resolve every rubocop offense before calling `ask_for_next_plan`. RSpec
failures from removed-functionality test files should not exist after this
phase (they were deleted) — other failures are acceptable and will be
addressed in subsequent phases.