diff --git a/CHANGELOG.md b/CHANGELOG.md
index b13074b..ace2e99 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## v2.1.3 (2026-05-19)
+
+- **Fixed Crof mimo-v2.5-pro stopping mid-response (finish_reason=length)**
+ - Root cause: model emits 600+ `reasoning_content` SSE chunks that exhaust `max_tokens` before any actual content is generated
+ - Strip `reasoning_content` from proxy output — Codex doesn't use reasoning, avoids wasting output tokens on invisible text
+ - Force `max_tokens` minimum of 64000 for openai-compat providers — gives models room for both reasoning and content
+ - Works for all openai-compat providers (Crof, Z.AI, DeepSeek, OpenRouter, etc.)
+
## v2.1.2 (2026-05-19)
- **Fixed Crof.ai and providers stopping after first tool call (root cause: None tool IDs)**
diff --git a/codex-launcher_2.1.2_all.deb b/codex-launcher_2.1.2_all.deb
deleted file mode 100644
index 00f3d80..0000000
Binary files a/codex-launcher_2.1.2_all.deb and /dev/null differ
diff --git a/codex-launcher_2.1.3_all.deb b/codex-launcher_2.1.3_all.deb
new file mode 100644
index 0000000..7245e9c
Binary files /dev/null and b/codex-launcher_2.1.3_all.deb differ
diff --git a/src/codex-launcher-gui b/src/codex-launcher-gui
index 9753029..f9de114 100755
--- a/src/codex-launcher-gui
+++ b/src/codex-launcher-gui
@@ -24,6 +24,11 @@ model_catalog_json = ""
"""
CHANGELOG = [
+ ("2.1.3", "2026-05-19", [
+ "Fixed Crof mimo-v2.5-pro stopping: reasoning_content exhausted all output tokens",
+ "Strip reasoning_content from proxy output — Codex doesn't use it, avoids token waste",
+ "Force max_tokens=64000 minimum for openai-compat providers — gives models room for both reasoning and content",
+ ]),
("2.1.2", "2026-05-19", [
"Fixed Crof.ai and providers stopping after first tool call (root cause: None tool IDs)",
"Codex sends function_call items with id=None — proxy now matches tool results to calls by position",
@@ -527,7 +532,7 @@ class LauncherWin(Gtk.Window):
# header row
hdr = Gtk.Box(spacing=8)
vbox.pack_start(hdr, False, False, 0)
- lbl = Gtk.Label(label="Codex Launcher v2.1.2")
+ lbl = Gtk.Label(label="Codex Launcher v2.1.3")
lbl.set_use_markup(True)
hdr.pack_start(lbl, False, False, 0)
changelog_btn = Gtk.Button(label="Changelog")
diff --git a/src/translate-proxy.py b/src/translate-proxy.py
index 6477672..ffb2d33 100755
--- a/src/translate-proxy.py
+++ b/src/translate-proxy.py
@@ -370,10 +370,6 @@ def oa_resp_to_responses(chat_resp, model, resp_id=None):
fm = {"stop": "completed", "length": "incomplete", "tool_calls": "completed", "content_filter": "incomplete"}
status = fm.get(finish, "incomplete")
outputs = []
- rc = msg.get("reasoning_content")
- if rc:
- outputs.append({"type": "reasoning", "id": uid("rsn"), "status": "completed",
- "content": [{"type": "text", "text": rc}]})
if content:
outputs.append({"type": "message", "id": uid("msg"), "role": "assistant", "status": "completed",
"content": [{"type": "output_text", "text": content, "annotations": []}]})
@@ -447,9 +443,7 @@ def oa_stream_to_sse(chat_stream, model, req_id):
yield emit("response.output_text.delta", {"type": "response.function_call_arguments.delta",
"delta": fn["arguments"], "item_id": tc_buf[idx]["id"]})
- rc = delta.get("reasoning_content")
- if rc:
- yield emit("response.reasoning.delta", {"type": "response.reasoning.delta", "delta": rc})
+
if msg_opened:
yield emit("response.output_text.done", {"type": "response.output_text.done",
@@ -885,9 +879,10 @@ class Handler(http.server.BaseHTTPRequestHandler):
if instructions:
messages.insert(0, {"role": "system", "content": instructions})
chat_body = {"model": model, "messages": messages}
- for k in ("temperature", "top_p", "max_output_tokens"):
+ for k in ("temperature", "top_p"):
if k in body:
- chat_body["max_tokens" if k == "max_output_tokens" else k] = body[k]
+ chat_body[k] = body[k]
+ chat_body["max_tokens"] = max(body.get("max_output_tokens", 0), 64000)
tools = oa_convert_tools(body.get("tools"))
if tools:
chat_body["tools"] = tools