From b30c002a11cbd130dc16212d766cc87b1491824e Mon Sep 17 00:00:00 2001 From: lucaszhu-hue Date: Tue, 9 Jun 2026 13:59:57 +0800 Subject: [PATCH 1/2] feat: add Atlas Cloud as LLM provider for agents Atlas Cloud offers 59 frontier models (DeepSeek-V4, Qwen3, Kimi K2, GPT-5, Gemini 2.5 Pro, Claude, Grok-4, and more) via a single OpenAI-compatible endpoint. This commit registers Atlas Cloud as an agent provider in Emdash, letting users configure any OpenAI-compatible CLI agent (e.g. opencode) to route through Atlas Cloud's API. - Add 'atlascloud' to AGENT_PROVIDER_IDS and AGENT_PROVIDERS registry - Wire atlas.png icon in the renderer provider meta map - Add Atlas Cloud sponsor/info block at the top of README --- README.md | 76 +++++++++++++++++++ .../src/renderer/lib/providers/meta.ts | 2 + .../core/agents/agent-provider-registry.ts | 21 +++++ 3 files changed, 99 insertions(+) diff --git a/README.md b/README.md index 10b73741a..8dbc558bc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,79 @@ +

+ + Atlas Cloud + +

+ +> **[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=emdash)** is a full-modal AI inference platform — 59 frontier models (DeepSeek-V4, Qwen3, Kimi K2, GPT-5, Gemini 2.5 Pro, Claude, Grok-4…) via a single OpenAI-compatible endpoint. Power your Emdash agents with Atlas Cloud. [View all models](https://www.atlascloud.ai/models) · [Coding Plan](https://www.atlascloud.ai/console/coding-plan) + +
+📋 59 models available on Atlas Cloud + +| Model | Type | +|-------|------| +| deepseek-ai/deepseek-v4-pro | LLM | +| deepseek-ai/deepseek-v4-0520 | LLM | +| deepseek-ai/deepseek-v4-flash | LLM | +| deepseek-ai/deepseek-r2 | LLM | +| deepseek-ai/deepseek-r2-0528 | LLM | +| deepseek-ai/deepseek-r1-0528 | LLM | +| deepseek-ai/deepseek-r1 | LLM | +| deepseek-ai/deepseek-prover-v2 | LLM | +| moonshot-ai/kimi-k2 | LLM | +| moonshot-ai/kimi-k2-0711 | LLM | +| moonshot-ai/kimi-k1.5-long | LLM | +| qwen/qwen3-235b-a22b | LLM | +| qwen/qwen3-30b-a3b | LLM | +| qwen/qwen3-32b | LLM | +| qwen/qwq-32b | LLM | +| openai/gpt-5 | LLM | +| openai/gpt-5-mini | LLM | +| openai/gpt-4.1 | LLM | +| openai/gpt-4o | LLM | +| openai/o3 | LLM | +| openai/o4-mini | LLM | +| openai/o3-mini | LLM | +| anthropic/claude-sonnet-4-5 | LLM | +| anthropic/claude-opus-4 | LLM | +| anthropic/claude-sonnet-4 | LLM | +| anthropic/claude-haiku-4-5 | LLM | +| google/gemini-2.5-pro | LLM | +| google/gemini-2.5-flash | LLM | +| google/gemini-2.5-flash-lite | LLM | +| google/gemini-2.0-flash | LLM | +| xai/grok-4 | LLM | +| xai/grok-3 | LLM | +| xai/grok-3-mini | LLM | +| meta-llama/llama-4-scout | LLM | +| meta-llama/llama-4-maverick | LLM | +| meta-llama/llama-3.3-70b | LLM | +| cohere/command-a | LLM | +| mistral/mistral-large | LLM | +| minimax/minimax-m1 | LLM | +| 01ai/yi-lightning | LLM | +| seedance/seedance-v1-pro | Video | +| seedance/seedance-v1-pro-fast | Video | +| seedance/seedance-v1-lite | Video | +| kling/kling-v2.1-pro | Video | +| kling/kling-v2.1-standard | Video | +| kling/kling-v1.6-pro | Video | +| kling/kling-v1.6-standard | Video | +| wan2/wan2.1-t2v-turbo | Video | +| wan2/wan2.1-i2v-turbo | Video | +| veo/veo3.1-fast | Video | +| veo/veo3-fast | Video | +| veo/veo3 | Video | +| runway/gen4-turbo | Video | +| stable-diffusion/sd3.5-large | Image | +| flux/flux1.1-pro-ultra | Image | +| flux/flux1.1-pro | Image | +| ideogram/ideogram-v3 | Image | +| recraft/recraft-v3 | Image | +| minimax/hailuo-i2v-01-live | Video | +
+ +--- + Emdash
diff --git a/apps/emdash-desktop/src/renderer/lib/providers/meta.ts b/apps/emdash-desktop/src/renderer/lib/providers/meta.ts index 27fd95cec..912fb0a7e 100644 --- a/apps/emdash-desktop/src/renderer/lib/providers/meta.ts +++ b/apps/emdash-desktop/src/renderer/lib/providers/meta.ts @@ -1,4 +1,5 @@ import ampcodeIcon from '@/assets/images/ampcode.svg?raw'; +import atlascloudIcon from '@/assets/images/atlas.png'; import antigravityIcon from '@/assets/images/antigravity.svg?raw'; import atlassianIcon from '@/assets/images/atlassian.png'; import augmentcodeIcon from '@/assets/images/Auggie.svg?raw'; @@ -57,6 +58,7 @@ const ICONS: Record = { 'kiro.png': kiroIcon, 'letta.svg': lettaIcon, 'atlassian.png': atlassianIcon, + 'atlas.png': atlascloudIcon, 'cline.png': clineIcon, 'continue.png': continueIcon, 'codebuff.png': codebuffIcon, diff --git a/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts b/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts index cd74c2e38..606443717 100644 --- a/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts +++ b/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts @@ -30,6 +30,7 @@ export const AGENT_PROVIDER_IDS = [ 'pi', 'letta', 'autohand', + 'atlascloud', ] as const; export type AgentProviderId = (typeof AGENT_PROVIDER_IDS)[number]; @@ -657,6 +658,26 @@ export const AGENT_PROVIDERS: AgentProviderDefinition[] = [ alt: 'Autohand Code CLI', terminalOnly: true, }, + { + id: 'atlascloud', + name: 'Atlas Cloud', + description: + 'Atlas Cloud provides 59 frontier models (DeepSeek-V4, Qwen3, Kimi K2, GPT-5, Gemini 2.5 Pro, Claude, Grok-4…) via a single OpenAI-compatible endpoint. Configure any OpenAI-compatible agent CLI to use Atlas Cloud as the LLM backend.', + docUrl: 'https://www.atlascloud.ai/docs', + installCommand: 'npm install -g opencode-ai', + commands: ['opencode'], + versionArgs: ['--version'], + cli: 'opencode', + autoApproveViaEnv: true, + initialPromptFlag: '--prompt', + resumeFlag: '--session', + sessionIdFlag: '--session', + sessionIdOnResumeOnly: true, + resumeWithoutSessionFlag: '--continue', + icon: 'atlas.png', + alt: 'Atlas Cloud', + terminalOnly: true, + }, ]; const PROVIDER_MAP = new Map( From b3b0a08e14f2e7b99dd3d80b0c32c54fd46969c4 Mon Sep 17 00:00:00 2001 From: lucaszhu-hue Date: Tue, 9 Jun 2026 14:50:04 +0800 Subject: [PATCH 2/2] fix: resolve Atlas Cloud provider collision with opencode binary probe Greptile review caught that the atlascloud provider reused commands: ['opencode'] and the same installCommand as the native opencode provider, causing both to probe the same binary indistinguishably (buildAgentDependencies keys each provider's dependency on its `commands`, so any user with opencode installed made atlascloud spuriously report "available"). On top of that, a spawned atlascloud session ran plain opencode with no Atlas routing at all. Atlas Cloud is an OpenAI-compatible API endpoint reached *through* the opencode CLI, not a separate binary, so configure it via env injection instead of duplicating the CLI provider: - Drop the duplicated commands/installCommand and mark atlascloud detectable:false so it no longer registers a second, identical opencode dependency probe. - Inject OPENAI_BASE_URL=https://api.atlascloud.ai/v1 (user-overridable) and inherit opencode's auto-approve permission env in resolveProviderEnv; the API key is supplied via the provider's env settings (ATLASCLOUD_API_KEY/OPENAI_API_KEY). - Share opencode's session-id validation for atlascloud (runs via opencode). - Add the missing atlascloud entry to agentConfig (Record was incomplete, breaking the renderer/typecheck) and fix meta.ts import ordering. - Cover the new env behavior with provider-env tests. Co-Authored-By: Claude Opus 4.8 --- .../conversations/impl/provider-env.test.ts | 25 +++++++++++++++++++ .../core/conversations/impl/provider-env.ts | 15 ++++++++++- .../src/renderer/lib/providers/meta.ts | 2 +- .../src/renderer/utils/agentConfig.ts | 2 ++ .../core/agents/agent-provider-registry.ts | 16 ++++++++---- 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.test.ts b/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.test.ts index e83d05c69..3c60158fc 100644 --- a/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.test.ts +++ b/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.test.ts @@ -63,4 +63,29 @@ describe('resolveProviderEnv', () => { resolveProviderEnv(undefined, { providerId: 'claude', autoApprove: true }) ).toBeUndefined(); }); + + it('points Atlas Cloud at the Atlas OpenAI-compatible endpoint', () => { + expect(resolveProviderEnv(undefined, { providerId: 'atlascloud' })).toEqual({ + OPENAI_BASE_URL: 'https://api.atlascloud.ai/v1', + }); + }); + + it('lets the user override the Atlas Cloud base URL', () => { + expect( + resolveProviderEnv( + { env: { OPENAI_BASE_URL: 'https://proxy.example/v1', OPENAI_API_KEY: 'sk-test' } }, + { providerId: 'atlascloud' } + ) + ).toEqual({ + OPENAI_BASE_URL: 'https://proxy.example/v1', + OPENAI_API_KEY: 'sk-test', + }); + }); + + it('inherits opencode auto-approve permissions for Atlas Cloud (runs via opencode)', () => { + expect(resolveProviderEnv(undefined, { providerId: 'atlascloud', autoApprove: true })).toEqual({ + OPENCODE_PERMISSION: '{"*":"allow"}', + OPENAI_BASE_URL: 'https://api.atlascloud.ai/v1', + }); + }); }); diff --git a/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.ts b/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.ts index d3eed2ccc..b965d494e 100644 --- a/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.ts +++ b/apps/emdash-desktop/src/main/core/conversations/impl/provider-env.ts @@ -4,6 +4,7 @@ import type { ProviderCustomConfig } from '@shared/core/app-settings'; const ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/; const OPENCODE_ALLOW_ALL_PERMISSIONS = JSON.stringify({ '*': 'allow' }); const GEMINI_TRUST_WORKSPACE = 'true'; +const ATLASCLOUD_BASE_URL = 'https://api.atlascloud.ai/v1'; export function resolveProviderEnv( providerConfig: ProviderCustomConfig | undefined, @@ -11,10 +12,22 @@ export function resolveProviderEnv( ): Record | undefined { const env: Record = {}; - if (options.providerId === 'opencode' && options.autoApprove) { + // Atlas Cloud is the OpenCode CLI pointed at Atlas's OpenAI-compatible + // endpoint, so it inherits OpenCode's auto-approve permission env and gets + // the Atlas base URL injected. The API key is supplied by the user via this + // provider's `env` settings (ATLASCLOUD_API_KEY / OPENAI_API_KEY) and merged + // in below; OPENAI_BASE_URL is defaulted here unless the user overrode it. + const isOpencodeBackend = + options.providerId === 'opencode' || options.providerId === 'atlascloud'; + + if (isOpencodeBackend && options.autoApprove) { env.OPENCODE_PERMISSION = OPENCODE_ALLOW_ALL_PERMISSIONS; } + if (options.providerId === 'atlascloud' && !providerConfig?.env?.OPENAI_BASE_URL) { + env.OPENAI_BASE_URL = ATLASCLOUD_BASE_URL; + } + if (options.providerId === 'gemini' && options.autoApprove) { env.GEMINI_CLI_TRUST_WORKSPACE = GEMINI_TRUST_WORKSPACE; } diff --git a/apps/emdash-desktop/src/renderer/lib/providers/meta.ts b/apps/emdash-desktop/src/renderer/lib/providers/meta.ts index 912fb0a7e..ddd2b1788 100644 --- a/apps/emdash-desktop/src/renderer/lib/providers/meta.ts +++ b/apps/emdash-desktop/src/renderer/lib/providers/meta.ts @@ -1,6 +1,6 @@ import ampcodeIcon from '@/assets/images/ampcode.svg?raw'; -import atlascloudIcon from '@/assets/images/atlas.png'; import antigravityIcon from '@/assets/images/antigravity.svg?raw'; +import atlascloudIcon from '@/assets/images/atlas.png'; import atlassianIcon from '@/assets/images/atlassian.png'; import augmentcodeIcon from '@/assets/images/Auggie.svg?raw'; import autohandIcon from '@/assets/images/autohand.svg?raw'; diff --git a/apps/emdash-desktop/src/renderer/utils/agentConfig.ts b/apps/emdash-desktop/src/renderer/utils/agentConfig.ts index f411d64ff..16c2b5092 100644 --- a/apps/emdash-desktop/src/renderer/utils/agentConfig.ts +++ b/apps/emdash-desktop/src/renderer/utils/agentConfig.ts @@ -1,6 +1,7 @@ import { type AgentProviderId } from '@shared/core/agents/agent-provider-registry'; import ampLogo from '../../assets/images/ampcode.svg'; import antigravityLogo from '../../assets/images/antigravity.svg'; +import atlascloudLogo from '../../assets/images/atlas.png'; import atlassianLogo from '../../assets/images/atlassian.png'; import augmentLogoSvg from '../../assets/images/Auggie.svg?raw'; import autohandLogoSvg from '../../assets/images/autohand.svg?raw'; @@ -118,4 +119,5 @@ export const agentConfig: Record = { }, charm: { name: 'Charm', logo: charmLogo, alt: 'Charm Crush' }, rovo: { name: 'Rovo Dev', logo: atlassianLogo, alt: 'Rovo Dev' }, + atlascloud: { name: 'Atlas Cloud', logo: atlascloudLogo, alt: 'Atlas Cloud' }, }; diff --git a/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts b/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts index 606443717..b8f03c494 100644 --- a/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts +++ b/apps/emdash-desktop/src/shared/core/agents/agent-provider-registry.ts @@ -662,11 +662,14 @@ export const AGENT_PROVIDERS: AgentProviderDefinition[] = [ id: 'atlascloud', name: 'Atlas Cloud', description: - 'Atlas Cloud provides 59 frontier models (DeepSeek-V4, Qwen3, Kimi K2, GPT-5, Gemini 2.5 Pro, Claude, Grok-4…) via a single OpenAI-compatible endpoint. Configure any OpenAI-compatible agent CLI to use Atlas Cloud as the LLM backend.', + 'Route the OpenCode CLI through Atlas Cloud — 59 frontier models (DeepSeek-V4, Qwen3, Kimi K2, GPT-5, Gemini 2.5 Pro, Claude, Grok-4…) via a single OpenAI-compatible endpoint. Requires OpenCode; set ATLASCLOUD_API_KEY (or OPENAI_API_KEY) in this provider’s environment settings.', docUrl: 'https://www.atlascloud.ai/docs', - installCommand: 'npm install -g opencode-ai', - commands: ['opencode'], - versionArgs: ['--version'], + // Atlas Cloud is not a standalone CLI: it reuses the OpenCode binary and + // simply points it at Atlas's OpenAI-compatible endpoint via env injection + // (see resolveProviderEnv). Reusing OpenCode's command/installCommand here + // would register a second, indistinguishable probe of the `opencode` + // binary, so it is intentionally not separately detectable. + detectable: false, cli: 'opencode', autoApproveViaEnv: true, initialPromptFlag: '--prompt', @@ -702,7 +705,10 @@ export function isValidProviderId(value: unknown): value is AgentProviderId { } export function isValidProviderSessionId(providerId: string, providerSessionId: string): boolean { - if (providerId === 'opencode') return providerSessionId.startsWith('ses'); + // Atlas Cloud runs through the OpenCode CLI, so it shares OpenCode's session id format. + if (providerId === 'opencode' || providerId === 'atlascloud') { + return providerSessionId.startsWith('ses'); + } return true; }