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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Under the hood:

Model access is yours: pick a provider, paste your key, switch anytime. Supported out of the box:

**OpenAI · Anthropic · Google Gemini · Inkling (Thinking Machines) · GLM (Z.ai) · DeepSeek · Kimi (Moonshot) · Qwen · MiniMax · Mistral · Grok (xAI)** - plus open-weight models via **Together** and **Fireworks**, and fully local models via **Ollama**.
**OpenAI · Anthropic · Google Gemini · Inkling (Thinking Machines) · GLM (Z.ai) · DeepSeek · Kimi (Moonshot) · Qwen · MiniMax · Mistral · Grok (xAI)** - plus open-weight models via **Together** and **Fireworks**, hundreds of models behind one key via the **Vercel AI Gateway**, and fully local models via **Ollama**.

A curated model list marks what we've verified for tool-calling work. Adding any model string works at your own risk.

Expand Down
53 changes: 36 additions & 17 deletions coworker/providers/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
showing a made-up denominator. Values entered 2026-07-28 from vendor docs; verify alongside
the id refresh.

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.
Resellers: Together + Fireworks + OpenRouter + Vercel AI Gateway. 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.
"""

from __future__ import annotations
Expand All @@ -31,12 +31,17 @@
_AGENTIC = ModelCapabilities(
tools=True, vision=False, parallel_tool_calls=True, streaming=True
)
# The native three (OpenAI, Anthropic, Gemini) all take PDFs directly; every
# OpenAI-compatible vendor and reseller in the matrix does not (their chat APIs have
# no inline file part — checked 2026-07-17), so those fall back via pdf_support.py.
# The native three (OpenAI, Anthropic, Gemini) all take PDFs directly; compat vendors
# and resellers fall back via pdf_support.py instead (no inline file part — checked
# 2026-07-17; the Vercel gateway documents one, but its shape is unverified here, so
# it stays on the fallback too).
_AGENTIC_VISION = ModelCapabilities(
tools=True, vision=True, pdf=True, parallel_tool_calls=True, streaming=True
)
# Vision over an OpenAI-compat surface: tools and images, PDFs on the fallback (above).
_AGENTIC_VISION_COMPAT = ModelCapabilities(
tools=True, vision=True, parallel_tool_calls=True, streaming=True
)


@dataclass(frozen=True)
Expand Down Expand Up @@ -89,12 +94,7 @@ class ModelEntry:
# Muse Spark (Meta Model API, public preview 2026-07-09): multimodal + tools via
# their OpenAI-compat surface. Vision yes; PDFs unverified over compat — falls
# back via pdf_support.py like the other compat vendors.
"meta:muse-spark-1.1": ModelEntry(
"Muse Spark 1.1 · Meta",
ModelCapabilities(
tools=True, vision=True, parallel_tool_calls=True, streaming=True
),
),
"meta:muse-spark-1.1": ModelEntry("Muse Spark 1.1 · Meta", _AGENTIC_VISION_COMPAT),
"zai:glm-5.2": ModelEntry("GLM-5.2 · Z AI", _AGENTIC, 128_000),
"deepseek:deepseek-v4-flash": ModelEntry(
"DeepSeek V4 Flash · DeepSeek", _AGENTIC, 128_000
Expand All @@ -115,11 +115,7 @@ class ModelEntry:
# Kimi K3 on Together (landed late July 2026): 1M window, native vision; PDFs
# unverified over the compat surface (falls back via pdf_support.py, like Muse Spark).
"together:moonshotai/Kimi-K3": ModelEntry(
"Kimi K3 · via Together",
ModelCapabilities(
tools=True, vision=True, parallel_tool_calls=True, streaming=True
),
1_000_000,
"Kimi K3 · via Together", _AGENTIC_VISION_COMPAT, 1_000_000
),
"together:moonshotai/Kimi-K2.7-Code": ModelEntry(
"Kimi K2.7 Code · via Together", _AGENTIC, 256_000
Expand Down Expand Up @@ -157,6 +153,29 @@ class ModelEntry:
"openrouter:meta-llama/llama-4-maverick": ModelEntry(
"Llama 4 Maverick · via OpenRouter", _AGENTIC, 1_000_000
),
# Vercel AI Gateway: creator/model ids, verbatim. Curated to agent-capable,
# cost-efficient tiers, one per major creator. Windows and vision are the
# gateway's own /v1/models values (checked 2026-08-05) and are per-route —
# GLM-5.2 is 1M here vs 128k via Together. The catalog's pdf modality is
# deliberately unmapped (_AGENTIC_VISION_COMPAT: file-part shape unverified).
"vercel:anthropic/claude-haiku-4.5": ModelEntry(
"Claude Haiku 4.5 · via Vercel AI Gateway", _AGENTIC_VISION_COMPAT, 200_000
),
"vercel:zai/glm-5.2": ModelEntry(
"GLM-5.2 · via Vercel AI Gateway", _AGENTIC, 1_000_000
),
"vercel:deepseek/deepseek-v4-flash": ModelEntry(
"DeepSeek V4 Flash · via Vercel AI Gateway", _AGENTIC, 1_000_000
),
"vercel:openai/gpt-5.4-mini": ModelEntry(
"GPT-5.4 mini · via Vercel AI Gateway", _AGENTIC_VISION_COMPAT, 400_000
),
"vercel:google/gemini-3.6-flash": ModelEntry(
"Gemini 3.6 Flash · via Vercel AI Gateway", _AGENTIC_VISION_COMPAT, 1_000_000
),
"vercel:moonshotai/kimi-k2.7-code": ModelEntry(
"Kimi K2.7 Code · via Vercel AI Gateway", _AGENTIC_VISION_COMPAT, 256_000
),
# -- cloud accounts (models running in the user's own AWS/GCP) ----------------
# Bedrock ids carry a family segment (claude/ → native Anthropic path, other/ →
# Converse) plus AWS's own `-v<n>:<m>` version suffix. Some regions require the
Expand Down
7 changes: 7 additions & 0 deletions coworker/providers/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,13 @@ def _compat(
recommended_model="z-ai/glm-5.2",
env_key="OPENROUTER_API_KEY",
),
_compat(
"vercel",
"Vercel AI Gateway",
base_url="https://ai-gateway.vercel.sh/v1",
recommended_model="anthropic/claude-haiku-4.5",
env_key="AI_GATEWAY_API_KEY", # Vercel's documented name for this key
),
ProviderDescriptor(
name="ollama",
title="Ollama (local models)",
Expand Down
5 changes: 5 additions & 0 deletions surfaces/gui/src/providers/ProviderSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export const KEY_HELP: Record<string, { url: string; label: string }> = {
bedrock: { url: "https://console.aws.amazon.com/bedrock/home#/api-keys", label: "the AWS Bedrock console" },
fireworks: { url: "https://fireworks.ai/account/api-keys", label: "fireworks.ai" },
together: { url: "https://api.together.xyz/settings/api-keys", label: "together.xyz" },
// Vercel's own docs deep-link (resolves the signed-in team's dashboard).
vercel: {
url: "https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai-gateway%2Fapi-keys&title=AI+Gateway+API+Keys",
label: "vercel.com",
},
zai: { url: "https://z.ai/manage-apikey/apikey-list", label: "z.ai" },
kimi: { url: "https://platform.moonshot.ai/console/api-keys", label: "platform.moonshot.ai" },
deepseek: { url: "https://platform.deepseek.com/api_keys", label: "platform.deepseek.com" },
Expand Down
3 changes: 3 additions & 0 deletions surfaces/gui/src/providers/logos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import vertex from "./logos/vertex.svg";
import openrouter from "./logos/openrouter.svg";
import fireworks from "./logos/fireworks.svg";
import together from "./logos/together.svg";
import vercel from "./logos/vercel.svg";
import zai from "./logos/zai.svg";
import kimi from "./logos/kimi.svg";
import deepseek from "./logos/deepseek.svg";
Expand All @@ -34,6 +35,7 @@ export const PROVIDER_LOGOS: Record<string, string> = {
openrouter,
fireworks,
together,
vercel,
zai,
kimi,
deepseek,
Expand All @@ -54,6 +56,7 @@ export const PROVIDER_ORDER = [
"openrouter",
"fireworks",
"together",
"vercel",
"zai",
"kimi",
"deepseek",
Expand Down
1 change: 1 addition & 0 deletions surfaces/gui/src/providers/logos/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion tests/test_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ def test_compat_models_route_and_get_tool_capabilities():
"qwen:qwen3-max",
"xai:grok-4.3",
"mistral:mistral-large-latest",
"vercel:zai/glm-5.2",
):
prefix = model.split(":", 1)[0]
assert router._provider_name(model) == prefix
Expand Down Expand Up @@ -383,6 +384,8 @@ def test_matrix_answers_capabilities_for_reseller_ids():
"fireworks:accounts/fireworks/models/kimi-k2p6",
"openrouter:z-ai/glm-5.2",
"openrouter:meta-llama/llama-4-maverick",
"vercel:anthropic/claude-haiku-4.5",
"vercel:moonshotai/kimi-k2.7-code",
):
caps = capabilities_for(mid)
assert caps.tools and caps.parallel_tool_calls and caps.streaming
Expand All @@ -409,7 +412,7 @@ def test_reseller_descriptors_and_matrix_stay_in_lockstep():
from coworker.providers.matrix import models_for_provider
from coworker.providers.registry import get_descriptor

for name in ("together", "fireworks", "openrouter"):
for name in ("together", "fireworks", "openrouter", "vercel"):
d = get_descriptor(name)
assert d is not None and d.needs_key
curated = models_for_provider(name)
Expand Down