Compare commits

...

2 Commits

Author SHA1 Message Date
Teknium
b7b3c8797f fix(display): show reasoning during streaming even when tool calls suppress content
When a model generates content (containing <REASONING_SCRATCHPAD> tags)
alongside tool calls in the same API response, content deltas were
suppressed from streaming once any tool call chunk arrived. This
prevented the CLI's tag extraction from running, so reasoning was
never shown during streaming. The post-response fallback then
displayed reasoning AFTER the already-visible streamed response,
creating a confusing reversed order.

Fix: route suppressed content to stream_delta_callback even when tool
calls are present. The CLI's _stream_delta handles tag extraction —
reasoning tags are routed to the reasoning display box, while
non-reasoning text is handled by the existing stream display logic.
This ensures reasoning appears before tool execution and the final
response, matching the expected visual order.
2026-03-28 12:32:00 -07:00
Teknium
c038ba35bb fix(provider): remove MiniMax /v1→/anthropic auto-correction to allow user override
The minimax-specific auto-correction in runtime_provider.py was
preventing users from overriding to the OpenAI-compatible endpoint
via MINIMAX_BASE_URL. Users in certain regions get nginx 404 on
api.minimax.io/anthropic and need to switch to api.minimax.chat/v1.

The generic URL-suffix detection already handles /anthropic →
anthropic_messages, so the minimax-specific code was redundant for
the default path and harmful for the override path.

Now: default /anthropic URL works via generic detection, user
override to /v1 gets chat_completions mode naturally.

Closes #3546 (different approach — respects user overrides instead
of changing the default endpoint).
2026-03-28 11:31:47 -07:00
3 changed files with 26 additions and 15 deletions

View File

@@ -407,12 +407,6 @@ def resolve_runtime_provider(
# (e.g. https://api.minimax.io/anthropic, https://dashscope.../anthropic)
elif base_url.rstrip("/").endswith("/anthropic"):
api_mode = "anthropic_messages"
# MiniMax providers always use Anthropic Messages API.
# Auto-correct stale /v1 URLs (from old .env or config) to /anthropic.
elif provider in ("minimax", "minimax-cn"):
api_mode = "anthropic_messages"
if base_url.rstrip("/").endswith("/v1"):
base_url = base_url.rstrip("/")[:-3] + "/anthropic"
return {
"provider": provider,
"api_mode": api_mode,

View File

@@ -3903,6 +3903,23 @@ class AIAgent:
_fire_first_delta()
self._fire_stream_delta(delta.content)
deltas_were_sent["yes"] = True
else:
# Tool calls suppress regular content streaming (avoids
# displaying chatty "I'll use the tool..." text alongside
# tool calls). But reasoning tags embedded in suppressed
# content should still reach the display — otherwise the
# reasoning box only appears as a post-response fallback,
# rendering it confusingly after the already-streamed
# response. Route suppressed content through the stream
# delta callback so its tag extraction can fire the
# reasoning display. Non-reasoning text is harmlessly
# suppressed by the CLI's _stream_delta when the stream
# box is already closed (tool boundary flush).
if self.stream_delta_callback:
try:
self.stream_delta_callback(delta.content)
except Exception:
pass
# Accumulate tool call deltas — notify display on first name
if delta and delta.tool_calls:

View File

@@ -493,22 +493,22 @@ def test_minimax_default_url_uses_anthropic_messages(monkeypatch):
assert resolved["base_url"] == "https://api.minimax.io/anthropic"
def test_minimax_stale_v1_url_auto_corrected(monkeypatch):
"""MiniMax with stale /v1 base URL should be auto-corrected to /anthropic."""
def test_minimax_v1_url_uses_chat_completions(monkeypatch):
"""MiniMax with /v1 base URL should use chat_completions (user override for regions where /anthropic 404s)."""
monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "minimax")
monkeypatch.setattr(rp, "_get_model_config", lambda: {})
monkeypatch.setenv("MINIMAX_API_KEY", "test-minimax-key")
monkeypatch.setenv("MINIMAX_BASE_URL", "https://api.minimax.io/v1")
monkeypatch.setenv("MINIMAX_BASE_URL", "https://api.minimax.chat/v1")
resolved = rp.resolve_runtime_provider(requested="minimax")
assert resolved["provider"] == "minimax"
assert resolved["api_mode"] == "anthropic_messages"
assert resolved["base_url"] == "https://api.minimax.io/anthropic"
assert resolved["api_mode"] == "chat_completions"
assert resolved["base_url"] == "https://api.minimax.chat/v1"
def test_minimax_cn_stale_v1_url_auto_corrected(monkeypatch):
"""MiniMax-CN with stale /v1 base URL should be auto-corrected to /anthropic."""
def test_minimax_cn_v1_url_uses_chat_completions(monkeypatch):
"""MiniMax-CN with /v1 base URL should use chat_completions (user override)."""
monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "minimax-cn")
monkeypatch.setattr(rp, "_get_model_config", lambda: {})
monkeypatch.setenv("MINIMAX_CN_API_KEY", "test-minimax-cn-key")
@@ -517,8 +517,8 @@ def test_minimax_cn_stale_v1_url_auto_corrected(monkeypatch):
resolved = rp.resolve_runtime_provider(requested="minimax-cn")
assert resolved["provider"] == "minimax-cn"
assert resolved["api_mode"] == "anthropic_messages"
assert resolved["base_url"] == "https://api.minimaxi.com/anthropic"
assert resolved["api_mode"] == "chat_completions"
assert resolved["base_url"] == "https://api.minimaxi.com/v1"
def test_minimax_explicit_api_mode_respected(monkeypatch):