From 31501a8d2bca8ad3fcb75c78c41504893648ac1d Mon Sep 17 00:00:00 2001 From: BX166 Date: Mon, 14 Sep 2026 19:46:16 +0800 Subject: [PATCH 1/2] feat(providers): add AICraft as an OpenAI-compatible provider template --- crates/config/src/provider_templates.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/crates/config/src/provider_templates.rs b/crates/config/src/provider_templates.rs index ba913f6b9c..82af4b6dc0 100644 --- a/crates/config/src/provider_templates.rs +++ b/crates/config/src/provider_templates.rs @@ -6,7 +6,7 @@ //! - first-class gateways users still treat as "paste a Base URL" //! (OpenCode Zen / Go), and //! - named OpenAI-compatible custom routes that are not `ProviderKind` -//! variants (SenseNova, Baseten, Groq, Cerebras, Command Code). Hosted +//! variants (SenseNova, Baseten, Groq, Cerebras, Command Code, AICraft). Hosted //! Chat Completions backends are descriptor rows — not new enum variants //! and not compiled model rosters. Live `GET /v1/models` and the //! Codewhale catalog are the offering list. Distinct *wires* @@ -31,6 +31,12 @@ pub const SENSENOVA_BASE_URL: &str = "https://token.sensenova.cn/v1"; pub const SENSENOVA_DEFAULT_MODEL: &str = "deepseek-v4-flash"; pub const SENSENOVA_API_KEY_ENV: &str = "SENSENOVA_API_KEY"; +/// AICraft — OpenAI-compatible MaaS gateway (aicraftapi.com). +pub const AICRAFT_TEMPLATE_ID: &str = "aicraft"; +pub const AICRAFT_BASE_URL: &str = "https://aicraftapi.com/v1"; +pub const AICRAFT_DEFAULT_MODEL: &str = "claude-4.6-sonnet"; +pub const AICRAFT_API_KEY_ENV: &str = "AICRAFT_API_KEY"; + /// Agnes is requested by #5350 but has no published OpenAI-compatible /// host in this repository. pub const AGNES_TEMPLATE_ID: &str = "agnes"; @@ -282,6 +288,17 @@ const TEMPLATES: &[ProviderSetupTemplate] = &[ credential_url: Some("https://commandcode.ai/provider"), guidance: "Published Provider API. Live GET /v1/models is the roster. Do not import the Command Code CLI login. Store COMMAND_CODE_API_KEY, not a raw key.", }, + ProviderSetupTemplate { + id: AICRAFT_TEMPLATE_ID, + display_name: "AICraft", + apply: ProviderSetupApply::Compatible, + base_url: Some(AICRAFT_BASE_URL), + default_model: Some(AICRAFT_DEFAULT_MODEL), + api_key_env: Some(AICRAFT_API_KEY_ENV), + docs_url: Some("https://aicraftapi.com"), + credential_url: Some("https://aicraftapi.com"), + guidance: "AICraft MaaS gateway. OpenAI Chat Completions at aicraftapi.com. Store AICRAFT_API_KEY, not a raw key.", + }, ProviderSetupTemplate { id: AGNES_TEMPLATE_ID, display_name: "Agnes", @@ -484,7 +501,7 @@ mod tests { fn settings_value_names_fillable_then_unpublished() { assert_eq!( ProviderSetupTemplate::settings_value(), - "opencode-zen, opencode-go, sensenova, baseten, groq, cerebras, command-code; agnes unpublished" + "opencode-zen, opencode-go, sensenova, baseten, groq, cerebras, command-code, aicraft; agnes unpublished" ); } @@ -528,6 +545,7 @@ mod tests { "https://api.commandcode.ai/provider/v1", "COMMAND_CODE_API_KEY", ), + ("aicraft", AICRAFT_TEMPLATE_ID, AICRAFT_BASE_URL, AICRAFT_API_KEY_ENV), ] { let template = provider_setup_template(alias).unwrap_or_else(|| panic!("{alias}")); assert_eq!(template.id, id); From 936f1e81a43a197b16009b1af40d5f52d49f6301 Mon Sep 17 00:00:00 2001 From: BX166 Date: Mon, 14 Sep 2026 20:05:14 +0800 Subject: [PATCH 2/2] docs(providers): document AICraft in PROVIDERS.md --- docs/PROVIDERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/PROVIDERS.md b/docs/PROVIDERS.md index bd5d8f5494..f8dfac3fce 100644 --- a/docs/PROVIDERS.md +++ b/docs/PROVIDERS.md @@ -36,6 +36,7 @@ where every Chat Completions host belongs. | Groq | compatible | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` | | Cerebras | compatible | `https://api.cerebras.ai/v1` | `llama-3.3-70b` | `CEREBRAS_API_KEY` | | Command Code | compatible | `https://api.commandcode.ai/provider/v1` | `deepseek/deepseek-v4-flash` | `COMMAND_CODE_API_KEY` | +| AICraft | compatible | `https://aicraftapi.com/v1` | `claude-4.6-sonnet` | `AICRAFT_API_KEY` | | Agnes | unpublished | none in this repository | — | — | Agnes has no published URL here, so it is catalogued as unpublished rather than