mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-06-02 06:13:46 +02:00
feat(admin): add Fireworks API key and proxy to admin manifest
Registers FIREWORKS_API_KEY / FIREWORKS_PROXY in api/admin_config FIELDS so the UI can set credentials and provider status stays accurate. Adds admin apply test and contract guards linking PROVIDER_CATALOG to FIELD_BY_KEY; updates .env.example.
This commit is contained in:
+7
-1
@@ -26,6 +26,10 @@ OPENCODE_API_KEY=""
|
||||
ZAI_API_KEY=""
|
||||
|
||||
|
||||
# Fireworks AI Config (OpenAI-compatible Chat Completions at api.fireworks.ai/inference/v1)
|
||||
FIREWORKS_API_KEY=""
|
||||
|
||||
|
||||
# LM Studio Config (local provider, no API key required)
|
||||
LM_STUDIO_BASE_URL="http://localhost:1234/v1"
|
||||
|
||||
@@ -40,7 +44,7 @@ OLLAMA_BASE_URL="http://localhost:11434"
|
||||
|
||||
# All Claude model requests are mapped to these models, plain model is fallback
|
||||
# Format: provider_type/model/name
|
||||
# Valid providers: "nvidia_nim" | "open_router" | "deepseek" | "lmstudio" | "llamacpp" | "ollama" | "kimi" | "wafer" | "opencode" | "zai"
|
||||
# Valid providers: "nvidia_nim" | "open_router" | "deepseek" | "lmstudio" | "llamacpp" | "ollama" | "kimi" | "wafer" | "opencode" | "zai" | "fireworks"
|
||||
MODEL_OPUS=
|
||||
MODEL_SONNET=
|
||||
MODEL_HAIKU=
|
||||
@@ -59,6 +63,7 @@ FCC_SMOKE_MODEL_KIMI=
|
||||
FCC_SMOKE_MODEL_WAFER=
|
||||
FCC_SMOKE_MODEL_OPENCODE=
|
||||
FCC_SMOKE_MODEL_ZAI=
|
||||
FCC_SMOKE_MODEL_FIREWORKS=
|
||||
FCC_SMOKE_NIM_MODELS=
|
||||
FCC_SMOKE_NIM_EXTRA_MODELS=
|
||||
FCC_SMOKE_OPENROUTER_FREE_MODELS=
|
||||
@@ -84,6 +89,7 @@ KIMI_PROXY=""
|
||||
WAFER_PROXY=""
|
||||
OPENCODE_PROXY=""
|
||||
ZAI_PROXY=""
|
||||
FIREWORKS_PROXY=""
|
||||
|
||||
PROVIDER_RATE_LIMIT=1
|
||||
PROVIDER_RATE_WINDOW=3
|
||||
|
||||
@@ -176,6 +176,15 @@ FIELDS: tuple[ConfigFieldSpec, ...] = (
|
||||
secret=True,
|
||||
description="Z.ai Coding Plan API key.",
|
||||
),
|
||||
ConfigFieldSpec(
|
||||
"FIREWORKS_API_KEY",
|
||||
"Fireworks API Key",
|
||||
"providers",
|
||||
"secret",
|
||||
settings_attr="fireworks_api_key",
|
||||
secret=True,
|
||||
description="Fireworks AI inference API key.",
|
||||
),
|
||||
ConfigFieldSpec(
|
||||
"LM_STUDIO_BASE_URL",
|
||||
"LM Studio Base URL",
|
||||
@@ -269,6 +278,15 @@ FIELDS: tuple[ConfigFieldSpec, ...] = (
|
||||
secret=True,
|
||||
advanced=True,
|
||||
),
|
||||
ConfigFieldSpec(
|
||||
"FIREWORKS_PROXY",
|
||||
"Fireworks Proxy",
|
||||
"providers",
|
||||
"secret",
|
||||
settings_attr="fireworks_proxy",
|
||||
secret=True,
|
||||
advanced=True,
|
||||
),
|
||||
ConfigFieldSpec(
|
||||
"MODEL",
|
||||
"Default Model",
|
||||
|
||||
@@ -102,6 +102,7 @@ def test_admin_config_masks_secrets_and_exposes_manifest(monkeypatch, tmp_path):
|
||||
keys = {field["key"] for field in body["fields"]}
|
||||
assert "ANTHROPIC_AUTH_TOKEN" in keys
|
||||
assert "OPENROUTER_API_KEY" in keys
|
||||
assert "FIREWORKS_API_KEY" in keys
|
||||
assert "ZAI_BASE_URL" not in keys
|
||||
assert "CLAUDE_WORKSPACE" not in keys
|
||||
assert "CLAUDE_CLI_BIN" not in keys
|
||||
@@ -181,6 +182,31 @@ def test_admin_apply_writes_complete_managed_env_and_masks_preview(
|
||||
}
|
||||
|
||||
|
||||
def test_admin_apply_writes_fireworks_key_and_masks_preview(monkeypatch, tmp_path):
|
||||
_set_home(monkeypatch, tmp_path)
|
||||
_clear_process_config(monkeypatch)
|
||||
app = create_app(lifespan_enabled=False)
|
||||
|
||||
response = _local_client(app).post(
|
||||
"/admin/api/config/apply",
|
||||
json={
|
||||
"values": {
|
||||
"MODEL": "fireworks/test-model",
|
||||
"FIREWORKS_API_KEY": "fw-secret",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
assert body["applied"] is True
|
||||
assert "FIREWORKS_API_KEY=********" in body["env_preview"]
|
||||
env_file = tmp_path / ".fcc" / ".env"
|
||||
text = env_file.read_text(encoding="utf-8")
|
||||
assert "MODEL=fireworks/test-model" in text
|
||||
assert "FIREWORKS_API_KEY=fw-secret" in text
|
||||
|
||||
|
||||
def test_admin_apply_preserves_hidden_diagnostics_and_smoke_values(
|
||||
monkeypatch, tmp_path
|
||||
):
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
"""Ensure admin UI manifest exposes every catalog credential/proxy binding."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from api.admin_config import FIELD_BY_KEY
|
||||
from config.provider_catalog import PROVIDER_CATALOG
|
||||
from config.settings import Settings
|
||||
|
||||
|
||||
def test_provider_catalog_remote_credentials_in_admin_manifest() -> None:
|
||||
missing: list[str] = []
|
||||
wrong_attr: list[str] = []
|
||||
|
||||
for provider_id, desc in PROVIDER_CATALOG.items():
|
||||
if desc.credential_env is None:
|
||||
continue
|
||||
if desc.credential_attr is None:
|
||||
missing.append(
|
||||
f"{provider_id}: credential_env set but credential_attr missing"
|
||||
)
|
||||
continue
|
||||
entry = FIELD_BY_KEY.get(desc.credential_env)
|
||||
if entry is None:
|
||||
missing.append(
|
||||
f"{provider_id}: {desc.credential_env} not in admin FIELD_BY_KEY"
|
||||
)
|
||||
continue
|
||||
if entry.settings_attr != desc.credential_attr:
|
||||
wrong_attr.append(
|
||||
f"{provider_id}: {desc.credential_env} maps settings_attr="
|
||||
f"{entry.settings_attr!r}, catalog expects "
|
||||
f"{desc.credential_attr!r}"
|
||||
)
|
||||
|
||||
assert not missing and not wrong_attr, "\n".join(missing + wrong_attr)
|
||||
|
||||
|
||||
def test_provider_catalog_proxy_attrs_in_admin_manifest() -> None:
|
||||
missing_key: list[str] = []
|
||||
wrong_attr: list[str] = []
|
||||
|
||||
for provider_id, desc in PROVIDER_CATALOG.items():
|
||||
if desc.proxy_attr is None:
|
||||
continue
|
||||
mf = Settings.model_fields[desc.proxy_attr]
|
||||
alias = mf.validation_alias
|
||||
if alias is None:
|
||||
missing_key.append(
|
||||
f"{provider_id}: {desc.proxy_attr} has no validation_alias "
|
||||
"(admin manifest expects env-backed proxy)"
|
||||
)
|
||||
continue
|
||||
env_key = str(alias)
|
||||
entry = FIELD_BY_KEY.get(env_key)
|
||||
if entry is None:
|
||||
missing_key.append(
|
||||
f"{provider_id}: proxy env {env_key} not in FIELD_BY_KEY"
|
||||
)
|
||||
continue
|
||||
if entry.settings_attr != desc.proxy_attr:
|
||||
wrong_attr.append(
|
||||
f"{provider_id}: {env_key} maps settings_attr="
|
||||
f"{entry.settings_attr!r}, catalog expects {desc.proxy_attr!r}"
|
||||
)
|
||||
|
||||
assert not missing_key and not wrong_attr, "\n".join(missing_key + wrong_attr)
|
||||
Reference in New Issue
Block a user