mimo2codex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md ADDED
@@ -0,0 +1,124 @@
1
+ # Agent instructions for the mimo2codex repo
2
+
3
+ This repo is a local proxy that lets the latest OpenAI Codex CLI / desktop talk
4
+ to **Xiaomi MiMo V2.5** by translating the Responses API to MiMo's Chat
5
+ Completions API. When you (the agent) run inside Codex pointed at this proxy,
6
+ the chat backend is **MiMo, not OpenAI** — adjust your assumptions accordingly.
7
+
8
+ ## Hard rules
9
+
10
+ 1. **Never `pip install openai` and never `import openai`.** This project
11
+ intentionally avoids the OpenAI Python SDK. The user's API key is for
12
+ Xiaomi MiMo, not OpenAI — `openai` SDK calls would either fail
13
+ authentication or hit endpoints that don't exist. The sandbox also blocks
14
+ network installs.
15
+
16
+ 2. **Never assume image generation is available natively.** MiMo V2.5 does not
17
+ have an image generation endpoint. Codex's `/hatch` (which calls OpenAI's
18
+ `gpt-image-1`) does not work when Codex is pointed at MiMo. There is a
19
+ ready-made workaround in `mimoskill/`; use that instead of writing fresh
20
+ code to call `gpt-image-1`.
21
+
22
+ 3. **Don't fight the sandbox by asking the user to install packages.** If you
23
+ would normally write code that needs a Python dependency, first check
24
+ `mimoskill/scripts/` — most things you need are already there using only
25
+ stdlib (`urllib.request`, `json`, etc.). If you genuinely need a new
26
+ dependency, say so explicitly with the user before adding code that
27
+ depends on it.
28
+
29
+ ## Where things are
30
+
31
+ - `src/` — TypeScript source for the mimo2codex proxy itself (Node 18+).
32
+ Compiled to `dist/` via `npm run build`. Tests in `test/`.
33
+ - `scripts/install.sh` and `scripts/install.ps1` — bootstrap scripts (clone or
34
+ in-repo run, install deps, build, test).
35
+ - `mimoskill/` — a self-contained directory with helpers for MiMo + workarounds
36
+ for what MiMo doesn't do. **This is where you should look first when the
37
+ user asks for anything beyond plain chat.**
38
+
39
+ ## Specifically: generating a Codex pet from an image
40
+
41
+ The user almost certainly hits this when they say "generate a pet" /
42
+ "`/hatch` doesn't work" / "the image generation tool isn't available". The
43
+ flow you should follow is **already implemented** — just invoke it, do not
44
+ rewrite it from scratch:
45
+
46
+ ```bash
47
+ # 1. Generate the pet image. --provider auto picks the best available backend
48
+ # given the env vars: gpt-image-1 if PET_OPENAI_API_KEY is set, otherwise
49
+ # pollinations.ai (free, no key, no signup). With only MIMO_API_KEY,
50
+ # auto = pollinations.
51
+ python3 mimoskill/scripts/generate_pet.py \
52
+ --description "<short chibi pet description>" \
53
+ --out /tmp/pet.png
54
+
55
+ # 2. Optional: bundle of three states (idle / working / done) from one call
56
+ python3 mimoskill/scripts/generate_pet.py \
57
+ --description "<...>" \
58
+ --bundle /tmp/my-pet/
59
+
60
+ # 3. Install into Codex's pet directory (probes macOS/Linux/Windows paths)
61
+ bash mimoskill/scripts/install_pet.sh /tmp/pet.png "<pet-name>"
62
+ # or for the bundle:
63
+ bash mimoskill/scripts/install_pet.sh --bundle /tmp/my-pet/ "<pet-name>"
64
+ ```
65
+
66
+ If the sandbox blocks the network call (Pollinations / OpenAI / Replicate),
67
+ do NOT respond with "please install openai". The correct response is:
68
+
69
+ > "I can't reach the network from inside the sandbox. Please run the
70
+ > following in a regular terminal (outside Codex), then tell me when it's
71
+ > done and I'll continue:
72
+ >
73
+ > python3 mimoskill/scripts/generate_pet.py --description "..." --out /tmp/pet.png
74
+ > bash mimoskill/scripts/install_pet.sh /tmp/pet.png "<pet-name>"
75
+ >
76
+ > No `pip install` is needed — the script uses only the Python standard
77
+ > library."
78
+
79
+ ## Other MiMo capability gaps
80
+
81
+ When the user asks for something MiMo doesn't natively support, the answer
82
+ is in `mimoskill/references/models.md`. Quick rules:
83
+
84
+ - **Image input (vision)** — only `mimo-v2.5` and `mimo-v2-omni` accept it.
85
+ `mimo-v2.5-pro` does NOT. mimo2codex auto-strips images on non-vision
86
+ models.
87
+ - **Image generation** — none of MiMo's models do this. Use
88
+ `mimoskill/scripts/generate_pet.py` (works for any image-gen task, not
89
+ just pets).
90
+ - **TTS / ASR** — separate MiMo endpoints (`mimo-v2.5-tts`, `mimo-v2.5-asr`).
91
+ Out of scope for the chat completions proxy; call them directly.
92
+ - **Code interpreter / sandboxed Python** — not provided by MiMo. Run code
93
+ locally if needed.
94
+ - **`computer_use_preview` / `file_search`** — server-side OpenAI tools with
95
+ no MiMo equivalent. mimo2codex silently drops them.
96
+
97
+ ## Field quirks when calling MiMo directly
98
+
99
+ These bite people; use them when writing chat-completions calls:
100
+
101
+ - Use `max_completion_tokens`, NOT `max_tokens`.
102
+ - When you send `image_url` content, you MUST also send a `text` content part
103
+ in the same array — image-only messages return 400 "Param Incorrect:
104
+ `text` is not set". An empty space `" "` is enough.
105
+ - Reasoning is `reasoning_content` on the assistant message (DeepSeek-style),
106
+ not `reasoning_summary`.
107
+ - Web search is a builtin tool of `type: "web_search"` — **not** a function
108
+ tool. Requires the user to have activated the Web Search Plugin in their
109
+ MiMo console (separately metered).
110
+ - `tool_choice` other than `"auto"` is silently ignored upstream right now.
111
+
112
+ For the canonical reference, hit
113
+ `https://platform.xiaomimimo.com/docs/api/chat/openai-api`.
114
+
115
+ ## When in doubt
116
+
117
+ - Read `README.md` (English) or `README.zh.md` (Chinese) for the proxy itself.
118
+ - Read `mimoskill/SKILL.md` for the MiMo helper library and pet workflow.
119
+ - Both `node dist/cli.js print-config` and `node dist/cli.js print-cc-switch`
120
+ emit ready-to-paste config snippets — prefer those over hand-crafting
121
+ TOML / JSON.
122
+ - If you find yourself writing a new `import openai` or `pip install
123
+ openai` line, stop and use `mimoskill/scripts/mimo_chat.py` (chat) or
124
+ `mimoskill/scripts/generate_pet.py` (image gen) instead.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 7as0nch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,536 @@
1
+ # mimo2codex
2
+
3
+ > English · [中文文档](./README.zh.md)
4
+
5
+ Local proxy that lets the **latest OpenAI Codex CLI** and **Codex desktop app** talk to **Xiaomi MiMo V2.5 Pro** by translating Codex's Responses API ↔ MiMo's Chat Completions API on the fly. Works standalone, or as a custom Codex provider in [cc-switch](https://github.com/farion1231/cc-switch) — switch between OpenAI / MiMo / Azure / OpenRouter etc. with one click.
6
+
7
+ > Why? MiMo's official [Codex integration doc](https://platform.xiaomimimo.com/docs/zh-CN/integration/codex) tells you the only supported wire is `wire_api = "chat"`, but newer Codex versions hard-error with `wire_api = chat is no longer supported`. The official workaround is to downgrade Codex (losing the new pet, tool, and desktop features). This proxy is a better workaround: leave Codex on the latest version, run mimo2codex locally, and Codex will think it's talking to a native Responses-API backend.
8
+ >
9
+ > Conceptually similar to [openrouter](https://openrouter.ai), [claude-code-router](https://github.com/musistudio/claude-code-router) and [y-router](https://github.com/luohy15/y-router) — pure stateless protocol translation, no scheduling, no storage.
10
+
11
+ ## What works
12
+
13
+ - ✅ Codex CLI 0.x with `wire_api = "responses"`
14
+ - ✅ Codex desktop app (macOS / Windows) — same `~/.codex/config.toml`
15
+ - ✅ Pet companion (status driven by SSE event lifecycle, no special handling needed)
16
+ - ✅ Tool calling — function tools, including parallel calls
17
+ - ✅ Multi-turn conversations with mixed tool calls + reasoning
18
+ - ✅ Streaming SSE with full Responses event schema (`response.created`, `output_item.added`, `output_text.delta`, `function_call_arguments.delta`, `reasoning_summary_text.delta`, `completed`, …)
19
+ - ✅ Thinking mode passthrough — MiMo's `reasoning_content` is shown in Codex's reasoning panel and re-injected on follow-up turns to keep multi-turn tool quality high (per MiMo's docs)
20
+ - ✅ 1M context — pass `mimo-v2.5-pro[1m]` as the model
21
+ - ✅ **cc-switch integration** — `mimo2codex print-cc-switch` outputs the auth.json + config.toml snippets you paste into cc-switch's "Add Provider → Codex → Custom" dialog
22
+
23
+ ## Install
24
+
25
+ Pick one:
26
+
27
+ ### 🟢 Option 1: npm (recommended for most users)
28
+
29
+ ```bash
30
+ npm install -g mimo2codex
31
+ mimo2codex --version
32
+ ```
33
+
34
+ Requires Node.js ≥ 18. After install, `mimo2codex` is on your PATH:
35
+
36
+ ```bash
37
+ export MIMO_API_KEY=sk-xxxxxxxxxxxxxxxx
38
+ mimo2codex # start the proxy
39
+ mimo2codex print-config # print the ~/.codex/config.toml snippet
40
+ mimo2codex print-cc-switch # print the cc-switch config snippet
41
+ mimo2codex --port 9000 --verbose
42
+ ```
43
+
44
+ Upgrade later: `npm update -g mimo2codex`. Remove: `npm rm -g mimo2codex`.
45
+
46
+ If you only want to use it, Options 2 and 3 below are not needed — skip to [Get a MiMo API key](#get-a-mimo-api-key).
47
+
48
+ ---
49
+
50
+ ### 🛠 Option 2: clone + one-shot script (for contributors)
51
+
52
+ The repo ships [`scripts/install.sh`](./scripts/install.sh) (Linux / macOS / Git Bash / WSL) and [`scripts/install.ps1`](./scripts/install.ps1) (Windows PowerShell) that:
53
+
54
+ 1. Verify git / Node.js ≥ 18 / npm — and tell you how to install each if missing
55
+ 2. Clone the repo on first run; on subsequent runs `git pull --ff-only`
56
+ 3. `npm install` → `npm run build` → `npm test`
57
+ 4. Print exactly what to do next
58
+
59
+ **Linux / macOS / Git Bash / WSL:**
60
+
61
+ ```bash
62
+ # Remote one-liner (replace with your actual raw URL)
63
+ curl -fsSL https://raw.githubusercontent.com/7as0nch/mimo2codex/main/scripts/install.sh | bash
64
+
65
+ # Or local: clone first, then run
66
+ git clone https://github.com/your-org/mimo2codex.git
67
+ cd mimo2codex
68
+ ./scripts/install.sh
69
+
70
+ # Install + start the proxy in one go
71
+ MIMO_API_KEY=sk-xxx ./scripts/install.sh --start
72
+ ```
73
+
74
+ **Windows PowerShell:**
75
+
76
+ ```powershell
77
+ # Remote one-liner
78
+ irm https://raw.githubusercontent.com/7as0nch/mimo2codex/main/scripts/install.ps1 | iex
79
+
80
+ # Or local
81
+ git clone https://github.com/your-org/mimo2codex.git
82
+ cd mimo2codex
83
+ .\scripts\install.ps1
84
+
85
+ # Install + start
86
+ $env:MIMO_API_KEY = "sk-xxx"
87
+ .\scripts\install.ps1 -Start
88
+ ```
89
+
90
+ > If PowerShell complains "running scripts is disabled", run once:
91
+ > `Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned`
92
+
93
+ The scripts are **idempotent** — rerun anytime to pull, rebuild, retest. Use this to upgrade.
94
+
95
+ ---
96
+
97
+ ### 🔧 Option 3: manual setup (full control over each step)
98
+
99
+ Skip this section if Option 1 or 2 worked — it's only here for people who want to do each step by hand.
100
+
101
+ #### 0. Prerequisites
102
+
103
+ | Tool | Required | Check |
104
+ |---|---|---|
105
+ | Node.js | **≥ 18** | `node -v` |
106
+ | npm | bundled with Node | `npm -v` |
107
+ | git | any | `git --version` |
108
+
109
+ If `node -v` is missing or below 18, grab an LTS from [nodejs.org](https://nodejs.org). Windows users can also use [nvs](https://github.com/jasongin/nvs) or [nvm-windows](https://github.com/coreybutler/nvm-windows).
110
+
111
+ #### 1. Clone & install dependencies
112
+
113
+ ```bash
114
+ git clone https://github.com/your-org/mimo2codex.git
115
+ cd mimo2codex
116
+ npm install
117
+ ```
118
+
119
+ Installs ~87 packages (typescript, vitest, tsx, nanoid, eventsource-parser); takes 30–60s.
120
+
121
+ #### 2. Pick a run mode
122
+
123
+ #### Mode A — dev mode (no build, fastest to try)
124
+
125
+ Runs the TypeScript directly via `tsx`:
126
+
127
+ ```bash
128
+ # Linux / macOS / Git Bash
129
+ export MIMO_API_KEY=sk-xxxxxxxxxxxxxxxx
130
+ npm run dev
131
+
132
+ # Windows PowerShell
133
+ $env:MIMO_API_KEY="sk-xxxxxxxxxxxxxxxx"
134
+ npm run dev
135
+
136
+ # Windows CMD
137
+ set MIMO_API_KEY=sk-xxxxxxxxxxxxxxxx
138
+ npm run dev
139
+ ```
140
+
141
+ Pass extra flags after `--`:
142
+
143
+ ```bash
144
+ npm run dev -- --port 9000
145
+ npm run dev -- --base-url https://token-plan-cn.xiaomimimo.com/v1
146
+ npm run dev -- print-cc-switch
147
+ ```
148
+
149
+ #### Mode B — build then run (lowest runtime overhead)
150
+
151
+ Compiles to plain JS, runs with vanilla Node — startup < 100ms, no tsx in process:
152
+
153
+ ```bash
154
+ npm run build # one-time
155
+ npm start # or: node dist/cli.js
156
+ npm start -- --port 9000
157
+ node dist/cli.js print-cc-switch
158
+ ```
159
+
160
+ `dist/` is git-ignored. Re-run `npm run build` after editing source.
161
+
162
+ #### Mode C — register `mimo2codex` as a global command (no publish needed)
163
+
164
+ ```bash
165
+ npm run build
166
+ npm link
167
+ ```
168
+
169
+ Then from any directory:
170
+
171
+ ```bash
172
+ mimo2codex --version
173
+ mimo2codex print-cc-switch
174
+ MIMO_API_KEY=sk-xxx mimo2codex
175
+ ```
176
+
177
+ To undo: `npm unlink` in the repo, or `npm rm -g mimo2codex` globally.
178
+
179
+ > Throughout the rest of this README, `mimo2codex …` means whichever invocation matches your mode: `npm run dev -- …` (A), `node dist/cli.js …` (B), or `mimo2codex …` (C).
180
+
181
+ #### 3. Run the tests (optional)
182
+
183
+ ```bash
184
+ npm test
185
+ ```
186
+
187
+ Expect 25 passing across 3 files.
188
+
189
+ #### 4. Keep the proxy running in the background
190
+
191
+ #### macOS / Linux — systemd user unit
192
+
193
+ Create `~/.config/systemd/user/mimo2codex.service`:
194
+
195
+ ```ini
196
+ [Unit]
197
+ Description=mimo2codex — Codex Responses → Xiaomi MiMo proxy
198
+ After=network.target
199
+
200
+ [Service]
201
+ Type=simple
202
+ WorkingDirectory=/absolute/path/to/mimo2codex
203
+ Environment="MIMO_API_KEY=sk-xxxxxxxxxxxxxxxx"
204
+ ExecStart=/usr/bin/node dist/cli.js
205
+ Restart=on-failure
206
+
207
+ [Install]
208
+ WantedBy=default.target
209
+ ```
210
+
211
+ ```bash
212
+ systemctl --user daemon-reload
213
+ systemctl --user enable --now mimo2codex
214
+ journalctl --user -u mimo2codex -f
215
+ ```
216
+
217
+ #### Cross-platform — pm2
218
+
219
+ ```bash
220
+ npm install -g pm2
221
+ cd mimo2codex && npm run build
222
+ MIMO_API_KEY=sk-xxx pm2 start dist/cli.js --name mimo2codex
223
+ pm2 save && pm2 startup
224
+ ```
225
+
226
+ #### Windows — Task Scheduler
227
+
228
+ 1. Task Scheduler → Create Basic Task
229
+ 2. Trigger: At log on
230
+ 3. Action: Start a program
231
+ - Program: `C:\Program Files\nodejs\node.exe`
232
+ - Arguments: `D:\path\to\mimo2codex\dist\cli.js`
233
+ - Start in: `D:\path\to\mimo2codex`
234
+ 4. Set `MIMO_API_KEY` in the task's environment, or globally in System Properties → Environment Variables
235
+
236
+ #### 5. Updating
237
+
238
+ ```bash
239
+ cd mimo2codex
240
+ git pull
241
+ npm install # only if dependencies changed
242
+ npm run build # required for Mode B/C
243
+ # restart your background process
244
+ ```
245
+
246
+ ---
247
+
248
+ ## Get a MiMo API key
249
+
250
+ Sign up at [platform.xiaomimimo.com](https://platform.xiaomimimo.com), create a key in **Console → API Keys**. Either pay-as-you-go (`sk-xxx`) or token-plan (`tp-xxx`) works.
251
+
252
+ ## Use
253
+
254
+ ### 1. Start the proxy
255
+
256
+ Pick whichever launch mode you set up above:
257
+
258
+ ```bash
259
+ export MIMO_API_KEY=sk-xxxxxxxxxxxxxxxx
260
+ npm run dev # or: node dist/cli.js / mimo2codex
261
+ ```
262
+
263
+ The startup banner prints the **default snippet** (auth.json variant — works for Codex CLI **and** desktop app, no env vars needed):
264
+
265
+ ```
266
+ mimo2codex v0.1.0 listening on http://127.0.0.1:8788
267
+ upstream: https://api.xiaomimimo.com/v1
268
+
269
+ # Step 1 — write ~/.codex/auth.json
270
+ {
271
+ "OPENAI_API_KEY": "mimo2codex-local"
272
+ }
273
+
274
+ # Step 2 — append to ~/.codex/config.toml
275
+ model = "mimo-v2.5-pro"
276
+ model_provider = "mimo"
277
+
278
+ [model_providers.mimo]
279
+ name = "MiMo (via mimo2codex)"
280
+ base_url = "http://127.0.0.1:8788/v1"
281
+ wire_api = "responses"
282
+ requires_openai_auth = true
283
+ request_max_retries = 1
284
+ ```
285
+
286
+ ### 2. Write the two files
287
+
288
+ | file | macOS / Linux | Windows |
289
+ |---|---|---|
290
+ | auth.json | `~/.codex/auth.json` | `%USERPROFILE%\.codex\auth.json` |
291
+ | config.toml | `~/.codex/config.toml` | `%USERPROFILE%\.codex\config.toml` |
292
+
293
+ The `OPENAI_API_KEY` value is just a placeholder — the proxy doesn't validate inbound credentials. Your real MiMo key stays in `MIMO_API_KEY` on the machine running mimo2codex.
294
+
295
+ > ⚠️ If you also use Codex with your real OpenAI account, this overwrites your OpenAI login. Use cc-switch (next section) to manage multiple providers cleanly.
296
+
297
+ ### 3. Restart Codex (desktop app: required)
298
+
299
+ If you use the **Codex desktop app**: fully quit it (system tray / menu bar → Quit, not just close the window) and relaunch — otherwise it won't pick up the new auth.json.
300
+
301
+ If you use the **Codex CLI**: just run it:
302
+
303
+ ```bash
304
+ codex
305
+ > Write a Python fibonacci function and save it to fib.py
306
+ ```
307
+
308
+ The pet, tool calls, reasoning summary, and multi-turn flow all work. Pass `--no-reasoning` when starting the proxy to hide reasoning from the terminal (it's still re-injected to MiMo for multi-turn quality).
309
+
310
+ > 💡 **Want the env-var variant** (preserves your OpenAI auth.json untouched)? Run `npm run dev -- print-config --env-key`. **Codex CLI only** — desktop apps launched from Finder/Start Menu don't see shell env vars.
311
+
312
+ ## Use with cc-switch
313
+
314
+ [cc-switch](https://github.com/farion1231/cc-switch) is a desktop app that manages multiple Codex / Claude Code / OpenCode providers and lets you switch between them in one click. Its built-in Codex preset list does **not** include MiMo (because MiMo doesn't speak Responses API) — but you can plug mimo2codex in as a custom provider.
315
+
316
+ > ⚠️ **Two parts must run side-by-side**: the **mimo2codex proxy** (a long-running HTTP server you keep alive) and the **cc-switch GUI** (which holds your provider configs). `print-cc-switch` only prints config text to copy — it doesn't start anything.
317
+
318
+ 1. **Keep mimo2codex running** in a terminal (don't close it):
319
+
320
+ ```bash
321
+ cd /path/to/mimo2codex
322
+ export MIMO_API_KEY=sk-xxxxxxxxxxxxxxxx
323
+ npm run dev # or node dist/cli.js, see "Run from source" above
324
+ ```
325
+
326
+ Wait for `listening on http://127.0.0.1:8788`. To run it as a background service, see [step 4 above](#4-keep-the-proxy-running-in-the-background).
327
+
328
+ 2. **In a separate terminal**, print the cc-switch snippets:
329
+
330
+ ```bash
331
+ cd /path/to/mimo2codex
332
+ npm run dev -- print-cc-switch # or: node dist/cli.js print-cc-switch
333
+ ```
334
+
335
+ It outputs two blocks: an `auth.json` block and a `config.toml` block.
336
+
337
+ 3. In cc-switch GUI: switch to the **Codex** tab → click **+** → choose **App-specific Provider** → preset = **Custom**.
338
+ 4. Paste the `auth.json` block into the auth.json textarea, paste the `config.toml` block into the config.toml textarea, set the name to `MiMo (via mimo2codex)`, click **Add**.
339
+ 5. Click the new entry to make it active. cc-switch writes `~/.codex/auth.json` + `~/.codex/config.toml` for you.
340
+ 6. Run `codex`. Switch back to OpenAI Official / Azure / OpenRouter / etc. anytime by clicking another entry in cc-switch — mimo2codex keeps running and only sees traffic when its provider is selected.
341
+
342
+ cc-switch's "Fetch Models" button on the provider form calls `/v1/models`, which mimo2codex implements — so the model dropdown will list `mimo-v2.5-pro`, `mimo-v2.5-pro[1m]`, and `mimo-v2-flash` automatically.
343
+
344
+ ## CLI flags
345
+
346
+ | Flag | Env | Default | Notes |
347
+ |---|---|---|---|
348
+ | `--port`, `-p` | `MIMO2CODEX_PORT` | `8788` | listen port |
349
+ | `--host` | `MIMO2CODEX_HOST` | `127.0.0.1` | bind host (keep on loopback) |
350
+ | `--base-url` | `MIMO_BASE_URL` | `https://api.xiaomimimo.com/v1` | switch to `https://token-plan-cn.xiaomimimo.com/v1` for the Token Plan |
351
+ | `--api-key` | `MIMO_API_KEY` | _required_ | upstream MiMo key |
352
+ | `--no-reasoning` | `MIMO2CODEX_NO_REASONING=1` | off | hide reasoning from Codex (still preserved between turns) |
353
+ | `--verbose`, `-v` | `MIMO2CODEX_VERBOSE=1` | off | log every translated request |
354
+
355
+ Subcommands:
356
+
357
+ ```bash
358
+ mimo2codex print-config # write the ~/.codex/config.toml snippet to stdout
359
+ mimo2codex print-cc-switch # write the cc-switch auth.json + config.toml snippets
360
+ mimo2codex --port 9000 print-config # adjust port in the snippet
361
+ ```
362
+
363
+ ## How it works
364
+
365
+ ```
366
+ ┌─────────────┐ POST /v1/responses ┌──────────────┐ POST /v1/chat/completions ┌─────────────┐
367
+ │ Codex CLI / │ (wire_api="responses") │ mimo2codex │ (chat completions, SSE) │ Xiaomimimo │
368
+ │ Codex App │ ──────────────────────► │ 127.0.0.1 │ ────────────────────────────► │ MiMo V2.5 │
369
+ └─────────────┘ ◄────────────────────── │ :8788 │ ◄──────────────────────────── └─────────────┘
370
+ Responses SSE └──────────────┘ Chat SSE
371
+ ```
372
+
373
+ For each request:
374
+
375
+ 1. Codex POSTs a Responses payload (`input` array of message/function_call/function_call_output/reasoning items).
376
+ 2. mimo2codex translates `input` → Chat `messages`, folding consecutive `reasoning` + `function_call` items into a single assistant turn with `reasoning_content` + `tool_calls`.
377
+ 3. mimo2codex POSTs to MiMo's `/v1/chat/completions` (Bearer auth).
378
+ 4. Streams back Chat SSE chunks; the state machine in `streamToSse.ts` rewrites them as Responses SSE events.
379
+
380
+ That's it. The proxy is fully stateless — no `previous_response_id` storage, no caching, no key validation against incoming requests. Run as many instances as you want.
381
+
382
+ ## Troubleshooting
383
+
384
+ **Codex shows `Missing environment variable: MIMO2CODEX_KEY` (or similar env var error)**
385
+
386
+ Your `~/.codex/config.toml` has `env_key = "MIMO2CODEX_KEY"`, which makes Codex require that env var to be set in **its own** process environment. The Codex desktop app — launched from Finder / Start Menu — does **not** inherit shell env vars set via `export` or `setx`.
387
+
388
+ **Fix (recommended — switch to auth.json, works for CLI and desktop)**:
389
+
390
+ 1. In `~/.codex/config.toml`, replace:
391
+ ```toml
392
+ env_key = "MIMO2CODEX_KEY"
393
+ ```
394
+ with:
395
+ ```toml
396
+ requires_openai_auth = true
397
+ ```
398
+ 2. Write `~/.codex/auth.json`:
399
+ ```json
400
+ { "OPENAI_API_KEY": "mimo2codex-local" }
401
+ ```
402
+ 3. **Fully quit and relaunch Codex** (system tray → Quit on desktop; not just close).
403
+
404
+ Or just run `npm run dev -- print-config` to get the ready-made snippets.
405
+
406
+ **Want to keep the env-var approach (CLI only)**: ensure the env var is set in the shell that launches `codex`. On Windows use `setx MIMO2CODEX_KEY anything` and open a **new** CMD window — `setx` doesn't affect already-open shells. Desktop apps still won't see this; use the auth.json variant or cc-switch instead.
407
+
408
+ ---
409
+
410
+ **mimo2codex is running but Codex hangs / 504 / connection refused**
411
+
412
+ Check:
413
+ 1. The mimo2codex terminal still shows `listening on http://127.0.0.1:8788`
414
+ 2. `curl http://127.0.0.1:8788/healthz` returns `{"ok":true,...}`
415
+ 3. config.toml `base_url` ends with `/v1`: `http://127.0.0.1:8788/v1`
416
+ 4. Port not in use? Switch with `npm run dev -- --port 9999` and update `base_url` accordingly
417
+
418
+ ---
419
+
420
+ **Upstream returns 401 / `authentication_error`**
421
+
422
+ Your `MIMO_API_KEY` (the one mimo2codex uses to call MiMo) is invalid. Get a new one at the [MiMo console](https://platform.xiaomimimo.com/#/console/api-keys). `sk-xxx` keys go with `https://api.xiaomimimo.com/v1`; `tp-xxx` keys go with `https://token-plan-cn.xiaomimimo.com/v1`.
423
+
424
+ ---
425
+
426
+ **`MiMo returned 404 ... No endpoints found that support image input`**
427
+
428
+ The request has images but your model doesn't accept them. Per [MiMo's docs](https://platform.xiaomimimo.com/docs/zh-CN/usage-guide/multimodal-understanding/image-understanding), **only `mimo-v2.5` and `mimo-v2-omni` support image input** — `mimo-v2.5-pro`, `mimo-v2.5-pro[1m]`, and `mimo-v2-flash` do **not**.
429
+
430
+ mimo2codex auto-detects this:
431
+
432
+ | Model | Vision |
433
+ |---|---|
434
+ | `mimo-v2.5` / `mimo-v2.5[1m]` | ✅ |
435
+ | `mimo-v2-omni` / `mimo-v2-omni[1m]` | ✅ |
436
+ | `mimo-v2.5-pro` / `mimo-v2.5-pro[1m]` | ❌ (images stripped + placeholder text inserted) |
437
+ | `mimo-v2-flash` | ❌ |
438
+
439
+ For vision, set the model to `mimo-v2.5` or `mimo-v2-omni` in `~/.codex/config.toml`.
440
+
441
+ ---
442
+
443
+ **`MiMo returned 400 Param Incorrect: \`text\` is not set`**
444
+
445
+ MiMo's image-understanding API **requires every image-bearing user message to include at least one text part** alongside the image. OpenAI's chat API doesn't enforce this, so Codex sometimes sends image-only messages (e.g. paste-and-send on the desktop app), which MiMo then rejects.
446
+
447
+ mimo2codex now adds a single-space text part automatically whenever it sees an `image_url` part with no companion text. The image alone is enough for the model to infer intent (it'll describe what it sees), and your request stops 400'ing.
448
+
449
+ ---
450
+
451
+ **`dropping unsupported tool type "xxx"` warnings in the log**
452
+
453
+ Here's how each tool type from Codex is handled:
454
+
455
+ | Tool type | What mimo2codex does | Notes |
456
+ |---|---|---|
457
+ | `function` | ✅ pass through | standard |
458
+ | `local_shell` | ✅ rewritten as `shell` function tool | Codex routes both names to the same handler |
459
+ | `custom` | ✅ rewritten as a function tool | grammar enforcement is lost but the model can still call it |
460
+ | `namespace` | ✅ recursed into, nested tools flattened | MCP servers, grouped tools |
461
+ | **`web_search` / `web_search_preview`** | ✅ **translated to MiMo's native `web_search` builtin** | see below |
462
+ | `code_interpreter` | ❌ silently dropped (debug log) | OpenAI/Azure server-side; no MiMo equivalent |
463
+ | `file_search` / `image_generation` | ❌ silently dropped | server-side |
464
+ | `computer_use_preview` / `computer_use` | ❌ silently dropped | server-side |
465
+ | anything else | ❌ dropped, **WARN on first occurrence per type** | open an issue if you hit this |
466
+
467
+ The "server-side" tools have no implementation outside OpenAI/Azure infrastructure — forwarding them to MiMo would just produce errors. The previous version warned on every request (very noisy); now known server-side tools are completely silent at default log level, and unknown types log only the first time.
468
+
469
+ ---
470
+
471
+ **Does web search work?**
472
+
473
+ **Yes.** mimo2codex translates Codex's `web_search` / `web_search_preview` tool definitions into MiMo's native [Web Search builtin](https://platform.xiaomimimo.com/#/docs/usage-guide/tool-calling/web-search), including:
474
+
475
+ - forwarding `user_location` (country / region / city / lat-lon)
476
+ - forwarding MiMo-specific knobs (`max_keyword`, `force_search`, `limit`) if Codex sent them
477
+ - translating MiMo's `annotations` (citations) back into Codex's `url_citation` annotations on the `output_text` content part — Codex shows them as inline link citations
478
+ - emitting `response.output_text.annotation.added` events per citation while streaming
479
+
480
+ **Prerequisites**:
481
+
482
+ 1. Activate the **Web Search Plugin** in [your MiMo console → Plugin Management](https://platform.xiaomimimo.com/#/console/plugin) (separately billed, see [Pricing](https://platform.xiaomimimo.com/#/docs/pricing))
483
+ 2. Be aware: a single search round may invoke multiple concurrent keyword searches — each is billed. Use `max_keyword` to cap.
484
+
485
+ Once activated, no extra config is needed. Just enable web search in Codex and ask a current-events question.
486
+
487
+ ---
488
+
489
+ ## FAQ
490
+
491
+ **Does this support Codex's pet feature?**
492
+ Yes — pets are a desktop UI overlay driven by Codex's internal status (working / waiting-input / done / error). That status is computed from the Responses SSE event lifecycle (`response.created`, `response.in_progress`, `response.output_item.added`, `response.completed`, `response.failed`). The proxy emits exactly those events, so pets behave normally.
493
+
494
+ **Does this support tool calling?**
495
+ Yes. Codex's local shell, file edit, web fetch, and any custom tools all flow through unchanged — the proxy translates `function_call` Responses items ↔ `tool_calls` Chat fields, including arguments-delta streaming for parallel calls.
496
+
497
+ **What about images / audio?**
498
+ The proxy passes `input_image` parts through as `image_url` parts. Note: MiMo's chat API only accepts images on the `mimo-v2-omni` model; on `mimo-v2.5-pro` they will be silently dropped by upstream. `input_file` is dropped with a warning (MiMo chat API doesn't support it).
499
+
500
+ **Token plan endpoint?**
501
+ Pass `--base-url https://token-plan-cn.xiaomimimo.com/v1` and use your `tp-xxx` key.
502
+
503
+ **Is reasoning ever lost?**
504
+ No. Even with `--no-reasoning` the proxy still receives and stores `reasoning_content` so it can re-inject it on the next turn (MiMo recommends this for multi-turn tool quality). The flag only controls whether reasoning is surfaced to the Codex terminal.
505
+
506
+ **Why not just patch Codex to accept the chat wire?**
507
+ That works for the CLI today (downgrade to 0.80.0), but you lose pets, the new desktop release, and any future improvements. A protocol shim is a smaller, longer-lived fix.
508
+
509
+ **How do I see what the proxy is doing?**
510
+ Start with `--verbose` (or `MIMO2CODEX_VERBOSE=1`). Each upstream POST is logged to stderr with model, message count, tool count, stream flag, and a redacted key. No request bodies are logged.
511
+
512
+ ## Project layout
513
+
514
+ ```
515
+ mimo2codex/
516
+ ├── src/
517
+ │ ├── cli.ts # entry: argv, server boot, snippet printing
518
+ │ ├── server.ts # node:http server, routes /v1/responses, /v1/models, /healthz
519
+ │ ├── config.ts # env + flag merge
520
+ │ ├── upstream/
521
+ │ │ ├── mimoClient.ts # fetch wrapper (retry, error normalization)
522
+ │ │ └── chatStream.ts # upstream Chat SSE → ChatStreamChunk async iterator
523
+ │ ├── translate/
524
+ │ │ ├── types.ts # Responses + ChatCompletions types
525
+ │ │ ├── reqToChat.ts # request-direction translator
526
+ │ │ ├── respToResponses.ts # non-stream response translator
527
+ │ │ └── streamToSse.ts # streaming state machine
528
+ │ └── util/{ids,sse,log}.ts
529
+ ├── test/ # 25 vitest tests
530
+ ├── dist/ # tsc output (generated)
531
+ ├── package.json / tsconfig.json / vitest.config.ts
532
+ ```
533
+
534
+ ## License
535
+
536
+ MIT