summaryrefslogtreecommitdiffhomepage
path: root/.rules/plan/02-30-strip-oauth-and-anthropic-machinery.md
diff options
context:
space:
mode:
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.md213
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.