ai-switch-cli 0.3.2__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.
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/PKG-INFO +68 -9
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/README.md +67 -8
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/ai_switch.py +846 -38
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/ai_switch_cli.egg-info/PKG-INFO +68 -9
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/pyproject.toml +1 -1
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/ai_switch_cli.egg-info/SOURCES.txt +0 -0
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/ai_switch_cli.egg-info/dependency_links.txt +0 -0
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/ai_switch_cli.egg-info/entry_points.txt +0 -0
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/ai_switch_cli.egg-info/top_level.txt +0 -0
- {ai_switch_cli-0.3.2 → ai_switch_cli-0.5.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-switch-cli
|
|
3
|
-
Version: 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
|
|
@@ -84,12 +84,26 @@ default for new sessions is the one you last used, or the profile default. Add `
|
|
|
84
84
|
asked, or `-m/--model` to set the default directly.
|
|
85
85
|
|
|
86
86
|
```text
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
+
╰──────────────────────────────────────────────────────────╯
|
|
91
99
|
```
|
|
92
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
|
+
|
|
93
107
|
With `--choose` you get the picker instead:
|
|
94
108
|
|
|
95
109
|
```text
|
|
@@ -132,7 +146,25 @@ Update an existing profile description:
|
|
|
132
146
|
ai-switch describe default "Default daily configuration"
|
|
133
147
|
```
|
|
134
148
|
|
|
135
|
-
`list` shows the active marker, profile name, configured clients, description, detected models, and endpoint hostnames.
|
|
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.
|
|
136
168
|
|
|
137
169
|
## Choosing a model
|
|
138
170
|
|
|
@@ -170,6 +202,32 @@ ai-switch use deepseek -m deepseek-flash
|
|
|
170
202
|
|
|
171
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.
|
|
172
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
|
+
|
|
173
231
|
## Session history
|
|
174
232
|
|
|
175
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:
|
|
@@ -204,7 +262,7 @@ ai-switch doctor --fix # quarantine damaged Codex runtime databases
|
|
|
204
262
|
|
|
205
263
|
## Safety and storage
|
|
206
264
|
|
|
207
|
-
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
|
|
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.
|
|
208
266
|
|
|
209
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.
|
|
210
268
|
|
|
@@ -213,9 +271,10 @@ Set `AI_SWITCH_HOME` to use a different profile directory, `CODEX_HOME`/`CLAUDE_
|
|
|
213
271
|
```text
|
|
214
272
|
ai-switch init NAME [-d DESCRIPTION] Save current files as a new profile
|
|
215
273
|
ai-switch list List profiles and configuration summaries
|
|
216
|
-
ai-switch use NAME [-m 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)
|
|
217
276
|
ai-switch models [NAME] [--json] Show the models a profile offers
|
|
218
|
-
ai-switch current
|
|
277
|
+
ai-switch current [-p] Show every profile, its models and the live state (-p: name only)
|
|
219
278
|
ai-switch describe NAME TEXT Set a profile description
|
|
220
279
|
ai-switch upgrade NAME Derive models.json for a profile from an older release
|
|
221
280
|
ai-switch add Create a profile interactively (GLM, DeepSeek, or custom)
|
|
@@ -70,12 +70,26 @@ default for new sessions is the one you last used, or the profile default. Add `
|
|
|
70
70
|
asked, or `-m/--model` to set the default directly.
|
|
71
71
|
|
|
72
72
|
```text
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
+
╰──────────────────────────────────────────────────────────╯
|
|
77
85
|
```
|
|
78
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
|
+
|
|
79
93
|
With `--choose` you get the picker instead:
|
|
80
94
|
|
|
81
95
|
```text
|
|
@@ -118,7 +132,25 @@ Update an existing profile description:
|
|
|
118
132
|
ai-switch describe default "Default daily configuration"
|
|
119
133
|
```
|
|
120
134
|
|
|
121
|
-
`list` shows the active marker, profile name, configured clients, description, detected models, and endpoint hostnames.
|
|
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.
|
|
122
154
|
|
|
123
155
|
## Choosing a model
|
|
124
156
|
|
|
@@ -156,6 +188,32 @@ ai-switch use deepseek -m deepseek-flash
|
|
|
156
188
|
|
|
157
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.
|
|
158
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
|
+
|
|
159
217
|
## Session history
|
|
160
218
|
|
|
161
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:
|
|
@@ -190,7 +248,7 @@ ai-switch doctor --fix # quarantine damaged Codex runtime databases
|
|
|
190
248
|
|
|
191
249
|
## Safety and storage
|
|
192
250
|
|
|
193
|
-
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
|
|
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.
|
|
194
252
|
|
|
195
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.
|
|
196
254
|
|
|
@@ -199,9 +257,10 @@ Set `AI_SWITCH_HOME` to use a different profile directory, `CODEX_HOME`/`CLAUDE_
|
|
|
199
257
|
```text
|
|
200
258
|
ai-switch init NAME [-d DESCRIPTION] Save current files as a new profile
|
|
201
259
|
ai-switch list List profiles and configuration summaries
|
|
202
|
-
ai-switch use NAME [-m 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)
|
|
203
262
|
ai-switch models [NAME] [--json] Show the models a profile offers
|
|
204
|
-
ai-switch current
|
|
263
|
+
ai-switch current [-p] Show every profile, its models and the live state (-p: name only)
|
|
205
264
|
ai-switch describe NAME TEXT Set a profile description
|
|
206
265
|
ai-switch upgrade NAME Derive models.json for a profile from an older release
|
|
207
266
|
ai-switch add Create a profile interactively (GLM, DeepSeek, or custom)
|