ai-switch-cli 0.3.0__tar.gz → 0.5.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-switch-cli
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: One-command provider and model switching for Claude Code and Codex, with session-history checks
5
5
  Author: ZidongS
6
6
  License: MIT
@@ -78,13 +78,40 @@ Select `glm` or `deepseek`, enter the API key, and activate the generated config
78
78
  ai-switch use glm
79
79
  ```
80
80
 
81
- `use` lists the models the profile offers and remembers your choice:
81
+ `use` activates the profile and does **not** ask anything: the profile's whole model list is published, so you
82
+ pick the model inside the agent with `/model` (Codex) or its Opus/Sonnet/Haiku categories (Claude Code). The
83
+ default for new sessions is the one you last used, or the profile default. Add `--choose` if you want to be
84
+ asked, or `-m/--model` to set the default directly.
82
85
 
83
86
  ```text
84
- This profile provides 2 models:
87
+ ⠸ ▰▰▰▰▰▰▱▱▱▱▱▱▱▱▱▱ 38% 2/5 writing ~/.codex/models.json
88
+ ✓ ▰▰▰▰▰▰▰▰▰▰▰▰▱▱▱▱ 75% 4/5 write ~/.codex/models.json 3 model(s)
89
+ ✓ ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100% 5/5 save profile state glm is now the active profile
90
+ ╭──────────────────────────────────────────────────────────╮
91
+ │ ✦ glm is active (0.73s) │
92
+ ├──────────────────────────────────────────────────────────┤
93
+ │ profile glm │
94
+ │ default glm-5.3 │
95
+ │ models 3 published · switch inside codex with /model │
96
+ │ backup ~/.config/ai-switch/backups/20260915-203657 │
97
+ │ next restart claude/codex to reload │
98
+ ╰──────────────────────────────────────────────────────────╯
99
+ ```
100
+
101
+ The bar is a colour ramp (cyan → green) with a bright leading edge and it always finishes completely
102
+ filled at 100%, followed by a short sweep as the closing flourish.
103
+
104
+ The progress animation needs a terminal — piped output, `TERM=dumb`, `--plain` and `--no-color` keep the
105
+ plain one-line-per-action form (handy for scripts). `NO_COLOR=1` mutes the colours but keeps the spinner.
106
+
107
+ With `--choose` you get the picker instead:
108
+
109
+ ```text
110
+ This profile provides 3 models:
85
111
  1) glm-5.3 GLM-5.3 flagship (1M context) [default]
86
- 2) glm-5.3-flash GLM-5.3 flash (fast, 1M context)
87
- Select model [1-2, Enter=glm-5.3, q=cancel]:
112
+ 2) glm-5.3-flash GLM-5.3 Flash (fast, text+image, 1M context)
113
+ 3) glm-5-turbo GLM-5 Turbo (agent-optimized, 200K context)
114
+ Select model [1-3, Enter=glm-5.3, q=cancel]:
88
115
  ```
89
116
 
90
117
  For scripts and servers, choose without prompting (name, unique prefix, or index):
@@ -93,8 +120,11 @@ For scripts and servers, choose without prompting (name, unique prefix, or index
93
120
  ai-switch use glm --model glm-5.3-flash
94
121
  ai-switch use glm -m 2 -y
95
122
  ai-switch use glm --dry-run # show what would change
123
+ ai-switch use glm -m glm-5.3 --pin # publish only this model (see below)
96
124
  ```
97
125
 
126
+ Selecting a model sets the **default for new sessions** in both agents, and the profile's other models stay in the catalogue so you can still switch inside the agent. That means an in-app `/model` choice is a per-session override — and Codex writes its own choice back to `~/.codex/config.toml` when it exits, so the two agents can drift apart without anything else noticing; `ai-switch doctor` reports exactly that. If you want an activation to be exclusive instead, add `--pin`: the published catalogue then holds only the selected model, so Codex's own picker has nothing else to switch to (the next `ai-switch use` without `--pin` restores the full menu).
127
+
98
128
  Edit `~/.codex/config.toml` and `~/.claude/settings.json` for another provider, then save that configuration as a second profile:
99
129
 
100
130
  ```bash
@@ -116,7 +146,25 @@ Update an existing profile description:
116
146
  ai-switch describe default "Default daily configuration"
117
147
  ```
118
148
 
119
- `list` shows the active marker, profile name, configured clients, description, detected models, and endpoint hostnames. API keys are never printed.
149
+ `list` shows the active marker, profile name, configured clients, description, detected models, and endpoint hostnames. `current` prints a panel of **every** profile with its models, the default one (★), the endpoint and — for the active profile — whether the live agent configuration still matches:
150
+
151
+ ```text
152
+ ai-switch · 4 profile(s) · ~/.config/ai-switch
153
+ ────────────────────────────────────────────────────────────────────
154
+ ○ glm glm-coding-plan
155
+ Codex glm-5.3 · 3 models
156
+ Claude glm-5.3 · 2 Claude category mappings
157
+ host open.bigmodel.cn
158
+ models glm-5.3 ★, glm-5.3-flash, glm-5-turbo
159
+
160
+ ● paratera custom paratera active
161
+ Codex DeepSeek-V4.1-Flash · 31 models
162
+ Claude DeepSeek-V4.1-Flash · opus/sonnet/haiku → DeepSeek-V4.1-Flash
163
+ host llmapi.paratera.com
164
+ models DeepSeek-V4.1-Flash ★, DeepSeek-V4-Pro, …, MiniMax-Text-01
165
+ ```
166
+
167
+ Use `current --plain` to print just the active profile name. API keys are never printed.
120
168
 
121
169
  ## Choosing a model
122
170
 
@@ -154,6 +202,32 @@ ai-switch use deepseek -m deepseek-flash
154
202
 
155
203
  Model suffixes are proxy-specific: DeepSeek's Claude endpoint accepts and strips a `[1m]` marker (`deepseek-v4-pro[1m]`), while ZAI rejects it as an unknown model — `glm-5.3` is already 1M context and must be used without a suffix. Worth a one-token request before trusting a name in a profile.
156
204
 
205
+ ## Gateways that break Codex's tool calls
206
+
207
+ Codex 0.154 records an assistant `message` item **between** a turn's tool calls and their results — the text it said before calling the tools, or an empty string when it said nothing. That is valid in the Responses API, but a gateway that translates Responses into Chat completions emits it as its own chat message, which leaves the `tool_calls` message without the `tool` messages that must follow it directly. The next request is then rejected and the session dies:
208
+
209
+ ```text
210
+ OpenAIException - The request is invalid: An assistant message with 'tool_calls' must be
211
+ followed by tool messages responding to each 'tool_call_id'. (insufficient tool messages
212
+ following tool_calls message)
213
+ ```
214
+
215
+ Paratera (`llmapi.paratera.com`) does this. Claude Code is unaffected, because it speaks the Anthropic API rather than the Responses API — only Codex hits the translation.
216
+
217
+ For such a profile, `ai-switch use` starts a small local proxy that moves that message back in front of the calls, points Codex at it, and stops it again when you activate a profile that does not need it:
218
+
219
+ ```text
220
+ Note: Codex will use the llmapi.paratera.com patch proxy on 127.0.0.1:8791
221
+ (Paratera translates Responses into Chat completions and splits a turn's tool calls from their results).
222
+ ```
223
+
224
+ * The profile keeps the provider's real endpoint. Only the live `~/.codex/config.toml` is repointed, and only Codex's own configuration — Claude Code still talks to the provider directly.
225
+ * The proxy listens on `127.0.0.1` only, forwards your key and your request body untouched apart from the item order, and logs counts and status codes (never keys, prompts or answers) to `~/.config/ai-switch/patch.log`.
226
+ * If the process dies (a reboot, a kill), Codex cannot reach its endpoint. `ai-switch doctor` reports it and `ai-switch use NAME` starts it again. `ai-switch current` shows whether it is up.
227
+ * Nothing here is needed once the gateway's translation is fixed: `ai-switch use NAME --no-patch` activates the profile without the proxy and stops it if it is running.
228
+
229
+ This is a workaround for the gateway, not a fix — the rewriting is deliberately narrow (only a completed `calls + message + results` turn, only on `/responses`), and anything else is forwarded byte for byte.
230
+
157
231
  ## Session history
158
232
 
159
233
  Conversation history belongs to the agents, not to a provider, so ai-switch never manages it. These files are deliberately excluded from profiles and switches:
@@ -188,7 +262,7 @@ ai-switch doctor --fix # quarantine damaged Codex runtime databases
188
262
 
189
263
  ## Safety and storage
190
264
 
191
- Before activation, the current Codex and Claude files are backed up under `~/.config/ai-switch/backups/<timestamp>/` (files that a switch removes are kept under `removed/`). Profiles are stored under `~/.config/ai-switch/profiles/`; directories use mode 700 and files use mode 600. The active profile and the last used model are recorded in `~/.config/ai-switch/state.json`. Restart `claude` or `codex` after switching so the process reloads its configuration.
265
+ Before activation, the current Codex and Claude files are backed up under `~/.config/ai-switch/backups/<timestamp>/` (files that a switch removes are kept under `removed/`). Profiles are stored under `~/.config/ai-switch/profiles/`; directories use mode 700 and files use mode 600. The active profile, the last used model and the running gateway patch proxy (pid, port, endpoint) are recorded in `~/.config/ai-switch/state.json`; that proxy's log is `~/.config/ai-switch/patch.log`. Restart `claude` or `codex` after switching so the process reloads its configuration.
192
266
 
193
267
  Set `AI_SWITCH_HOME` to use a different profile directory, `CODEX_HOME`/`CLAUDE_CONFIG_DIR` for relocated agent configurations, and `AI_SWITCH_API_KEY` to fill the API key prompt non-interactively.
194
268
 
@@ -197,9 +271,10 @@ Set `AI_SWITCH_HOME` to use a different profile directory, `CODEX_HOME`/`CLAUDE_
197
271
  ```text
198
272
  ai-switch init NAME [-d DESCRIPTION] Save current files as a new profile
199
273
  ai-switch list List profiles and configuration summaries
200
- ai-switch use NAME [-m MODEL] [-y] [-n] Back up and activate a profile (and a model)
274
+ ai-switch use NAME [-m MODEL] [--choose] [--pin] [--plain] [--no-patch]
275
+ Back up and activate a profile (animated, -m sets the default)
201
276
  ai-switch models [NAME] [--json] Show the models a profile offers
202
- ai-switch current Print the active profile
277
+ ai-switch current [-p] Show every profile, its models and the live state (-p: name only)
203
278
  ai-switch describe NAME TEXT Set a profile description
204
279
  ai-switch upgrade NAME Derive models.json for a profile from an older release
205
280
  ai-switch add Create a profile interactively (GLM, DeepSeek, or custom)
@@ -64,13 +64,40 @@ Select `glm` or `deepseek`, enter the API key, and activate the generated config
64
64
  ai-switch use glm
65
65
  ```
66
66
 
67
- `use` lists the models the profile offers and remembers your choice:
67
+ `use` activates the profile and does **not** ask anything: the profile's whole model list is published, so you
68
+ pick the model inside the agent with `/model` (Codex) or its Opus/Sonnet/Haiku categories (Claude Code). The
69
+ default for new sessions is the one you last used, or the profile default. Add `--choose` if you want to be
70
+ asked, or `-m/--model` to set the default directly.
68
71
 
69
72
  ```text
70
- This profile provides 2 models:
73
+ ⠸ ▰▰▰▰▰▰▱▱▱▱▱▱▱▱▱▱ 38% 2/5 writing ~/.codex/models.json
74
+ ✓ ▰▰▰▰▰▰▰▰▰▰▰▰▱▱▱▱ 75% 4/5 write ~/.codex/models.json 3 model(s)
75
+ ✓ ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100% 5/5 save profile state glm is now the active profile
76
+ ╭──────────────────────────────────────────────────────────╮
77
+ │ ✦ glm is active (0.73s) │
78
+ ├──────────────────────────────────────────────────────────┤
79
+ │ profile glm │
80
+ │ default glm-5.3 │
81
+ │ models 3 published · switch inside codex with /model │
82
+ │ backup ~/.config/ai-switch/backups/20260915-203657 │
83
+ │ next restart claude/codex to reload │
84
+ ╰──────────────────────────────────────────────────────────╯
85
+ ```
86
+
87
+ The bar is a colour ramp (cyan → green) with a bright leading edge and it always finishes completely
88
+ filled at 100%, followed by a short sweep as the closing flourish.
89
+
90
+ The progress animation needs a terminal — piped output, `TERM=dumb`, `--plain` and `--no-color` keep the
91
+ plain one-line-per-action form (handy for scripts). `NO_COLOR=1` mutes the colours but keeps the spinner.
92
+
93
+ With `--choose` you get the picker instead:
94
+
95
+ ```text
96
+ This profile provides 3 models:
71
97
  1) glm-5.3 GLM-5.3 flagship (1M context) [default]
72
- 2) glm-5.3-flash GLM-5.3 flash (fast, 1M context)
73
- Select model [1-2, Enter=glm-5.3, q=cancel]:
98
+ 2) glm-5.3-flash GLM-5.3 Flash (fast, text+image, 1M context)
99
+ 3) glm-5-turbo GLM-5 Turbo (agent-optimized, 200K context)
100
+ Select model [1-3, Enter=glm-5.3, q=cancel]:
74
101
  ```
75
102
 
76
103
  For scripts and servers, choose without prompting (name, unique prefix, or index):
@@ -79,8 +106,11 @@ For scripts and servers, choose without prompting (name, unique prefix, or index
79
106
  ai-switch use glm --model glm-5.3-flash
80
107
  ai-switch use glm -m 2 -y
81
108
  ai-switch use glm --dry-run # show what would change
109
+ ai-switch use glm -m glm-5.3 --pin # publish only this model (see below)
82
110
  ```
83
111
 
112
+ Selecting a model sets the **default for new sessions** in both agents, and the profile's other models stay in the catalogue so you can still switch inside the agent. That means an in-app `/model` choice is a per-session override — and Codex writes its own choice back to `~/.codex/config.toml` when it exits, so the two agents can drift apart without anything else noticing; `ai-switch doctor` reports exactly that. If you want an activation to be exclusive instead, add `--pin`: the published catalogue then holds only the selected model, so Codex's own picker has nothing else to switch to (the next `ai-switch use` without `--pin` restores the full menu).
113
+
84
114
  Edit `~/.codex/config.toml` and `~/.claude/settings.json` for another provider, then save that configuration as a second profile:
85
115
 
86
116
  ```bash
@@ -102,7 +132,25 @@ Update an existing profile description:
102
132
  ai-switch describe default "Default daily configuration"
103
133
  ```
104
134
 
105
- `list` shows the active marker, profile name, configured clients, description, detected models, and endpoint hostnames. API keys are never printed.
135
+ `list` shows the active marker, profile name, configured clients, description, detected models, and endpoint hostnames. `current` prints a panel of **every** profile with its models, the default one (★), the endpoint and — for the active profile — whether the live agent configuration still matches:
136
+
137
+ ```text
138
+ ai-switch · 4 profile(s) · ~/.config/ai-switch
139
+ ────────────────────────────────────────────────────────────────────
140
+ ○ glm glm-coding-plan
141
+ Codex glm-5.3 · 3 models
142
+ Claude glm-5.3 · 2 Claude category mappings
143
+ host open.bigmodel.cn
144
+ models glm-5.3 ★, glm-5.3-flash, glm-5-turbo
145
+
146
+ ● paratera custom paratera active
147
+ Codex DeepSeek-V4.1-Flash · 31 models
148
+ Claude DeepSeek-V4.1-Flash · opus/sonnet/haiku → DeepSeek-V4.1-Flash
149
+ host llmapi.paratera.com
150
+ models DeepSeek-V4.1-Flash ★, DeepSeek-V4-Pro, …, MiniMax-Text-01
151
+ ```
152
+
153
+ Use `current --plain` to print just the active profile name. API keys are never printed.
106
154
 
107
155
  ## Choosing a model
108
156
 
@@ -140,6 +188,32 @@ ai-switch use deepseek -m deepseek-flash
140
188
 
141
189
  Model suffixes are proxy-specific: DeepSeek's Claude endpoint accepts and strips a `[1m]` marker (`deepseek-v4-pro[1m]`), while ZAI rejects it as an unknown model — `glm-5.3` is already 1M context and must be used without a suffix. Worth a one-token request before trusting a name in a profile.
142
190
 
191
+ ## Gateways that break Codex's tool calls
192
+
193
+ Codex 0.154 records an assistant `message` item **between** a turn's tool calls and their results — the text it said before calling the tools, or an empty string when it said nothing. That is valid in the Responses API, but a gateway that translates Responses into Chat completions emits it as its own chat message, which leaves the `tool_calls` message without the `tool` messages that must follow it directly. The next request is then rejected and the session dies:
194
+
195
+ ```text
196
+ OpenAIException - The request is invalid: An assistant message with 'tool_calls' must be
197
+ followed by tool messages responding to each 'tool_call_id'. (insufficient tool messages
198
+ following tool_calls message)
199
+ ```
200
+
201
+ Paratera (`llmapi.paratera.com`) does this. Claude Code is unaffected, because it speaks the Anthropic API rather than the Responses API — only Codex hits the translation.
202
+
203
+ For such a profile, `ai-switch use` starts a small local proxy that moves that message back in front of the calls, points Codex at it, and stops it again when you activate a profile that does not need it:
204
+
205
+ ```text
206
+ Note: Codex will use the llmapi.paratera.com patch proxy on 127.0.0.1:8791
207
+ (Paratera translates Responses into Chat completions and splits a turn's tool calls from their results).
208
+ ```
209
+
210
+ * The profile keeps the provider's real endpoint. Only the live `~/.codex/config.toml` is repointed, and only Codex's own configuration — Claude Code still talks to the provider directly.
211
+ * The proxy listens on `127.0.0.1` only, forwards your key and your request body untouched apart from the item order, and logs counts and status codes (never keys, prompts or answers) to `~/.config/ai-switch/patch.log`.
212
+ * If the process dies (a reboot, a kill), Codex cannot reach its endpoint. `ai-switch doctor` reports it and `ai-switch use NAME` starts it again. `ai-switch current` shows whether it is up.
213
+ * Nothing here is needed once the gateway's translation is fixed: `ai-switch use NAME --no-patch` activates the profile without the proxy and stops it if it is running.
214
+
215
+ This is a workaround for the gateway, not a fix — the rewriting is deliberately narrow (only a completed `calls + message + results` turn, only on `/responses`), and anything else is forwarded byte for byte.
216
+
143
217
  ## Session history
144
218
 
145
219
  Conversation history belongs to the agents, not to a provider, so ai-switch never manages it. These files are deliberately excluded from profiles and switches:
@@ -174,7 +248,7 @@ ai-switch doctor --fix # quarantine damaged Codex runtime databases
174
248
 
175
249
  ## Safety and storage
176
250
 
177
- Before activation, the current Codex and Claude files are backed up under `~/.config/ai-switch/backups/<timestamp>/` (files that a switch removes are kept under `removed/`). Profiles are stored under `~/.config/ai-switch/profiles/`; directories use mode 700 and files use mode 600. The active profile and the last used model are recorded in `~/.config/ai-switch/state.json`. Restart `claude` or `codex` after switching so the process reloads its configuration.
251
+ Before activation, the current Codex and Claude files are backed up under `~/.config/ai-switch/backups/<timestamp>/` (files that a switch removes are kept under `removed/`). Profiles are stored under `~/.config/ai-switch/profiles/`; directories use mode 700 and files use mode 600. The active profile, the last used model and the running gateway patch proxy (pid, port, endpoint) are recorded in `~/.config/ai-switch/state.json`; that proxy's log is `~/.config/ai-switch/patch.log`. Restart `claude` or `codex` after switching so the process reloads its configuration.
178
252
 
179
253
  Set `AI_SWITCH_HOME` to use a different profile directory, `CODEX_HOME`/`CLAUDE_CONFIG_DIR` for relocated agent configurations, and `AI_SWITCH_API_KEY` to fill the API key prompt non-interactively.
180
254
 
@@ -183,9 +257,10 @@ Set `AI_SWITCH_HOME` to use a different profile directory, `CODEX_HOME`/`CLAUDE_
183
257
  ```text
184
258
  ai-switch init NAME [-d DESCRIPTION] Save current files as a new profile
185
259
  ai-switch list List profiles and configuration summaries
186
- ai-switch use NAME [-m MODEL] [-y] [-n] Back up and activate a profile (and a model)
260
+ ai-switch use NAME [-m MODEL] [--choose] [--pin] [--plain] [--no-patch]
261
+ Back up and activate a profile (animated, -m sets the default)
187
262
  ai-switch models [NAME] [--json] Show the models a profile offers
188
- ai-switch current Print the active profile
263
+ ai-switch current [-p] Show every profile, its models and the live state (-p: name only)
189
264
  ai-switch describe NAME TEXT Set a profile description
190
265
  ai-switch upgrade NAME Derive models.json for a profile from an older release
191
266
  ai-switch add Create a profile interactively (GLM, DeepSeek, or custom)