llm-switcher 1.2.12 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog — LLM Switcher
2
2
 
3
+ ## Release 1.3.1
4
+
5
+ - **agy note:** `switch plugin status` now names agy 1.2.14. This release of agy also loads `~/.gemini/antigravity-cli/hooks.json` but does not run its hooks (measured 2026-10-03), so the shim toast is still the notice for agy.
6
+ - **Tests:** A test covers an error in a converted agy stream. The error goes to agy bare, as Code Assist sends it. The agy end-to-end tests now pass in any order.
7
+
8
+ ## Release 1.3.0
9
+
10
+ - **Antigravity CLI (`agy`):** A third tool, beside Claude Code and Codex. A profile with `"tool": "agy"` routes it, and `switch agy <profile>` turns it on. `switch off agy` turns it off and leaves the other tools alone. The dashboard has an agy row and an **agy on intact** template.
11
+ - **No proxy and no certificate for agy:** The `agy` shim sets `CLOUD_CODE_URL` to the gateway. agy is a Go program, and Go on Windows trusts only the system store, so an interceptor would need a certificate in that store. `CLOUD_CODE_URL` needs none. agy also ignores `HTTPS_PROXY`.
12
+ - **What agy sends where:** Only the agent turns of agy go to its profile. Checkpoint summaries, the model list, quota, sign-in state and analytics go to Google with the token of the person, unchanged. While agy is off, every call goes to Google.
13
+ - **Remote control:** agy reaches its remote control through `jetski-webchannel.googleapis.com`, not through `CLOUD_CODE_URL`. It stays connected while the switcher routes agy.
14
+ - **Model slot:** An agy profile has one slot, `main`. A `*` in the value stands for the model that agy picked, so `antigravity/*` keeps the choice of agy on an intact pool.
15
+ - **Conversion:** An agent turn on any other upstream is converted from Code Assist and back. Each answer chunk is wrapped as `{"response": …, "traceId": …}`, and each function call keeps its id, so agy matches the tool result.
16
+ - **Bifrost for agy and Codex:** When intact names the client of a model (`bifrost_ua`), the request crosses unchanged. agy goes to `/v1/v1internal:<method>` and Codex (HTTP) to `/v1/responses`. Only the key changes. The Google token of agy never reaches intact. Codex over the WebSocket transport keeps the normal route.
17
+ - **Usage of a passthrough:** The usage tap reads Gemini `usageMetadata`, so a Bifrost answer of agy reports its tokens in the inspector.
18
+ - **Launch notice:** `switch plugin install` also writes an entry into `~/.gemini/antigravity-cli/hooks.json`. agy 1.2.7 loads this file but does not run global hooks yet, so the shim toast is the notice for agy today. `switch plugin status` says so.
19
+ - **The agy shim proves the gateway first:** agy sends its Google token in clear text to `CLOUD_CODE_URL`, so the shim asks the gateway for its identity proof (`verify-gateway.mjs`). If no proof comes within 3 seconds, the shim removes the variable and agy keeps its official endpoint.
20
+ - **Passthrough limits:** A Code Assist call that the gateway does not route has an idle limit (`LLM_SWITCHER_CODE_ASSIST_TIMEOUT_MS`, default 5 minutes). A broken upstream answer cuts the connection to agy instead of ending it as if it were complete.
21
+ - **Passthrough headers:** A call to Google keeps every header of agy, `x-goog-*` included. Only the headers of the gateway (`x-llm-profile`, `x-profile`, `x-llm-switcher-token`, `x-intact-*`) and the proxy headers (`proxy-authorization`, `x-forwarded-*`, `x-real-ip`) are removed.
22
+ - **No silent fallback to Google:** While agy is routed, an agent turn that the gateway cannot route gets an error. A config that never loaded gives 503. A named profile that does not exist gives 400. A body that does not parse gives 400. A request with no model on a `*` slot gives 400.
23
+ - **Bifrost lookup:** A failed lookup (no answer, or any answer that is not 2xx, a 404 too) keeps the normal route for 30 seconds only (`LLM_SWITCHER_BIFROST_RETRY_MS`), and the gateway prints one line for each series of failures. Before, an error answer held the normal route for 10 minutes without a word.
24
+ - **Broken Bifrost stream:** If a Bifrost or direct stream breaks, the gateway cuts the connection. Before, the client got a clean end of a half answer.
25
+ - **`switch plugin`:** Each tool installs on its own, so a fault in one hooks file does not stop the others. If the path of `hook-status.mjs` holds a space, agy is skipped (`[Skip]`), not failed. An agy `hooks.json` whose root is not an object is never changed. `switch plugin status` names an agy `hooks.json` that does not parse.
26
+ - **Migration:** The migration of an old `config.json` keeps `activeProfiles.agy`, and a pointer to a profile renamed because its key became a command word (`agy` becomes `agy-profile`) follows the rename.
27
+ - **`switch shim status` on Windows:** It now finds the command the way Windows does, by directory and then by `PATHEXT`. Before, an `agy.exe` earlier on `PATH` than the shim was reported as "shim active".
28
+ - **The launch files of agy** (`env-agy.*`, `route-agy.txt`) are ignored by git and npm, like those of the other tools.
29
+ - **Needs intact 0.1.14 or newer** for Bifrost of agy and Codex.
30
+
3
31
  ## Release 1.2.12
4
32
 
5
33
  - **Update now:** The update notice on the dashboard has an **Update now** button. The gateway installs the release, and a new gateway process starts on the new code. Then the dashboard reloads. `switch update` does the same from a terminal.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <p align="center">
4
4
  <b>Zero-dependency, multi-protocol edge gateway & provider switcher</b><br>
5
- Bridge <b>Claude Code</b> and <b>Codex</b> to any upstream LLM API: OpenAI-compatible, Anthropic, or Vertex.<br>
5
+ Bridge <b>Claude Code</b>, <b>Codex</b> and the <b>Antigravity CLI</b> to any upstream LLM API: OpenAI-compatible, Anthropic, or Vertex.<br>
6
6
  Full bi-directional protocol conversion, official-model context windows, thinking protocol extraction, and edge message healing.
7
7
  </p>
8
8
 
@@ -27,7 +27,7 @@
27
27
  > **LLM Switcher solves this at the local network edge:**
28
28
  > - **100% Native Emulation:** Normalizes upstream APIs (intact, 9Router, Vertex, DeepSeek) into genuine Anthropic SSE (`thinking_delta` + `tool_use`) for Claude Code, and genuine Responses API events for Codex.
29
29
  > - **Client-Side Edge Companion:** Intentionally offloads heavy account pooling and key rotation to **[intact](https://github.com/louisphamdev/intact)** (recommended) or 9Router (basic alternative), keeping LLM Switcher zero-dependency and bloat-free.
30
- > - **Targeted Tool Scope:** Built specifically for **Claude Code** and **OpenAI Codex** (OpenCode natively supports custom models without shims; refer to intact for account pooling; and Antigravity isn't worth building for 😏).
30
+ > - **Targeted Tool Scope:** Built specifically for **Claude Code**, **OpenAI Codex** and the **Antigravity CLI** (`agy`). OpenCode supports custom models without shims; refer to intact for account pooling.
31
31
 
32
32
  ---
33
33
 
@@ -132,9 +132,9 @@ LLM Switcher acts as a transparent man-in-the-middle without ever touching clien
132
132
 
133
133
  - **Zero-Dependency Architecture:** Built 100% on Node.js standard libraries (`http`, `fs`, `os`, `path`, `fetch`). No npm dependencies, no bundled runtime bloat, cold-start under 50ms.
134
134
  - **Bi-Directional Protocol Conversion:**
135
- - **4 Client Inbound Formats:** Anthropic Messages, OpenAI Chat Completions, Codex Responses API, Vertex `generateContent`.
135
+ - **3 Client Inbound Formats:** Anthropic Messages (Claude Code), Codex Responses API (Codex), Code Assist (Antigravity CLI).
136
136
  - **3 Upstream Outbound Formats:** OpenAI Chat, Anthropic Native, Vertex Native.
137
- - **Bifrost:** Claude Code on a Claude Code account of intact goes through unchanged. Only the key changes. No conversion, no healer, no filter. The gateway turns it on by itself. [Bifrost](#bifrost-claude-code-to-a-claude-code-account-on-intact)
137
+ - **Bifrost:** A coding tool on an account of its own provider in intact goes through unchanged. Only the key changes. No conversion, no healer, no filter. This works for Claude Code, Codex and the Antigravity CLI. The gateway turns it on by itself. [Bifrost](#bifrost-a-coding-tool-to-its-own-account-on-intact)
138
138
  - **Multi-Active CLI Routing:** Run Claude Code on Profile A, Codex on Profile B, and Cursor on Profile C simultaneously on a single gateway instance.
139
139
  - **Deep Thinking & Reasoning Extraction:** Tested on 48 live response combinations. Accurately extracts `reasoning_content`, `<think>` tags, Vertex `thought` parts, and signatures into native `thinking_delta` blocks.
140
140
  - **Edge Healer Engine (Anti-Collision for Token Optimizers):**
@@ -148,7 +148,12 @@ LLM Switcher acts as a transparent man-in-the-middle without ever touching clien
148
148
 
149
149
  ---
150
150
 
151
- ## Recent Highlights (v1.2.0)
151
+ ## Recent Highlights (v1.3.0)
152
+
153
+ - **Antigravity CLI (`agy`):** A third tool with its own profile. `switch agy <profile>` routes it. agy reaches the gateway through `CLOUD_CODE_URL`, so it needs no proxy and no certificate. Remote control keeps working, because it uses its own host. [Antigravity CLI setup](#antigravity-cli-agy-setup)
154
+ - **Bifrost for agy and Codex:** On an intact pool, agy and Codex requests cross unchanged, as Claude Code requests already did.
155
+
156
+ ## Earlier Highlights (v1.2.0)
152
157
 
153
158
  - **Zero-Mutation Interceptor:** All traffic routes via `HTTPS_PROXY` without editing client configs (`~/.claude/settings.json`, `~/.codex/config.toml`).
154
159
  - **Concurrent Multi-Tool Support:** Simultaneously configures `{ claude, codex }` profiles with dynamic, zero-downtime switching (`POST /_control/active-tools`).
@@ -224,12 +229,14 @@ Each tool gets its own file instead, and only the matching shim loads it:
224
229
  | --- | --- |
225
230
  | `env-claude.sh` / `env-claude.cmd` | the `claude` shim |
226
231
  | `env-codex.sh` / `env-codex.cmd` | the `codex` shim |
232
+ | `env-agy.sh` / `env-agy.cmd` | the `agy` shim |
227
233
  | `env.sh` / `env.cmd` | nobody. Neutral stub, kept only so an old rc line stays silent |
228
234
 
229
235
  An empty per-tool file means that tool is off: the shim then leaves the environment alone and the
230
236
  tool reaches its official endpoint. Before it loads anything, the shim also scrubs a stale
231
237
  `ANTHROPIC_BASE_URL`, `OPENAI_BASE_URL` or `ANTHROPIC_DEFAULT_<TIER>_MODEL` inherited from an older
232
- release or from your own shell, so `switch off` really is off.
238
+ release or from your own shell, so `switch off` really is off. The `agy` shim removes a
239
+ `CLOUD_CODE_URL` that points at the gateway while agy is off.
233
240
 
234
241
  In practice you never call these files. `switch shim install` puts `~/.llm-switcher/bin` on `PATH`,
235
242
  and every `claude` and `codex` invocation — including `claude --resume` in a brand-new terminal —
@@ -273,6 +280,63 @@ On Windows, add `%USERPROFILE%\.llm-switcher\bin` before the real Codex director
273
280
 
274
281
  The shim never edits `~/.codex/config.toml`. Codex reaches the gateway cleanly through `HTTPS_PROXY` and the interceptor, retaining its own model names and context windows. Model catalog entries are served dynamically at `/v1/models`.
275
282
 
283
+ ### Antigravity CLI (agy) setup
284
+
285
+ agy is the command-line client of Google Antigravity. It reads the variable `CLOUD_CODE_URL` and
286
+ sends every Code Assist call to that address. The `agy` shim sets this variable to the gateway,
287
+ so agy needs no proxy and no certificate.
288
+
289
+ 1. Sign in to agy with your Google account. agy needs this sign-in for its own calls.
290
+ 2. Create a profile with `"tool": "agy"`. The dashboard has a template, **agy on intact**.
291
+ 3. Run these commands, then open a new terminal:
292
+ ```bash
293
+ switch shim install
294
+ switch agy <profile>
295
+ agy
296
+ ```
297
+
298
+ The gateway routes the calls of agy as follows:
299
+
300
+ | Call | Where it goes |
301
+ | --- | --- |
302
+ | An agent turn (`requestType: "agent"`) | The profile of agy: Bifrost on intact, or a conversion to any upstream |
303
+ | A checkpoint summary, the model list, quota, sign-in state, analytics | Google, with your own token |
304
+ | Any call while agy is off | Google |
305
+
306
+ A call to Google keeps its headers and its bytes. The gateway removes only its own headers
307
+ (`x-llm-profile`, `x-profile`, `x-llm-switcher-token`, and the contract-lab headers `x-intact-probe`
308
+ and `x-intact-trace`) and the headers of a proxy in front of it (`proxy-authorization`,
309
+ `x-forwarded-*`, `x-real-ip`).
310
+
311
+ While agy is routed, the gateway refuses an agent turn that it cannot route. It never sends that
312
+ turn to Google instead:
313
+
314
+ | Condition | Answer to agy |
315
+ | --- | --- |
316
+ | `config.json` never loaded | 503 |
317
+ | The request names a profile that does not exist (`x-llm-profile`, `?profile=`) | 400 |
318
+ | The request body does not parse | 400 |
319
+ | The request names no model, and the `main` slot holds a `*` | 400 |
320
+
321
+ The profile has one model slot, `main`. A `*` in the value stands for the model that agy picked:
322
+
323
+ - `antigravity/*` sends `gemini-3.8-flash-high` to intact as `antigravity/gemini-3.8-flash-high`.
324
+ intact names agy as the own client of its Antigravity pool, so the request crosses through
325
+ Bifrost.
326
+ - `claude/claude-opus-5` sends every agent turn to that model. The gateway converts the Code
327
+ Assist request, and converts the answer back to the Code Assist shape.
328
+
329
+ Remote control of agy uses its own host (`jetski-webchannel.googleapis.com`). It does not use
330
+ `CLOUD_CODE_URL`, so it works while the switcher routes agy.
331
+
332
+ The Google token of agy goes only to Google. A Bifrost or converted request carries the key of the
333
+ profile, never this token.
334
+
335
+ agy sends this token in clear text to `CLOUD_CODE_URL`. For this reason, the `agy` shim asks the
336
+ gateway for its identity proof before it gives agy the variable. If the port does not answer with
337
+ the proof of this install within 3 seconds, the shim removes the variable, prints one line, and agy
338
+ uses its official endpoint.
339
+
276
340
  ### Blindfold mode (optional)
277
341
 
278
342
  A base URL override makes Codex print one line on its own `/model` screen:
@@ -404,18 +468,27 @@ Add the server to your MCP configuration (for example `opencode.jsonc`, `claude_
404
468
 
405
469
  ---
406
470
 
407
- ## Bifrost: Claude Code to a Claude Code account on intact
471
+ ## Bifrost: a coding tool to its own account on intact
408
472
 
409
- Bifrost sends a Claude Code request to intact without a change. Only the key changes. The healer, `thinkingMode`, and the format conversion do not run.
473
+ Bifrost sends a request of a coding tool to intact without a change. Only the key changes. The healer, `thinkingMode`, and the format conversion do not run.
410
474
 
411
475
  Bifrost has no setting. The gateway turns it on for each request when two conditions are true:
412
476
 
413
- 1. intact gives `bifrost_ua` for the mapped model in `GET /v1/models/{model}`. intact gives it only for a model of a Claude Code account.
477
+ 1. intact gives `bifrost_ua` for the mapped model in `GET /v1/models/{model}`. intact gives it only for a model of an account that belongs to the provider of the tool.
414
478
  2. The `User-Agent` of the client starts with the `bifrost_ua` value.
415
479
 
416
- The gateway keeps the answer from intact for 10 minutes for each model. If intact does not answer, the gateway keeps the result for 30 seconds and uses the normal route.
480
+ | Tool | `bifrost_ua` | Path on intact |
481
+ | --- | --- | --- |
482
+ | Claude Code | `claude-cli/` | `/v1/messages` |
483
+ | Codex (HTTP) | `codex_cli_rs/` | `/v1/responses` |
484
+ | Antigravity CLI | `antigravity/cli/` | `/v1/v1internal:streamGenerateContent`, `/v1/v1internal:generateContent` |
485
+
486
+ For agy, intact also writes the project of the chosen account into the request. Codex over its
487
+ WebSocket transport still uses the normal route.
488
+
489
+ The gateway keeps the answer from intact for 10 minutes for each model. Only a 2xx answer is kept that long. If intact does not answer, or answers with an error (a 404 too), the gateway uses the normal route. It asks again after 30 seconds (`LLM_SWITCHER_BIFROST_RETRY_MS`), and it prints one line for each series of failures.
417
490
 
418
- The gateway sends every client header, the body bytes, and the query string. It removes the credentials of the client and the hop-by-hop headers, and it sets `x-api-key` to the profile key. If the profile maps the model, the gateway also changes the `model` field. A different client, or a model that is not a Claude Code account, uses the normal route of the profile.
491
+ The gateway sends every client header, the body bytes, and the query string. It removes the credentials of the client and the hop-by-hop headers, and it sets `x-api-key` to the profile key. If the profile maps the model, the gateway also changes the `model` field. A different client, or a model of an account that does not belong to the provider of the tool, uses the normal route of the profile.
419
492
 
420
493
  ## CLI Reference
421
494
 
@@ -429,25 +502,27 @@ switch on [profile] # Start the gateway and activate a profile
429
502
  switch <profile> # Activate a profile for both tools
430
503
  switch claude <profile> # Set the active profile for Claude Code only
431
504
  switch codex <profile> # Set the active profile for Codex only
505
+ switch agy <profile> # Set the active profile for the Antigravity CLI only
432
506
  switch port <number> # Change the gateway port (restarts it if running)
433
507
  switch service install # Install OS background autostart service (Windows / macOS / Linux); updates at each logon
434
508
  switch service uninstall # Remove background autostart service
435
- switch shim install # Route new Claude and Codex sessions through the gateway
509
+ switch shim install # Route new Claude, Codex and agy sessions through the gateway
436
510
  switch shim status # Verify shims + detect running sessions that bypass the gateway
437
511
  switch shim uninstall # Remove the launcher shims
438
- switch plugin install # Optional: a launch notice inside Claude Code and Codex
512
+ switch plugin install # Optional: a launch notice inside Claude Code, Codex and agy
439
513
  switch plugin status # Report whether that notice is installed
440
514
  switch plugin uninstall # Remove that notice
441
515
  switch off # Stop everything and restore the official endpoints
442
516
  switch off claude # Turn Claude Code off; Codex keeps running
443
- switch off codex # Turn Codex off; Claude Code keeps running
517
+ switch off codex # Turn Codex off; the other tools keep running
518
+ switch off agy # Turn the Antigravity CLI off; the other tools keep running
444
519
  switch contract-probe [--model m] # Drive the contract-lab variants through the gateway
445
520
  switch contract-check # Turn the open contract findings into failing tests
446
521
  ```
447
522
 
448
- Targets are `claude` and `codex`, and they are the only two. A profile is one tool: `tool` is
449
- either `"claude"` or `"codex"` (or `null` for a profile that is switched off), so `switch claude` and
450
- `switch codex` can never point at the same profile by accident. There is no `openai` or `vertex`
523
+ Targets are `claude`, `codex` and `agy`. A profile is one tool: `tool` is `"claude"`, `"codex"` or
524
+ `"agy"` (or `null` for a profile that is switched off), so two targets can never point at the same
525
+ profile by accident. There is no `openai` or `vertex`
451
526
  target any more — the input routes those names stood for are gone.
452
527
 
453
528
  The service runs without your shell. `switch service install` therefore copies `LLM_SWITCHER_HOME`, `CLAUDE_CONFIG_DIR`, `LLM_SWITCHER_CONFIG`, `LLM_SWITCHER_STATE_DIR` and `LLM_SWITCHER_BLINDFOLD_CERTS` into the systemd unit or the launchd plist when they are set. The Windows task cannot carry them; set them as User environment variables instead. If the installed definition differs from the new one, for example after a hand edit, the old file is kept as `<file>.bak`. On Windows the task is created from an XML definition, so paths with spaces need no extra quoting and the task has no run-time limit. This Windows path is not tested on Windows yet.
@@ -546,6 +621,7 @@ This writes one file for each tool, and it opens no configuration file of either
546
621
  | --- | --- | --- |
547
622
  | Claude Code | `~/.claude/skills/llm-switcher-status/` | A folder with `.claude-plugin/plugin.json` under a skills directory loads as a plugin on the next session. There is no marketplace and no install step. |
548
623
  | Codex | `~/.codex/hooks.json` | Codex reads this file by itself. `config.toml` stays closed. |
624
+ | Antigravity CLI | `~/.gemini/antigravity-cli/hooks.json` | agy reads this file at the start. agy 1.2.14 loads it, but it does not run global hooks yet. Only `.agents/hooks.json` in a workspace runs. Until a release runs global hooks, the shim toast is the notice for agy. agy cannot run a quoted path, so if the path of `hook-status.mjs` holds a space, the install skips agy and prints `[Skip]`. |
549
625
 
550
626
  An existing `~/.codex/hooks.json` is merged. Your own hooks stay, and `switch plugin uninstall` takes
551
627
  only ours away. If the file does not parse, the install refuses it and changes nothing, because that
@@ -576,14 +652,15 @@ of the routing.
576
652
  "port": 3456,
577
653
  "activeProfiles": {
578
654
  "claude": "claude-default", // Active profile for Claude Code (/v1/messages)
579
- "codex": "codex-default" // Active profile for Codex (/v1/responses)
655
+ "codex": "codex-default", // Active profile for Codex (/v1/responses)
656
+ "agy": "agy-default" // Active profile for the Antigravity CLI (/v1internal:*)
580
657
  },
581
658
  "blindfold": { "port": 3457 }, // Interceptor port. Top-level, optional, default 3457
582
659
  "profiles": {
583
660
  "claude-default": {
584
661
  "name": "Intact Gateway",
585
662
  "mode": "convert", // hybrid | convert | direct
586
- "tool": "claude", // claude | codex | null (profile is off)
663
+ "tool": "claude", // claude | codex | agy | null (profile is off)
587
664
  "outFormat": "openai-chat", // openai-chat | anthropic | vertex
588
665
  "thinkingMode": "auto", // auto | native | off (see Advanced Options)
589
666
  "baseURL": "https://intact.example.com/v1", // or https://api.9router.com/v1
@@ -613,6 +690,16 @@ of the routing.
613
690
  "codexRoles": { "review": "gpt-5.6-sol" }, // optional: pair one role with another public name
614
691
  "defaultModels": { "main": "gemini-3.8-flash", "review": "gemini-3.7-flash-medium", "subagent": "gemini-3.6-flash-low" },
615
692
  "model1M": { "main": false, "review": false, "subagent": false }
693
+ },
694
+ "agy-default": {
695
+ "name": "agy via intact",
696
+ "mode": "convert",
697
+ "tool": "agy",
698
+ "outFormat": "openai-chat",
699
+ "baseURL": "https://intact.example.com/v1",
700
+ "apiKey": "sk-...",
701
+ // One slot. * stands for the model that agy picked; antigravity/* crosses Bifrost on intact.
702
+ "defaultModels": { "main": "antigravity/*" }
616
703
  }
617
704
  },
618
705
  "debug": false,
@@ -663,6 +750,9 @@ Because of this split, a provider fingerprint is never a rule in this gateway. I
663
750
  | `LLM_SWITCHER_CONFIG=/path/config.json` | Use a config file outside the data folder (the proxy, `switch` and `mcp.mjs` all honour it). |
664
751
  | `--port <n>` / `LLM_SWITCHER_PORT` | Override the listening port of the gateway (priority: flag > env > `config.port`). |
665
752
  | `LLM_SWITCHER_BLINDFOLD_PORT` | Override the listening port of the interceptor (priority: env > `config.blindfold.port` > 3457). Set it together with `LLM_SWITCHER_PORT` to run a second instance. |
753
+ | `LLM_SWITCHER_CODE_ASSIST_URL` | The Code Assist host that receives the agy calls the gateway does not route (default `https://daily-cloudcode-pa.googleapis.com`). |
754
+ | `LLM_SWITCHER_CODE_ASSIST_TIMEOUT_MS` | Idle time of such a call, from 1000 to 2147483647 ms (default 300000). Before the answer starts, agy gets a 504. After it starts, the connection is cut. |
755
+ | `LLM_SWITCHER_BIFROST_RETRY_MS` | Time before the gateway asks intact again after a failed Bifrost lookup (default 30000 ms). |
666
756
  | `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. |
667
757
  | `profile.thinkingMode` | `auto` (default, for gateways like intact or 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. |
668
758
  | `profile.endpoints.countTokens` | Override the Anthropic `count_tokens` URL. |
package/README.vi.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <p align="center">
4
4
  <b>Cổng ngõ biên (Edge Gateway) chuyển đổi đa giao thức LLM siêu nhẹ, Zero-Dependency</b><br>
5
- Cầu nối hai chiều giữa <b>Claude Code</b> và <b>Codex</b> với mọi nhà cung cấp LLM: OpenAI-compatible, Anthropic hoặc Vertex.<br>
5
+ Cầu nối hai chiều giữa <b>Claude Code</b>, <b>Codex</b> và <b>Antigravity CLI</b> với mọi nhà cung cấp LLM: OpenAI-compatible, Anthropic hoặc Vertex.<br>
6
6
  Chuyển đổi giao thức qua IR, cửa sổ context theo model chính thức, trích xuất thinking blocks và tự chữa lành đồ thị tin nhắn trước khi ra Internet.
7
7
  </p>
8
8
 
@@ -27,7 +27,7 @@
27
27
  > **LLM Switcher giải quyết triệt để vấn đề này ngay tại network edge cục bộ:**
28
28
  > - **100% Native Emulation:** Chuẩn hóa upstream API (intact, 9Router, Vertex, DeepSeek) thành luồng Anthropic SSE xịn (`thinking_delta` + `tool_use`) cho Claude Code, và Responses API event cho Codex.
29
29
  > - **Client-Side Edge Companion:** Cố tình tách biệt các tác vụ nặng như account pooling, key rotation cho **[intact](https://github.com/louisphamdev/intact)** (khuyên dùng) hoặc 9Router (cơ bản), giúp Switcher giữ vững tiêu chí Zero-Dependency siêu nhẹ.
30
- > - **Phạm vi Tập trung:** Tối ưu chuyên sâu cho **Claude Code** và **OpenAI Codex** (OpenCode đã hỗ trợ đổi model native ngay trong config; muốn pooling thì dùng intact; còn Antigravity thì không đáng để bận tâm làm 😏).
30
+ > - **Phạm vi Tập trung:** Tối ưu chuyên sâu cho **Claude Code**, **OpenAI Codex** và **Antigravity CLI** (`agy`). OpenCode đã hỗ trợ đổi model native ngay trong config; muốn pooling thì dùng intact.
31
31
 
32
32
  ---
33
33
 
@@ -132,9 +132,9 @@ LLM Switcher hoạt động như một lớp trung gian mạng trong suốt (tra
132
132
 
133
133
  - **Kiến trúc Zero-Dependency:** Xây dựng 100% bằng thư viện chuẩn của Node.js (`http`, `fs`, `os`, `path`, `fetch`). Không cần chạy `npm install`, không kéo theo runtime Bun hay binary nặng, khởi động dưới 50ms.
134
134
  - **Chuyển đổi Giao thức 2 Chiều Đối xứng:**
135
- - **4 Định dạng đầu vào (Client):** Anthropic Messages, OpenAI Chat Completions, Codex Responses API, Vertex `generateContent`.
135
+ - **3 Định dạng đầu vào (Client):** Anthropic Messages (Claude Code), Codex Responses API (Codex), Code Assist (Antigravity CLI).
136
136
  - **3 Định dạng đầu ra (Upstream):** OpenAI Chat, Anthropic Native, Vertex Native.
137
- - **Bifrost:** Claude Code tới tài khoản Claude Code trên intact đi nguyên vẹn. Chỉ key thay đổi. Không chuyển định dạng, không healer, không lọc. Gateway tự bật. [Bifrost](#bifrost-claude-code-tới-tài-khoản-claude-code-trên-intact)
137
+ - **Bifrost:** Một coding tool tới tài khoản của chính nhà cung cấp của nó trên intact đi nguyên vẹn. Chỉ key thay đổi. Không chuyển định dạng, không healer, không lọc. Áp dụng cho Claude Code, Codex và Antigravity CLI. Gateway tự bật. [Bifrost](#bifrost-coding-tool-tới-tài-khoản-của-chính-nó-trên-intact)
138
138
  - **Multi-Active CLI Routing:** Kích hoạt cùng lúc Claude Code dùng Profile A, Codex dùng Profile B, Cursor dùng Profile C trên cùng 1 gateway mà không tranh chấp cấu hình.
139
139
  - **Trích xuất Thinking & Reasoning Chuyên sâu:** Kiểm chứng thực tế qua 48 tổ hợp mẫu response live. Tự động bóc tách `reasoning_content`, thẻ `<think>`, các block `thought` của Vertex và thought signature thành các `thinking_delta` chuẩn của Anthropic.
140
140
  - **Edge Healer Engine (Tự chữa lành tin nhắn):**
@@ -148,7 +148,12 @@ LLM Switcher hoạt động như một lớp trung gian mạng trong suốt (tra
148
148
 
149
149
  ---
150
150
 
151
- ## Thay đổi gần đây (v1.2.0)
151
+ ## Thay đổi gần đây (v1.3.0)
152
+
153
+ - **Antigravity CLI (`agy`):** Công cụ thứ ba, có profile riêng. `switch agy <profile>` định tuyến nó. agy tới gateway qua `CLOUD_CODE_URL`, nên không cần proxy và không cần chứng chỉ. Remote control vẫn chạy, vì nó dùng host riêng. [Cấu hình Antigravity CLI](#cấu-hình-antigravity-cli-agy)
154
+ - **Bifrost cho agy và Codex:** Trên pool intact, request của agy và Codex đi nguyên vẹn, giống Claude Code từ trước.
155
+
156
+ ## Thay đổi trước đó (v1.2.0)
152
157
 
153
158
  - **Zero-Mutation Interceptor:** Định tuyến qua `HTTPS_PROXY`, tuyệt đối không can thiệp hay sửa file cấu hình của tool (`~/.claude/settings.json`, `~/.codex/config.toml`).
154
159
  - **Hỗ trợ đồng thời cả Claude Code & Codex:** Quản lý độc lập `{ claude, codex }`, chuyển đổi profile tức thì qua `POST /_control/active-tools` mà không cần restart cổng.
@@ -226,12 +231,14 @@ Mỗi công cụ có file riêng, và chỉ shim tương ứng mới nạp:
226
231
  | --- | --- |
227
232
  | `env-claude.sh` / `env-claude.cmd` | shim `claude` |
228
233
  | `env-codex.sh` / `env-codex.cmd` | shim `codex` |
234
+ | `env-agy.sh` / `env-agy.cmd` | shim `agy` |
229
235
  | `env.sh` / `env.cmd` | không ai. Stub trống, giữ lại chỉ để dòng rc cũ lặng lẽ |
230
236
 
231
237
  File của công cụ rỗng nghĩa là công cụ đó đang tắt: shim để nguyên môi trường và công cụ gọi thẳng
232
238
  endpoint chính thức. Trước khi nạp bất cứ thứ gì, shim cũng quét một `ANTHROPIC_BASE_URL`,
233
239
  `OPENAI_BASE_URL` hay `ANTHROPIC_DEFAULT_<TIER>_MODEL` cũ còn sót từ bản trước hoặc từ shell của
234
- bạn, nên `switch off` là off thật sự.
240
+ bạn, nên `switch off` là off thật sự. Shim `agy` gỡ một `CLOUD_CODE_URL` trỏ vào gateway khi agy
241
+ đang tắt.
235
242
 
236
243
  Trong thực tế bạn không bao giờ tự gọi các file này. `switch shim install` đặt `~/.llm-switcher/bin`
237
244
  vào `PATH`, và mọi lệnh `claude` hay `codex` — kể cả `claude --resume` trong một terminal hoàn toàn
@@ -275,6 +282,61 @@ Trên Windows, đặt `%USERPROFILE%\.llm-switcher\bin` trước thư mục Code
275
282
 
276
283
  Shim tuyệt đối không sửa `~/.codex/config.toml`. Codex kết nối tới gateway qua `HTTPS_PROXY` và interceptor mạng, giữ nguyên tên model và context window chính thức. Danh sách model được phục vụ động tại `/v1/models`.
277
284
 
285
+ ### Cấu hình Antigravity CLI (agy)
286
+
287
+ agy là client dòng lệnh của Google Antigravity. agy đọc biến `CLOUD_CODE_URL` và gửi mọi lệnh gọi
288
+ Code Assist tới địa chỉ đó. Shim `agy` đặt biến này trỏ vào gateway, nên agy không cần proxy và
289
+ không cần chứng chỉ.
290
+
291
+ 1. Đăng nhập agy bằng tài khoản Google của bạn. agy cần đăng nhập cho các lệnh gọi của chính nó.
292
+ 2. Tạo một profile có `"tool": "agy"`. Dashboard có sẵn template **agy on intact**.
293
+ 3. Chạy các lệnh sau, rồi mở terminal mới:
294
+ ```bash
295
+ switch shim install
296
+ switch agy <profile>
297
+ agy
298
+ ```
299
+
300
+ Gateway định tuyến các lệnh gọi của agy như sau:
301
+
302
+ | Lệnh gọi | Đi tới đâu |
303
+ | --- | --- |
304
+ | Lượt agent (`requestType: "agent"`) | Profile của agy: Bifrost trên intact, hoặc chuyển đổi sang upstream bất kỳ |
305
+ | Tóm tắt checkpoint, danh sách model, quota, trạng thái đăng nhập, analytics | Google, bằng token của chính bạn |
306
+ | Mọi lệnh gọi khi agy đang tắt | Google |
307
+
308
+ Lệnh gọi tới Google giữ nguyên header và byte. Gateway chỉ bỏ header của chính nó
309
+ (`x-llm-profile`, `x-profile`, `x-llm-switcher-token`, và header contract-lab `x-intact-probe`,
310
+ `x-intact-trace`) và header của proxy đứng trước nó (`proxy-authorization`, `x-forwarded-*`,
311
+ `x-real-ip`).
312
+
313
+ Khi agy đang được định tuyến, gateway từ chối lượt agent mà nó không định tuyến được. Gateway không
314
+ bao giờ gửi lượt đó sang Google thay thế:
315
+
316
+ | Điều kiện | agy nhận |
317
+ | --- | --- |
318
+ | `config.json` chưa từng nạp được | 503 |
319
+ | Request chỉ định một profile không tồn tại (`x-llm-profile`, `?profile=`) | 400 |
320
+ | Body request không parse được | 400 |
321
+ | Request không có model, và slot `main` chứa `*` | 400 |
322
+
323
+ Profile có một slot model là `main`. Dấu `*` trong giá trị thay cho model mà agy đã chọn:
324
+
325
+ - `antigravity/*` gửi `gemini-3.8-flash-high` tới intact dưới tên `antigravity/gemini-3.8-flash-high`.
326
+ intact nhận agy là client của chính pool Antigravity, nên request đi qua Bifrost.
327
+ - `claude/claude-opus-5` gửi mọi lượt agent tới model đó. Gateway chuyển request Code Assist sang
328
+ định dạng của upstream, rồi chuyển câu trả lời về lại định dạng Code Assist.
329
+
330
+ Remote control của agy dùng host riêng (`jetski-webchannel.googleapis.com`). Nó không dùng
331
+ `CLOUD_CODE_URL`, nên vẫn chạy khi switcher định tuyến agy.
332
+
333
+ Token Google của agy chỉ đi tới Google. Request Bifrost hay request đã chuyển đổi mang key của
334
+ profile, không bao giờ mang token này.
335
+
336
+ agy gửi token này dạng rõ tới `CLOUD_CODE_URL`. Vì vậy shim `agy` hỏi gateway bằng chứng danh tính
337
+ trước khi giao biến này cho agy. Nếu cổng không trả lời đúng bằng chứng của bản cài này trong 3 giây,
338
+ shim gỡ biến, in một dòng thông báo, và agy dùng endpoint chính thức.
339
+
278
340
  ### Chế độ blindfold (tùy chọn)
279
341
 
280
342
  Khi có override base URL, Codex in một dòng ngay trên màn `/model` của nó:
@@ -401,18 +463,27 @@ Thêm server vào cấu hình MCP (ví dụ `opencode.jsonc`, `claude_desktop_co
401
463
 
402
464
  ---
403
465
 
404
- ## Bifrost: Claude Code tới tài khoản Claude Code trên intact
466
+ ## Bifrost: coding tool tới tài khoản của chính nó trên intact
405
467
 
406
- Bifrost gửi request của Claude Code tới intact nguyên vẹn. Chỉ key thay đổi. Healer, `thinkingMode` và bước chuyển định dạng không chạy.
468
+ Bifrost gửi request của một coding tool tới intact nguyên vẹn. Chỉ key thay đổi. Healer, `thinkingMode` và bước chuyển định dạng không chạy.
407
469
 
408
470
  Bifrost không có cấu hình. Gateway tự bật Bifrost cho từng request khi đủ hai điều kiện:
409
471
 
410
- 1. intact trả `bifrost_ua` cho model đã map trong `GET /v1/models/{model}`. intact chỉ trả trường này cho model của tài khoản Claude Code.
472
+ 1. intact trả `bifrost_ua` cho model đã map trong `GET /v1/models/{model}`. intact chỉ trả trường này cho model của tài khoản thuộc nhà cung cấp của công cụ.
411
473
  2. `User-Agent` của client bắt đầu bằng giá trị `bifrost_ua`.
412
474
 
413
- Gateway giữ câu trả lời của intact 10 phút cho mỗi model. Nếu intact không trả lời, gateway giữ kết quả 30 giây và dùng đường thường.
475
+ | Công cụ | `bifrost_ua` | Path trên intact |
476
+ | --- | --- | --- |
477
+ | Claude Code | `claude-cli/` | `/v1/messages` |
478
+ | Codex (HTTP) | `codex_cli_rs/` | `/v1/responses` |
479
+ | Antigravity CLI | `antigravity/cli/` | `/v1/v1internal:streamGenerateContent`, `/v1/v1internal:generateContent` |
480
+
481
+ Với agy, intact ghi thêm project của tài khoản được chọn vào request. Codex qua WebSocket vẫn đi
482
+ đường thường.
483
+
484
+ Gateway giữ câu trả lời của intact 10 phút cho mỗi model. Chỉ câu trả lời 2xx được giữ lâu như vậy. Nếu intact không trả lời, hoặc trả lỗi (kể cả 404), gateway dùng đường thường. Gateway hỏi lại sau 30 giây (`LLM_SWITCHER_BIFROST_RETRY_MS`) và in một dòng cho mỗi chuỗi lỗi.
414
485
 
415
- Gateway gửi mọi header của client, nguyên byte body và query string. Gateway bỏ credential của client và các header hop-by-hop, rồi đặt `x-api-key` bằng key của profile. Nếu profile map model, gateway đổi thêm trường `model`. Client khác, hoặc model không thuộc tài khoản Claude Code, đi đường thường của profile.
486
+ Gateway gửi mọi header của client, nguyên byte body và query string. Gateway bỏ credential của client và các header hop-by-hop, rồi đặt `x-api-key` bằng key của profile. Nếu profile map model, gateway đổi thêm trường `model`. Client khác, hoặc model của tài khoản không thuộc nhà cung cấp của công cụ, đi đường thường của profile.
416
487
 
417
488
  ## Bảng Tra cứu Lệnh CLI (`switch`)
418
489
 
@@ -426,25 +497,27 @@ switch on [profile] # Khởi động gateway và kích hoạt một p
426
497
  switch <profile> # Kích hoạt một profile cho cả hai công cụ
427
498
  switch claude <profile> # Đặt profile kích hoạt riêng cho Claude Code
428
499
  switch codex <profile> # Đặt profile kích hoạt riêng cho Codex
500
+ switch agy <profile> # Đặt profile kích hoạt riêng cho Antigravity CLI
429
501
  switch port <number> # Đổi cổng gateway (tự restart nếu đang chạy)
430
502
  switch service install # Cài đặt gateway thành service chạy ngầm tự bật cùng máy; tự update mỗi lần đăng nhập
431
503
  switch service uninstall # Gỡ bỏ service chạy ngầm
432
- switch shim install # Route phiên Claude và Codex mới qua gateway
504
+ switch shim install # Route phiên Claude, Codex và agy mới qua gateway
433
505
  switch shim status # Kiểm tra shim + phát hiện phiên đang chạy ngoài gateway
434
506
  switch shim uninstall # Gỡ shim khỏi launcher
435
- switch plugin install # Tuỳ chọn: nhắc nhở ngay trong Claude Code và Codex
507
+ switch plugin install # Tuỳ chọn: nhắc nhở ngay trong Claude Code, Codex và agy
436
508
  switch plugin status # Xem nhắc nhở đó đã cài chưa
437
509
  switch plugin uninstall # Gỡ nhắc nhở đó
438
510
  switch off # Tắt tất cả và quay về endpoint chính thức
439
511
  switch off claude # Tắt Claude Code; Codex vẫn chạy tiếp
440
- switch off codex # Tắt Codex; Claude Code vẫn chạy tiếp
512
+ switch off codex # Tắt Codex; các công cụ khác vẫn chạy tiếp
513
+ switch off agy # Tắt Antigravity CLI; các công cụ khác vẫn chạy tiếp
441
514
  switch contract-probe [--model m] # Chạy các biến thể contract-lab qua gateway
442
515
  switch contract-check # Chuyển các findings hợp đồng còn mở thành test case
443
516
  ```
444
517
 
445
- Target chỉ có `claude` và `codex`, và đó là hai target duy nhất. Một profile phục vụ đúng một công
446
- cụ: `tool` là `"claude"` hoặc `"codex"` (hoặc `null` khi profile đang tắt), nên `switch claude` và
447
- `switch codex` không bao giờ chỉ nhầm vào cùng một profile. Không còn target `openai` hay `vertex` —
518
+ Target là `claude`, `codex` và `agy`. Một profile phục vụ đúng một công cụ: `tool` là `"claude"`,
519
+ `"codex"` hoặc `"agy"` (hoặc `null` khi profile đang tắt), nên hai target không bao giờ chỉ nhầm vào
520
+ cùng một profile. Không còn target `openai` hay `vertex` —
448
521
  các route đầu vào mà chúng đại diện đã bị gỡ.
449
522
 
450
523
 
@@ -541,6 +614,7 @@ Lệnh này ghi một file cho mỗi tool, và không mở file cấu hình nào
541
614
  | --- | --- | --- |
542
615
  | Claude Code | `~/.claude/skills/llm-switcher-status/` | Một thư mục có `.claude-plugin/plugin.json` nằm dưới skills directory sẽ được nạp như một plugin ở phiên kế tiếp. Không cần marketplace, không cần bước install. |
543
616
  | Codex | `~/.codex/hooks.json` | Codex tự đọc file này. `config.toml` không bị mở. |
617
+ | Antigravity CLI | `~/.gemini/antigravity-cli/hooks.json` | agy đọc file này khi khởi động. agy 1.2.14 nạp file này nhưng chưa chạy hook toàn cục. Chỉ `.agents/hooks.json` trong workspace mới chạy. Cho tới khi có bản chạy hook toàn cục, toast của shim là nhắc nhở cho agy. agy không chạy được đường dẫn có dấu nháy, nên nếu đường dẫn của `hook-status.mjs` có dấu cách, lệnh cài bỏ qua agy và in `[Skip]`. |
544
618
 
545
619
  Nếu `~/.codex/hooks.json` đã có sẵn thì lệnh sẽ **merge**. Hook của bạn được giữ nguyên, và
546
620
  `switch plugin uninstall` chỉ lấy đi phần của switcher. Nếu file không parse được thì lệnh từ chối và
@@ -572,14 +646,15 @@ route.
572
646
  "port": 3456,
573
647
  "activeProfiles": {
574
648
  "claude": "claude-default", // Profile active cho Claude Code (/v1/messages)
575
- "codex": "codex-default" // Profile active cho Codex (/v1/responses)
649
+ "codex": "codex-default", // Profile active cho Codex (/v1/responses)
650
+ "agy": "agy-default" // Profile active cho Antigravity CLI (/v1internal:*)
576
651
  },
577
652
  "blindfold": { "port": 3457 }, // Cổng interceptor. Cấp cao nhất, không bắt buộc, mặc định 3457
578
653
  "profiles": {
579
654
  "claude-default": {
580
655
  "name": "Intact Gateway",
581
656
  "mode": "convert", // hybrid | convert | direct
582
- "tool": "claude", // claude | codex | null (profile đang tắt)
657
+ "tool": "claude", // claude | codex | agy | null (profile đang tắt)
583
658
  "outFormat": "openai-chat", // openai-chat | anthropic | vertex
584
659
  "thinkingMode": "auto", // auto | native | off (xem Tuỳ chọn Nâng cao)
585
660
  "baseURL": "https://intact.example.com/v1", // hoặc https://api.9router.com/v1
@@ -609,6 +684,16 @@ route.
609
684
  "codexRoles": { "review": "gpt-5.6-sol" }, // không bắt buộc: ghép một vai trò với tên public khác
610
685
  "defaultModels": { "main": "gemini-3.8-flash", "review": "gemini-3.7-flash-medium", "subagent": "gemini-3.6-flash-low" },
611
686
  "model1M": { "main": false, "review": false, "subagent": false }
687
+ },
688
+ "agy-default": {
689
+ "name": "agy qua intact",
690
+ "mode": "convert",
691
+ "tool": "agy",
692
+ "outFormat": "openai-chat",
693
+ "baseURL": "https://intact.example.com/v1",
694
+ "apiKey": "sk-...",
695
+ // Một slot. * thay cho model agy đã chọn; antigravity/* đi Bifrost trên intact.
696
+ "defaultModels": { "main": "antigravity/*" }
612
697
  }
613
698
  },
614
699
  "debug": false,
@@ -660,6 +745,9 @@ Nhờ cách chia này, fingerprint của provider không bao giờ là rule tron
660
745
  | `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ợ). |
661
746
  | `--port <n>` / `LLM_SWITCHER_PORT` | Ghi đè cổng lắng nghe của gateway (ưu tiên: flag > env > `config.port`). |
662
747
  | `LLM_SWITCHER_BLINDFOLD_PORT` | Ghi đè cổng lắng nghe của interceptor (ưu tiên: env > `config.blindfold.port` > 3457). Đảm bảo đặt cùng `LLM_SWITCHER_PORT` khi chạy instance thứ hai. |
748
+ | `LLM_SWITCHER_CODE_ASSIST_URL` | Host Code Assist nhận các lệnh gọi của agy mà gateway không định tuyến (mặc định `https://daily-cloudcode-pa.googleapis.com`). |
749
+ | `LLM_SWITCHER_CODE_ASSIST_TIMEOUT_MS` | Thời gian chờ không có dữ liệu của lệnh gọi đó, từ 1000 tới 2147483647 ms (mặc định 300000). Trước khi câu trả lời bắt đầu, agy nhận 504. Sau khi đã bắt đầu, kết nối bị cắt. |
750
+ | `LLM_SWITCHER_BIFROST_RETRY_MS` | Thời gian trước khi gateway hỏi lại intact sau một lần tra cứu Bifrost thất bại (mặc định 30000 ms). |
663
751
  | 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. |
664
752
  | `profile.thinkingMode` | `auto` (mặc định, cho gateway như intact hoặc 9Router): phục hồi thinking bị xoá, inject 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. |
665
753
  | `profile.endpoints.countTokens` | Ghi đè URL `count_tokens` của Anthropic. |
@@ -2,7 +2,8 @@
2
2
  "port": 3456,
3
3
  "activeProfiles": {
4
4
  "claude": "claude-default",
5
- "codex": "codex-default"
5
+ "codex": "codex-default",
6
+ "agy": "agy-default"
6
7
  },
7
8
  "blindfold": {
8
9
  "port": 3457
@@ -51,6 +52,17 @@
51
52
  "review": false,
52
53
  "subagent": false
53
54
  }
55
+ },
56
+ "agy-default": {
57
+ "name": "agy default (Antigravity CLI -> intact Antigravity pool, Bifrost)",
58
+ "mode": "convert",
59
+ "tool": "agy",
60
+ "outFormat": "openai-chat",
61
+ "baseURL": "https://YOUR-INTACT-HOST/v1",
62
+ "apiKey": "sk-REPLACE-ME",
63
+ "defaultModels": {
64
+ "main": "antigravity/*"
65
+ }
54
66
  }
55
67
  },
56
68
  "debug": false,