From 9599823e178bf7b0fe6ee9ad142663890fd53869 Mon Sep 17 00:00:00 2001 From: Sandeep Nandal Date: Tue, 13 Oct 2026 00:00:34 +0530 Subject: [PATCH] Add BytesBrains Cruise as a curated provider (closes #24) Cruise is an OpenAI-compatible gateway with per-project budget caps. Adds a ProviderSpec entry (CRUISE_API_KEY, GLM 5.3 default, prompt caching on) and lists it in the primary picker next to the other gateways. CRUISE_BASE_URL / CRUISE_MODEL overrides come from resolve(). Co-Authored-By: Claude Opus 5.5 --- openhack/providers.py | 6 ++++++ tests/test_providers.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/openhack/providers.py b/openhack/providers.py index 4bfe5e6..4dc6c81 100644 --- a/openhack/providers.py +++ b/openhack/providers.py @@ -66,6 +66,11 @@ class ProviderSpec: "AI_GATEWAY_API_KEY", "anthropic/claude-sonnet-4.6", True, hint="Hundreds of models through Vercel AI Gateway", ), + "cruise": ProviderSpec( + "cruise", "BytesBrains Cruise", "https://cruise.bytesbrains.net/v1", + "CRUISE_API_KEY", "workers-ai/@cf/zai-org/glm-5.3", True, + hint="One key across open models, with budget caps", + ), "cloudflare-workers-ai": ProviderSpec( "cloudflare-workers-ai", "Cloudflare Workers AI", "https://api.cloudflare.com/client/v4/accounts/" @@ -164,6 +169,7 @@ class ProviderSpec: "openrouter", "google", "vercel", + "cruise", "cloudflare-workers-ai", "fireworks-ai", "groq", diff --git a/tests/test_providers.py b/tests/test_providers.py index 8d12b6f..fce1fdf 100644 --- a/tests/test_providers.py +++ b/tests/test_providers.py @@ -29,6 +29,7 @@ def test_curated_provider_list_matches_primary_picker(): "openrouter", "google", "vercel", + "cruise", "cloudflare-workers-ai", "fireworks-ai", "groq", @@ -103,6 +104,19 @@ def test_resolve_openai_reads_key_and_base(monkeypatch): assert r.model # a default model +def test_resolve_cruise_reads_key_and_base(monkeypatch): + monkeypatch.setenv("CRUISE_API_KEY", "ck-test") + monkeypatch.delenv("CRUISE_BASE_URL", raising=False) + monkeypatch.delenv("CRUISE_MODEL", raising=False) + monkeypatch.setattr(providers, "get_credential", lambda name: None) + r = providers.resolve("cruise") + assert r.base_url == "https://cruise.bytesbrains.net/v1" + assert r.api_key == "ck-test" + assert r.model == "workers-ai/@cf/zai-org/glm-5.3" + assert r.supports_prompt_cache is True + assert r.missing_key_env is None + + def test_resolve_reports_missing_key(monkeypatch): monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False) r = providers.resolve("anthropic")