Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions coworker/providers/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,19 @@ class ModelEntry:
),
),
"zai:glm-5.2": ModelEntry("GLM-5.2 · Z AI", _AGENTIC, 128_000),
"zai-coding:glm-5.2": ModelEntry("GLM-5.2 · Z AI Coding Plan", _AGENTIC, 128_000),
"zai-coding:glm-4.7": ModelEntry("GLM-4.7 · Z AI Coding Plan", _AGENTIC, 128_000),
"zai-coding:glm-4-coder": ModelEntry("GLM-4 Coder · Z AI Coding Plan", _AGENTIC, 128_000),
"deepseek:deepseek-v4-flash": ModelEntry(
"DeepSeek V4 Flash · DeepSeek", _AGENTIC, 128_000
),
"deepseek:deepseek-v4-pro": ModelEntry(
"DeepSeek V4 Pro · DeepSeek", _AGENTIC, 128_000
),
"github:gpt-4o": ModelEntry("GPT-4o · GitHub Models", _AGENTIC_VISION, 128_000),
"github:gpt-4o-mini": ModelEntry("GPT-4o Mini · GitHub Models", _AGENTIC_VISION, 128_000),
"github:Meta-Llama-3.1-405B-Instruct": ModelEntry("Llama 3.1 405B · GitHub Models", _AGENTIC, 128_000),
"github:Meta-Llama-3.1-70B-Instruct": ModelEntry("Llama 3.1 70B · GitHub Models", _AGENTIC, 128_000),
"kimi:kimi-k2.6": ModelEntry("Kimi K2.6 · Moonshot", _AGENTIC, 256_000),
"minimax:MiniMax-M2.5": ModelEntry("MiniMax M2.5 · MiniMax"),
"qwen:qwen3-max": ModelEntry("Qwen3 Max · Alibaba", _AGENTIC, 256_000),
Expand Down
63 changes: 46 additions & 17 deletions coworker/providers/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,28 +263,41 @@ def _compat(
env_key: str,
endpoint_help: str = "",
) -> ProviderDescriptor:
"""Descriptor for an OpenAI-compatible vendor: key + a prefilled, editable endpoint."""
"""Descriptor for an OpenAI-compatible vendor: key + a prefilled, editable endpoint + default model."""
vendor = title.split(" (")[0]

fields = [
ProviderField(
"api_key",
f"{vendor} API key",
secret=True,
),
ProviderField(
"base_url",
"Endpoint",
required=False,
default=base_url,
placeholder=base_url,
help=endpoint_help
or f"Prefilled with {vendor}'s official endpoint; edit only for a regional or proxy variant.",
),
]

fields.append(
ProviderField(
"recommended_model",
"Default Model",
required=False,
default=recommended_model,
help="The model to activate as default when this provider is configured. You can enter any compatible model name.",
)
)

return ProviderDescriptor(
name=name,
title=title,
needs_key=True,
fields=[
ProviderField(
"api_key",
f"{vendor} API key",
secret=True,
),
ProviderField(
"base_url",
"Endpoint",
required=False,
default=base_url,
placeholder=base_url,
help=endpoint_help
or f"Prefilled with {vendor}'s official endpoint; edit only for a regional or proxy variant.",
),
],
fields=fields,
build=_openai_compat(vendor, base_url, env_key),
recommended_model=recommended_model,
env_key=env_key,
Expand Down Expand Up @@ -591,13 +604,29 @@ def _responses_compat(
env_key="ZAI_API_KEY",
endpoint_help="Prefilled with Z AI's international endpoint. China mainland: https://open.bigmodel.cn/api/paas/v4",
),
_compat(
"zai-coding",
"Z AI Coding Plan",
base_url="https://api.z.ai/api/coding/paas/v4",
recommended_model="glm-5.2",
env_key="ZAI_CODING_API_KEY",
endpoint_help="Prefilled with Z AI's Coding Plan endpoint. Note: This requires a separate Coding Plan subscription.",
),
_compat(
"deepseek",
"DeepSeek",
base_url="https://api.deepseek.com",
recommended_model="deepseek-v4-flash",
env_key="DEEPSEEK_API_KEY",
),
_compat(
"github",
"GitHub Models",
base_url="https://models.inference.ai.azure.com",
recommended_model="gpt-4o",
env_key="GITHUB_MODELS_TOKEN",
endpoint_help="GitHub Models API endpoint. Requires a GitHub Personal Access Token (PAT).",
),
_compat(
"kimi",
"Kimi (Moonshot AI)",
Expand Down
12 changes: 10 additions & 2 deletions coworker/server/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3004,9 +3004,17 @@ def set_provider(
self._refresh_provider(name)
# Convenience: if the provider recommends a model and it's actually available, add it to
# the curated list so it shows up in the composer right after configuring the provider.
rec = d.recommended_model
user_choice = profile.get("recommended_model")
rec = user_choice or d.recommended_model

# If the user explicitly overrode the default model, always add it.
# If falling back to (or explicitly matching) the provider's default, only add it if available.
is_override = bool(user_choice and user_choice.strip() != d.recommended_model)
should_add = is_override or (rec and rec in self._suggested_models(name))
added: Optional[str] = None
if rec and rec in self._suggested_models(name):


if should_add and rec:
# OpenAI models stay bare (the router's default); others carry their prefix.
added = rec if name == "openai" else f"{name}:{rec}"
self.add_model(added)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,9 +510,9 @@ def test_matrix_labels_and_custom_model_fallback():
assert labels["together:zai-org/GLM-5.2"] == "GLM-5.2 · via Together"
assert labels["zai:glm-5.2"] == "GLM-5.2 · Z AI"
# Deliberately small: agent-capable current models only (owner call, 2026-07-04).
# 60→65 (2026-08-24): the stealth ox-alpha preview slug tipped it; reclaim slack by
# 65→75 (2026-08-28): raised to accommodate Z AI Coding Plan and GitHub Models; reclaim slack by
# pruning retired entries before raising this again.
assert len(MATRIX) < 65
assert len(MATRIX) < 75
Comment on lines 512 to +515
assert all(e.caps.tools for e in MATRIX.values())
# A custom (unlisted) reseller model falls back to the conservative default — usable,
# but at the user's own risk (no parallel tool calls assumed).
Expand Down