feat: add Atlas Cloud LLM provider#21
Conversation
Reviewer's GuideAdds a new OpenAI-compatible Atlas Cloud LLM provider and wires it into the runtime: provider manager, env resolution, auto-detection, provider defaults, response-format handling, provider assignment, tests, docs, and platform knowledge copy are all updated to treat Atlas Cloud as the 12th first-class provider. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- Consider removing or gating the
console.logcalls inAtlasCloudProvider.initializeandshutdownto avoid noisy logs in production; other providers tend to avoid logging at this level. - The
ProviderConfigEntry.configunion inAIModelProviderManageris becoming large; you might want to refactor it into a mapped type keyed by providerId or a discriminated union to keep the type easier to maintain as new providers likeatlascloudare added.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider removing or gating the `console.log` calls in `AtlasCloudProvider.initialize` and `shutdown` to avoid noisy logs in production; other providers tend to avoid logging at this level.
- The `ProviderConfigEntry.config` union in `AIModelProviderManager` is becoming large; you might want to refactor it into a mapped type keyed by providerId or a discriminated union to keep the type easier to maintain as new providers like `atlascloud` are added.
## Individual Comments
### Comment 1
<location path="src/core/llm/providers/implementations/AtlasCloudProvider.ts" line_range="128-129" />
<code_context>
+ }
+
+ public async listAvailableModels(filter?: { capability?: string }): Promise<ModelInfo[]> {
+ if (filter?.capability) {
+ return ATLAS_CLOUD_MODELS.filter(m => m.capabilities.includes(filter.capability!));
+ }
+ return [...ATLAS_CLOUD_MODELS];
</code_context>
<issue_to_address>
**nitpick:** Avoid the non-null assertion in the capabilities filter to keep the implementation cleaner and safer.
Within the `if (filter?.capability)` block, `filter.capability` is already typed as `string`, so the `!` is unnecessary. Use `includes(filter.capability)` instead to avoid redundant assertions and keep the code safer if the filter type changes in the future.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
PR Summary by QodoAdd Atlas Cloud as a new OpenAI-compatible LLM provider
AI Description
Diagram
Files changed (18)
|
📝 WalkthroughWalkthroughAtlas Cloud was added as an OpenAI-compatible LLM provider, including model defaults, environment-based resolution, auto-detection, response formatting, provider assignment, tests, and documentation updates. Provider-count references were updated from 11 to 12. ChangesAtlas Cloud provider support
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant AIModelProviderManager
participant AtlasCloudProvider
participant OpenAIProvider
AIModelProviderManager->>AtlasCloudProvider: initialize provider configuration
AtlasCloudProvider->>OpenAIProvider: initialize compatible transport
AtlasCloudProvider->>OpenAIProvider: delegate completion or streaming request
OpenAIProvider-->>AtlasCloudProvider: return completion response
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 846378f240
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // are set". | ||
| { envKey: 'OPENROUTER_API_KEY', provider: 'openrouter' }, | ||
| { envKey: 'OPENAI_API_KEY', provider: 'openai' }, | ||
| { envKey: 'ATLASCLOUD_API_KEY', provider: 'atlascloud' }, |
There was a problem hiding this comment.
Wire Atlas Cloud into QueryRouter defaults
When only ATLASCLOUD_API_KEY is configured and a caller uses the QueryRouter/platform-knowledge defaults, this new auto-detect entry makes the public API recognize Atlas Cloud, but QueryRouter still has separate hard-coded provider lists: src/orchestration/pipeline/query/types.ts:789-798 omits Atlas when choosing the default provider, src/orchestration/pipeline/query/QueryRouter.ts:1614-1623 omits its API key, and the cheap/strong model maps omit Atlas model IDs. In that environment QueryRouter falls back to openai and passes apiKey: '' into generateText, so routing fails with an OpenAI credential error instead of using Atlas Cloud. Add ATLASCLOUD_API_KEY and the Atlas default models to the QueryRouter resolver paths as part of registering the provider.
Useful? React with 👍 / 👎.
Code Review by Qodo
1. Cheap model capability mismatch
|
| this.isInitialized = true; | ||
| console.log(`AtlasCloudProvider initialized. Default model: ${this.defaultModelId}.`); | ||
| } |
There was a problem hiding this comment.
1. Unconditional provider logs 🐞 Bug ◔ Observability
AtlasCloudProvider logs initialization/shutdown via console.log unconditionally, bypassing the existing debug/log-level gating used by AIModelProviderManager and OpenAIProvider. This will add noisy stdout output for library consumers and can unexpectedly surface operational configuration (e.g., default model) even when debug is off.
Agent Prompt
### Issue description
`AtlasCloudProvider` uses unconditional `console.log` statements on initialize/shutdown. The rest of the provider stack already has log-gating (AGENTOS_DEBUG / AGENTOS_LOG_LEVEL), so these logs should be similarly gated or routed through the same logging mechanism.
### Issue Context
- `AIModelProviderManager` only logs init traces when debug is enabled.
- `OpenAIProvider` only logs init success when debug is enabled.
- `AtlasCloudProvider` currently always logs, which is inconsistent and noisy.
### Fix Focus Areas
- src/core/llm/providers/implementations/AtlasCloudProvider.ts[81-97]
- src/core/llm/providers/implementations/AtlasCloudProvider.ts[144-149]
- src/core/llm/providers/AIModelProviderManager.ts[68-81]
- src/core/llm/providers/implementations/OpenAIProvider.ts[471-497]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| atlascloud: { | ||
| text: 'deepseek-ai/deepseek-v4-pro', | ||
| cheap: 'qwen/qwen3.5-flash', | ||
| }, |
There was a problem hiding this comment.
2. Cheap model capability mismatch 🐞 Bug ≡ Correctness
PROVIDER_DEFAULTS sets Atlas Cloud’s cheap model to qwen/qwen3.5-flash, but AtlasCloudProvider’s model catalog declares that model as chat-only (no tool_use / json_mode), while response-format selection treats all atlascloud calls as JSON-mode capable. This internal mismatch can suppress tools (and raise TOOLS_NOT_SUPPORTED) for cheapest routing while still emitting JSON response-format payloads for the same provider.
Agent Prompt
### Issue description
Atlas Cloud’s `cheap` default model is configured as `qwen/qwen3.5-flash`, but the in-repo model metadata marks it as lacking `tool_use` and `json_mode`. The runtime derives tool support from `capabilities.includes('tool_use')` and may suppress tool schema injection / flag errors, while `buildResponseFormatForProvider` still emits OpenAI-style JSON response formats for providerId `atlascloud` without model-specific gating.
### Issue Context
This is an internal consistency issue between:
- The model chosen by default for “cheap” routing.
- The declared capabilities used to determine tool support.
- The provider-level responseFormat behavior that assumes JSON-mode compatibility.
### Fix Focus Areas
- src/api/runtime/provider-defaults.ts[58-61]
- src/core/llm/providers/implementations/AtlasCloudProvider.ts[44-65]
- src/api/runtime/responseFormatForProvider.ts[21-110]
- src/cognition/substrate/GMI.ts[806-816]
- src/core/llm/PromptEngine.ts[271-273]
- src/core/llm/PromptEngine.ts[394-396]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/features/LLM_PROVIDERS.md`:
- Line 3: Update the provider breakdown in the introductory text and the
corresponding reference around the provider matrix: describe twelve providers as
9 API-key providers, Ollama, and 2 CLI providers, ensuring the category counts
sum to twelve and removing the incorrect “10 via API key” wording.
In `@src/orchestration/planning/ProviderAssignmentEngine.ts`:
- Line 109: Update the assignBalanced method’s cheap, strong, and standard
preferred-provider lists to include atlascloud in the same priority positions
used by the corresponding best and cheapest strategies, while preserving the
existing balanced rotation keys and tier selection logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: bedc9ccf-dd65-4f83-8f1c-c8e0f74832fb
📒 Files selected for processing (18)
CITATION.cffREADME.mddocs/architecture/ARCHITECTURE.mddocs/features/LLM_PROVIDERS.mdpackage.jsonscripts/build-knowledge-corpus.mjssrc/api/model.tssrc/api/runtime/__tests__/provider-defaults.test.tssrc/api/runtime/__tests__/responseFormatForProvider.test.tssrc/api/runtime/provider-defaults.tssrc/api/runtime/responseFormatForProvider.tssrc/core/llm/providers/AIModelProviderManager.tssrc/core/llm/providers/__tests__/OpenAICompatProviders.test.tssrc/core/llm/providers/implementations/AtlasCloudProvider.tssrc/orchestration/pipeline/query/__tests__/platform-knowledge.test.tssrc/orchestration/planning/ProviderAssignmentEngine.tstests/api/model.spec.tstests/e2e/platform-knowledge.e2e.spec.ts
| # LLM Providers — multi-provider configuration & routing | ||
|
|
||
| AgentOS abstracts every LLM behind a single [`IProvider`](https://github.com/framerslab/agentos/blob/master/src/core/llm/providers/IProvider.ts) interface. Eleven providers are wired in directly — nine via API key, two via local CLI bridges that ride an existing Claude Max or Google account subscription. OpenRouter, included in the eleven, fans out to 200+ additional models from the same set of vendors. Every provider speaks the same streaming protocol, supports the same tool-call shape (with the documented exceptions below), and participates in the same cost ledger. The fallback chain is auto-built from whichever keys are set in the environment and is overridable per agent. | ||
| AgentOS abstracts every LLM behind a single [`IProvider`](https://github.com/framerslab/agentos/blob/master/src/core/llm/providers/IProvider.ts) interface. Twelve providers are wired in directly — ten via API key, two via local CLI bridges that ride an existing Claude Max or Google account subscription. OpenRouter, included in the twelve, fans out to 200+ additional models from the same set of vendors. Every provider speaks the same streaming protocol, supports the same tool-call shape (with the documented exceptions below), and participates in the same cost ledger. The fallback chain is auto-built from whichever keys are set in the environment and is overridable per agent. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the provider breakdown.
The provider matrix contains 9 API-key providers + Ollama + 2 CLI providers, not “10 API-key + 2 CLI-based.” Update both references so the documented categories sum to twelve.
Also applies to: 40-40
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/features/LLM_PROVIDERS.md` at line 3, Update the provider breakdown in
the introductory text and the corresponding reference around the provider
matrix: describe twelve providers as 9 API-key providers, Ollama, and 2 CLI
providers, ensuring the category counts sum to twelve and removing the incorrect
“10 via API key” wording.
| const provider = this.pickProvider( | ||
| 'cheapest', | ||
| ['groq', 'gemini', 'openai', 'openrouter', 'together', 'mistral', 'xai', 'anthropic', 'ollama'], | ||
| ['groq', 'gemini', 'atlascloud', 'openai', 'openrouter', 'together', 'mistral', 'xai', 'anthropic', 'ollama'], |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add atlascloud to the balanced assignment strategies.
atlascloud was successfully added to the preferred lists for the best and cheapest strategies, but it appears to be missing from the balanced tiers implemented below (lines 129-144). If omitted there, atlascloud won't be chosen for balanced workloads when other preferred providers are available.
Consider updating the assignBalanced method to include atlascloud in its preferred lists to ensure it properly participates in balanced provider rotation.
💡 Proposed fix for assignBalanced
Apply the following modifications to assignBalanced (around lines 129-144):
const provider =
tier === 'cheap'
? this.pickProvider(
'balanced:cheap',
['groq', 'gemini', 'atlascloud', 'openai', 'openrouter', 'together', 'mistral', 'xai', 'anthropic', 'ollama'],
)
: tier === 'strong'
? this.pickProvider(
'balanced:strong',
['anthropic', 'openai', 'openrouter', 'atlascloud', 'gemini', 'groq', 'xai', 'mistral', 'together', 'ollama'],
)
: this.pickProvider(
'balanced:standard',
['openai', 'openrouter', 'atlascloud', 'anthropic', 'gemini', 'groq', 'mistral', 'xai', 'together', 'ollama'],
);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/orchestration/planning/ProviderAssignmentEngine.ts` at line 109, Update
the assignBalanced method’s cheap, strong, and standard preferred-provider lists
to include atlascloud in the same priority positions used by the corresponding
best and cheapest strategies, while preserving the existing balanced rotation
keys and tier selection logic.
Summary
atlascloudOpenAI-compatible LLM provider wrapper with Atlas Cloud defaultsValidation
./node_modules/.bin/vitest run src/core/llm/providers/__tests__/OpenAICompatProviders.test.ts src/api/runtime/__tests__/provider-defaults.test.ts src/api/runtime/__tests__/responseFormatForProvider.test.ts tests/api/model.spec.ts src/orchestration/pipeline/query/__tests__/platform-knowledge.test.ts(88 tests passed)./node_modules/.bin/tsc --noEmit./node_modules/.bin/eslint "src/**/*.ts"(passes with existing warnings)git diff --checkdeepseek-ai/deepseek-v4-proandqwen/qwen3.5-flashNote:
pnpm install --frozen-lockfilecompleted dependency resolution and ran the repository build successfully, but exited afterward withERR_PNPM_IGNORED_BUILDSbecause this local pnpm setup requires approving build scripts for optional native dependencies.Summary by Sourcery
Add Atlas Cloud as an OpenAI-compatible LLM provider and wire it into runtime defaults, auto-detection, provider assignment, and JSON response-format handling.
New Features:
Enhancements:
Tests:
Summary by CodeRabbit
New Features
ATLASCLOUD_API_KEY.Documentation