Skip to content

feat(ai-providers): add OpenCode Zen provider (#1400)#1417

Merged
datlechin merged 3 commits into
mainfrom
feat/1400-opencode-provider
May 26, 2026
Merged

feat(ai-providers): add OpenCode Zen provider (#1400)#1417
datlechin merged 3 commits into
mainfrom
feat/1400-opencode-provider

Conversation

@datlechin
Copy link
Copy Markdown
Member

Summary

Adds OpenCode Zen (https://opencode.ai/docs/zen) as a first-class AI provider, and fixes the base-URL handling that made it (and other gateways) fail as a Custom Provider. Closes #1400.

OpenCode Zen is a clean OpenAI-compatible gateway: POST /zen/v1/chat/completions (Bearer auth) serves every model family it offers, and GET /zen/v1/models returns the list. So it reuses the existing OpenAICompatibleProvider with no new transport.

  • New AIProviderType.openCode — display name "OpenCode Zen", default endpoint https://opencode.ai/zen, API-key auth, sparkles icon.
  • Registered through the existing OpenAI-compatible loop in AIProviderRegistration (same wiring as OpenRouter); the model picker auto-loads from /v1/models, so there's no hardcoded model list to go stale.
  • Added to the "Add Provider" list in AI settings.

Why the reporter's Custom Provider failed (root cause)

OpenCode documents its base URL as https://opencode.ai/zen/v1, but OpenAICompatibleProvider appended /v1/... to the stored endpoint, so a pasted .../zen/v1 became .../zen/v1/v1/chat/completions and 404'd. This is a footgun for every gateway whose documented base ends in /v1.

Fix: a new String.openAIPath(_:) appends /v1/<resource> only when the endpoint doesn't already end in /v1. Used in the three URL builds (chat, test-connection, models). Backward-compatible: the built-in endpoints (https://api.openai.com, https://openrouter.ai/api) don't end in /v1, so their behavior is unchanged; and any custom gateway now tolerates a pasted /v1 base URL.

Verified against the live API

  • GET https://opencode.ai/zen/v1/models returns a standard OpenAI list with bare ids (gpt-5.5, claude-opus-4-7, big-pickle, ...).
  • POST .../v1/chat/completions with a Claude/GPT/Gemini id returns 401 Missing API key (accepted, just needs a key), and the free big-pickle model returns a full chat.completion with no key. So one OpenAI-compatible transport covers all of Zen's models.

Files

  • Models/AI/AIModels.swift — new .openCode case + displayName / defaultEndpoint / symbolName.
  • Core/AI/Registry/AIProviderRegistration.swift.openCode added to the OpenAI-compatible loop.
  • Views/Settings/AISettingsView.swift — added to the addable provider list.
  • Core/AI/String+AIEndpoint.swift — new openAIPath(_:).
  • Core/AI/OpenAICompatibleProvider.swift — chat / test / models URLs use openAIPath.
  • TableProTests/Core/AI/StringAIEndpointTests.swift — new.
  • docs/features/ai-assistant.mdx, CHANGELOG.md.

Notes

  • The model picker lists all of Zen's models (including Claude/GPT/Gemini, which also work through Zen); Zen's real value here is its open models (DeepSeek, GLM, Qwen, Kimi, ...) under one key. Claude/OpenAI/Gemini still have their own first-class providers.
  • "OpenCode Go" is a billing tier on the same endpoint/key, so this one preset covers it.
  • "OpenCode Zen" is a brand name, so the display name is not localized (matches OpenRouter/Gemini).

Test plan

  • Settings > AI > Add Provider lists "OpenCode Zen"; adding it pre-fills the endpoint and the model picker loads from /v1/models after pasting a key.
  • A chat turn against an OpenCode model streams a response.
  • StringAIEndpointTests passes: endpoint without /v1 gets one appended; endpoint ending in /v1 is not doubled; trailing slash normalized.
  • Existing OpenRouter / Ollama / Custom providers still build the same URLs as before.
  • A Custom Provider with base URL https://opencode.ai/zen/v1 now works (no doubled /v1).

@datlechin datlechin merged commit 39c8c9e into main May 26, 2026
2 checks passed
@datlechin datlechin deleted the feat/1400-opencode-provider branch May 26, 2026 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenCode Zen or Go as an LLM provider

1 participant