mirror of
https://github.com/andrewyng/openworker.git
synced 2026-09-14 00:00:58 +00:00
Add OpenRouter as an OpenAI-compatible reseller provider
Descriptor + curated matrix rows + sk-or- key auto-detect (server and GUI).
This commit is contained in:
@@ -11,8 +11,8 @@ falls back to the conservative heuristics in ``capabilities.py`` at their own ri
|
||||
degraded results. Ids verified against vendor/reseller catalogs on 2026-07-04; refresh the
|
||||
reseller rows when catalogs rotate (they rename on every model generation).
|
||||
|
||||
Resellers: Together + Fireworks for now. TODO: add Groq and OpenRouter entries here AND their
|
||||
descriptors in ``registry.py`` once the current provider surface is tested — deliberately
|
||||
Resellers: Together + Fireworks + OpenRouter. TODO: add Groq entries here AND its
|
||||
descriptor in ``registry.py`` once the current provider surface is tested — deliberately
|
||||
deferred to bound how much needs verifying at once.
|
||||
"""
|
||||
|
||||
@@ -112,6 +112,14 @@ MATRIX: dict[str, ModelEntry] = {
|
||||
"fireworks:accounts/fireworks/models/llama4-maverick-instruct-basic": ModelEntry(
|
||||
"Llama 4 Maverick · via Fireworks"
|
||||
),
|
||||
# OpenRouter slugs are lowercase `<lab>/<model>` (checked against their catalog
|
||||
# 2026-07-25); same labs as above, one key for all of them.
|
||||
"openrouter:z-ai/glm-5.2": ModelEntry("GLM-5.2 · via OpenRouter"),
|
||||
"openrouter:moonshotai/kimi-k2.6": ModelEntry("Kimi K2.6 · via OpenRouter"),
|
||||
"openrouter:deepseek/deepseek-v4-pro": ModelEntry("DeepSeek V4 Pro · via OpenRouter"),
|
||||
"openrouter:meta-llama/llama-4-maverick": ModelEntry(
|
||||
"Llama 4 Maverick · via OpenRouter"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ DESCRIPTORS: list[ProviderDescriptor] = [
|
||||
secret=False,
|
||||
required=False,
|
||||
placeholder="https://…/openai/v1",
|
||||
help="For Azure OpenAI, OpenRouter, vLLM, or any OpenAI-compliant server. Leave blank for api.openai.com.",
|
||||
help="For Azure OpenAI, vLLM, or any OpenAI-compliant server. Leave blank for api.openai.com.",
|
||||
),
|
||||
],
|
||||
build=_build_openai,
|
||||
@@ -316,9 +316,9 @@ DESCRIPTORS: list[ProviderDescriptor] = [
|
||||
endpoint_help="Prefilled with the Meta Model API endpoint (public preview, US-only as of 2026-07).",
|
||||
),
|
||||
# Resellers: many labs' models behind one key, using THEIR model namespaces (the curated
|
||||
# ids + display labels live in providers/matrix.py). TODO: add Groq and OpenRouter here
|
||||
# (+ their matrix rows) once the current provider surface is tested — deliberately
|
||||
# deferred to bound how much needs verifying at once (owner call, 2026-07-04).
|
||||
# ids + display labels live in providers/matrix.py). TODO: add Groq here (+ its matrix
|
||||
# rows) once the current provider surface is tested — deliberately deferred to bound
|
||||
# how much needs verifying at once (owner call, 2026-07-04).
|
||||
_compat(
|
||||
"together",
|
||||
"Together AI",
|
||||
@@ -333,6 +333,13 @@ DESCRIPTORS: list[ProviderDescriptor] = [
|
||||
recommended_model="accounts/fireworks/models/glm-5p2",
|
||||
env_key="FIREWORKS_API_KEY",
|
||||
),
|
||||
_compat(
|
||||
"openrouter",
|
||||
"OpenRouter",
|
||||
base_url="https://openrouter.ai/api/v1",
|
||||
recommended_model="z-ai/glm-5.2",
|
||||
env_key="OPENROUTER_API_KEY",
|
||||
),
|
||||
ProviderDescriptor(
|
||||
name="ollama",
|
||||
title="Ollama (local models)",
|
||||
@@ -386,6 +393,8 @@ def detect_provider(api_key: str) -> Optional[str]:
|
||||
return None
|
||||
if key.startswith("sk-ant-"):
|
||||
return "anthropic"
|
||||
if key.startswith("sk-or-"):
|
||||
return "openrouter"
|
||||
if key.startswith("AIza"):
|
||||
return "gemini"
|
||||
if key.startswith(("sk-", "sk_")):
|
||||
|
||||
@@ -1324,6 +1324,7 @@ export function detectProvider(apiKey: string): string | null {
|
||||
const key = (apiKey || "").trim();
|
||||
if (!key) return null;
|
||||
if (key.startsWith("sk-ant-")) return "anthropic";
|
||||
if (key.startsWith("sk-or-")) return "openrouter";
|
||||
if (key.startsWith("AIza")) return "gemini";
|
||||
if (key.startsWith("sk-") || key.startsWith("sk_")) return "openai";
|
||||
return null;
|
||||
|
||||
@@ -15,6 +15,7 @@ from coworker.providers import detect_provider, verify_provider_key
|
||||
"key,expected",
|
||||
[
|
||||
("sk-ant-api03-abc", "anthropic"),
|
||||
("sk-or-v1-abc", "openrouter"),
|
||||
("AIzaSyAbc123", "gemini"),
|
||||
("sk-proj-abc", "openai"),
|
||||
("sk_live_abc", "openai"),
|
||||
|
||||
@@ -381,6 +381,8 @@ def test_matrix_answers_capabilities_for_reseller_ids():
|
||||
"together:zai-org/GLM-5.2",
|
||||
"together:meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8",
|
||||
"fireworks:accounts/fireworks/models/kimi-k2p6",
|
||||
"openrouter:z-ai/glm-5.2",
|
||||
"openrouter:meta-llama/llama-4-maverick",
|
||||
):
|
||||
caps = capabilities_for(mid)
|
||||
assert caps.tools and caps.parallel_tool_calls and caps.streaming
|
||||
@@ -402,12 +404,12 @@ def test_matrix_labels_and_custom_model_fallback():
|
||||
|
||||
|
||||
def test_reseller_descriptors_and_matrix_stay_in_lockstep():
|
||||
"""Together/Fireworks suggested models derive from the matrix, and each descriptor's
|
||||
"""Reseller suggested models derive from the matrix, and each descriptor's
|
||||
recommended model must be one of them (set_provider's auto-add depends on it)."""
|
||||
from coworker.providers.matrix import models_for_provider
|
||||
from coworker.providers.registry import get_descriptor
|
||||
|
||||
for name in ("together", "fireworks"):
|
||||
for name in ("together", "fireworks", "openrouter"):
|
||||
d = get_descriptor(name)
|
||||
assert d is not None and d.needs_key
|
||||
curated = models_for_provider(name)
|
||||
|
||||
Reference in New Issue
Block a user