From 202ea778242da0a5ff8dd8d8c1d215d11d2bda37 Mon Sep 17 00:00:00 2001 From: hujuncheng Date: Fri, 26 Jun 2026 01:25:11 +0800 Subject: [PATCH 1/2] feat(provider): add CrossModel provider CrossModel (https://crossmodel.ai) is an OpenAI- and Anthropic-compatible multi-provider API gateway. Adds it as an OpenAI-compatible provider so users can call its catalog (OpenAI, Anthropic, DeepSeek, Gemini, Qwen, Kimi, GLM and more) with one API key. Models can be fetched dynamically from /v1/models. --- core/llm/autodetect.ts | 1 + core/llm/llms/CrossModel.ts | 38 +++++++++++++ core/llm/llms/CrossModel.vitest.ts | 38 +++++++++++++ core/llm/llms/index.ts | 2 + core/llm/toolSupport.ts | 10 ++++ .../model-providers/more/crossmodel.mdx | 53 +++++++++++++++++++ docs/docs.json | 1 + extensions/vscode/config_schema.json | 2 + gui/public/logos/crossmodel.svg | 12 +++++ .../pages/AddNewModel/configs/providers.ts | 30 +++++++++++ packages/openai-adapters/src/index.ts | 2 + packages/openai-adapters/src/types.ts | 1 + 12 files changed, 190 insertions(+) create mode 100644 core/llm/llms/CrossModel.ts create mode 100644 core/llm/llms/CrossModel.vitest.ts create mode 100644 docs/customize/model-providers/more/crossmodel.mdx create mode 100644 gui/public/logos/crossmodel.svg diff --git a/core/llm/autodetect.ts b/core/llm/autodetect.ts index c8511554b8b..4665c66c645 100644 --- a/core/llm/autodetect.ts +++ b/core/llm/autodetect.ts @@ -123,6 +123,7 @@ const PROVIDER_SUPPORTS_IMAGES: string[] = [ "sagemaker", "openrouter", "clawrouter", + "crossmodel", "venice", "sambanova", "vertexai", diff --git a/core/llm/llms/CrossModel.ts b/core/llm/llms/CrossModel.ts new file mode 100644 index 00000000000..37340faa48d --- /dev/null +++ b/core/llm/llms/CrossModel.ts @@ -0,0 +1,38 @@ +import { LLMOptions } from "../../index.js"; +import { osModelsEditPrompt } from "../templates/edit.js"; + +import OpenAI from "./OpenAI.js"; + +/** + * CrossModel LLM provider. + * + * CrossModel (https://crossmodel.ai) is an OpenAI- and Anthropic-compatible + * multi-provider API gateway. A single API key and base URL routes to models + * from OpenAI, Anthropic, DeepSeek, Gemini, Qwen, Kimi, GLM and more, with + * unified billing and usage tracking. + * + * Uses the OpenAI-compatible Chat Completions API. The available models can be + * listed dynamically from the gateway's `/v1/models` endpoint, so users can + * fetch the current catalog after entering their API key. + * + * @see https://crossmodel.ai/docs + */ +class CrossModel extends OpenAI { + static providerName = "crossmodel"; + + // CrossModel routes to reasoning-capable models and surfaces their + // reasoning content over the OpenAI-compatible wire format. + protected supportsReasoningField = true; + protected supportsReasoningDetailsField = true; + + static defaultOptions: Partial = { + apiBase: "https://api.crossmodel.ai/v1/", + model: "anthropic/claude-sonnet-4-6", + promptTemplates: { + edit: osModelsEditPrompt, + }, + useLegacyCompletionsEndpoint: false, + }; +} + +export default CrossModel; diff --git a/core/llm/llms/CrossModel.vitest.ts b/core/llm/llms/CrossModel.vitest.ts new file mode 100644 index 00000000000..1225a3abcdc --- /dev/null +++ b/core/llm/llms/CrossModel.vitest.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from "vitest"; + +import CrossModel from "./CrossModel"; + +describe("CrossModel", () => { + it("should have correct provider name", () => { + expect(CrossModel.providerName).toBe("crossmodel"); + }); + + it("should have correct default options", () => { + expect(CrossModel.defaultOptions.apiBase).toBe( + "https://api.crossmodel.ai/v1/", + ); + expect(CrossModel.defaultOptions.useLegacyCompletionsEndpoint).toBe(false); + }); + + it("should support reasoning fields", () => { + const crossModel = new CrossModel({ + model: "anthropic/claude-sonnet-4-6", + }); + + expect(crossModel["supportsReasoningField"]).toBe(true); + expect(crossModel["supportsReasoningDetailsField"]).toBe(true); + }); + + it("should preserve the configured model id", () => { + const models = [ + "anthropic/claude-opus-4-8", + "openai/gpt-5.5", + "deepseek/deepseek-v4-pro", + ]; + + for (const model of models) { + const crossModel = new CrossModel({ model }); + expect(crossModel.model).toBe(model); + } + }); +}); diff --git a/core/llm/llms/index.ts b/core/llm/llms/index.ts index 4978f0617f2..a7603277e61 100644 --- a/core/llm/llms/index.ts +++ b/core/llm/llms/index.ts @@ -18,6 +18,7 @@ import Cerebras from "./Cerebras"; import Cloudflare from "./Cloudflare"; import Cohere from "./Cohere"; import CometAPI from "./CometAPI"; +import CrossModel from "./CrossModel"; import DeepInfra from "./DeepInfra"; import Deepseek from "./Deepseek"; import Docker from "./Docker"; @@ -74,6 +75,7 @@ export const LLMClasses = [ Anthropic, Cohere, CometAPI, + CrossModel, FunctionNetwork, Gemini, Llamafile, diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 3f65473233c..a68b5f800ba 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -378,6 +378,16 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = return false; }, + crossmodel: (model) => { + // CrossModel is an OpenAI/Anthropic-compatible gateway whose catalog is + // made up of tool-capable chat models, addressed as `/`. + const lower = model.toLowerCase(); + const unsupported = ["embedding", "embed", "whisper", "tts", "moderation"]; + if (unsupported.some((p) => lower.includes(p))) { + return false; + } + return true; + }, clawrouter: (model) => { // ClawRouter routes to various providers, so we check common tool-supporting patterns const lower = model.toLowerCase(); diff --git a/docs/customize/model-providers/more/crossmodel.mdx b/docs/customize/model-providers/more/crossmodel.mdx new file mode 100644 index 00000000000..45757878a4e --- /dev/null +++ b/docs/customize/model-providers/more/crossmodel.mdx @@ -0,0 +1,53 @@ +--- +title: "How to Configure CrossModel with Continue" +sidebarTitle: "CrossModel" +--- + +[CrossModel](https://crossmodel.ai) is an OpenAI- and Anthropic-compatible API gateway. Use one API key and base URL to call models from OpenAI, Anthropic, DeepSeek, Gemini, Qwen, Kimi, GLM and more, with unified billing and usage tracking. + + + Sign up at [crossmodel.ai](https://crossmodel.ai) and create an API key from + the [console](https://www.crossmodel.ai/console/api-keys). + + +## Configuration + + + + ```yaml title="config.yaml" + name: My Config + version: 0.0.1 + schema: v1 + + models: + - name: Claude Sonnet 4.6 + provider: crossmodel + model: anthropic/claude-sonnet-4-6 + apiKey: + ``` + + + ```json title="config.json" + { + "models": [ + { + "title": "Claude Sonnet 4.6", + "provider": "crossmodel", + "model": "anthropic/claude-sonnet-4-6", + "apiKey": "" + } + ] + } + ``` + + + +## Available Models + +Model IDs follow the `/` convention (for example `anthropic/claude-opus-4-8`, `openai/gpt-5.5`, `deepseek/deepseek-v4-pro`, `gemini/gemini-3.5-flash`). The full, up-to-date catalog with pricing is at [crossmodel.ai/models](https://www.crossmodel.ai/models), and can also be listed from the gateway's OpenAI-compatible `/v1/models` endpoint. + +## Notes + +- CrossModel uses an OpenAI-compatible API at `https://api.crossmodel.ai/v1` +- Set the `CROSSMODEL_API_KEY` environment variable or configure `apiKey` in your config +- An Anthropic-compatible endpoint is also available at the same host for tools that speak the Anthropic Messages API diff --git a/docs/docs.json b/docs/docs.json index b7a1d83f13a..698a87f667c 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -107,6 +107,7 @@ "pages": [ "customize/model-providers/more/asksage", "customize/model-providers/more/clawrouter", + "customize/model-providers/more/crossmodel", "customize/model-providers/more/deepseek", "customize/model-providers/more/deepinfra", "customize/model-providers/more/groq", diff --git a/extensions/vscode/config_schema.json b/extensions/vscode/config_schema.json index fb3f4c61362..2c6a74f4b1b 100644 --- a/extensions/vscode/config_schema.json +++ b/extensions/vscode/config_schema.json @@ -217,6 +217,7 @@ "watsonx", "openrouter", "clawrouter", + "crossmodel", "sambanova", "nvidia", "vllm", @@ -270,6 +271,7 @@ "### IBM watsonx\nwatsonx, developed by IBM, offers a variety of pre-trained AI foundation models that can be used for natural language processing (NLP), computer vision, and speech recognition tasks.", "### OpenRouter\nOpenRouter offers a single API to access almost any language model. To get started, obtain an API key from [their console](https://openrouter.ai/settings/keys).", "### ClawRouter\nClawRouter is an open-source LLM router that automatically selects the cheapest capable model for each request based on prompt complexity, providing 78-96% cost savings. To get started, run `npx clawrouter` to start the router at localhost:1337. A wallet is auto-generated on first run - fund it with USDC (Solana/Base) to access premium models, or use `blockrun/free` tier without payment.\n> [Reference](https://github.com/BlockRunAI/ClawRouter)", + "### CrossModel\nCrossModel is an OpenAI- and Anthropic-compatible API gateway. Use one API key and base URL to call models from OpenAI, Anthropic, DeepSeek, Gemini, Qwen, Kimi, GLM and more, with unified billing and usage tracking. Obtain an API key from [the console](https://www.crossmodel.ai/console/api-keys).\n> [Reference](https://crossmodel.ai/docs)", "### SambaNova\n SambaNova provides fast inference of open-source language models with zero data retention. To get started, obtain an API key in [SambaNova Cloud](https://cloud.sambanova.ai/apis?utm_source=continue&utm_medium=external&utm_campaign=cloud_signup ).", "### NVIDIA NIMs\nNVIDIA offers a single API to access almost any language model. To find out more, visit the [LLM APIs Documentation](https://docs.api.nvidia.com/nim/reference/llm-apis).\nFor information specific to getting a key, please check out the [docs here](https://docs.nvidia.com/nim/large-language-models/latest/getting-started.html#option-1-from-api-catalog)", "### vLLM\nvLLM is a highly performant way of hosting LLMs for a team. To get started, follow their [quickstart](https://docs.vllm.ai/en/latest/getting_started/quickstart.html) to set up your server.", diff --git a/gui/public/logos/crossmodel.svg b/gui/public/logos/crossmodel.svg new file mode 100644 index 00000000000..e4dee1de79f --- /dev/null +++ b/gui/public/logos/crossmodel.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/gui/src/pages/AddNewModel/configs/providers.ts b/gui/src/pages/AddNewModel/configs/providers.ts index 9e2aba08c5c..b21d756d5e9 100644 --- a/gui/src/pages/AddNewModel/configs/providers.ts +++ b/gui/src/pages/AddNewModel/configs/providers.ts @@ -194,6 +194,36 @@ export const providers: Partial> = { ], apiKeyUrl: "https://console.anthropic.com/account/keys", }, + crossmodel: { + title: "CrossModel", + provider: "crossmodel", + refPage: "crossmodel", + description: + "OpenAI- and Anthropic-compatible gateway to models from OpenAI, Anthropic, DeepSeek, Gemini, Qwen, Kimi, GLM and more", + longDescription: + "[CrossModel](https://crossmodel.ai) is an OpenAI- and Anthropic-compatible API gateway. Use one API key and base URL to call models from OpenAI, Anthropic, DeepSeek, Gemini, Qwen, Kimi, GLM and more, with unified billing and usage tracking. Sign up at [crossmodel.ai](https://crossmodel.ai), create an API key, then enter it below and fetch the available models.", + icon: "crossmodel.svg", + tags: [ModelProviderTags.RequiresApiKey], + apiKeyUrl: "https://www.crossmodel.ai/console/api-keys", + collectInputFor: [ + { + inputType: "text", + key: "apiKey", + label: "API Key", + placeholder: "Enter your CrossModel API key", + required: true, + }, + ...completionParamsInputsConfigs, + ], + packages: [ + { + title: "Loading models...", + description: "Enter your API key and fetch available models from CrossModel", + params: { model: "placeholder" }, + isOpenSource: false, + }, + ], + }, openrouter: { title: "OpenRouter", provider: "openrouter", diff --git a/packages/openai-adapters/src/index.ts b/packages/openai-adapters/src/index.ts index 52fb2d33a0c..5dbf26067aa 100644 --- a/packages/openai-adapters/src/index.ts +++ b/packages/openai-adapters/src/index.ts @@ -180,6 +180,8 @@ export function constructLlmApi(config: LLMConfig): BaseLlmApi | undefined { return new OpenRouterApi(config); case "clawrouter": return new ClawRouterApi(config); + case "crossmodel": + return openAICompatible("https://api.crossmodel.ai/v1/", config); case "llama.cpp": case "llamafile": return openAICompatible("http://localhost:8000/", config); diff --git a/packages/openai-adapters/src/types.ts b/packages/openai-adapters/src/types.ts index 14b9512f75b..e98b642e1d6 100644 --- a/packages/openai-adapters/src/types.ts +++ b/packages/openai-adapters/src/types.ts @@ -53,6 +53,7 @@ export const OpenAIConfigSchema = BasePlusConfig.extend({ z.literal("msty"), z.literal("openrouter"), z.literal("clawrouter"), + z.literal("crossmodel"), z.literal("sambanova"), z.literal("text-gen-webui"), z.literal("vllm"), From 8b61cc5e401e64035a3565729eeb07672f7a644c Mon Sep 17 00:00:00 2001 From: hujuncheng Date: Fri, 26 Jun 2026 10:53:49 +0800 Subject: [PATCH 2/2] fix(crossmodel): require apiKey in config schema + prettier formatting --- core/llm/toolSupport.ts | 8 +++++++- extensions/vscode/config_schema.json | 3 ++- gui/src/pages/AddNewModel/configs/providers.ts | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index a68b5f800ba..4fb6194f63c 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -382,7 +382,13 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = // CrossModel is an OpenAI/Anthropic-compatible gateway whose catalog is // made up of tool-capable chat models, addressed as `/`. const lower = model.toLowerCase(); - const unsupported = ["embedding", "embed", "whisper", "tts", "moderation"]; + const unsupported = [ + "embedding", + "embed", + "whisper", + "tts", + "moderation", + ]; if (unsupported.some((p) => lower.includes(p))) { return false; } diff --git a/extensions/vscode/config_schema.json b/extensions/vscode/config_schema.json index 2c6a74f4b1b..ae30cc1c6d2 100644 --- a/extensions/vscode/config_schema.json +++ b/extensions/vscode/config_schema.json @@ -538,7 +538,8 @@ "kindo", "scaleway", "ovhcloud", - "venice" + "venice", + "crossmodel" ] } }, diff --git a/gui/src/pages/AddNewModel/configs/providers.ts b/gui/src/pages/AddNewModel/configs/providers.ts index b21d756d5e9..dc239209a66 100644 --- a/gui/src/pages/AddNewModel/configs/providers.ts +++ b/gui/src/pages/AddNewModel/configs/providers.ts @@ -218,7 +218,8 @@ export const providers: Partial> = { packages: [ { title: "Loading models...", - description: "Enter your API key and fetch available models from CrossModel", + description: + "Enter your API key and fetch available models from CrossModel", params: { model: "placeholder" }, isOpenSource: false, },