codex-antigravity-auth 2.2.0__tar.gz → 2.3.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.
- {codex_antigravity_auth-2.2.0/codex_antigravity_auth.egg-info → codex_antigravity_auth-2.3.0}/PKG-INFO +90 -36
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/README.md +89 -35
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/account_state.py +13 -5
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/accounts.py +147 -52
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/cli.py +120 -7
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/cli_doctor.py +37 -16
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/cli_service.py +15 -2
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/cli_setup.py +110 -42
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/models.py +17 -7
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/schema.py +12 -8
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/server.py +907 -78
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/service.py +47 -9
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/SKILL.md +27 -17
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/scripts/anti.py +2390 -346
- codex_antigravity_auth-2.3.0/codex_antigravity_auth/skills/anti/scripts/anti_lib/chunking.py +126 -0
- codex_antigravity_auth-2.3.0/codex_antigravity_auth/skills/anti/scripts/anti_lib/ledger.py +24 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/scripts/anti_lib/reflections.py +70 -31
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/scripts/anti_lib/verifier.py +4 -1
- codex_antigravity_auth-2.3.0/codex_antigravity_auth/skills/anti/tests/fixtures/v5-lane-opus.json +20 -0
- codex_antigravity_auth-2.3.0/codex_antigravity_auth/skills/anti/tests/fixtures/v5-lane-sonnet.json +21 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/tests/test_anti.py +1405 -60
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/transform.py +37 -17
- codex_antigravity_auth-2.3.0/codex_antigravity_auth/unified.py +413 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0/codex_antigravity_auth.egg-info}/PKG-INFO +90 -36
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth.egg-info/SOURCES.txt +5 -1
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/pyproject.toml +2 -1
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_accounts.py +197 -1
- codex_antigravity_auth-2.3.0/tests/test_anti_new_features.py +833 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_cli.py +51 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_fidelity_edge_cases.py +31 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_regressions.py +77 -4
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_release_workflow.py +1 -1
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_schema_sanitization.py +5 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_server_streaming.py +695 -13
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_service_manager.py +40 -1
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_transform.py +19 -0
- codex_antigravity_auth-2.3.0/tests/test_unified_model_picker.py +490 -0
- codex_antigravity_auth-2.2.0/codex_antigravity_auth/skills/anti/scripts/anti_lib/chunking.py +0 -40
- codex_antigravity_auth-2.2.0/codex_antigravity_auth/skills/anti/scripts/anti_lib/ledger.py +0 -17
- codex_antigravity_auth-2.2.0/tests/test_anti_new_features.py +0 -351
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/LICENSE +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/MANIFEST.in +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/__init__.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/byok.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/constants.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/google_transport.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/oauth.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/observability.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/onepassword.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/openai_transport.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/redaction.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/response_protocol.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/secure_store.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/service_manager.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/agents/openai.yaml +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/scripts/anti_lib/__init__.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/scripts/anti_lib/context.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/scripts/anti_lib/redaction.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/skills/anti/scripts/anti_lib/runner.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth/storage.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth.egg-info/dependency_links.txt +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth.egg-info/entry_points.txt +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth.egg-info/requires.txt +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/codex_antigravity_auth.egg-info/top_level.txt +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/setup.cfg +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/conftest.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_account_state.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_byok_providers.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_fidelity_transforms.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_google_transport.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_openai_transport.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_response_protocol.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_secure_store.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_security_hardening.py +0 -0
- {codex_antigravity_auth-2.2.0 → codex_antigravity_auth-2.3.0}/tests/test_storage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-antigravity-auth
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Google Antigravity OAuth model access for OpenAI Codex
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/Reedtrullz/codex-antigravity-auth
|
|
@@ -65,7 +65,7 @@ Use `$anti` only as an optional sidecar reviewer/planner after the gateway is wo
|
|
|
65
65
|
- **OS-Native Keyring Encryption**: Encrypts Google account tokens and stored BYOK provider config at rest via macOS Keychain, Windows Credential Manager, Linux Secret Service, or a private local fallback key.
|
|
66
66
|
- **Transaction-Safe Cooldown Rotations**: Automatically rotates accounts on backend failures (such as `401`, `403`, or `429` rate limiters) with clean exponential backoff.
|
|
67
67
|
- **High-Fidelity SSE Translation**: Translates stream candidate envelopes, role alignments, reasoning-text deltas, function-call items, and VALIDATED tool parameter modes into Responses API events.
|
|
68
|
-
- **BYOK Provider Routing**: Route model IDs like `deepseek:deepseek-v4-pro`, `
|
|
68
|
+
- **BYOK Provider Routing**: Route model IDs like `deepseek:deepseek-v4-pro`, `xai:grok-code-fast-1`, `kimi:kimi-k2-0711-preview`, `ollama:gpt-oss:20b`, and custom OpenAI-compatible endpoints through encrypted API-key config.
|
|
69
69
|
|
|
70
70
|
## Installation
|
|
71
71
|
|
|
@@ -185,32 +185,19 @@ The skill also ships a helper-level panel mode inspired by MoA/Fusion workflows.
|
|
|
185
185
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode review --scope staged
|
|
186
186
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode plan --scope working-tree --prompt "Plan this PR"
|
|
187
187
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode ask --model sonnet --model openrouter:deepseek/deepseek-chat --judge opus --prompt "Compare these approaches"
|
|
188
|
-
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode ask --collab claude-grok --prompt "Compare these approaches"
|
|
189
|
-
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode ask --collab claude-grok --model sonnet --model opus --model grok-bluesminds --prompt "Compare these approaches"
|
|
190
188
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode review --scope staged --output findings
|
|
191
|
-
python3 ~/.codex/skills/anti/scripts/anti.py moa --mode review --model deepseek-v4-pro --
|
|
192
|
-
python3 ~/.codex/skills/anti/scripts/anti.py fusion --mode plan --model opus --model
|
|
189
|
+
python3 ~/.codex/skills/anti/scripts/anti.py moa --mode review --model deepseek-v4-pro --judge opus --scope staged
|
|
190
|
+
python3 ~/.codex/skills/anti/scripts/anti.py fusion --mode plan --model opus --model deepseek-v4-pro --judge opus --scope working-tree --prompt "Plan this repository change"
|
|
193
191
|
```
|
|
194
192
|
|
|
195
|
-
Panel consensus is not proof and should not patch code directly. Structured findings include `id`, `claim`, `severity`, `lanes`, and `verify`; run the `verify` hint locally before acting. Text and JSON outputs include per-lane/judge usage and latency when the gateway/provider returns it. Broad review panels summarize oversized scopes once before fan-out instead of silently truncating raw context for every lane.
|
|
193
|
+
Panel consensus is not proof and should not patch code directly. Structured findings include `id`, `claim`, `severity`, `lanes`, and `verify`; run the `verify` hint locally before acting. Findings remain `unverified` until native/local checks confirm or reject them. Text and JSON outputs include per-lane/judge usage and latency when the gateway/provider returns it. Broad review panels summarize oversized scopes once before fan-out instead of silently truncating raw context for every lane.
|
|
196
194
|
|
|
197
|
-
Panel JSON keeps requested and actual execution identities separate (`requestedModel`, `actualModel`, `provider`, `fallbackChain`, `primaryError`, and `fallbackReason`). The panel status is `complete_multi_model`, `partial_multi_model`, `degraded_single_model`, or `failed`; distinct actual provider/model identities, rather than repeated logical fallback lanes, satisfy `--min-successes
|
|
195
|
+
Panel JSON keeps requested and actual execution identities separate (`requestedModel`, `actualModel`, `provider`, `fallbackChain`, `primaryError`, and `fallbackReason`). The panel status is `complete_multi_model`, `partial_multi_model`, `same_provider_multi_model`, `degraded_single_model`, or `failed`; distinct actual provider/model identities, rather than repeated logical fallback lanes, satisfy `--min-successes`, and `--min-providers` can require provider diversity. `/v1/models` is only a catalog/readiness hint—the bounded generation call is the live model health check. Every saved run exposes top-level `runStatus`, `scopeStatus`, `panelStatus`, `coverage`, and `resultPath`.
|
|
198
196
|
When the diversity minimum is not met, the panel fails closed before judge synthesis; `--json` and `--output findings` still return the lane evidence and status with a non-zero exit code.
|
|
199
197
|
|
|
200
|
-
|
|
198
|
+
Panel lanes are selected explicitly from the native Sonnet/Opus defaults or from models advertised by the running gateway. BYOK examples include `openrouter:...`, `deepseek:...`, `xai:...`, `kimi:...`, `ollama:...`, and `opencode:...`; they require the corresponding API key or a key-optional local provider. When a BYOK lane receives repository, diff, or file context, the helper prints and records a disclosure naming the provider lane. Virtual picker models such as `panel:*`, `moa:*`, or `fusion:*` remain helper aliases rather than gateway-side fan-out.
|
|
201
199
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
### Choosing complementary reviewer lanes
|
|
205
|
-
|
|
206
|
-
- DeepSeek V4 Flash is for a fast code second opinion, debugging, and an explicitly selected retryable fallback. It is never an automatic cross-provider fallback.
|
|
207
|
-
- DeepSeek V4 Pro is for correctness, security, architecture, and deep code review. Treat it as unproven until the live V4 Pro generation, structured-output, and tool-loop gate passes.
|
|
208
|
-
- xAI OAuth Grok is for adversarial assumptions, runtime surprises, and product/UX blind spots.
|
|
209
|
-
- BluesMinds Grok/GLM aliases exist but remain unavailable/degraded until the requested route is advertised by `/v1/models` and the provider live-health gate passes. Every BluesMinds example is conditional on both checks.
|
|
210
|
-
|
|
211
|
-
The normal service intentionally omits BluesMinds. The last bounded live checks returned a billing error for Grok 4.5 and an upstream 429 for GLM-5.2, so neither route is operationally enabled.
|
|
212
|
-
|
|
213
|
-
A future enablement gate must pass first in a temporary process: catalog identity; non-streaming output and exact model identity; SSE completion and `[DONE]`; structured JSON; tool call and continuation; usage accounting; and bounded retries and no billing/capacity error. Only then may a later authorized task add `BLUESMINDS_API_KEY=op://...` to the durable service reference file and reinstall the service.
|
|
200
|
+
The current xAI preset is API-key based and uses `XAI_API_KEY`. Provider availability is determined by the gateway's `/v1/models` catalog; a catalog entry is not proof that a live generation will succeed.
|
|
214
201
|
|
|
215
202
|
Repository context leaves the Google Antigravity lane only after explicit selection and the existing BYOK disclosure. Opus remains the default judge; native Codex remains the acting agent and must verify advisory output locally.
|
|
216
203
|
|
|
@@ -221,16 +208,13 @@ python3 ~/.codex/skills/anti/scripts/anti.py workflow review-ready --scope stage
|
|
|
221
208
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow plan-deep --scope working-tree --prompt "Plan this PR" --progress
|
|
222
209
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow ship-gate --scope diff --base origin/main --json
|
|
223
210
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow provider-compare --model sonnet --model openrouter:deepseek/deepseek-chat --prompt "Compare these approaches"
|
|
224
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow provider-compare --model deepseek-v4-pro --
|
|
211
|
+
python3 ~/.codex/skills/anti/scripts/anti.py workflow provider-compare --model deepseek-v4-pro --prompt "Compare this approach with the native review lane"
|
|
225
212
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow security-review --scope staged --output findings
|
|
226
213
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow debug-consensus --prompt "Intermittent 502s after rotation"
|
|
227
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow claude-grok --panel-mode review --scope staged --output findings
|
|
228
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow claude-grok --panel-mode ask --prompt "Should this UX use route A or B?"
|
|
229
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow claude-grok --model sonnet --model opus --model grok-bluesminds --panel-mode ask --prompt "Stress-test this design"
|
|
230
214
|
python3 ~/.codex/skills/anti/scripts/anti.py runs list
|
|
231
215
|
```
|
|
232
216
|
|
|
233
|
-
Workflow runs save sanitized summaries under `~/.codex/anti-runs` by default; primitive `consult`, `plan`, `review`, and `panel` commands default to not writing a ledger unless `--save-output summary` or `--save-output full` is passed. Saved runs include the Anti run id, which is also sent as `metadata.run_id` to the gateway and appears in sanitized request logs for correlation.
|
|
217
|
+
Workflow runs save sanitized summaries under `~/.codex/anti-runs` by default; primitive `consult`, `plan`, `review`, and `panel` commands default to not writing a ledger unless `--save-output summary` or `--save-output full` is passed. Saved runs include the Anti run id, which is also sent as `metadata.run_id` to the gateway and appears in sanitized request logs for correlation. Run records never retain raw prompts: full mode keeps sanitized per-call output plus prompt hashes/counts, while summary mode keeps a short index and the complete sanitized answer in `result.json`. `plan` and `review` use a conservative Claude safety budget with `--chunked auto`, so broad Opus/Sonnet work is split into bounded chunk calls before synthesis instead of being sent as one giant request; `--chunked off` preserves exact scope and refuses when the request cannot fit, including when `--max-prompt-chars 0` is set. Partial results retain explicit non-zero exits and coverage; `--allow-partial` only permits the call, it does not make the result complete. Use `--required-file` to fail closed if priority files must be fully covered. `--fallback-model sonnet --fallback-policy on-retryable` and `--progress` are available for long-running model calls that may otherwise fail silently or hit transient backend rotation errors.
|
|
234
218
|
|
|
235
219
|
Before running `codex-antigravity login`, create a Google OAuth desktop client. The local callback listener uses:
|
|
236
220
|
|
|
@@ -324,23 +308,19 @@ Overlay ids must be simple printable model ids, cannot shadow built-in ids, back
|
|
|
324
308
|
|
|
325
309
|
### BYOK providers
|
|
326
310
|
|
|
327
|
-
Built-in presets are available for OpenRouter,
|
|
311
|
+
Built-in presets are available for OpenRouter, DeepSeek, xAI, Kimi/Moonshot, Ollama, OpenCode-compatible local servers, and custom OpenAI-compatible APIs:
|
|
328
312
|
|
|
329
313
|
```bash
|
|
330
314
|
codex-antigravity provider presets
|
|
331
|
-
codex-antigravity provider set
|
|
315
|
+
codex-antigravity provider set openrouter --api-key-env OPENROUTER_API_KEY --model openrouter/auto
|
|
332
316
|
codex-antigravity provider set deepseek --api-key-env DEEPSEEK_API_KEY --model deepseek-v4-pro --model deepseek-v4-flash
|
|
333
|
-
codex-antigravity provider set
|
|
334
|
-
codex-antigravity provider set xai --api-key-env XAI_API_KEY --model grok-build-0.1
|
|
335
|
-
codex-antigravity provider login xai-oauth
|
|
317
|
+
codex-antigravity provider set xai --api-key-env XAI_API_KEY --model grok-code-fast-1
|
|
336
318
|
codex-antigravity provider set kimi --api-key-env KIMI_API_KEY --model kimi-k2-0711-preview
|
|
337
319
|
codex-antigravity provider set ollama --base-url http://localhost:11434/v1 --model gpt-oss:20b
|
|
338
320
|
codex-antigravity provider list
|
|
339
321
|
```
|
|
340
322
|
|
|
341
|
-
Provider presets show their supported
|
|
342
|
-
|
|
343
|
-
BluesMinds uses the gateway's mature OpenAI Chat Completions adapter, not the native Responses transport. Its authenticated model catalog advertised `grok-4.5` and `z-ai/glm-5.2`, but successful Responses streaming, structured output, tool calls, usage, and identity fidelity have not been proven. GLM-5.2 is therefore documented as an advisory long-context planning/repository-review lane, with Opus remaining the default Anti judge. DeepSeek V4 uses the official DeepSeek Chat Completions API as `deepseek:deepseek-v4-pro` and `deepseek:deepseek-v4-flash`.
|
|
323
|
+
Provider presets show their supported API-key modes and model defaults. The xAI preset uses `XAI_API_KEY` and exposes `xai:grok-build-0.1`, `xai:grok-4.3`, and `xai:grok-code-fast-1`; no provider-specific OAuth flow is part of the current preset catalog. DeepSeek exposes `deepseek-v4-flash`, `deepseek-v4-pro`, `deepseek-chat`, and `deepseek-reasoner`.
|
|
344
324
|
|
|
345
325
|
For BYOK-only use, point Codex at a BYOK model when writing the provider block:
|
|
346
326
|
|
|
@@ -350,8 +330,8 @@ codex-antigravity configure-codex --write --model deepseek:deepseek-chat
|
|
|
350
330
|
codex-antigravity doctor --byok-only
|
|
351
331
|
```
|
|
352
332
|
|
|
353
|
-
`--api-key-env` avoids persisting provider keys and reads them from the gateway process environment. It may name an existing environment variable instead of the preset default, for example `codex-antigravity provider set
|
|
354
|
-
The `/v1/models` catalog only advertises BYOK models when the provider has a usable stored/env key
|
|
333
|
+
`--api-key-env` avoids persisting provider keys and reads them from the gateway process environment. It may name an existing environment variable instead of the preset default, for example `codex-antigravity provider set deepseek --api-key-env DEV_DEEPSEEK_KEY`. If you intentionally want a provider key stored locally, pass `--api-key`; stored provider keys are encrypted in `~/.codex/antigravity-providers.json`. Use `--auth-mode api-key` explicitly only when you want an API-key provider config to record that mode. Built-in provider env vars include `OPENROUTER_API_KEY`, `DEEPSEEK_API_KEY`, `XAI_API_KEY`, `KIMI_API_KEY`, `MOONSHOT_API_KEY`, `OLLAMA_API_KEY`, and `OPENCODE_API_KEY`.
|
|
334
|
+
The `/v1/models` catalog only advertises BYOK models when the provider has a usable stored/env key or explicitly supports key-optional loopback/local use. The generic `custom` preset is not auto-enabled; run `codex-antigravity provider set custom --base-url ... --model ...` before routing `custom:model`.
|
|
355
335
|
When `provider set` is given `--api-key-env`, models are configured but remain hidden from `/v1/models` until that environment variable is available to the running gateway.
|
|
356
336
|
Provider ids reserve model-name separators and may only contain letters, numbers, underscores, and hyphens; model ids themselves may still contain `/` or `:`, but not whitespace or control characters. Unknown `provider:model` prefixes are rejected as BYOK routing errors before any Google account selection.
|
|
357
337
|
Custom provider and Codex gateway base URLs must be absolute `http` or `https` URLs without embedded credentials, whitespace/control characters, query strings, fragments, invalid ports, or malformed bracketed hosts. Plain `http` base URLs are accepted only for loopback/local hosts; remote BYOK providers and remote gateway URLs must use `https`. Non-preset custom BYOK providers must provide a base URL before models are exposed. Stored/env BYOK API keys and extra BYOK provider header values must be printable ASCII without control characters; model-picker display names must not contain control characters. Provider API-key env var names must contain only letters, numbers, and underscores and must not start with a number. Extra headers may not override gateway-managed auth, content, host, or transport headers. Invalid BYOK provider URLs, API keys, env vars, model ids, display names, and headers are rejected before config writes; invalid BYOK provider URLs, timeouts, headers, API keys, and missing API keys are also rejected before streaming starts so Codex gets a normal HTTP error instead of a partial SSE response. Key-optional BYOK providers are only treated as keyless on loopback/local base URLs; remote custom or cloud URLs need a usable stored or env API key before they appear in Codex's picker or route requests. Function/tool names and forced `tool_choice` function names must contain only letters, numbers, underscores, and hyphens, and be 1-64 characters; malformed names are rejected or dropped before routing. Non-streaming Google failure responses use a structured `detail` object with `message` and sanitized `diagnostics`; clients should handle both this shape and older string details. BYOK streams surface provider error frames as failed Responses API streams instead of successful empty completions, ignore never-named tool-call deltas, and wait for complete valid streamed function names instead of emitting empty, partial, or malformed function names. BYOK structured tool outputs are serialized to JSON text before being sent as Chat Completions tool messages.
|
|
@@ -397,6 +377,64 @@ model_provider = "antigravity"
|
|
|
397
377
|
wire_api = "responses"
|
|
398
378
|
```
|
|
399
379
|
|
|
380
|
+
## Unified Codex model picker
|
|
381
|
+
|
|
382
|
+
Allows Codex to display and use OpenAI, Claude and Gemini models from a
|
|
383
|
+
single configured provider by routing requests through the local gateway.
|
|
384
|
+
|
|
385
|
+
This is opt-in and does not change classic behaviour unless you enable it:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
export OPENAI_API_KEY="sk-..."
|
|
389
|
+
codex-antigravity configure-codex --write --unified-model-picker --model gpt-5.6
|
|
390
|
+
codex-antigravity start --unified-model-picker
|
|
391
|
+
# Or durably:
|
|
392
|
+
codex-antigravity service install --port 51122 --host 127.0.0.1 --unified-model-picker
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Unified mode writes a separate provider block so classic configs are preserved:
|
|
396
|
+
|
|
397
|
+
```toml
|
|
398
|
+
[model_providers.antigravity-unified]
|
|
399
|
+
name = "Antigravity Unified"
|
|
400
|
+
base_url = "http://localhost:51122/v1"
|
|
401
|
+
wire_api = "responses"
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
```toml
|
|
405
|
+
model = "gpt-5.6"
|
|
406
|
+
model_provider = "antigravity-unified"
|
|
407
|
+
wire_api = "responses"
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
When enabled, `GET /v1/models` advertises Antigravity native models, OpenAI/Codex
|
|
411
|
+
ids (`gpt-5.6`, `gpt-5.6-codex`, …), and configured BYOK `provider:model` ids in
|
|
412
|
+
one picker. The gateway routes per model (BYOK → existing provider, OpenAI →
|
|
413
|
+
OpenAI upstream, Claude/Gemini → Antigravity) and returns provider-qualified
|
|
414
|
+
errors for unknown models, missing OpenAI auth, or unreachable upstreams. OpenAI
|
|
415
|
+
requests never fall through to Antigravity and vice versa.
|
|
416
|
+
|
|
417
|
+
OpenAI authentication, in order of preference:
|
|
418
|
+
|
|
419
|
+
1. Explicit `OPENAI_API_KEY` (env) proxied to `https://api.openai.com/v1/responses`
|
|
420
|
+
(override base with `OPENAI_BASE_URL`; file alternative
|
|
421
|
+
`~/.codex/antigravity-openai.json` with `{"api_key": ...}`).
|
|
422
|
+
2. Optional ChatGPT-subscription reuse: `ANTIGRAVITY_OPENAI_USE_CODEX_AUTH=1`
|
|
423
|
+
reads `~/.codex/auth.json` (or `$CODEX_HOME/auth.json`) read-only after
|
|
424
|
+
`codex login` and proxies to `https://chatgpt.com/backend-api/codex/responses`.
|
|
425
|
+
No token refresh is attempted; an expired token returns a clear 401 telling
|
|
426
|
+
you to run `codex login` again. This path is explicit because the auth file
|
|
427
|
+
format is owned by Codex and may change.
|
|
428
|
+
|
|
429
|
+
Extend the OpenAI registry without code changes:
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
export ANTIGRAVITY_OPENAI_MODELS="gpt-5.6,gpt-5.6-codex,my-codex-model"
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Disable unified mode at any time to restore historical behaviour
|
|
436
|
+
(`ANTIGRAVITY_UNIFIED_MODEL_PICKER` unset, classic `antigravity` provider).
|
|
437
|
+
|
|
400
438
|
## Verification
|
|
401
439
|
|
|
402
440
|
To run connection check diagnostics and verify token security:
|
|
@@ -462,6 +500,22 @@ codex-antigravity doctor --codex-ready
|
|
|
462
500
|
codex-antigravity start --port 51122
|
|
463
501
|
```
|
|
464
502
|
|
|
503
|
+
### Unified picker: OpenAI 401 / unknown model
|
|
504
|
+
|
|
505
|
+
If `gpt-5.6` returns 401, the OpenAI upstream has no credentials:
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
export OPENAI_API_KEY="sk-..."
|
|
509
|
+
codex-antigravity start --unified-model-picker
|
|
510
|
+
curl http://127.0.0.1:51122/health
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
If it returns 404 `Unknown model`, the id is not in the OpenAI registry,
|
|
514
|
+
native catalog, or BYOK config. Check `/v1/models`, extend
|
|
515
|
+
`ANTIGRAVITY_OPENAI_MODELS` if needed, and ensure the gateway was restarted
|
|
516
|
+
with `--unified-model-picker`. Classic mode never advertises OpenAI ids; use
|
|
517
|
+
the `antigravity-unified` provider block for unified pickers.
|
|
518
|
+
|
|
465
519
|
## Release Automation
|
|
466
520
|
|
|
467
521
|
Tagged releases are prepared for PyPI Trusted Publishing. The `.github/workflows/publish.yml` workflow runs on `v*` tags, requires the full Ubuntu Python 3.10/3.11/3.12/3.14 plus Windows Python 3.12 test matrix and a checked sdist/wheel build, then publishes with `pypa/gh-action-pypi-publish@release/v1` using OIDC (`id-token: write`) in the `pypi` environment. The tag must exactly match the package version.
|
|
@@ -32,7 +32,7 @@ Use `$anti` only as an optional sidecar reviewer/planner after the gateway is wo
|
|
|
32
32
|
- **OS-Native Keyring Encryption**: Encrypts Google account tokens and stored BYOK provider config at rest via macOS Keychain, Windows Credential Manager, Linux Secret Service, or a private local fallback key.
|
|
33
33
|
- **Transaction-Safe Cooldown Rotations**: Automatically rotates accounts on backend failures (such as `401`, `403`, or `429` rate limiters) with clean exponential backoff.
|
|
34
34
|
- **High-Fidelity SSE Translation**: Translates stream candidate envelopes, role alignments, reasoning-text deltas, function-call items, and VALIDATED tool parameter modes into Responses API events.
|
|
35
|
-
- **BYOK Provider Routing**: Route model IDs like `deepseek:deepseek-v4-pro`, `
|
|
35
|
+
- **BYOK Provider Routing**: Route model IDs like `deepseek:deepseek-v4-pro`, `xai:grok-code-fast-1`, `kimi:kimi-k2-0711-preview`, `ollama:gpt-oss:20b`, and custom OpenAI-compatible endpoints through encrypted API-key config.
|
|
36
36
|
|
|
37
37
|
## Installation
|
|
38
38
|
|
|
@@ -152,32 +152,19 @@ The skill also ships a helper-level panel mode inspired by MoA/Fusion workflows.
|
|
|
152
152
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode review --scope staged
|
|
153
153
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode plan --scope working-tree --prompt "Plan this PR"
|
|
154
154
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode ask --model sonnet --model openrouter:deepseek/deepseek-chat --judge opus --prompt "Compare these approaches"
|
|
155
|
-
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode ask --collab claude-grok --prompt "Compare these approaches"
|
|
156
|
-
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode ask --collab claude-grok --model sonnet --model opus --model grok-bluesminds --prompt "Compare these approaches"
|
|
157
155
|
python3 ~/.codex/skills/anti/scripts/anti.py panel --mode review --scope staged --output findings
|
|
158
|
-
python3 ~/.codex/skills/anti/scripts/anti.py moa --mode review --model deepseek-v4-pro --
|
|
159
|
-
python3 ~/.codex/skills/anti/scripts/anti.py fusion --mode plan --model opus --model
|
|
156
|
+
python3 ~/.codex/skills/anti/scripts/anti.py moa --mode review --model deepseek-v4-pro --judge opus --scope staged
|
|
157
|
+
python3 ~/.codex/skills/anti/scripts/anti.py fusion --mode plan --model opus --model deepseek-v4-pro --judge opus --scope working-tree --prompt "Plan this repository change"
|
|
160
158
|
```
|
|
161
159
|
|
|
162
|
-
Panel consensus is not proof and should not patch code directly. Structured findings include `id`, `claim`, `severity`, `lanes`, and `verify`; run the `verify` hint locally before acting. Text and JSON outputs include per-lane/judge usage and latency when the gateway/provider returns it. Broad review panels summarize oversized scopes once before fan-out instead of silently truncating raw context for every lane.
|
|
160
|
+
Panel consensus is not proof and should not patch code directly. Structured findings include `id`, `claim`, `severity`, `lanes`, and `verify`; run the `verify` hint locally before acting. Findings remain `unverified` until native/local checks confirm or reject them. Text and JSON outputs include per-lane/judge usage and latency when the gateway/provider returns it. Broad review panels summarize oversized scopes once before fan-out instead of silently truncating raw context for every lane.
|
|
163
161
|
|
|
164
|
-
Panel JSON keeps requested and actual execution identities separate (`requestedModel`, `actualModel`, `provider`, `fallbackChain`, `primaryError`, and `fallbackReason`). The panel status is `complete_multi_model`, `partial_multi_model`, `degraded_single_model`, or `failed`; distinct actual provider/model identities, rather than repeated logical fallback lanes, satisfy `--min-successes
|
|
162
|
+
Panel JSON keeps requested and actual execution identities separate (`requestedModel`, `actualModel`, `provider`, `fallbackChain`, `primaryError`, and `fallbackReason`). The panel status is `complete_multi_model`, `partial_multi_model`, `same_provider_multi_model`, `degraded_single_model`, or `failed`; distinct actual provider/model identities, rather than repeated logical fallback lanes, satisfy `--min-successes`, and `--min-providers` can require provider diversity. `/v1/models` is only a catalog/readiness hint—the bounded generation call is the live model health check. Every saved run exposes top-level `runStatus`, `scopeStatus`, `panelStatus`, `coverage`, and `resultPath`.
|
|
165
163
|
When the diversity minimum is not met, the panel fails closed before judge synthesis; `--json` and `--output findings` still return the lane evidence and status with a non-zero exit code.
|
|
166
164
|
|
|
167
|
-
|
|
165
|
+
Panel lanes are selected explicitly from the native Sonnet/Opus defaults or from models advertised by the running gateway. BYOK examples include `openrouter:...`, `deepseek:...`, `xai:...`, `kimi:...`, `ollama:...`, and `opencode:...`; they require the corresponding API key or a key-optional local provider. When a BYOK lane receives repository, diff, or file context, the helper prints and records a disclosure naming the provider lane. Virtual picker models such as `panel:*`, `moa:*`, or `fusion:*` remain helper aliases rather than gateway-side fan-out.
|
|
168
166
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
### Choosing complementary reviewer lanes
|
|
172
|
-
|
|
173
|
-
- DeepSeek V4 Flash is for a fast code second opinion, debugging, and an explicitly selected retryable fallback. It is never an automatic cross-provider fallback.
|
|
174
|
-
- DeepSeek V4 Pro is for correctness, security, architecture, and deep code review. Treat it as unproven until the live V4 Pro generation, structured-output, and tool-loop gate passes.
|
|
175
|
-
- xAI OAuth Grok is for adversarial assumptions, runtime surprises, and product/UX blind spots.
|
|
176
|
-
- BluesMinds Grok/GLM aliases exist but remain unavailable/degraded until the requested route is advertised by `/v1/models` and the provider live-health gate passes. Every BluesMinds example is conditional on both checks.
|
|
177
|
-
|
|
178
|
-
The normal service intentionally omits BluesMinds. The last bounded live checks returned a billing error for Grok 4.5 and an upstream 429 for GLM-5.2, so neither route is operationally enabled.
|
|
179
|
-
|
|
180
|
-
A future enablement gate must pass first in a temporary process: catalog identity; non-streaming output and exact model identity; SSE completion and `[DONE]`; structured JSON; tool call and continuation; usage accounting; and bounded retries and no billing/capacity error. Only then may a later authorized task add `BLUESMINDS_API_KEY=op://...` to the durable service reference file and reinstall the service.
|
|
167
|
+
The current xAI preset is API-key based and uses `XAI_API_KEY`. Provider availability is determined by the gateway's `/v1/models` catalog; a catalog entry is not proof that a live generation will succeed.
|
|
181
168
|
|
|
182
169
|
Repository context leaves the Google Antigravity lane only after explicit selection and the existing BYOK disclosure. Opus remains the default judge; native Codex remains the acting agent and must verify advisory output locally.
|
|
183
170
|
|
|
@@ -188,16 +175,13 @@ python3 ~/.codex/skills/anti/scripts/anti.py workflow review-ready --scope stage
|
|
|
188
175
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow plan-deep --scope working-tree --prompt "Plan this PR" --progress
|
|
189
176
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow ship-gate --scope diff --base origin/main --json
|
|
190
177
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow provider-compare --model sonnet --model openrouter:deepseek/deepseek-chat --prompt "Compare these approaches"
|
|
191
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow provider-compare --model deepseek-v4-pro --
|
|
178
|
+
python3 ~/.codex/skills/anti/scripts/anti.py workflow provider-compare --model deepseek-v4-pro --prompt "Compare this approach with the native review lane"
|
|
192
179
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow security-review --scope staged --output findings
|
|
193
180
|
python3 ~/.codex/skills/anti/scripts/anti.py workflow debug-consensus --prompt "Intermittent 502s after rotation"
|
|
194
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow claude-grok --panel-mode review --scope staged --output findings
|
|
195
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow claude-grok --panel-mode ask --prompt "Should this UX use route A or B?"
|
|
196
|
-
python3 ~/.codex/skills/anti/scripts/anti.py workflow claude-grok --model sonnet --model opus --model grok-bluesminds --panel-mode ask --prompt "Stress-test this design"
|
|
197
181
|
python3 ~/.codex/skills/anti/scripts/anti.py runs list
|
|
198
182
|
```
|
|
199
183
|
|
|
200
|
-
Workflow runs save sanitized summaries under `~/.codex/anti-runs` by default; primitive `consult`, `plan`, `review`, and `panel` commands default to not writing a ledger unless `--save-output summary` or `--save-output full` is passed. Saved runs include the Anti run id, which is also sent as `metadata.run_id` to the gateway and appears in sanitized request logs for correlation.
|
|
184
|
+
Workflow runs save sanitized summaries under `~/.codex/anti-runs` by default; primitive `consult`, `plan`, `review`, and `panel` commands default to not writing a ledger unless `--save-output summary` or `--save-output full` is passed. Saved runs include the Anti run id, which is also sent as `metadata.run_id` to the gateway and appears in sanitized request logs for correlation. Run records never retain raw prompts: full mode keeps sanitized per-call output plus prompt hashes/counts, while summary mode keeps a short index and the complete sanitized answer in `result.json`. `plan` and `review` use a conservative Claude safety budget with `--chunked auto`, so broad Opus/Sonnet work is split into bounded chunk calls before synthesis instead of being sent as one giant request; `--chunked off` preserves exact scope and refuses when the request cannot fit, including when `--max-prompt-chars 0` is set. Partial results retain explicit non-zero exits and coverage; `--allow-partial` only permits the call, it does not make the result complete. Use `--required-file` to fail closed if priority files must be fully covered. `--fallback-model sonnet --fallback-policy on-retryable` and `--progress` are available for long-running model calls that may otherwise fail silently or hit transient backend rotation errors.
|
|
201
185
|
|
|
202
186
|
Before running `codex-antigravity login`, create a Google OAuth desktop client. The local callback listener uses:
|
|
203
187
|
|
|
@@ -291,23 +275,19 @@ Overlay ids must be simple printable model ids, cannot shadow built-in ids, back
|
|
|
291
275
|
|
|
292
276
|
### BYOK providers
|
|
293
277
|
|
|
294
|
-
Built-in presets are available for OpenRouter,
|
|
278
|
+
Built-in presets are available for OpenRouter, DeepSeek, xAI, Kimi/Moonshot, Ollama, OpenCode-compatible local servers, and custom OpenAI-compatible APIs:
|
|
295
279
|
|
|
296
280
|
```bash
|
|
297
281
|
codex-antigravity provider presets
|
|
298
|
-
codex-antigravity provider set
|
|
282
|
+
codex-antigravity provider set openrouter --api-key-env OPENROUTER_API_KEY --model openrouter/auto
|
|
299
283
|
codex-antigravity provider set deepseek --api-key-env DEEPSEEK_API_KEY --model deepseek-v4-pro --model deepseek-v4-flash
|
|
300
|
-
codex-antigravity provider set
|
|
301
|
-
codex-antigravity provider set xai --api-key-env XAI_API_KEY --model grok-build-0.1
|
|
302
|
-
codex-antigravity provider login xai-oauth
|
|
284
|
+
codex-antigravity provider set xai --api-key-env XAI_API_KEY --model grok-code-fast-1
|
|
303
285
|
codex-antigravity provider set kimi --api-key-env KIMI_API_KEY --model kimi-k2-0711-preview
|
|
304
286
|
codex-antigravity provider set ollama --base-url http://localhost:11434/v1 --model gpt-oss:20b
|
|
305
287
|
codex-antigravity provider list
|
|
306
288
|
```
|
|
307
289
|
|
|
308
|
-
Provider presets show their supported
|
|
309
|
-
|
|
310
|
-
BluesMinds uses the gateway's mature OpenAI Chat Completions adapter, not the native Responses transport. Its authenticated model catalog advertised `grok-4.5` and `z-ai/glm-5.2`, but successful Responses streaming, structured output, tool calls, usage, and identity fidelity have not been proven. GLM-5.2 is therefore documented as an advisory long-context planning/repository-review lane, with Opus remaining the default Anti judge. DeepSeek V4 uses the official DeepSeek Chat Completions API as `deepseek:deepseek-v4-pro` and `deepseek:deepseek-v4-flash`.
|
|
290
|
+
Provider presets show their supported API-key modes and model defaults. The xAI preset uses `XAI_API_KEY` and exposes `xai:grok-build-0.1`, `xai:grok-4.3`, and `xai:grok-code-fast-1`; no provider-specific OAuth flow is part of the current preset catalog. DeepSeek exposes `deepseek-v4-flash`, `deepseek-v4-pro`, `deepseek-chat`, and `deepseek-reasoner`.
|
|
311
291
|
|
|
312
292
|
For BYOK-only use, point Codex at a BYOK model when writing the provider block:
|
|
313
293
|
|
|
@@ -317,8 +297,8 @@ codex-antigravity configure-codex --write --model deepseek:deepseek-chat
|
|
|
317
297
|
codex-antigravity doctor --byok-only
|
|
318
298
|
```
|
|
319
299
|
|
|
320
|
-
`--api-key-env` avoids persisting provider keys and reads them from the gateway process environment. It may name an existing environment variable instead of the preset default, for example `codex-antigravity provider set
|
|
321
|
-
The `/v1/models` catalog only advertises BYOK models when the provider has a usable stored/env key
|
|
300
|
+
`--api-key-env` avoids persisting provider keys and reads them from the gateway process environment. It may name an existing environment variable instead of the preset default, for example `codex-antigravity provider set deepseek --api-key-env DEV_DEEPSEEK_KEY`. If you intentionally want a provider key stored locally, pass `--api-key`; stored provider keys are encrypted in `~/.codex/antigravity-providers.json`. Use `--auth-mode api-key` explicitly only when you want an API-key provider config to record that mode. Built-in provider env vars include `OPENROUTER_API_KEY`, `DEEPSEEK_API_KEY`, `XAI_API_KEY`, `KIMI_API_KEY`, `MOONSHOT_API_KEY`, `OLLAMA_API_KEY`, and `OPENCODE_API_KEY`.
|
|
301
|
+
The `/v1/models` catalog only advertises BYOK models when the provider has a usable stored/env key or explicitly supports key-optional loopback/local use. The generic `custom` preset is not auto-enabled; run `codex-antigravity provider set custom --base-url ... --model ...` before routing `custom:model`.
|
|
322
302
|
When `provider set` is given `--api-key-env`, models are configured but remain hidden from `/v1/models` until that environment variable is available to the running gateway.
|
|
323
303
|
Provider ids reserve model-name separators and may only contain letters, numbers, underscores, and hyphens; model ids themselves may still contain `/` or `:`, but not whitespace or control characters. Unknown `provider:model` prefixes are rejected as BYOK routing errors before any Google account selection.
|
|
324
304
|
Custom provider and Codex gateway base URLs must be absolute `http` or `https` URLs without embedded credentials, whitespace/control characters, query strings, fragments, invalid ports, or malformed bracketed hosts. Plain `http` base URLs are accepted only for loopback/local hosts; remote BYOK providers and remote gateway URLs must use `https`. Non-preset custom BYOK providers must provide a base URL before models are exposed. Stored/env BYOK API keys and extra BYOK provider header values must be printable ASCII without control characters; model-picker display names must not contain control characters. Provider API-key env var names must contain only letters, numbers, and underscores and must not start with a number. Extra headers may not override gateway-managed auth, content, host, or transport headers. Invalid BYOK provider URLs, API keys, env vars, model ids, display names, and headers are rejected before config writes; invalid BYOK provider URLs, timeouts, headers, API keys, and missing API keys are also rejected before streaming starts so Codex gets a normal HTTP error instead of a partial SSE response. Key-optional BYOK providers are only treated as keyless on loopback/local base URLs; remote custom or cloud URLs need a usable stored or env API key before they appear in Codex's picker or route requests. Function/tool names and forced `tool_choice` function names must contain only letters, numbers, underscores, and hyphens, and be 1-64 characters; malformed names are rejected or dropped before routing. Non-streaming Google failure responses use a structured `detail` object with `message` and sanitized `diagnostics`; clients should handle both this shape and older string details. BYOK streams surface provider error frames as failed Responses API streams instead of successful empty completions, ignore never-named tool-call deltas, and wait for complete valid streamed function names instead of emitting empty, partial, or malformed function names. BYOK structured tool outputs are serialized to JSON text before being sent as Chat Completions tool messages.
|
|
@@ -364,6 +344,64 @@ model_provider = "antigravity"
|
|
|
364
344
|
wire_api = "responses"
|
|
365
345
|
```
|
|
366
346
|
|
|
347
|
+
## Unified Codex model picker
|
|
348
|
+
|
|
349
|
+
Allows Codex to display and use OpenAI, Claude and Gemini models from a
|
|
350
|
+
single configured provider by routing requests through the local gateway.
|
|
351
|
+
|
|
352
|
+
This is opt-in and does not change classic behaviour unless you enable it:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
export OPENAI_API_KEY="sk-..."
|
|
356
|
+
codex-antigravity configure-codex --write --unified-model-picker --model gpt-5.6
|
|
357
|
+
codex-antigravity start --unified-model-picker
|
|
358
|
+
# Or durably:
|
|
359
|
+
codex-antigravity service install --port 51122 --host 127.0.0.1 --unified-model-picker
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Unified mode writes a separate provider block so classic configs are preserved:
|
|
363
|
+
|
|
364
|
+
```toml
|
|
365
|
+
[model_providers.antigravity-unified]
|
|
366
|
+
name = "Antigravity Unified"
|
|
367
|
+
base_url = "http://localhost:51122/v1"
|
|
368
|
+
wire_api = "responses"
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
```toml
|
|
372
|
+
model = "gpt-5.6"
|
|
373
|
+
model_provider = "antigravity-unified"
|
|
374
|
+
wire_api = "responses"
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
When enabled, `GET /v1/models` advertises Antigravity native models, OpenAI/Codex
|
|
378
|
+
ids (`gpt-5.6`, `gpt-5.6-codex`, …), and configured BYOK `provider:model` ids in
|
|
379
|
+
one picker. The gateway routes per model (BYOK → existing provider, OpenAI →
|
|
380
|
+
OpenAI upstream, Claude/Gemini → Antigravity) and returns provider-qualified
|
|
381
|
+
errors for unknown models, missing OpenAI auth, or unreachable upstreams. OpenAI
|
|
382
|
+
requests never fall through to Antigravity and vice versa.
|
|
383
|
+
|
|
384
|
+
OpenAI authentication, in order of preference:
|
|
385
|
+
|
|
386
|
+
1. Explicit `OPENAI_API_KEY` (env) proxied to `https://api.openai.com/v1/responses`
|
|
387
|
+
(override base with `OPENAI_BASE_URL`; file alternative
|
|
388
|
+
`~/.codex/antigravity-openai.json` with `{"api_key": ...}`).
|
|
389
|
+
2. Optional ChatGPT-subscription reuse: `ANTIGRAVITY_OPENAI_USE_CODEX_AUTH=1`
|
|
390
|
+
reads `~/.codex/auth.json` (or `$CODEX_HOME/auth.json`) read-only after
|
|
391
|
+
`codex login` and proxies to `https://chatgpt.com/backend-api/codex/responses`.
|
|
392
|
+
No token refresh is attempted; an expired token returns a clear 401 telling
|
|
393
|
+
you to run `codex login` again. This path is explicit because the auth file
|
|
394
|
+
format is owned by Codex and may change.
|
|
395
|
+
|
|
396
|
+
Extend the OpenAI registry without code changes:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
export ANTIGRAVITY_OPENAI_MODELS="gpt-5.6,gpt-5.6-codex,my-codex-model"
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Disable unified mode at any time to restore historical behaviour
|
|
403
|
+
(`ANTIGRAVITY_UNIFIED_MODEL_PICKER` unset, classic `antigravity` provider).
|
|
404
|
+
|
|
367
405
|
## Verification
|
|
368
406
|
|
|
369
407
|
To run connection check diagnostics and verify token security:
|
|
@@ -429,6 +467,22 @@ codex-antigravity doctor --codex-ready
|
|
|
429
467
|
codex-antigravity start --port 51122
|
|
430
468
|
```
|
|
431
469
|
|
|
470
|
+
### Unified picker: OpenAI 401 / unknown model
|
|
471
|
+
|
|
472
|
+
If `gpt-5.6` returns 401, the OpenAI upstream has no credentials:
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
export OPENAI_API_KEY="sk-..."
|
|
476
|
+
codex-antigravity start --unified-model-picker
|
|
477
|
+
curl http://127.0.0.1:51122/health
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
If it returns 404 `Unknown model`, the id is not in the OpenAI registry,
|
|
481
|
+
native catalog, or BYOK config. Check `/v1/models`, extend
|
|
482
|
+
`ANTIGRAVITY_OPENAI_MODELS` if needed, and ensure the gateway was restarted
|
|
483
|
+
with `--unified-model-picker`. Classic mode never advertises OpenAI ids; use
|
|
484
|
+
the `antigravity-unified` provider block for unified pickers.
|
|
485
|
+
|
|
432
486
|
## Release Automation
|
|
433
487
|
|
|
434
488
|
Tagged releases are prepared for PyPI Trusted Publishing. The `.github/workflows/publish.yml` workflow runs on `v*` tags, requires the full Ubuntu Python 3.10/3.11/3.12/3.14 plus Windows Python 3.12 test matrix and a checked sdist/wheel build, then publishes with `pypa/gh-action-pypi-publish@release/v1` using OIDC (`id-token: write`) in the `pypi` environment. The tag must exactly match the package version.
|
|
@@ -151,7 +151,13 @@ class AccountState:
|
|
|
151
151
|
def state(self) -> dict[str, Any]:
|
|
152
152
|
return self.data["accountState"]
|
|
153
153
|
|
|
154
|
-
def _select(
|
|
154
|
+
def _select(
|
|
155
|
+
self,
|
|
156
|
+
family: str,
|
|
157
|
+
*,
|
|
158
|
+
acquire: bool,
|
|
159
|
+
exclude_emails: set[str] | None = None,
|
|
160
|
+
) -> Lease | None:
|
|
155
161
|
if family not in FAMILIES:
|
|
156
162
|
raise ValueError(f"unsupported model family: {family}")
|
|
157
163
|
with self._lock:
|
|
@@ -170,6 +176,8 @@ class AccountState:
|
|
|
170
176
|
if not isinstance(account, dict) or not account.get("email"):
|
|
171
177
|
continue
|
|
172
178
|
email = str(account["email"])
|
|
179
|
+
if exclude_emails and email in exclude_emails:
|
|
180
|
+
continue
|
|
173
181
|
scoped = self.state["cooldowns"].get(email, {})
|
|
174
182
|
if scoped.get("account", 0) > now or scoped.get(family, 0) > now:
|
|
175
183
|
continue
|
|
@@ -187,11 +195,11 @@ class AccountState:
|
|
|
187
195
|
self._in_flight[email] = self._in_flight.get(email, 0) + 1
|
|
188
196
|
return Lease(account=account, family=family)
|
|
189
197
|
|
|
190
|
-
def select(self, family: str) -> Lease | None:
|
|
191
|
-
return self._select(family, acquire=False)
|
|
198
|
+
def select(self, family: str, *, exclude_emails: set[str] | None = None) -> Lease | None:
|
|
199
|
+
return self._select(family, acquire=False, exclude_emails=exclude_emails)
|
|
192
200
|
|
|
193
|
-
def acquire(self, family: str) -> Lease | None:
|
|
194
|
-
return self._select(family, acquire=True)
|
|
201
|
+
def acquire(self, family: str, *, exclude_emails: set[str] | None = None) -> Lease | None:
|
|
202
|
+
return self._select(family, acquire=True, exclude_emails=exclude_emails)
|
|
195
203
|
|
|
196
204
|
def release(self, lease: Lease | None) -> None:
|
|
197
205
|
if lease is not None:
|