summaryrefslogtreecommitdiffhomepage
path: root/.rules/plan/14-25-retarget-response-builder-and-streaming-internals-specs.md
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-04-30 20:24:33 +0900
committerAdam Malczewski <[email protected]>2026-04-30 20:24:33 +0900
commit262aa7395c50b449ce0a897f28b1e33c319f5dc7 (patch)
tree2ccc7c7f6402e76aea6b8788046215e82650fdfc /.rules/plan/14-25-retarget-response-builder-and-streaming-internals-specs.md
parent1e7a273bda744f93f230d21df895b54d2a81ce15 (diff)
downloaddispatch-adapter-minimax-main.tar.gz
dispatch-adapter-minimax-main.zip
add plan to updateHEADmain
Diffstat (limited to '.rules/plan/14-25-retarget-response-builder-and-streaming-internals-specs.md')
-rw-r--r--.rules/plan/14-25-retarget-response-builder-and-streaming-internals-specs.md161
1 files changed, 161 insertions, 0 deletions
diff --git a/.rules/plan/14-25-retarget-response-builder-and-streaming-internals-specs.md b/.rules/plan/14-25-retarget-response-builder-and-streaming-internals-specs.md
new file mode 100644
index 0000000..32c5176
--- /dev/null
+++ b/.rules/plan/14-25-retarget-response-builder-and-streaming-internals-specs.md
@@ -0,0 +1,161 @@
+# Phase 14 — Retarget response-builder and streaming-internals specs
+
+**Estimated time:** ~25 minutes
+**Touches:**
+`spec/dispatch/adapter/minimax/response_builder_spec.rb`,
+`spec/dispatch/adapter/minimax/sse_parser_spec.rb`,
+`spec/dispatch/adapter/minimax/stream_collector_spec.rb`.
+
+## Goal
+
+Update the three specs that consume the new fixtures created in phase
+12. The structural change is small: with `is_oauth` and cloaking gone
+(phase 02), there is no `proxy_` prefix to strip, and the response /
+stream pipelines are pure Anthropic-compatible parsers fed by MiniMax-
+shaped data.
+
+## Pre-reading
+
+1. `spec/fixtures/sse/*.sse` (already updated in phase 12)
+2. `spec/fixtures/responses/*.json` (already updated in phase 12)
+3. `lib/dispatch/adapter/minimax/response_builder.rb`
+4. `lib/dispatch/adapter/minimax/sse_parser.rb`
+5. `lib/dispatch/adapter/minimax/stream_collector.rb`
+
+## Steps for response_builder_spec.rb
+
+### 1. Drop the `is_oauth` parameter from every call
+
+`ResponseBuilder.build(json, model_info: ..., is_oauth: ...)` becomes
+`ResponseBuilder.build(json, model_info: ...)`. Phase 02 removed the
+keyword from the lib code; remove it from all spec calls here.
+
+### 2. Update fixture references and assertions
+
+The fixtures are now MiniMax-flavoured:
+
+- `model: "MiniMax-M2.7"` instead of a Claude id.
+- Token counts changed (input 15/50/42, output 8/18/24).
+- `id` strings begin with `msg_minimax_*` and `toolu_minimax_*`.
+- Tool name in tool-use fixtures is `"get_weather"` with input
+ `{"city":"Boston"}`.
+
+Update every assertion that compared against old values.
+
+### 3. Drop the cloaking strip-prefix examples
+
+Any example asserting that `proxy_get_weather` arrives in the response
+and is stripped to `get_weather` before being returned should be
+DELETED. There is no proxy prefix to strip anymore — MiniMax sends
+plain tool names.
+
+### 4. Cost assertions
+
+Examples that asserted `usage.cost.total_cost > 0.0` (or any non-zero
+sub-cost) must be updated to expect `0.0` because phase 06 zeroed the
+pricing table. Token counts are still meaningful — only the
+*per-token rate* is zero.
+
+### 5. Remove cache_creation/cache_read examples that depended on
+non-zero pricing if any.
+
+If the old `messages-text.json` exposed cache token counts, the
+fixture in phase 12 may not include them. Add them back ONLY IF the
+spec needs to exercise that code path (i.e. a `usage_hash` with
+`cache_creation_input_tokens` / `cache_read_input_tokens`). If you do,
+edit `spec/fixtures/responses/messages-text.json` to add those keys to
+`usage` — phase 12's fixture omits them but adding them is fine.
+
+## Steps for sse_parser_spec.rb
+
+### 1. Update model id references
+
+Replace `"claude-sonnet-4-5-20250929"` (or whatever Claude model id was
+used) with `"MiniMax-M2.7"` in any in-spec hand-built event payloads.
+
+### 2. Re-load fixtures
+
+Specs that read SSE fixtures by path (`File.read("spec/fixtures/sse/text-only.sse")`)
+will pick up the new content automatically. Update the assertions to
+match the new event count and content:
+
+- `text-only.sse` → 8 frames (text-only fixture: message_start,
+ content_block_start, ping, content_block_delta×2, content_block_stop,
+ message_delta, message_stop). Verify by reading the fixture.
+- `tool-use.sse` → 7 frames.
+- `thinking-then-text.sse` → 11 frames.
+
+Update text/tool/thinking string assertions to match the new fixture
+content (`"Hello, world!"` → `"Hello, "` + `"world!"`,
+`"get_weather"` with city=Boston, etc.).
+
+### 3. Truncated fixtures
+
+`truncated-mid-text.sse` ends mid-frame after emitting some text
+deltas. The parser is content-agnostic at chunk boundary; the higher-
+level `StreamCollector` decides whether to retry. The parser-level
+spec should assert that `flush` raises `RequestError` (because there
+is dangling non-empty data when the stream ends).
+
+`truncated-before-message-start.sse` is just a `ping` event followed
+by EOF — the parser yields the ping (or silently drops it depending on
+implementation) and `flush` is a no-op since there is no dangling data.
+
+## Steps for stream_collector_spec.rb
+
+### 1. Drop `is_oauth:` from `StreamCollector.new` calls
+
+Phase 02 removed the keyword. Remove from spec setup.
+
+### 2. Update fixture-driven assertions
+
+For the `text-only.sse` fixture, the collector should now assemble:
+
+- One `TextBlock` with text `"Hello, world!"`
+- `stop_reason: :end_turn`
+- `usage.input_tokens: 15`
+- `usage.output_tokens: 8`
+- `model: "MiniMax-M2.7"`
+
+For `tool-use.sse`:
+
+- Zero text blocks.
+- One `ToolUseBlock` with id `toolu_minimax01`, name `get_weather`,
+ arguments `{"city" => "Boston"}`.
+- `stop_reason: :tool_use`.
+- `usage.input_tokens: 50`, `usage.output_tokens: 18`.
+
+For `thinking-then-text.sse`:
+
+- One `ThinkingBlock` with thinking
+ `"Considering the question... the answer is two."` and signature `""`
+ (or `nil`, depending on how the existing builder handles empty
+ signatures — match the actual lib behavior).
+- One `TextBlock` with text `"The answer is 2."`
+- `stop_reason: :end_turn`.
+
+### 3. Drop cloaking assertions
+
+Any assertion that the collector strips a `proxy_` prefix from tool
+names should be DELETED — there is no prefix to strip.
+
+### 4. Cost assertions
+
+Same as response builder spec: update any cost assertions to expect
+`0.0` since pricing is zeroed.
+
+## Acceptance criteria
+
+- `response_builder_spec.rb`, `sse_parser_spec.rb`, and
+ `stream_collector_spec.rb` all pass cleanly.
+- No `.skip` or `pending` examples remain in any of the three.
+- `grep -n 'is_oauth\|proxy_\|claude-sonnet\|claude-3' spec/dispatch/adapter/minimax/{response_builder_spec,sse_parser_spec,stream_collector_spec}.rb`
+ returns ZERO matches.
+- `bundle exec rubocop --autocorrect-all` exits 0.
+
+## Verification
+
+Run `run_tests` with `project_path=reference/dispatch-adapter-minimax`.
+Rubocop and these three retargeted specs must pass. Other spec
+failures (chat_*, list_models, etc.) are acceptable and fixed in
+phases 15–16.