Skip to content

Add Atlas Cloud chat completion provider#9288

Open
binyangzhu000-sudo wants to merge 1 commit into
AstrBotDevs:masterfrom
binyangzhu000-sudo:codex/add-atlascloud-provider
Open

Add Atlas Cloud chat completion provider#9288
binyangzhu000-sudo wants to merge 1 commit into
AstrBotDevs:masterfrom
binyangzhu000-sudo:codex/add-atlascloud-provider

Conversation

@binyangzhu000-sudo

@binyangzhu000-sudo binyangzhu000-sudo commented Jul 15, 2026

Copy link
Copy Markdown

Summary

  • add an Atlas Cloud OpenAI-compatible chat completion provider adapter
  • expose Atlas Cloud in the default provider source templates
  • add focused provider tests for default and custom endpoint handling

Validation

  • uv run --python 3.12 python -m compileall astrbot/core/provider/sources/atlascloud_source.py astrbot/core/provider/manager.py astrbot/core/config/default.py tests/test_openai_source.py
  • uv run --python 3.12 pytest tests/test_openai_source.py -q
  • uv run --python 3.12 ruff check astrbot/core/provider/sources/atlascloud_source.py astrbot/core/provider/manager.py astrbot/core/config/default.py tests/test_openai_source.py

No README changes. No sponsor, logo, credits, or partner placement.

Summary by Sourcery

Add an Atlas Cloud OpenAI-compatible chat completion provider and wire it into the default configuration and provider manager.

New Features:

  • Introduce an Atlas Cloud chat completion provider adapter built on the existing OpenAI-compatible provider.
  • Expose Atlas Cloud as a selectable provider in the default configuration templates.

Enhancements:

  • Extend the provider manager to dynamically import the Atlas Cloud provider adapter based on its type.

Tests:

  • Add focused tests to verify Atlas Cloud default API base and model selection as well as honoring custom endpoint and model overrides.

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. labels Jul 15, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the Atlas Cloud chat completion provider. It adds the default configuration for Atlas Cloud, registers the provider adapter with dynamic import support, and implements the ProviderAtlasCloud class which inherits from the official OpenAI provider. Additionally, unit tests have been added to verify the default and custom endpoint/model configurations. I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues, and left some high level feedback:

  • In ProviderAtlasCloud.get_models, catching a bare Exception and silently passing makes debugging harder; consider narrowing the exception type and/or emitting a log so unexpected failures don't get completely swallowed.
  • The ProviderAtlasCloud constructor mutates the incoming provider_config dict to set defaults; if callers reuse these dicts elsewhere, consider copying the config before modification to avoid surprising side effects.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `ProviderAtlasCloud.get_models`, catching a bare `Exception` and silently `pass`ing makes debugging harder; consider narrowing the exception type and/or emitting a log so unexpected failures don't get completely swallowed.
- The `ProviderAtlasCloud` constructor mutates the incoming `provider_config` dict to set defaults; if callers reuse these dicts elsewhere, consider copying the config before modification to avoid surprising side effects.

## Individual Comments

### Comment 1
<location path="astrbot/core/provider/sources/atlascloud_source.py" line_range="32-37" />
<code_context>
+
+        super().__init__(provider_config, provider_settings)
+
+    async def get_models(self) -> list[str]:
+        try:
+            models = await super().get_models()
+            if models:
+                return models
+        except Exception:
+            pass
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The broad exception handler in get_models silently swallows all errors, which could make debugging difficult.

Catching `Exception` and then `pass`-ing will mask real issues (auth, network, schema changes, etc.). Please either narrow the exception type or at least log the failure with enough context so provider-related problems can be diagnosed while still falling back to the static list.

Suggested implementation:

```python
    async def get_models(self) -> list[str]:
        try:
            models = await super().get_models()
            if models:
                return models
        except Exception as exc:
            logger.warning(
                "AtlasCloudSource.get_models: failed to fetch models from upstream; "
                "falling back to static ATLASCLOUD_MODELS list.",
                exc_info=exc,
            )

        return ATLASCLOUD_MODELS

```

To fully implement this change, ensure there is a module-level logger defined in this file, for example:

1. At the top of `astrbot/core/provider/sources/atlascloud_source.py`:
   - Add `import logging` if it is not already present.
   - Add `logger = logging.getLogger(__name__)` alongside other module-level definitions.

If this project uses a different logging convention (e.g., a shared logger utility), replace `logger = logging.getLogger(__name__)` and the `logger.warning(...)` call with the appropriate project-specific logger.
</issue_to_address>

### Comment 2
<location path="astrbot/core/provider/sources/atlascloud_source.py" line_range="5-7" />
<code_context>
+from .openai_source import ProviderOpenAIOfficial
+
+ATLASCLOUD_DEFAULT_API_BASE = "https://api.atlascloud.ai/v1"
+ATLASCLOUD_DEFAULT_MODEL = "qwen/qwen3.5-flash"
+ATLASCLOUD_MODELS = [
+    "qwen/qwen3.5-flash",
+    "deepseek-ai/deepseek-v4-pro",
+    "deepseek-ai/deepseek-v4-flash",
</code_context>
<issue_to_address>
**nitpick:** Keep the default model DRY by reusing ATLASCLOUD_DEFAULT_MODEL in ATLASCLOUD_MODELS.

The default model string is defined both in `ATLASCLOUD_DEFAULT_MODEL` and in `ATLASCLOUD_MODELS`, so any change would require updating two places. Referencing the constant in the list (e.g., `ATLASCLOUD_MODELS = [ATLASCLOUD_DEFAULT_MODEL, ...]`) keeps them in sync.
</issue_to_address>

### Comment 3
<location path="tests/test_openai_source.py" line_range="140-144" />
<code_context>
     assert captured["httpx_module"] is openai_source_module.httpx


+def test_atlascloud_provider_sets_default_openai_compatible_endpoint():
+    provider = _make_atlascloud_provider()
+
+    assert str(provider.client.base_url).rstrip("/") == "https://api.atlascloud.ai/v1"
+    assert provider.get_model() == "qwen/qwen3.5-flash"
+
+
</code_context>
<issue_to_address>
**question (testing):** Consider adding tests for explicit-but-falsy api_base/model values (e.g. empty strings)

`ProviderAtlasCloud` treats `if not provider_config.get("api_base")` / `if not provider_config.get("model")` as “missing”, so values like `""` or `None` are replaced with defaults. Current tests only cover absent or non-empty values.

Please add tests that exercise falsy-but-explicit values, for example:
- `{"api_base": "", "model": ""}` to confirm that defaults are applied (if that’s the intended behavior), or
- A case that asserts empty strings are preserved, if that’s what we want.

This will clarify and lock in the expected behavior for falsy config values.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +32 to +37
async def get_models(self) -> list[str]:
try:
models = await super().get_models()
if models:
return models
except Exception:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): The broad exception handler in get_models silently swallows all errors, which could make debugging difficult.

Catching Exception and then pass-ing will mask real issues (auth, network, schema changes, etc.). Please either narrow the exception type or at least log the failure with enough context so provider-related problems can be diagnosed while still falling back to the static list.

Suggested implementation:

    async def get_models(self) -> list[str]:
        try:
            models = await super().get_models()
            if models:
                return models
        except Exception as exc:
            logger.warning(
                "AtlasCloudSource.get_models: failed to fetch models from upstream; "
                "falling back to static ATLASCLOUD_MODELS list.",
                exc_info=exc,
            )

        return ATLASCLOUD_MODELS

To fully implement this change, ensure there is a module-level logger defined in this file, for example:

  1. At the top of astrbot/core/provider/sources/atlascloud_source.py:
    • Add import logging if it is not already present.
    • Add logger = logging.getLogger(__name__) alongside other module-level definitions.

If this project uses a different logging convention (e.g., a shared logger utility), replace logger = logging.getLogger(__name__) and the logger.warning(...) call with the appropriate project-specific logger.

Comment on lines +5 to +7
ATLASCLOUD_DEFAULT_MODEL = "qwen/qwen3.5-flash"
ATLASCLOUD_MODELS = [
"qwen/qwen3.5-flash",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Keep the default model DRY by reusing ATLASCLOUD_DEFAULT_MODEL in ATLASCLOUD_MODELS.

The default model string is defined both in ATLASCLOUD_DEFAULT_MODEL and in ATLASCLOUD_MODELS, so any change would require updating two places. Referencing the constant in the list (e.g., ATLASCLOUD_MODELS = [ATLASCLOUD_DEFAULT_MODEL, ...]) keeps them in sync.

Comment on lines +140 to +144
def test_atlascloud_provider_sets_default_openai_compatible_endpoint():
provider = _make_atlascloud_provider()

assert str(provider.client.base_url).rstrip("/") == "https://api.atlascloud.ai/v1"
assert provider.get_model() == "qwen/qwen3.5-flash"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (testing): Consider adding tests for explicit-but-falsy api_base/model values (e.g. empty strings)

ProviderAtlasCloud treats if not provider_config.get("api_base") / if not provider_config.get("model") as “missing”, so values like "" or None are replaced with defaults. Current tests only cover absent or non-empty values.

Please add tests that exercise falsy-but-explicit values, for example:

  • {"api_base": "", "model": ""} to confirm that defaults are applied (if that’s the intended behavior), or
  • A case that asserts empty strings are preserved, if that’s what we want.

This will clarify and lock in the expected behavior for falsy config values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant