llm-switcher 1.1.0 → 1.1.1
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/README.md +22 -22
- package/README.vi.md +21 -19
- package/blindfold/make-certs.sh +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -235,21 +235,18 @@ A checkout keeps its data next to the code, as before. To use another folder in
|
|
|
235
235
|
|
|
236
236
|
Edit `config.json` with your provider base URLs and API keys.
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
The **data folder** is `~/.llm-switcher` for an npm install and the checkout folder for a git clone. The examples below use the npm install. For a checkout, run `node switch.mjs <command>` instead of `switch <command>`, or put the checkout folder on `PATH`.
|
|
239
239
|
|
|
240
240
|
### 3. Start the Gateway
|
|
241
241
|
```bash
|
|
242
|
-
# Start in
|
|
243
|
-
|
|
242
|
+
# Start the gateway in the background:
|
|
243
|
+
switch on
|
|
244
244
|
|
|
245
|
-
# Or run
|
|
246
|
-
node proxy.mjs
|
|
245
|
+
# Or run it in the foreground (npm install):
|
|
246
|
+
node "$(npm root -g)/llm-switcher/proxy.mjs"
|
|
247
247
|
```
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
`switch.cmd` for Windows. Put the repository directory on PATH and `switch <command>`
|
|
251
|
-
works the same on all three. Platform differences, and the two features that are not
|
|
252
|
-
available everywhere, are in [📖 `docs/cross-platform.md`](docs/cross-platform.md).
|
|
249
|
+
`switch <command>` works the same on Linux, macOS and Windows. A checkout has its own launchers: `switch` for Linux and macOS, `switch.cmd` for Windows. Platform differences, and the two features that are not available everywhere, are in [📖 `docs/cross-platform.md`](docs/cross-platform.md).
|
|
253
250
|
|
|
254
251
|
Open the Web Dashboard at: **[http://127.0.0.1:3456/ui](http://127.0.0.1:3456/ui)**
|
|
255
252
|
|
|
@@ -259,22 +256,24 @@ Open the Web Dashboard at: **[http://127.0.0.1:3456/ui](http://127.0.0.1:3456/ui
|
|
|
259
256
|
|
|
260
257
|
### Universal Environment Loader (`env.cmd` / `env.sh`)
|
|
261
258
|
|
|
262
|
-
Every time you switch profiles, LLM Switcher writes ready-to-use environment loaders:
|
|
259
|
+
Every time you switch profiles, LLM Switcher writes ready-to-use environment loaders into the data folder:
|
|
263
260
|
|
|
264
261
|
- **Windows (Command Prompt / PowerShell wrapper):**
|
|
265
262
|
```cmd
|
|
266
|
-
call "
|
|
263
|
+
call "%USERPROFILE%\.llm-switcher\env.cmd"
|
|
267
264
|
```
|
|
268
265
|
- **macOS / Linux (Bash / Zsh):**
|
|
269
266
|
```bash
|
|
270
|
-
source
|
|
267
|
+
source ~/.llm-switcher/env.sh
|
|
271
268
|
```
|
|
272
269
|
|
|
270
|
+
For a checkout, use the same files in the checkout folder.
|
|
271
|
+
|
|
273
272
|
---
|
|
274
273
|
|
|
275
274
|
### Claude Code Setup (Windows)
|
|
276
275
|
|
|
277
|
-
1.
|
|
276
|
+
1. With the npm install, `switch` is already on `PATH`. With a checkout, create a wrapper on your `PATH` (for example `cc-switch.cmd`):
|
|
278
277
|
```cmd
|
|
279
278
|
@echo off
|
|
280
279
|
node "path\to\llm-switcher\switch.mjs" %*
|
|
@@ -283,18 +282,18 @@ Every time you switch profiles, LLM Switcher writes ready-to-use environment loa
|
|
|
283
282
|
2. Patch your global Claude Code launcher (`claude.cmd` in your npm global directory):
|
|
284
283
|
```cmd
|
|
285
284
|
SETLOCAL EnableDelayedExpansion
|
|
286
|
-
IF EXIST "
|
|
285
|
+
IF EXIST "%USERPROFILE%\.llm-switcher\active.flag" (
|
|
287
286
|
SET "ANTHROPIC_BASE_URL=http://127.0.0.1:3456"
|
|
288
287
|
SET "CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1"
|
|
289
288
|
)
|
|
290
|
-
IF EXIST "
|
|
291
|
-
SET /P M1M=<"
|
|
289
|
+
IF EXIST "%USERPROFILE%\.llm-switcher\1m.flag" (
|
|
290
|
+
SET /P M1M=<"%USERPROFILE%\.llm-switcher\1m.flag"
|
|
292
291
|
IF "!M1M!"=="" SET "M1M=opus[1m]"
|
|
293
292
|
SET "ANTHROPIC_MODEL=!M1M!"
|
|
294
293
|
SET "CLAUDE_CODE_AUTO_COMPACT_WINDOW=900000"
|
|
295
294
|
)
|
|
296
295
|
```
|
|
297
|
-
> `SETLOCAL EnableDelayedExpansion` is required for `!M1M!`. npm rewrites `claude.cmd` on every update, so prefer a separate wrapper that runs `call "
|
|
296
|
+
> `SETLOCAL EnableDelayedExpansion` is required for `!M1M!`. npm rewrites `claude.cmd` on every update, so prefer a separate wrapper that runs `call "%USERPROFILE%\.llm-switcher\env.cmd"` and then `claude %*`. For a checkout, replace `%USERPROFILE%\.llm-switcher` with the checkout folder. Only `env.cmd` / `env.sh` carry the per-tier `ANTHROPIC_DEFAULT_<TIER>_MODEL=<tier>[1m]` variables.
|
|
298
297
|
|
|
299
298
|
---
|
|
300
299
|
|
|
@@ -337,7 +336,7 @@ base URL is overridden to http://127.0.0.1:3456/v1. Selecting models may not be
|
|
|
337
336
|
Blindfold mode removes that line. Codex keeps its official endpoint, and the switcher intercepts the network hop instead. It needs no administrator rights, no certificate in a system trust store, and no change to `~/.codex/config.toml`.
|
|
338
337
|
|
|
339
338
|
```bash
|
|
340
|
-
bash blindfold/make-certs.sh chatgpt.com # once
|
|
339
|
+
bash "$(npm root -g)/llm-switcher/blindfold/make-certs.sh" chatgpt.com # once; a checkout runs blindfold/make-certs.sh
|
|
341
340
|
# then set "blindfold": true in the Codex profile
|
|
342
341
|
switch codex <profile> # the gateway starts the interceptor
|
|
343
342
|
```
|
|
@@ -414,12 +413,12 @@ A zero-dependency Model Context Protocol (MCP) server communicating over `stdio`
|
|
|
414
413
|
|
|
415
414
|
NOTE: `switcher_recent_logs` returns the first 150 characters of each recent prompt, from every client that used the gateway. The agent that calls the tool can read them.
|
|
416
415
|
|
|
417
|
-
Add to your MCP configuration (
|
|
416
|
+
Add the server to your MCP configuration (for example `opencode.jsonc`, `claude_desktop_config.json`, or Cursor). Run `npm root -g` to get the folder that holds `llm-switcher/mcp.mjs`. For a checkout, use the `mcp.mjs` in the checkout folder.
|
|
418
417
|
```json
|
|
419
418
|
"mcp": {
|
|
420
419
|
"llm-switcher": {
|
|
421
420
|
"type": "local",
|
|
422
|
-
"command": ["node", "path/
|
|
421
|
+
"command": ["node", "/path/from/npm-root-g/llm-switcher/mcp.mjs"],
|
|
423
422
|
"enabled": true
|
|
424
423
|
}
|
|
425
424
|
}
|
|
@@ -548,14 +547,15 @@ The contract lab finds fields that the converter loses. It is off by default.
|
|
|
548
547
|
|
|
549
548
|
| Option | Description |
|
|
550
549
|
|---|---|
|
|
551
|
-
| `
|
|
550
|
+
| `LLM_SWITCHER_HOME=/path` | Use this folder as the data folder (config, admin token, launch files, logs) for an npm install or a checkout. |
|
|
551
|
+
| `LLM_SWITCHER_CONFIG=/path/config.json` | Use a config file outside the data folder (the proxy, `switch` and `mcp.mjs` all honour it). |
|
|
552
552
|
| `--port <n>` / `LLM_SWITCHER_PORT` | Override the listening port (priority: flag > env > `config.port`). |
|
|
553
553
|
| `x-llm-profile: <key>` header (alias `x-profile`) or `?profile=<key>` | Route a single request through a specific profile. An unknown key returns HTTP 400 instead of silently falling back. |
|
|
554
554
|
| `profile.thinkingMode` | `auto` (default, for gateways like 9Router): restore stripped thinking, inject a `<think>` guide for non-reasoning models, send `thinking` + `reasoning_effort`. `native` (strict OpenAI APIs): send only `reasoning_effort` when the client asks, never touch the prompt, use `max_completion_tokens`. `off`: never send reasoning parameters. |
|
|
555
555
|
| `profile.endpoints.countTokens` | Override the Anthropic `count_tokens` URL. |
|
|
556
556
|
| `profile.endpoints` | Override upstream URLs per format: `{ "openai-chat": "...", "anthropic": "...", "vertex": "https://.../models/{model}:{action}" }`. |
|
|
557
557
|
| `CLAUDE_CONFIG_DIR` | Respected when locating Claude Code's `settings.json`. |
|
|
558
|
-
| `LLM_SWITCHER_STATE_DIR` | Move the launch files and the logs out of the
|
|
558
|
+
| `LLM_SWITCHER_STATE_DIR` | Move the launch files and the logs out of the data folder. The tests use it; the shims read the directory that was set when they were installed. |
|
|
559
559
|
|
|
560
560
|
## Security Model
|
|
561
561
|
|
package/README.vi.md
CHANGED
|
@@ -235,19 +235,18 @@ Bản checkout lưu dữ liệu cạnh mã nguồn như trước. Muốn dùng t
|
|
|
235
235
|
|
|
236
236
|
Điền URL và API key của các nhà cung cấp vào `config.json`.
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
**Thư mục dữ liệu** là `~/.llm-switcher` với bản cài bằng npm, và là thư mục checkout với bản git clone. Các ví dụ bên dưới dùng bản cài bằng npm. Với bản checkout, chạy `node switch.mjs <lệnh>` thay cho `switch <lệnh>`, hoặc thêm thư mục checkout vào `PATH`.
|
|
239
239
|
|
|
240
240
|
### 3. Khởi động Gateway
|
|
241
241
|
```bash
|
|
242
242
|
# Bật gateway chạy ngầm:
|
|
243
|
-
|
|
243
|
+
switch on
|
|
244
244
|
|
|
245
|
-
# Hoặc chạy trực tiếp trên terminal:
|
|
246
|
-
node proxy.mjs
|
|
245
|
+
# Hoặc chạy trực tiếp trên terminal (bản cài bằng npm):
|
|
246
|
+
node "$(npm root -g)/llm-switcher/proxy.mjs"
|
|
247
247
|
```
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
cho Windows. Thêm thư mục repo vào PATH là `switch <lệnh>` chạy giống nhau trên cả ba.
|
|
249
|
+
`switch <lệnh>` chạy giống nhau trên Linux, macOS và Windows. Bản checkout có sẵn hai launcher: `switch` cho Linux và macOS, `switch.cmd` cho Windows.
|
|
251
250
|
Khác biệt giữa các nền tảng, và hai tính năng không chạy ở mọi nơi, nằm trong
|
|
252
251
|
[📖 `docs/cross-platform.md`](docs/cross-platform.md).
|
|
253
252
|
|
|
@@ -259,22 +258,24 @@ Mở Bảng điều khiển Web Dashboard tại: **[http://127.0.0.1:3456/ui](ht
|
|
|
259
258
|
|
|
260
259
|
### Bộ nạp Biến Môi trường Toàn năng (`env.cmd` / `env.sh`)
|
|
261
260
|
|
|
262
|
-
Mỗi khi bạn chuyển đổi profile, LLM Switcher
|
|
261
|
+
Mỗi khi bạn chuyển đổi profile, LLM Switcher sinh file nạp môi trường trong thư mục dữ liệu:
|
|
263
262
|
|
|
264
263
|
- **Trên Windows (CMD / PowerShell wrapper):**
|
|
265
264
|
```cmd
|
|
266
|
-
call "
|
|
265
|
+
call "%USERPROFILE%\.llm-switcher\env.cmd"
|
|
267
266
|
```
|
|
268
267
|
- **Trên macOS / Linux (Bash / Zsh):**
|
|
269
268
|
```bash
|
|
270
|
-
source
|
|
269
|
+
source ~/.llm-switcher/env.sh
|
|
271
270
|
```
|
|
272
271
|
|
|
272
|
+
Với bản checkout, dùng các file này trong thư mục checkout.
|
|
273
|
+
|
|
273
274
|
---
|
|
274
275
|
|
|
275
276
|
### Cấu hình cho Claude Code (Windows)
|
|
276
277
|
|
|
277
|
-
1.
|
|
278
|
+
1. Với bản cài bằng npm, `switch` đã có sẵn trong `PATH`. Với bản checkout, tạo file wrapper trong `PATH` (ví dụ `cc-switch.cmd`):
|
|
278
279
|
```cmd
|
|
279
280
|
@echo off
|
|
280
281
|
node "path\to\llm-switcher\switch.mjs" %*
|
|
@@ -283,18 +284,18 @@ Mỗi khi bạn chuyển đổi profile, LLM Switcher sẽ tự động sinh fil
|
|
|
283
284
|
2. Thêm đoạn mã sau vào wrapper chính của Claude Code (`claude.cmd` trong thư mục global npm):
|
|
284
285
|
```cmd
|
|
285
286
|
SETLOCAL EnableDelayedExpansion
|
|
286
|
-
IF EXIST "
|
|
287
|
+
IF EXIST "%USERPROFILE%\.llm-switcher\active.flag" (
|
|
287
288
|
SET "ANTHROPIC_BASE_URL=http://127.0.0.1:3456"
|
|
288
289
|
SET "CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1"
|
|
289
290
|
)
|
|
290
|
-
IF EXIST "
|
|
291
|
-
SET /P M1M=<"
|
|
291
|
+
IF EXIST "%USERPROFILE%\.llm-switcher\1m.flag" (
|
|
292
|
+
SET /P M1M=<"%USERPROFILE%\.llm-switcher\1m.flag"
|
|
292
293
|
IF "!M1M!"=="" SET "M1M=opus[1m]"
|
|
293
294
|
SET "ANTHROPIC_MODEL=!M1M!"
|
|
294
295
|
SET "CLAUDE_CODE_AUTO_COMPACT_WINDOW=900000"
|
|
295
296
|
)
|
|
296
297
|
```
|
|
297
|
-
> Cần `SETLOCAL EnableDelayedExpansion` để `!M1M!` hoạt động. npm ghi đè `claude.cmd` mỗi lần update, nên tốt hơn là tạo wrapper riêng chạy `call "
|
|
298
|
+
> Cần `SETLOCAL EnableDelayedExpansion` để `!M1M!` hoạt động. npm ghi đè `claude.cmd` mỗi lần update, nên tốt hơn là tạo wrapper riêng chạy `call "%USERPROFILE%\.llm-switcher\env.cmd"` rồi `claude %*`. Với bản checkout, thay `%USERPROFILE%\.llm-switcher` bằng thư mục checkout. Chỉ `env.cmd` / `env.sh` mới có các biến `ANTHROPIC_DEFAULT_<TIER>_MODEL=<tier>[1m]` theo từng tier.
|
|
298
299
|
|
|
299
300
|
---
|
|
300
301
|
|
|
@@ -337,7 +338,7 @@ base URL is overridden to http://127.0.0.1:3456/v1. Selecting models may not be
|
|
|
337
338
|
Blindfold xóa dòng đó. Codex giữ nguyên endpoint chính thức, switcher chặn ở tầng mạng. Không cần quyền admin, không cài chứng chỉ vào system trust store, không sửa `~/.codex/config.toml`.
|
|
338
339
|
|
|
339
340
|
```bash
|
|
340
|
-
bash blindfold/make-certs.sh chatgpt.com # chạy một lần
|
|
341
|
+
bash "$(npm root -g)/llm-switcher/blindfold/make-certs.sh" chatgpt.com # chạy một lần; bản checkout chạy blindfold/make-certs.sh
|
|
341
342
|
# rồi đặt "blindfold": true trong profile Codex
|
|
342
343
|
switch codex <profile> # gateway khởi động interceptor
|
|
343
344
|
```
|
|
@@ -414,12 +415,12 @@ Một server Model Context Protocol (MCP) chạy qua `stdio` cực nhẹ (Zero-d
|
|
|
414
415
|
|
|
415
416
|
LƯU Ý: `switcher_recent_logs` trả 150 ký tự đầu của mỗi prompt gần đây, từ mọi client đã dùng gateway. Agent gọi tool này đọc được chúng.
|
|
416
417
|
|
|
417
|
-
Thêm vào cấu hình MCP (ví dụ `opencode.jsonc`, `claude_desktop_config.json`, hoặc Cursor)
|
|
418
|
+
Thêm server vào cấu hình MCP (ví dụ `opencode.jsonc`, `claude_desktop_config.json`, hoặc Cursor). Chạy `npm root -g` để biết thư mục chứa `llm-switcher/mcp.mjs`. Với bản checkout, dùng `mcp.mjs` trong thư mục checkout.
|
|
418
419
|
```json
|
|
419
420
|
"mcp": {
|
|
420
421
|
"llm-switcher": {
|
|
421
422
|
"type": "local",
|
|
422
|
-
"command": ["node", "path/
|
|
423
|
+
"command": ["node", "/path/from/npm-root-g/llm-switcher/mcp.mjs"],
|
|
423
424
|
"enabled": true
|
|
424
425
|
}
|
|
425
426
|
}
|
|
@@ -546,13 +547,14 @@ Contract lab tìm các field mà converter làm mất. Mặc định tính năng
|
|
|
546
547
|
|
|
547
548
|
| Tuỳ chọn | Mô tả |
|
|
548
549
|
|---|---|
|
|
549
|
-
| `
|
|
550
|
+
| `LLM_SWITCHER_HOME=/path` | Dùng thư mục này làm thư mục dữ liệu (config, admin token, file launcher, log) cho cả bản npm lẫn bản checkout. |
|
|
551
|
+
| `LLM_SWITCHER_CONFIG=/path/config.json` | Dùng file cấu hình nằm ngoài thư mục dữ liệu (proxy, `switch` và `mcp.mjs` đều hỗ trợ). |
|
|
550
552
|
| `--port <n>` / `LLM_SWITCHER_PORT` | Ghi đè cổng lắng nghe (ưu tiên: flag > env > `config.port`). |
|
|
551
553
|
| Header `x-llm-profile: <key>` (tên khác `x-profile`) hoặc `?profile=<key>` | Định tuyến riêng 1 request qua profile chỉ định. Key không tồn tại trả HTTP 400 thay vì âm thầm dùng profile khác. |
|
|
552
554
|
| `profile.thinkingMode` | `auto` (mặc định, cho gateway như 9Router): phục hồi thinking bị xoá, chèn hướng dẫn `<think>` cho model không có reasoning, gửi `thinking` + `reasoning_effort`. `native` (API OpenAI nghiêm ngặt): chỉ gửi `reasoning_effort` khi client yêu cầu, không sửa prompt, dùng `max_completion_tokens`. `off`: không bao giờ gửi tham số reasoning. |
|
|
553
555
|
| `profile.endpoints.countTokens` | Ghi đè URL `count_tokens` của Anthropic. |
|
|
554
556
|
| `profile.endpoints` | Ghi đè URL upstream theo từng format: `{ "openai-chat": "...", "anthropic": "...", "vertex": "https://.../models/{model}:{action}" }`. |
|
|
555
|
-
| `LLM_SWITCHER_STATE_DIR` | Chuyển file launcher và log ra khỏi thư mục
|
|
557
|
+
| `LLM_SWITCHER_STATE_DIR` | Chuyển file launcher và log ra khỏi thư mục dữ liệu. Test dùng biến này; shim đọc thư mục đã đặt lúc cài shim. |
|
|
556
558
|
| `CLAUDE_CONFIG_DIR` | Được tôn trọng khi tìm `settings.json` của Claude Code. |
|
|
557
559
|
|
|
558
560
|
## Mô hình Bảo mật
|
package/blindfold/make-certs.sh
CHANGED
|
@@ -14,7 +14,14 @@
|
|
|
14
14
|
set -euo pipefail
|
|
15
15
|
|
|
16
16
|
HOST="${1:-chatgpt.com}"
|
|
17
|
-
|
|
17
|
+
# The default must match the folder the gateway reads (state.mjs paths.blindfoldCA): an npm
|
|
18
|
+
# install keeps its data in ~/.llm-switcher, a git checkout next to the code.
|
|
19
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
20
|
+
if [ -n "${LLM_SWITCHER_BLINDFOLD_CERTS:-}" ]; then DEFAULT_OUT="$LLM_SWITCHER_BLINDFOLD_CERTS"
|
|
21
|
+
elif [ -n "${LLM_SWITCHER_HOME:-}" ]; then DEFAULT_OUT="$LLM_SWITCHER_HOME/blindfold/certs"
|
|
22
|
+
elif [ -d "$ROOT/.git" ]; then DEFAULT_OUT="$ROOT/blindfold/certs"
|
|
23
|
+
else DEFAULT_OUT="$HOME/.llm-switcher/blindfold/certs"; fi
|
|
24
|
+
OUT_DIR="${2:-$DEFAULT_OUT}"
|
|
18
25
|
CA_DAYS=3650
|
|
19
26
|
LEAF_DAYS=825
|
|
20
27
|
|