diff options
Diffstat (limited to '.rules/plan/02-30-strip-oauth-and-anthropic-machinery.md')
| -rw-r--r-- | .rules/plan/02-30-strip-oauth-and-anthropic-machinery.md | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/.rules/plan/02-30-strip-oauth-and-anthropic-machinery.md b/.rules/plan/02-30-strip-oauth-and-anthropic-machinery.md new file mode 100644 index 0000000..a4a278d --- /dev/null +++ b/.rules/plan/02-30-strip-oauth-and-anthropic-machinery.md @@ -0,0 +1,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. |
