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 +124 -0
- package/LICENSE +21 -0
- package/README.md +536 -0
- package/README.zh.md +750 -0
- package/dist/cli.js +202 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +86 -0
- package/dist/config.js.map +1 -0
- package/dist/server.js +161 -0
- package/dist/server.js.map +1 -0
- package/dist/translate/reqToChat.js +381 -0
- package/dist/translate/reqToChat.js.map +1 -0
- package/dist/translate/respToResponses.js +94 -0
- package/dist/translate/respToResponses.js.map +1 -0
- package/dist/translate/streamToSse.js +352 -0
- package/dist/translate/streamToSse.js.map +1 -0
- package/dist/translate/types.js +4 -0
- package/dist/translate/types.js.map +1 -0
- package/dist/upstream/chatStream.js +56 -0
- package/dist/upstream/chatStream.js.map +1 -0
- package/dist/upstream/mimoClient.js +99 -0
- package/dist/upstream/mimoClient.js.map +1 -0
- package/dist/util/ids.js +19 -0
- package/dist/util/ids.js.map +1 -0
- package/dist/util/log.js +32 -0
- package/dist/util/log.js.map +1 -0
- package/dist/util/sse.js +61 -0
- package/dist/util/sse.js.map +1 -0
- package/mimoskill/SKILL.md +145 -0
- package/mimoskill/assets/pet_prompt_template.md +94 -0
- package/mimoskill/references/models.md +111 -0
- package/mimoskill/references/pet_workflow.md +197 -0
- package/mimoskill/scripts/generate_pet.py +365 -0
- package/mimoskill/scripts/install_pet.sh +220 -0
- package/mimoskill/scripts/mimo_chat.py +199 -0
- package/package.json +69 -0
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
|