Skip to content

Commit ec07523

Browse files
Add Atlas Cloud provider preset (#55)
Co-authored-by: binyangzhu000-sudo <224954946+binyangzhu000-sudo@users.noreply.github.com>
1 parent 68f8fe3 commit ec07523

5 files changed

Lines changed: 83 additions & 10 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ skillclaw setup
210210

211211
The setup wizard prompts for the provider, model, local skills directory, PRM settings, optional CLI agent integration, and optional shared storage.
212212

213+
If you use Atlas Cloud as the upstream OpenAI-compatible provider, choose `atlascloud`, keep the default API base `https://api.atlascloud.ai/v1`, and enter your Atlas Cloud API key when prompted. The preset uses chat-compatible forwarding so Codex clients can use SkillClaw's Responses-to-chat bridge.
214+
213215
For a minimal first run:
214216

215217
- choose `none` for the CLI agent if you do not want SkillClaw to auto-configure an external agent yet

‎assets/README_ZH.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ skillclaw setup
209209

210210
设置向导会依次提示你选择 provider、模型、本地 skills 目录、PRM 设置、可选的 CLI agent 集成、以及可选的共享存储。
211211

212+
如果你使用 Atlas Cloud 作为上游 OpenAI 兼容 provider,可以选择 `atlascloud`,保留默认 API base `https://api.atlascloud.ai/v1`,并在提示时输入你的 Atlas Cloud API key。该预设默认走 chat-compatible 转发,因此 Codex 客户端也可以通过 SkillClaw 的 Responses-to-chat 桥接使用。
213+
212214
第一次最小化验证时,推荐这样选:
213215

214216
- `CLI agent` 选 `none`,先不要自动改外部 agent 配置

‎client_env.example.sh‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
export OPENAI_BASE_URL="https://your-model-gateway.example/v1"
1414
export OPENAI_API_KEY="your-openai-api-key"
1515

16+
# Atlas Cloud can be used as an OpenAI-compatible upstream:
17+
# export ATLASCLOUD_API_KEY="your-atlascloud-api-key"
18+
# export OPENAI_BASE_URL="https://api.atlascloud.ai/v1"
19+
# export OPENAI_API_KEY="$ATLASCLOUD_API_KEY"
20+
1621
# Convenience values for shared-skill setup discussions or local wrappers.
1722
export OSS_ENDPOINT="https://oss-cn-hangzhou.aliyuncs.com"
1823
export OSS_BUCKET="skillclaw-shared-skills"

‎skillclaw/setup_wizard.py‎

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
"api_base": "https://openrouter.ai/api/v1",
4040
"model_id": "google/gemini-2.5-pro",
4141
},
42+
"atlascloud": {
43+
"api_base": "https://api.atlascloud.ai/v1",
44+
"model_id": "deepseek-ai/DeepSeek-V3.1",
45+
},
4246
"bedrock": {
4347
"api_base": "",
4448
"model_id": "us.anthropic.claude-sonnet-4-6",
@@ -48,6 +52,10 @@
4852
"model_id": "",
4953
},
5054
}
55+
_PROVIDER_CHOICES = ["kimi", "qwen", "openai", "minimax", "novita", "openrouter", "atlascloud", "bedrock", "custom"]
56+
_PROVIDER_DEFAULT_API_MODE = {
57+
"atlascloud": "chat",
58+
}
5159

5260

5361
def _prompt(msg: str, default: str = "", hide: bool = False) -> str:
@@ -106,6 +114,10 @@ def _infer_existing_sharing_backend(current_sharing: dict) -> str:
106114
return "s3"
107115

108116

117+
def _default_llm_api_mode(provider: str, claw_type: str) -> str:
118+
return _PROVIDER_DEFAULT_API_MODE.get(provider, default_llm_api_mode_for_claw(claw_type))
119+
120+
109121
class SetupWizard:
110122
"""Interactive configuration wizard."""
111123

@@ -135,35 +147,36 @@ def run(self):
135147
current_provider = current_llm.get("provider", "custom")
136148
provider = _prompt_choice(
137149
"LLM provider",
138-
["kimi", "qwen", "openai", "minimax", "novita", "openrouter", "bedrock", "custom"],
150+
_PROVIDER_CHOICES,
139151
default=current_provider,
140152
)
153+
provider_unchanged = current_provider == provider
141154
preset = _PROVIDER_PRESETS[provider]
142155
openrouter_config: dict = existing.get("openrouter", {})
143156
if provider == "bedrock":
144157
api_base = ""
145158
api_key = ""
146159
model_id = _prompt(
147160
"Bedrock model ID (inference profile)",
148-
default=current_llm.get("model_id") or preset["model_id"],
161+
default=(current_llm.get("model_id") if provider_unchanged else "") or preset["model_id"],
149162
)
150163
bedrock_region = _prompt(
151164
"AWS region",
152-
default=current_llm.get("bedrock_region", "us-east-1"),
165+
default=(current_llm.get("bedrock_region") if provider_unchanged else "") or "us-east-1",
153166
)
154167
else:
155168
bedrock_region = ""
156169
preset_regions = preset.get("regions") or {}
157-
default_api_base = current_llm.get("api_base") or preset["api_base"]
170+
default_api_base = (current_llm.get("api_base") if provider_unchanged else "") or preset["api_base"]
158171
if preset_regions:
159172
region_choices = ["global_en", "cn_zh"]
160-
default_region = str(current_llm.get("region") or "global_en")
173+
default_region = str((current_llm.get("region") if provider_unchanged else "") or "global_en")
161174
region = _prompt_choice(
162175
"Region",
163176
region_choices,
164177
default=default_region if default_region in region_choices else "global_en",
165178
)
166-
default_api_base = current_llm.get("api_base") or preset_regions[region]
179+
default_api_base = (current_llm.get("api_base") if provider_unchanged else "") or preset_regions[region]
167180
else:
168181
region = ""
169182
api_base = _prompt(
@@ -172,11 +185,11 @@ def run(self):
172185
)
173186
model_id = _prompt(
174187
"Model ID",
175-
default=current_llm.get("model_id") or preset["model_id"],
188+
default=(current_llm.get("model_id") if provider_unchanged else "") or preset["model_id"],
176189
)
177190
api_key = _prompt(
178191
"API key",
179-
default=current_llm.get("api_key", ""),
192+
default=current_llm.get("api_key", "") if provider_unchanged else "",
180193
hide=True,
181194
)
182195

@@ -378,8 +391,11 @@ def run(self):
378391
proxy_config["port"] = proxy_port
379392
proxy_config.setdefault("host", "0.0.0.0")
380393
proxy_config["served_model_name"] = served_model_name or "skillclaw-model"
381-
default_api_mode = default_llm_api_mode_for_claw(claw_type)
382-
llm_api_mode = str(current_llm.get("api_mode", default_api_mode) or default_api_mode)
394+
default_api_mode = _default_llm_api_mode(provider, claw_type)
395+
if provider_unchanged:
396+
llm_api_mode = str(current_llm.get("api_mode", default_api_mode) or default_api_mode)
397+
else:
398+
llm_api_mode = default_api_mode
383399
data = {
384400
"claw_type": claw_type,
385401
"llm": {

‎tests/test_setup_wizard.py‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,54 @@ def save(self, data):
4141
assert saved["llm"]["api_mode"] == "responses"
4242

4343

44+
def test_setup_wizard_atlascloud_preset_uses_chat_bridge(monkeypatch, tmp_path):
45+
saved = {}
46+
47+
class FakeConfigStore:
48+
config_file = tmp_path / "config.yaml"
49+
50+
def exists(self):
51+
return True
52+
53+
def load(self):
54+
return {
55+
"claw_type": "codex",
56+
"llm": {
57+
"provider": "openai",
58+
"model_id": "gpt-4o",
59+
"api_base": "https://api.openai.com/v1",
60+
"api_key": "upstream-key",
61+
"api_mode": "responses",
62+
},
63+
"proxy": {"port": 30000, "served_model_name": "skillclaw-model"},
64+
"skills": {"enabled": False, "dir": str(tmp_path / "skills")},
65+
"prm": {"enabled": False},
66+
"sharing": {"enabled": False},
67+
}
68+
69+
def save(self, data):
70+
saved.update(data)
71+
72+
def choose_atlascloud_provider(msg, choices, default=""):
73+
if msg == "LLM provider":
74+
return "atlascloud"
75+
return default
76+
77+
monkeypatch.setattr(setup_wizard, "ConfigStore", FakeConfigStore)
78+
monkeypatch.setattr(setup_wizard, "_prompt_choice", choose_atlascloud_provider)
79+
monkeypatch.setattr(setup_wizard, "_prompt", lambda msg, default="", hide=False: default)
80+
monkeypatch.setattr(setup_wizard, "_prompt_bool", lambda msg, default=False: default)
81+
monkeypatch.setattr(setup_wizard, "_prompt_int", lambda msg, default=0: default)
82+
83+
SetupWizard().run()
84+
85+
assert saved["llm"]["provider"] == "atlascloud"
86+
assert saved["llm"]["api_base"] == "https://api.atlascloud.ai/v1"
87+
assert saved["llm"]["model_id"] == "deepseek-ai/DeepSeek-V3.1"
88+
assert saved["llm"]["api_key"] == ""
89+
assert saved["llm"]["api_mode"] == "chat"
90+
91+
4492
def test_setup_wizard_minimax_preset_defaults_to_m3_and_global_region(monkeypatch, tmp_path):
4593
saved = {}
4694

0 commit comments

Comments
 (0)