From f643e6eb96e49401932f83a0529f66e00beaeb23 Mon Sep 17 00:00:00 2001 From: binyangzhu000-sudo <224954946+binyangzhu000-sudo@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:34:27 +0800 Subject: [PATCH] feat: add Atlas Cloud provider preset Add Atlas Cloud as a built-in aggregator preset, shaped like the Requesty and OpenRouter entries. - presets.ts: new `atlascloud` preset after `api-route`, with three endpoints: OpenAI Chat (https://api.atlascloud.ai/v1, model list public), OpenAI Responses (same base) and Anthropic (https://api.atlascloud.ai, the client adds /v1/messages). Not marked as recommended. - Brand icon: lobehub ships an atlascloud glyph, so register the brand (BRANDS, rule, ProviderIcon import) instead of falling back to initials. - Tests: pinned the Anthropic URL row, added the preset to the public model-list set, the brand table, and a resolveBrand sample. - baseurl.ts: Atlas Cloud added to the `/v1` row of the doc table. Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: binyangzhu000-sudo <224954946+binyangzhu000-sudo@users.noreply.github.com> --- .../src/components/brand/ProviderIcon.tsx | 3 ++- .../components/brand/__tests__/brands.test.ts | 2 ++ src/renderer/src/components/brand/brands.ts | 2 ++ .../model/__tests__/preset-brands.test.ts | 1 + src/shared/domain/__tests__/presets.test.ts | 5 +++-- src/shared/domain/baseurl.ts | 2 +- src/shared/domain/presets.ts | 18 ++++++++++++++++++ 7 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/components/brand/ProviderIcon.tsx b/src/renderer/src/components/brand/ProviderIcon.tsx index eee05e6b..d74afe0b 100644 --- a/src/renderer/src/components/brand/ProviderIcon.tsx +++ b/src/renderer/src/components/brand/ProviderIcon.tsx @@ -28,6 +28,7 @@ import routinUrl from '../../../../../resources/images/routin-ai.webp' import ai302 from '@lobehub/icons-static-svg/icons/ai302.svg?raw' import aihubmix from '@lobehub/icons-static-svg/icons/aihubmix.svg?raw' +import atlascloud from '@lobehub/icons-static-svg/icons/atlascloud.svg?raw' import anthropic from '@lobehub/icons-static-svg/icons/anthropic.svg?raw' import azure from '@lobehub/icons-static-svg/icons/azure.svg?raw' import baichuan from '@lobehub/icons-static-svg/icons/baichuan.svg?raw' @@ -99,7 +100,7 @@ const RASTER: Record = { routin: routinUrl } * 而不是运行时的一个空图标。 */ const MARK: Record, string> = { - ai302, aihubmix, anthropic, azure, baichuan, baiducloud, bailian, bedrock, + ai302, aihubmix, anthropic, atlascloud, azure, baichuan, baiducloud, bailian, bedrock, claude, cohere, deepinfra, deepseek, doubao, fireworks, gemini, groq, hunyuan, kimi, lmstudio, menlo, meta, minimax, mistral, moonshot, ollama, openai, opencode, openrouter, perplexity, qwen, sensenova, siliconcloud, diff --git a/src/renderer/src/components/brand/__tests__/brands.test.ts b/src/renderer/src/components/brand/__tests__/brands.test.ts index 1aa80426..118b8b12 100644 --- a/src/renderer/src/components/brand/__tests__/brands.test.ts +++ b/src/renderer/src/components/brand/__tests__/brands.test.ts @@ -46,6 +46,8 @@ const SAMPLES: readonly (readonly [string, Brand])[] = [ ['Azure', 'azure'], ['302.AI', 'ai302'], ['AiHubMix', 'aihubmix'], + ['Atlas Cloud', 'atlascloud'], + ['atlascloud', 'atlascloud'], ['百度千帆', 'baiducloud'], ['阿里百炼', 'bailian'], ['command-r-plus', 'cohere'], diff --git a/src/renderer/src/components/brand/brands.ts b/src/renderer/src/components/brand/brands.ts index 6635a844..96f3632d 100644 --- a/src/renderer/src/components/brand/brands.ts +++ b/src/renderer/src/components/brand/brands.ts @@ -21,6 +21,7 @@ export const BRANDS = [ 'ai302', 'aihubmix', 'anthropic', + 'atlascloud', 'azure', 'baichuan', 'baiducloud', @@ -163,6 +164,7 @@ const RULES: readonly (readonly [RegExp, Brand | null])[] = [ // 因为它就是一家聚合商。 [/\broutin[\s_-]*ai\b|^routin(-plan)?$/i, 'routin'], [/aihubmix/i, 'aihubmix'], + [/atlas[\s_-]*cloud/i, 'atlascloud'], [/\b302\.?ai\b/i, 'ai302'], [/groq/i, 'groq'], [/together/i, 'together'], diff --git a/src/renderer/src/settings/pages/model/__tests__/preset-brands.test.ts b/src/renderer/src/settings/pages/model/__tests__/preset-brands.test.ts index a9d57ad5..6a63a77c 100644 --- a/src/renderer/src/settings/pages/model/__tests__/preset-brands.test.ts +++ b/src/renderer/src/settings/pages/model/__tests__/preset-brands.test.ts @@ -85,6 +85,7 @@ const EXPECTED: Readonly> = { requesty: null, opper: null, 'api-route': null, + atlascloud: 'atlascloud', siliconflow: 'siliconcloud', 'siliconflow-intl': 'siliconcloud', together: 'together', diff --git a/src/shared/domain/__tests__/presets.test.ts b/src/shared/domain/__tests__/presets.test.ts index 64828845..9a1b01a5 100644 --- a/src/shared/domain/__tests__/presets.test.ts +++ b/src/shared/domain/__tests__/presets.test.ts @@ -255,6 +255,7 @@ describe('预设表 × joinUpstreamUrl:拼出来的 URL 没有畸形', () => { ['fireworks', 'anthropic', 'https://api.fireworks.ai/inference/v1/messages'], ['openrouter', 'anthropic', 'https://openrouter.ai/api/v1/messages'], ['requesty', 'anthropic', 'https://router.requesty.ai/v1/messages'], + ['atlascloud', 'anthropic', 'https://api.atlascloud.ai/v1/messages'], ['opper', 'openai-chat', 'https://api.opper.ai/v3/compat/chat/completions'], ['opper', 'anthropic', 'https://api.opper.ai/v3/compat/v1/messages'], ['kimi-coding', 'anthropic', 'https://api.kimi.com/coding/v1/messages'], @@ -347,12 +348,12 @@ describe('预设表 · 模型列表', () => { }) }) - it('实测免鉴权的那五家标了 modelListPublic', () => { + it('实测免鉴权的那六家标了 modelListPublic', () => { const publics = PROVIDER_PRESETS.filter((p) => p.endpoints.some((e) => e.modelListPublic === true) ).map((p) => p.id) expect(new Set(publics)).toEqual( - new Set(['openrouter', 'requesty', 'deepinfra', 'opencode-go', 'ollama-cloud']) + new Set(['openrouter', 'requesty', 'atlascloud', 'deepinfra', 'opencode-go', 'ollama-cloud']) ) }) }) diff --git a/src/shared/domain/baseurl.ts b/src/shared/domain/baseurl.ts index d258518f..8799aa20 100644 --- a/src/shared/domain/baseurl.ts +++ b/src/shared/domain/baseurl.ts @@ -46,7 +46,7 @@ export function joinUpstreamUrl(baseUrl: string, path: string): string { * * | 形状 | 厂商 | * |---|---| - * | `/v1` | OpenAI、Moonshot、MiniMax、混元、StepFun、百川、Mistral、xAI、Together、硅基流动、Requesty | + * | `/v1` | OpenAI、Moonshot、MiniMax、混元、StepFun、百川、Mistral、xAI、Together、硅基流动、Requesty、Atlas Cloud | * | 别的前缀 | Groq `/openai/v1`、Fireworks `/inference/v1`、**DeepInfra `/v1/openai`**、OpenRouter `/api/v1`、**智谱 `/api/paas/v4`**、**火山 `/api/v3`**、百炼 `/compatible-mode/v1`、**千帆 `/v2`**、Cohere `/compatibility/v1`、Opper `/v3/compat` | * | 尾斜杠 | **Gemini `/v1beta/openai/`** | * diff --git a/src/shared/domain/presets.ts b/src/shared/domain/presets.ts index 25ebc3ad..6d3bc281 100644 --- a/src/shared/domain/presets.ts +++ b/src/shared/domain/presets.ts @@ -930,6 +930,24 @@ export const PROVIDER_PRESETS: readonly ProviderPreset[] = [ '使用模型列表返回的完整 ID(如 gpt-6.1-sol),无需添加厂商前缀。', verification: 'probed' }, + { + id: 'atlascloud', + name: 'Atlas Cloud', + category: 'aggregator', + endpoints: [ + oa('https://api.atlascloud.ai/v1', true, true), + resp('https://api.atlascloud.ai/v1', true), + anth('https://api.atlascloud.ai') + ], + docsUrl: 'https://www.atlascloud.ai/docs', + apiKeyUrl: 'https://console.atlascloud.ai/api-keys', + suggestedModels: ['deepseek-ai/deepseek-v4-flash', 'moonshotai/kimi-k3', 'zai-org/glm-5.2'], + notes: + '模型 ID 带厂商前缀(如 deepseek-ai/deepseek-v4-flash),请使用模型列表返回的完整 ID。' + + '模型列表免鉴权就能拉,没填 key 也能先看有哪些模型(因此列表能拉到不代表 key 有效)。' + + '同一个 key 也可走 OpenAI Responses 与 Anthropic 协议。', + verification: 'documented' + }, { id: 'siliconflow', name: '硅基流动(国内)',