Skip to content

Add user-defined provider presets + migrate zhipu/moonshot/minimax to presets - #11

Merged
codeking-ai merged 2 commits into
codeking-ai:masterfrom
m-musikhin:feature/user-provider-presets
Oct 15, 2026
Merged

codeking-ai merged 2 commits into
codeking-ai:masterfrom
m-musikhin:feature/user-provider-presets

Conversation

@m-musikhin

Copy link
Copy Markdown
Contributor

Summary

Two related changes in one PR (the second is a follow-up data fix to the first):

1. User-defined provider presets (~/.cligate/provider-presets.json)

Adding an OpenAI-compatible vendor previously required hardcoding a provider class. Now any vendor can be described declaratively in ~/.cligate/provider-presets.json (same schema as built-in presets: id, label, baseUrl, apiFormat, optional models/tiers/nativeModelPrefixes/passthroughModelMatch/pricing/validateModel) and it becomes a first-class provider everywhere: add-key form, model mapping with its own tier map, model discovery, protocol compatibility, pricing.

  • Loader runs at module init; each invalid entry is skipped with a console warning (bad id shape, missing baseUrl, unknown apiFormat/tier key, built-in id collision, duplicates → first wins). A bad file never blocks startup.
  • New preset field validateModel: for vendors without GET /models, key validation probes a 1-token chat request with this model (used by Zhipu).
  • Generic openai_chat provider serves chat + Anthropic bridge (/v1/messages works for Claude Code via translation); Codex goes through the Responses→chat fallback.

2. Zhipu (GLM) / Moonshot (Kimi) / MiniMax migrated to presets + catalogs actualized

The three bespoke provider classes are replaced by declarative presets served by the generic OpenAI-compatible class (like qwen/openrouter before them). Behavior changes:

  • Zhipu key validation now probes a 1-token chat request (validateModel: glm-4-flash) — previously there was no /models validation for Zhipu at all, so no regression.
  • Zhipu/Moonshot/MiniMax keys now also serve /v1/chat/completions and the Codex Responses fallback (they previously only served /v1/messages).
  • Each now has its own tier map and model list, so non-native incoming models are remapped instead of passing through verbatim, and the model-mapping page gives each its own editor instead of folding them into the OpenAI one (which the runtime never consulted for these keys — an existing UI/runtime contradiction, fixed in settings-page.js normalizeModelMappingProvider).
  • Model catalogs actualized to Oct 2026 (ids verified against OpenRouter vendor listings: z-ai/glm-5.3, moonshotai/kimi-k3, minimax/minimax-m3): zhipu glm-5.3 family, moonshot kimi-k3/k2.7-code/k2.6, minimax MiniMax-M3/M2.7; pricing tables synced.

Test plan

  • npm run test:unit: no new failures vs master (existing model-mapper.test.js failures are pre-existing on master and unrelated).
  • New tests: tests/unit/provider-user-presets.test.js (subprocess-based, fresh CLIGATE_CONFIG_DIR per case: merge, collision, invalid entries, duplicates), tests/unit/model-mapping-provider-normalization.test.js (UI provider identity 1:1 with runtime), extended tests/unit/provider-presets.test.js (migrated presets addable, tier remaps, validateModel).
  • Manual: user preset JSON → add-key form shows the vendor, mapping page shows its tier map, key validation, discovery.

🤖 Generated with Claude Code

m-musikhin and others added 2 commits October 14, 2026 00:55
…x to presets

- Load user-defined provider presets from ~/.cligate/provider-presets.json
  at module init; validated entries merge additively after built-ins and
  become first-class (add-key form, model mapping, discovery, protocols,
  pricing). Invalid entries are skipped with warnings; built-in ids are
  protected from collision.
- Migrate Zhipu/Moonshot/MiniMax from bespoke classes to declarative
  presets served by the generic OpenAI-compatible provider. Existing
  api-keys.json entries keep working (same ids, base URLs, pricing).
  New preset field validateModel: Zhipu key validation probes a 1-token
  chat request instead of GET /models (which Zhipu does not serve).
- Zhipu/Moonshot/MiniMax gain tier maps + static model lists: non-native
  models now remap via tiers instead of passing through verbatim.
- Fix settings-page normalizeModelMappingProvider: stop folding
  zhipu/moonshot/minimax into 'openai' — provider identity in the mapping
  UI is now 1:1 with runtime resolveModel(providerType, ...).
- Add docs/CUSTOM_PROVIDERS.md and unit tests for the loader, the
  migration, and the normalization fix.

Co-Authored-By: Claude Code <noreply@anthropic.com>
…2026)

Model ids verified against OpenRouter vendor listings (z-ai, moonshotai,
minimax) and official pricing pages (platform.kimi.ai, platform.minimax.io,
docs.z.ai).

- zhipu: glm-5.3 family (flagship glm-5.3, standard glm-5.2, fast
  glm-5.3-flash); drop retired glm-5-turbo/glm-4-plus/glm-4-air*
- moonshot: kimi-k3 flagship, kimi-k2.6 standard, kimi-k2.7-code
  highspeed fast; drop retired kimi-k2.5/kimi-k2-thinking
- minimax: MiniMax-M3 flagship, M2.7 standard; fix M2.7-highspeed
  input price (0.60, was 0.30)
- pricing tables synced: new cacheRead rates and 2026 prices;
  glm-4.7-flash/glm-4-flash are free

Co-Authored-By: Claude Code <noreply@anthropic.com>
@codeking-ai

Copy link
Copy Markdown
Owner

Thanks for this — the preset-driven approach is a clear improvement, and moving zhipu/moonshot/minimax onto the generic provider also fixes a real bug (the old classes inherited OpenAIProvider.sendAnthropicRequest, which POSTs to a /responses endpoint these vendors don't have). Related unit tests pass; the model-mapper.test.js failures are pre-existing on master. Merging.

A few follow-ups worth addressing (happy to take a follow-up PR, or I'll handle them):

  1. User presets accept apiFormat values that can't work. userPresetProblem allows anthropic / gemini_native, but api-key-manager.js always builds presets with makeOpenAICompatibleProvider, and credential-selector.js only wires openai_chat presets into protocol surfaces. Such a preset can be added but is never routed. Suggest restricting user presets to openai_chat until other formats are actually supported.
  2. Id-collision check only covers built-in presets, not the class-backed providers (openai, anthropic, gemini, azure-openai, vertex-ai, deepseek). A user preset with id: "openai" passes validation and shows in preset-driven UI/mapping, while api-key-manager silently keeps the real OpenAIProvider. Please reject those ids too (and probably ollama, which the local runtime owns).
  3. gateway-route.js still hard-codes minimax, moonshot, zhipu in typesToTry alongside ...presetIdsByFormat('openai_chat'), so they're tried twice per attempt now. handleListProviders also doesn't list preset providers. Both should derive from the preset list.
  4. Pricing entries removed for still-referenced models (glm-4-plus, glm-4-air, glm-4-airx, kimi-k2.5, kimi-k2-thinking, kimi-k2-thinking-turbo). Users who pin these via model mapping will now see $0 cost. Consider keeping legacy rows (pricing for unused models is harmless).
  5. Minor: worth calling out in the changelog that non-native model ids sent to zhipu/moonshot/minimax keys are now tier-remapped instead of passed through verbatim — it's a behavior change for anyone relying on passthrough.

@codeking-ai
codeking-ai merged commit e098176 into codeking-ai:master Oct 15, 2026
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.

2 participants