feat: add Atomic Chat as declarative OpenAI-compatible provider (#9210)

Co-authored-by: Yana Lyalyuk <yanalyalyuk@MacBook-Pro-Yana.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yanalialiuk
2026-05-14 22:29:56 +03:00
committed by GitHub
parent 147a7d14b7
commit e187fcddf7
4 changed files with 150 additions and 0 deletions
@@ -879,6 +879,44 @@ mod tests {
assert_eq!(result, "https://from-env.com/path"); assert_eq!(result, "https://from-env.com/path");
} }
#[test]
fn test_atomic_chat_json_deserializes() {
let json = include_str!("../providers/declarative/atomic_chat.json");
let config: DeclarativeProviderConfig =
serde_json::from_str(json).expect("atomic_chat.json should parse");
assert_eq!(config.name, "atomic_chat");
assert_eq!(config.display_name, "Atomic Chat");
assert_eq!(
config.description.as_deref(),
Some("Local models through Atomic Chat\u{2019}s OpenAI-compatible server")
);
assert!(matches!(config.engine, ProviderEngine::OpenAI));
assert_eq!(config.api_key_env, "");
assert!(!config.requires_auth);
assert!(config.skip_canonical_filtering);
assert_eq!(config.dynamic_models, Some(true));
assert_eq!(config.supports_streaming, Some(true));
assert_eq!(config.base_url, "${ATOMIC_CHAT_HOST}/v1/chat/completions");
assert!(config.models.is_empty());
assert!(config.model_doc_link.is_none());
assert!(config.setup_steps.is_empty());
let env_vars = config.env_vars.as_ref().expect("env_vars should be set");
assert_eq!(env_vars.len(), 1);
assert_eq!(env_vars[0].name, "ATOMIC_CHAT_HOST");
assert!(!env_vars[0].required);
assert!(!env_vars[0].secret);
assert_eq!(env_vars[0].primary, Some(true));
assert_eq!(
env_vars[0].default,
Some("http://localhost:1337".to_string())
);
assert_eq!(
env_vars[0].description.as_deref(),
Some("Base URL of the Atomic Chat server (default: http://localhost:1337)")
);
}
#[test] #[test]
fn test_routstr_json_deserializes() { fn test_routstr_json_deserializes() {
let json = include_str!("../providers/declarative/routstr.json"); let json = include_str!("../providers/declarative/routstr.json");
+39
View File
@@ -703,6 +703,28 @@ const SETUP_METADATA: &[CuratedSetupMetadata] = &[
default_value: None, default_value: None,
}], }],
}, },
CuratedSetupMetadata {
provider_id: "atomic_chat",
category: ProviderSetupCategory::Model,
setup_method: ProviderSetupMethod::ConfigFields,
group: ProviderSetupGroup::Additional,
display_name: None,
description: None,
docs_url: Some("https://github.com/AtomicBot-ai/Atomic-Chat?tab=readme-ov-file#readme"),
aliases: &[],
native_connect_query: None,
binary_name: None,
setup_capabilities: setup_capabilities(false, false, false),
show_only_when_installed: false,
synthetic: false,
secret_field_default: None,
field_overrides: &[CuratedFieldMetadata {
key: "ATOMIC_CHAT_HOST",
label: "Host URL",
placeholder: Some("http://localhost:1337"),
default_value: Some("http://localhost:1337"),
}],
},
CuratedSetupMetadata { CuratedSetupMetadata {
provider_id: "nvidia", provider_id: "nvidia",
category: ProviderSetupCategory::Model, category: ProviderSetupCategory::Model,
@@ -1093,6 +1115,22 @@ mod tests {
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
["DATABRICKS_HOST", "DATABRICKS_TOKEN"] ["DATABRICKS_HOST", "DATABRICKS_TOKEN"]
); );
let atomic_chat = entries
.iter()
.find(|entry| entry.provider_id == "atomic_chat")
.expect("setup catalog should include atomic_chat declarative provider");
assert_eq!(atomic_chat.setup_method, ProviderSetupMethod::ConfigFields);
let host_field = atomic_chat
.fields
.iter()
.find(|field| field.key == "ATOMIC_CHAT_HOST")
.expect("atomic_chat should expose ATOMIC_CHAT_HOST");
assert_eq!(host_field.label, "Host URL");
assert_eq!(
host_field.default_value.as_deref(),
Some("http://localhost:1337")
);
} }
#[tokio::test] #[tokio::test]
@@ -1105,6 +1143,7 @@ mod tests {
assert!(provider_ids.contains("claude-acp")); assert!(provider_ids.contains("claude-acp"));
assert!(provider_ids.contains("codex-acp")); assert!(provider_ids.contains("codex-acp"));
assert!(provider_ids.contains("atomic_chat"));
assert!(!provider_ids.contains("claude_code")); assert!(!provider_ids.contains("claude_code"));
assert!(!provider_ids.contains("codex")); assert!(!provider_ids.contains("codex"));
assert!(!provider_ids.contains("gemini_cli")); assert!(!provider_ids.contains("gemini_cli"));
@@ -0,0 +1,23 @@
{
"name": "atomic_chat",
"engine": "openai",
"display_name": "Atomic Chat",
"description": "Local models through Atomic Chat\u2019s OpenAI-compatible server",
"api_key_env": "",
"base_url": "${ATOMIC_CHAT_HOST}/v1/chat/completions",
"env_vars": [
{
"name": "ATOMIC_CHAT_HOST",
"required": false,
"secret": false,
"primary": true,
"default": "http://localhost:1337",
"description": "Base URL of the Atomic Chat server (default: http://localhost:1337)"
}
],
"dynamic_models": true,
"models": [],
"supports_streaming": true,
"requires_auth": false,
"skip_canonical_filtering": true
}
@@ -25,6 +25,7 @@ goose is compatible with a wide range of LLM providers, allowing you to choose a
| [Amazon Bedrock](https://aws.amazon.com/bedrock/) | Offers a variety of foundation models, including Claude, Jurassic-2, and others. **AWS environment variables must be set in advance, not configured through `goose configure`** | Credential auth: `AWS_PROFILE`, or `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`<br /><br />Bearer token auth: `AWS_BEARER_TOKEN_BEDROCK` and `AWS_REGION`, `AWS_DEFAULT_REGION`, or `AWS_PROFILE` | | [Amazon Bedrock](https://aws.amazon.com/bedrock/) | Offers a variety of foundation models, including Claude, Jurassic-2, and others. **AWS environment variables must be set in advance, not configured through `goose configure`** | Credential auth: `AWS_PROFILE`, or `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`<br /><br />Bearer token auth: `AWS_BEARER_TOKEN_BEDROCK` and `AWS_REGION`, `AWS_DEFAULT_REGION`, or `AWS_PROFILE` |
| [Amazon SageMaker TGI](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html) | Run Text Generation Inference models through Amazon SageMaker endpoints. **AWS credentials must be configured in advance.** | `SAGEMAKER_ENDPOINT_NAME`, `AWS_REGION` (optional), `AWS_PROFILE` (optional) | | [Amazon SageMaker TGI](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html) | Run Text Generation Inference models through Amazon SageMaker endpoints. **AWS credentials must be configured in advance.** | `SAGEMAKER_ENDPOINT_NAME`, `AWS_REGION` (optional), `AWS_PROFILE` (optional) |
| [Anthropic](https://www.anthropic.com/) | Offers Claude, an advanced AI model for natural language tasks. | `ANTHROPIC_API_KEY`, `ANTHROPIC_HOST` (optional) | | [Anthropic](https://www.anthropic.com/) | Offers Claude, an advanced AI model for natural language tasks. | `ANTHROPIC_API_KEY`, `ANTHROPIC_HOST` (optional) |
| [Atomic Chat](https://github.com/AtomicBot-ai/Atomic-Chat) | Run local models with Atomic Chat's OpenAI-compatible server. **Because this provider runs locally, you must first [download a model](#local-llms).** | None required. Connects to local server at `localhost:1337` by default. |
| [Avian](https://avian.io/) | Cost-effective inference API with DeepSeek, Kimi, GLM, and MiniMax models. OpenAI-compatible with streaming and function calling support. | `AVIAN_API_KEY`, `AVIAN_HOST` (optional) | | [Avian](https://avian.io/) | Cost-effective inference API with DeepSeek, Kimi, GLM, and MiniMax models. OpenAI-compatible with streaming and function calling support. | `AVIAN_API_KEY`, `AVIAN_HOST` (optional) |
| [Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-services/openai/) | Access Azure-hosted OpenAI models, including GPT-4 and GPT-3.5. Supports both API key and Azure credential chain authentication. | `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_DEPLOYMENT_NAME`, `AZURE_OPENAI_API_KEY` (optional) | | [Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-services/openai/) | Access Azure-hosted OpenAI models, including GPT-4 and GPT-3.5. Supports both API key and Azure credential chain authentication. | `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_DEPLOYMENT_NAME`, `AZURE_OPENAI_API_KEY` (optional) |
| [ChatGPT Codex](https://chatgpt.com/codex) | Access GPT-5 Codex models optimized for code generation and understanding. **Requires a ChatGPT Plus/Pro subscription.** | No manual key. Uses browser-based OAuth authentication for both CLI and Desktop. | | [ChatGPT Codex](https://chatgpt.com/codex) | Access GPT-5 Codex models optimized for code generation and understanding. **Requires a ChatGPT Plus/Pro subscription.** | No manual key. Uses browser-based OAuth authentication for both CLI and Desktop. |
@@ -1210,6 +1211,55 @@ Here are some local providers we support:
Make sure the model name you enter in goose matches the model identifier shown in LM Studio's server panel. Make sure the model name you enter in goose matches the model identifier shown in LM Studio's server panel.
::: :::
</TabItem> </TabItem>
<TabItem value="atomic-chat" label="Atomic Chat">
[Atomic Chat](https://github.com/AtomicBot-ai/Atomic-Chat) lets you run open-source models locally with an OpenAI-compatible API server.
1. Download and install Atomic Chat from [atomic.chat](https://atomic.chat/) or [GitHub Releases](https://github.com/AtomicBot-ai/Atomic-Chat/releases).
2. Open Atomic Chat and download a model that supports tool calling (e.g., Qwen, Llama, or Mistral variants).
3. Start the local server in Atomic Chat. The server runs on `http://localhost:1337` by default
4. Configure goose to use Atomic Chat:
<Tabs groupId="interface">
<TabItem value="ui" label="goose Desktop" default>
1. Click the <PanelLeft className="inline" size={16} /> button in the top-left to open the sidebar.
2. Click the `Settings` button on the sidebar.
3. Click the `Models` tab.
4. Click `Configure providers`.
5. Choose `Atomic Chat` from the provider list and click `Configure`.
6. Click `Submit` (no API key is needed).
7. Select the model you have loaded in Atomic Chat.
</TabItem>
<TabItem value="cli" label="goose CLI">
1. Run:
```sh
goose configure
```
2. Select `Configure Providers` from the menu.
3. Choose `Atomic Chat` as the provider.
4. Enter the model name that matches the model loaded in Atomic Chat.
```
┌ goose-configure
◇ What would you like to configure?
│ Configure Providers
◇ Which model provider should we use?
│ Atomic Chat
◇ Enter a model from that provider:
│ qwen2.5-7b-instruct
└ Configuration saved successfully
```
</TabItem>
</Tabs>
:::tip Model Name
Make sure the model name you enter in goose matches the model identifier shown for your server in Atomic Chat. If the API listens on a different origin than `http://localhost:1337`, set `ATOMIC_CHAT_HOST` in goose to match (scheme, host, and port only).
:::
</TabItem>
<TabItem value="docker" label="Docker Model Runner" default> <TabItem value="docker" label="Docker Model Runner" default>
1. [Get Docker](https://docs.docker.com/get-started/get-docker/) 1. [Get Docker](https://docs.docker.com/get-started/get-docker/)
2. [Enable Docker Model Runner](https://docs.docker.com/ai/model-runner/#enable-dmr-in-docker-desktop) 2. [Enable Docker Model Runner](https://docs.docker.com/ai/model-runner/#enable-dmr-in-docker-desktop)