remove Vercel AI Gateway and Vercel Sandbox (#33067)

* remove Vercel AI Gateway provider and Vercel Sandbox terminal backend

Both Vercel-hosted integrations are removed end-to-end. Users on the AI
Gateway should switch to OpenRouter or one of the other aggregators
(Nous Portal, Kilo Code). Users on the Vercel Sandbox backend should
switch to Docker, Modal, Daytona, or SSH.

What's removed:
- `plugins/model-providers/ai-gateway/` provider plugin
- `hermes_cli/vercel_auth.py` Vercel-Sandbox auth helper
- `tools/environments/vercel_sandbox.py` terminal backend
- `ai-gateway` provider wiring across auth, doctor, setup, models,
  config, status, providers, main, web_server, model_normalize, dump
- `vercel_sandbox` backend wiring across terminal_tool, file_tools,
  code_execution_tool, file_operations, approval, skills_tool,
  environments/local, credential_files, lazy_deps, prompt_builder,
  cli, gateway/run
- `AI_GATEWAY_BASE_URL` constant, `_AI_GATEWAY_HEADERS` auxiliary-client
  header set, run_agent base-URL header/reasoning special-cases
- `[vercel]` pyproject extra and `vercel`/`vercel-workers` from uv.lock
- env vars: `AI_GATEWAY_API_KEY`, `AI_GATEWAY_BASE_URL`, `VERCEL_TOKEN`,
  `VERCEL_PROJECT_ID`, `VERCEL_TEAM_ID`, `VERCEL_OIDC_TOKEN`,
  `TERMINAL_VERCEL_RUNTIME`
- Tests: deletes test_ai_gateway_models.py and
  test_vercel_sandbox_environment.py; scrubs references across 23
  surviving test files (no entire tests deleted unless they were
  dedicated to AI Gateway / Sandbox)
- Docs: provider tables, env-var reference, setup guides, security
  notes, tool config, terminal-backend tables — English plus zh-Hans
  i18n parity
- `hermes-agent` skill: provider table entry and remote-backend list

What stays (intentional):
- `popular-web-designs/templates/vercel.md` — CSS design reference,
  unrelated to Vercel-the-AI-product
- `x-vercel-id` in `stream_diag.py` headers — generic Vercel CDN
  response header, useful diag signal on any Vercel-hosted endpoint
- `vercel-labs/agent-browser` URL in browser config — lightpanda
  browser project, different OSS effort
- `userStories.json` historical contributor entry mentioning Vercel
  Sandbox — archive, not active docs

Validation:
- 1153 tests in the 22 targeted files pass (`scripts/run_tests.sh`)
- Full repo `py_compile` clean
- Live import of every touched module + invariant check (no
  `ai-gateway` in `PROVIDER_REGISTRY`, no `_AI_GATEWAY_HEADERS`, no
  `vercel_sandbox` in `_REMOTE_TERMINAL_BACKENDS`)

* test: convert profile-count check from change-detector to invariant

The hardcoded "== 34" assertion broke when ai-gateway was removed.
Per AGENTS.md change-detector-test guidance, assert the relationship
(registry count >= number of plugin dirs) instead of a literal count.
Counts shift when providers are added/removed; that's expected.
This commit is contained in:
Teknium 2026-05-27 00:43:32 -07:00 committed by GitHub
parent cb38ce28cb
commit febc4cfec0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
95 changed files with 111 additions and 3088 deletions

View file

@ -1,4 +1,4 @@
"""Tests for API-key provider support (z.ai/GLM, Kimi, MiniMax, AI Gateway)."""
"""Tests for API-key provider support (z.ai/GLM, Kimi, MiniMax)."""
import os
@ -40,7 +40,6 @@ class TestProviderRegistry:
("stepfun", "StepFun Step Plan", "api_key"),
("minimax", "MiniMax", "api_key"),
("minimax-cn", "MiniMax (China)", "api_key"),
("ai-gateway", "Vercel AI Gateway", "api_key"),
("kilocode", "Kilo Code", "api_key"),
("gmi", "GMI Cloud", "api_key"),
])
@ -97,11 +96,6 @@ class TestProviderRegistry:
assert pconfig.api_key_env_vars == ("MINIMAX_CN_API_KEY",)
assert pconfig.base_url_env_var == "MINIMAX_CN_BASE_URL"
def test_ai_gateway_env_vars(self):
pconfig = PROVIDER_REGISTRY["ai-gateway"]
assert pconfig.api_key_env_vars == ("AI_GATEWAY_API_KEY",)
assert pconfig.base_url_env_var == "AI_GATEWAY_BASE_URL"
def test_kilocode_env_vars(self):
pconfig = PROVIDER_REGISTRY["kilocode"]
assert pconfig.api_key_env_vars == ("KILOCODE_API_KEY",)
@ -125,7 +119,6 @@ class TestProviderRegistry:
assert PROVIDER_REGISTRY["stepfun"].inference_base_url == STEPFUN_STEP_PLAN_INTL_BASE_URL
assert PROVIDER_REGISTRY["minimax"].inference_base_url == "https://api.minimax.io/anthropic"
assert PROVIDER_REGISTRY["minimax-cn"].inference_base_url == "https://api.minimaxi.com/anthropic"
assert PROVIDER_REGISTRY["ai-gateway"].inference_base_url == "https://ai-gateway.vercel.sh/v1"
assert PROVIDER_REGISTRY["kilocode"].inference_base_url == "https://api.kilo.ai/api/gateway"
assert PROVIDER_REGISTRY["gmi"].inference_base_url == "https://api.gmi-serving.com/v1"
assert PROVIDER_REGISTRY["huggingface"].inference_base_url == "https://router.huggingface.co/v1"
@ -149,7 +142,6 @@ PROVIDER_ENV_VARS = (
"GLM_API_KEY", "ZAI_API_KEY", "Z_AI_API_KEY",
"KIMI_API_KEY", "KIMI_BASE_URL", "STEPFUN_API_KEY", "STEPFUN_BASE_URL",
"MINIMAX_API_KEY", "MINIMAX_CN_API_KEY",
"AI_GATEWAY_API_KEY", "AI_GATEWAY_BASE_URL",
"KILOCODE_API_KEY", "KILOCODE_BASE_URL",
"GMI_API_KEY", "GMI_BASE_URL",
"DASHSCOPE_API_KEY", "OPENCODE_ZEN_API_KEY", "OPENCODE_GO_API_KEY",
@ -184,9 +176,6 @@ class TestResolveProvider:
def test_explicit_minimax_cn(self):
assert resolve_provider("minimax-cn") == "minimax-cn"
def test_explicit_ai_gateway(self):
assert resolve_provider("ai-gateway") == "ai-gateway"
def test_explicit_gmi(self):
assert resolve_provider("gmi") == "gmi"
@ -211,12 +200,6 @@ class TestResolveProvider:
def test_alias_minimax_underscore(self):
assert resolve_provider("minimax_cn") == "minimax-cn"
def test_alias_aigateway(self):
assert resolve_provider("aigateway") == "ai-gateway"
def test_alias_vercel(self):
assert resolve_provider("vercel") == "ai-gateway"
def test_alias_gmi_cloud(self):
assert resolve_provider("gmi-cloud") == "gmi"
@ -291,10 +274,6 @@ class TestResolveProvider:
monkeypatch.setenv("MINIMAX_CN_API_KEY", "test-mm-cn-key")
assert resolve_provider("auto") == "minimax-cn"
def test_auto_detects_ai_gateway_key(self, monkeypatch):
monkeypatch.setenv("AI_GATEWAY_API_KEY", "test-gw-key")
assert resolve_provider("auto") == "ai-gateway"
def test_auto_detects_gmi_key(self, monkeypatch):
monkeypatch.setenv("GMI_API_KEY", "test-gmi-key")
assert resolve_provider("auto") == "gmi"
@ -535,13 +514,6 @@ class TestResolveApiKeyProviderCredentials:
assert creds["api_key"] == "mmcn-secret-key"
assert creds["base_url"] == "https://api.minimaxi.com/anthropic"
def test_resolve_ai_gateway_with_key(self, monkeypatch):
monkeypatch.setenv("AI_GATEWAY_API_KEY", "gw-secret-key")
creds = resolve_api_key_provider_credentials("ai-gateway")
assert creds["provider"] == "ai-gateway"
assert creds["api_key"] == "gw-secret-key"
assert creds["base_url"] == "https://ai-gateway.vercel.sh/v1"
def test_resolve_kilocode_with_key(self, monkeypatch):
monkeypatch.setenv("KILOCODE_API_KEY", "kilo-secret-key")
creds = resolve_api_key_provider_credentials("kilocode")
@ -641,15 +613,6 @@ class TestRuntimeProviderResolution:
assert result["provider"] == "minimax"
assert result["api_key"] == "mm-key"
def test_runtime_ai_gateway(self, monkeypatch):
monkeypatch.setenv("AI_GATEWAY_API_KEY", "gw-key")
from hermes_cli.runtime_provider import resolve_runtime_provider
result = resolve_runtime_provider(requested="ai-gateway")
assert result["provider"] == "ai-gateway"
assert result["api_mode"] == "chat_completions"
assert result["api_key"] == "gw-key"
assert "ai-gateway.vercel.sh" in result["base_url"]
def test_runtime_kilocode(self, monkeypatch):
monkeypatch.setenv("KILOCODE_API_KEY", "kilo-key")
from hermes_cli.runtime_provider import resolve_runtime_provider