From f21c0b293a42beed60356c68bc86f627b76dc4fd Mon Sep 17 00:00:00 2001 From: luoyanglang <238804951+luoyanglang@users.noreply.github.com> Date: Sat, 25 Apr 2026 07:39:55 +0000 Subject: [PATCH] fix(skills): remove broken default skills hub --- README.md | 45 ++++++++-------- docs/remote-skills-guide.md | 36 +++++++------ docs/remote-skills-quickstart.md | 80 +++++++++++++-------------- scripts/skill_manager.py | 86 ++++++++++++++--------------- tests/test_skill_manager.py | 92 ++++++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+), 124 deletions(-) create mode 100644 tests/test_skill_manager.py diff --git a/README.md b/README.md index 15ab905..dfc7cbb 100644 --- a/README.md +++ b/README.md @@ -550,24 +550,24 @@ edict/ #### 2️⃣ CLI 命令(最灵活) ```bash -# 从 GitHub 添加 code_review skill 到中书省 +# 从 GitHub 添加 mmx_cli skill 到门下省 python3 scripts/skill_manager.py add-remote \ - --agent zhongshu \ - --name code_review \ - --source https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/code_review/SKILL.md \ - --description "代码审查技能" + --agent menxia \ + --name mmx_cli \ + --source https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md \ + --description "MiniMax 多模态 CLI 技能" -# 一键导入官方 skills 库到指定 agents +# 一键导入默认 skills 到指定 agents python3 scripts/skill_manager.py import-official-hub \ - --agents zhongshu,menxia,shangshu,bingbu,xingbu + --agents menxia,shangshu # 列出所有已添加的远程 skills python3 scripts/skill_manager.py list-remote # 更新某个 skill 到最新版本 python3 scripts/skill_manager.py update-remote \ - --agent zhongshu \ - --name code_review + --agent menxia \ + --name mmx_cli ``` #### 3️⃣ API 请求(自动化集成) @@ -577,25 +577,22 @@ python3 scripts/skill_manager.py update-remote \ curl -X POST http://localhost:7891/api/add-remote-skill \ -H "Content-Type: application/json" \ -d '{ - "agentId": "zhongshu", - "skillName": "code_review", - "sourceUrl": "https://raw.githubusercontent.com/...", - "description": "代码审查" + "agentId": "menxia", + "skillName": "mmx_cli", + "sourceUrl": "https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md", + "description": "MiniMax 多模态 CLI 技能" }' # 查看所有远程 skills curl http://localhost:7891/api/remote-skills-list ``` -**官方 Skills Hub:** https://github.com/openclaw-ai/skills-hub +**默认可导入 Skill:** 支持的 Skills: -- `code_review` — 代码审查(Python/JS/Go) -- `api_design` — API 设计审查 -- `security_audit` — 安全审计 -- `data_analysis` — 数据分析 -- `doc_generation` — 文档生成 -- `test_framework` — 测试框架设计 +- `mmx_cli` — MiniMax 多模态 CLI 技能(文本、图像、视频、语音、音乐、搜索) + +如果你有自己的 Skills Hub,可以通过 `OPENCLAW_SKILLS_HUB_BASE` 或 `~/.openclaw/skills-hub-url` 配置自定义源。 详见 [🎓 远程 Skills 资源管理指南](docs/remote-skills-guide.md) @@ -636,7 +633,7 @@ curl http://localhost:7891/api/remote-skills-list - **[🎓 远程 Skills 资源管理指南](docs/remote-skills-guide.md)** — Skills 生态 - 从网上连接和增补 skills,支持 GitHub/Gitee/任意 HTTPS URL - - 官方 Skills Hub 预设能力库 + - 默认 Skills 源和自定义 Hub 支持 - CLI 工具 + 看板 UI + Restful API - Skills 文件规范与安全防护 - 支持版本管理和一键更新 @@ -711,17 +708,17 @@ docker compose up **排查**: ```bash # 测试网络连通性 -curl -I https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/code_review/SKILL.md +curl -I https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md # 如果超时,使用代理 export https_proxy=http://your-proxy:port -python3 scripts/skill_manager.py import-official-hub --agents zhongshu +python3 scripts/skill_manager.py import-official-hub --agents menxia ``` **常见原因**: - 中国大陆访问 GitHub raw 资源需要代理 - 网络超时(已增加到 30 秒 + 自动重试 3 次) -- 官方 Skills Hub 仓库维护中 +- 默认 skill 源无法访问,或自定义 Skills Hub 配置错误 diff --git a/docs/remote-skills-guide.md b/docs/remote-skills-guide.md index 49b54e0..112af1d 100644 --- a/docs/remote-skills-guide.md +++ b/docs/remote-skills-guide.md @@ -7,7 +7,7 @@ - **GitHub 仓库** (raw.githubusercontent.com) - **任何 HTTPS URL** (需返回有效的 skill 文件) - **本地文件路径** -- **内置仓库** (官方 skills 库) +- **默认 Skills 源** (经验证可访问的内置导入源) --- @@ -157,28 +157,32 @@ python3 scripts/skill_manager.py remove-remote \ --- -## 官方 Skills 库 +## 默认 Skills 源 -### OpenClaw Skills Hub +### MiniMax CLI Skill -> **官方 skills 库地址**: https://github.com/openclaw-ai/skills-hub +默认导入源包含经验证可访问的 MiniMax CLI skill。旧的 `openclaw-ai/skills-hub` 仓库当前不可用,因此不再作为默认官方源。 可用 skills 列表: | Skill 名称 | 描述 | 适用 Agent | 源 URL | |-----------|------|----------|--------| -| `code_review` | 代码审查(支持 Python/JS/Go) | 兵部/刑部 | https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/code_review/SKILL.md | -| `api_design` | API 设计审查 | 兵部/工部 | https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/api_design/SKILL.md | -| `security_audit` | 安全审计 | 刑部 | https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/security_audit/SKILL.md | -| `data_analysis` | 数据分析 | 户部 | https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/data_analysis/SKILL.md | -| `doc_generation` | 文档生成 | 礼部 | https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/doc_generation/SKILL.md | -| `test_framework` | 测试框架设计 | 工部/刑部 | https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/test_framework/SKILL.md | +| `mmx_cli` | MiniMax 多模态 CLI 技能 | 门下省/尚书省 | https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md | -**一键导入官方 skills** +如果你维护自己的 Skills Hub,可以使用以下方式指定 Hub base URL。指定后,`import-official-hub` 会按 `//SKILL.md` 解析 `code_review`、`api_design`、`security_audit`、`data_analysis`、`doc_generation`、`test_framework` 等传统 skill 名称。 + +```bash +export OPENCLAW_SKILLS_HUB_BASE=https://your-hub/raw-base + +# 或写入本地配置 +echo "https://your-hub/raw-base" > ~/.openclaw/skills-hub-url +``` + +**一键导入默认 skills** ```bash python3 scripts/skill_manager.py import-official-hub \ - --agents zhongshu,menxia,shangshu,bingbu,xingbu,libu + --agents menxia,shangshu ``` --- @@ -360,7 +364,7 @@ compatibleAgents: [bingbu, xingbu, menxia] 2. **大小限制**: 最多 10 MB 3. **超时保护**: 下载超过 30 秒自动中止 4. **路径遍历防护**: 检查解析后的 skill 名称,禁用 `../` 模式 -5. **checksum 验证**: 可选的 GPG 签名验证(仅官方库) +5. **checksum 验证**: 可选的 GPG 签名验证(适用于可信发布源) ### 隔离执行 @@ -397,7 +401,7 @@ A: 不支持(安全考虑)。可以: **Q: 如何创建自己的 skills 库?** -A: 参考 [OpenClaw Skills Hub](https://github.com/openclaw-ai/skills-hub) 的结构创建自己的仓库,然后: +A: 按 `/SKILL.md` 的结构创建自己的仓库,然后: ```bash git clone https://github.com/yourname/my-skills-hub.git @@ -406,7 +410,7 @@ cd my-skills-hub # 提交 & 推送到 GitHub ``` -然后通过 URL 或官方库导入功能添加即可。 +然后通过 URL 添加,或通过 `OPENCLAW_SKILLS_HUB_BASE` / `~/.openclaw/skills-hub-url` 配置为自定义 Hub 后导入。 --- @@ -442,7 +446,7 @@ python3 scripts/skill_manager.py check-updates --interval weekly ### 5. 贡献社区 -成熟的 skills 可向 [OpenClaw Skills Hub](https://github.com/openclaw-ai/skills-hub) 贡献。 +成熟的 skills 可以沉淀到你自己的公开 Skills Hub,并通过 `OPENCLAW_SKILLS_HUB_BASE` 分享给团队使用。 --- diff --git a/docs/remote-skills-quickstart.md b/docs/remote-skills-quickstart.md index 367aaa5..a9e2132 100644 --- a/docs/remote-skills-quickstart.md +++ b/docs/remote-skills-quickstart.md @@ -10,21 +10,21 @@ python3 dashboard/server.py # 输出: 三省六部看板启动 → http://127.0.0.1:7891 ``` -### 2. 添加官方 Skill(CLI) +### 2. 添加默认 Skill(CLI) ```bash -# 为中书省添加代码审查 skill +# 为门下省添加 MiniMax CLI skill python3 scripts/skill_manager.py add-remote \ - --agent zhongshu \ - --name code_review \ - --source https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/code_review/SKILL.md \ - --description "代码审查能力" + --agent menxia \ + --name mmx_cli \ + --source https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md \ + --description "MiniMax 多模态 CLI 技能" # 输出: # ⏳ 正在从 https://raw.githubusercontent.com/... 下载... -# ✅ 技能 code_review 已添加到 zhongshu -# 路径: /Users/xxx/.openclaw/workspace-zhongshu/skills/code_review/SKILL.md -# 大小: 2048 字节 +# ✅ 技能 mmx_cli 已添加到 menxia +# 路径: /Users/xxx/.openclaw/workspace-menxia/skills/mmx_cli/SKILL.md +# 大小: 14655 字节 ``` ### 3. 列出所有远程 Skills @@ -37,7 +37,7 @@ python3 scripts/skill_manager.py list-remote # # Agent | Skill 名称 | 描述 | 添加时间 # ------------|----------------------|--------------------------------|---------- -# zhongshu | code_review | 代码审查能力 | 2026-03-02 +# menxia | mmx_cli | MiniMax 多模态 CLI 技能 | 2026-03-02 ``` ### 4. 查看 API 响应 @@ -50,11 +50,11 @@ curl http://localhost:7891/api/remote-skills-list | jq . # "ok": true, # "remoteSkills": [ # { -# "skillName": "code_review", -# "agentId": "zhongshu", +# "skillName": "mmx_cli", +# "agentId": "menxia", # "sourceUrl": "https://raw.githubusercontent.com/...", -# "description": "代码审查能力", -# "localPath": "/Users/xxx/.openclaw/workspace-zhongshu/skills/code_review/SKILL.md", +# "description": "MiniMax 多模态 CLI 技能", +# "localPath": "/Users/xxx/.openclaw/workspace-menxia/skills/mmx_cli/SKILL.md", # "addedAt": "2026-03-02T14:30:00Z", # "lastUpdated": "2026-03-02T14:30:00Z", # "status": "valid" @@ -69,44 +69,47 @@ curl http://localhost:7891/api/remote-skills-list | jq . ## 常见操作 -### 一键导入官方库中的所有 skills +### 一键导入默认 skills ```bash python3 scripts/skill_manager.py import-official-hub \ - --agents zhongshu,menxia,shangshu,bingbu,xingbu + --agents menxia,shangshu ``` -这会自动为每个 agent 添加: -- **zhongshu**: code_review, api_design, doc_generation -- **menxia**: code_review, api_design, security_audit, data_analysis, doc_generation, test_framework -- **shangshu**: 同 menxia(协调者) -- **bingbu**: code_review, api_design, test_framework -- **xingbu**: code_review, security_audit, test_framework +这会为指定 agent 添加默认可用的 `mmx_cli` skill。旧的 `openclaw-ai/skills-hub` 仓库当前不可用,因此不再作为默认官方源。 + +如果你维护自己的 Skills Hub,可以通过环境变量或本地配置指定: + +```bash +export OPENCLAW_SKILLS_HUB_BASE=https://your-hub/raw-base +# 或 +echo "https://your-hub/raw-base" > ~/.openclaw/skills-hub-url +``` ### 更新某个 Skill 到最新版本 ```bash python3 scripts/skill_manager.py update-remote \ - --agent zhongshu \ - --name code_review + --agent menxia \ + --name mmx_cli # 输出: # ⏳ 正在从 https://raw.githubusercontent.com/... 下载... -# ✅ 技能 code_review 已添加到 zhongshu +# ✅ 技能 mmx_cli 已添加到 menxia # ✅ 技能已更新 -# 路径: /Users/xxx/.openclaw/workspace-zhongshu/skills/code_review/SKILL.md -# 大小: 2156 字节 +# 路径: /Users/xxx/.openclaw/workspace-menxia/skills/mmx_cli/SKILL.md +# 大小: 14655 字节 ``` ### 移除某个 Skill ```bash python3 scripts/skill_manager.py remove-remote \ - --agent zhongshu \ - --name code_review + --agent menxia \ + --name mmx_cli # 输出: -# ✅ 技能 code_review 已从 zhongshu 移除 +# ✅ 技能 mmx_cli 已从 menxia 移除 ``` --- @@ -119,10 +122,10 @@ python3 scripts/skill_manager.py remove-remote \ 2. 进入 🔧 **技能配置** 面板 3. 点击 **➕ 添加远程 Skill** 按钮 4. 填写表单: - - **Agent**: 从下拉列表选择(如 zhongshu) - - **Skill 名称**: 输入内部 ID 如 `code_review` - - **远程 URL**: 粘贴 GitHub URL 如 `https://raw.githubusercontent.com/openclaw-ai/skills-hub/main/code_review/SKILL.md` - - **中文描述**: 可选,如 `代码审查能力` + - **Agent**: 从下拉列表选择(如 menxia) + - **Skill 名称**: 输入内部 ID 如 `mmx_cli` + - **远程 URL**: 粘贴 GitHub URL 如 `https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md` + - **中文描述**: 可选,如 `MiniMax 多模态 CLI 技能` 5. 点击 **导入** 按钮 6. 等待 1-2 秒,看到 ✅ 成功提示 @@ -247,11 +250,11 @@ curl http://localhost:7891/api/remote-skills-list "ok": true, "remoteSkills": [ { - "skillName": "code_review", - "agentId": "zhongshu", + "skillName": "mmx_cli", + "agentId": "menxia", "sourceUrl": "https://raw.githubusercontent.com/...", - "description": "代码审查能力", - "localPath": "/Users/xxx/.openclaw/workspace-zhongshu/skills/code_review/SKILL.md", + "description": "MiniMax 多模态 CLI 技能", + "localPath": "/Users/xxx/.openclaw/workspace-menxia/skills/mmx_cli/SKILL.md", "addedAt": "2026-03-02T14:30:00Z", "lastUpdated": "2026-03-02T14:30:00Z", "status": "valid" @@ -333,4 +336,3 @@ ls -la ~/.openclaw/workspace-zhongshu/skills/ - 📚 [完整指南](remote-skills-guide.md) - 🏛️ [架构文档](task-dispatch-architecture.md) - 🤝 [项目贡献](../CONTRIBUTING.md) - diff --git a/scripts/skill_manager.py b/scripts/skill_manager.py index b220b62..2dc8249 100644 --- a/scripts/skill_manager.py +++ b/scripts/skill_manager.py @@ -14,7 +14,7 @@ Usage: python3 scripts/skill_manager.py remove-remote --agent zhongshu --name code_review - python3 scripts/skill_manager.py import-official-hub --agents zhongshu,menxia,shangshu + python3 scripts/skill_manager.py import-official-hub --agents menxia,shangshu """ import sys import json @@ -60,7 +60,7 @@ def _download_file(url: str, timeout: int = 30, retries: int = 3) -> str: if 'timed out' in str(last_error).lower() or '超时' in str(last_error): hint = '\n 💡 提示: 如果在中国大陆,请设置代理 export https_proxy=http://proxy:port' elif '404' in str(last_error): - hint = '\n 💡 提示: 官方 Skills Hub 可能尚未发布该 skill,请检查 URL 是否正确' + hint = '\n 💡 提示: 远程 skill URL 不存在,请检查 URL 或自定义 Skills Hub 配置' raise Exception(f'{last_error} (已重试 {retries} 次){hint}') @@ -218,34 +218,45 @@ def remove_remote(agent_id: str, name: str) -> bool: return False -OFFICIAL_SKILLS_HUB_BASE = 'https://raw.githubusercontent.com/openclaw-ai/skills-hub/main' -# 备用镜像(GitHub 国内访问不稳定时自动切换) -_FALLBACK_HUB_BASES = [ - 'https://ghproxy.com/https://raw.githubusercontent.com/openclaw-ai/skills-hub/main', - 'https://raw.gitmirror.com/openclaw-ai/skills-hub/main', -] - -# 支持通过环境变量覆盖 Hub 地址 +# 支持通过环境变量或本地配置指定自定义 Hub 地址 _HUB_BASE_ENV = 'OPENCLAW_SKILLS_HUB_BASE' -def _get_hub_url(skill_name): - """获取 skill 的 Hub URL,支持环境变量覆盖""" + +def _get_configured_hub_base(): + """Return a user-provided skills hub base URL, if configured.""" + env_base = os.environ.get(_HUB_BASE_ENV) + if env_base: + return env_base + hub_url_file = OCLAW_HOME / 'skills-hub-url' - base = hub_url_file.read_text().strip() if hub_url_file.exists() else None - base = base or os.environ.get(_HUB_BASE_ENV) or OFFICIAL_SKILLS_HUB_BASE + return hub_url_file.read_text().strip() if hub_url_file.exists() else None + + +def _get_hub_url(base, skill_name): + """获取 skill 的 Hub URL,支持环境变量/本地配置覆盖""" return f'{base.rstrip("/")}/{skill_name}/SKILL.md' OFFICIAL_SKILLS_HUB = { - 'code_review': _get_hub_url('code_review'), - 'api_design': _get_hub_url('api_design'), - 'security_audit': _get_hub_url('security_audit'), - 'data_analysis': _get_hub_url('data_analysis'), - 'doc_generation': _get_hub_url('doc_generation'), - 'test_framework': _get_hub_url('test_framework'), 'mmx_cli': 'https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md', } +_HUB_SKILL_NAMES = ( + 'code_review', + 'api_design', + 'security_audit', + 'data_analysis', + 'doc_generation', + 'test_framework', +) + +_configured_hub_base = _get_configured_hub_base() +if _configured_hub_base: + OFFICIAL_SKILLS_HUB.update({ + skill_name: _get_hub_url(_configured_hub_base, skill_name) + for skill_name in _HUB_SKILL_NAMES + }) + SKILL_AGENT_MAPPING = { 'code_review': ('bingbu', 'xingbu', 'menxia'), 'api_design': ('bingbu', 'gongbu', 'menxia'), @@ -258,14 +269,12 @@ SKILL_AGENT_MAPPING = { def import_official_hub(agent_ids: list) -> bool: - """从官方 Skills Hub 导入指定的 skills 到指定 agents。 + """从默认 Skills 源或自定义 Hub 导入 skills 到指定 agents。 如果未指定 agents,使用该 skill 的推荐 agents。 """ - if not agent_ids: - print('❌ 未指定 agent,使用推荐配置...\n') - for skill_name, recommended_agents in SKILL_AGENT_MAPPING.items(): - agent_ids.extend(recommended_agents) - agent_ids = list(set(agent_ids)) + requested_agents = list(agent_ids) + if not requested_agents: + print('ℹ️ 未指定 agent,使用推荐配置...\n') total = 0 success = 0 @@ -273,27 +282,14 @@ def import_official_hub(agent_ids: list) -> bool: for skill_name, url in OFFICIAL_SKILLS_HUB.items(): # 确定目标 agents - target_agents = agent_ids - if not agent_ids: - target_agents = SKILL_AGENT_MAPPING.get(skill_name, ['menxia']) + target_agents = requested_agents or list(SKILL_AGENT_MAPPING.get(skill_name, ['menxia'])) print(f'\n📥 正在导入 skill: {skill_name}') print(f' 目标 agents: {", ".join(target_agents)}') - # 尝试主 URL,失败则自动切换镜像 - effective_url = url for agent_id in target_agents: total += 1 - ok = add_remote(agent_id, skill_name, effective_url, f'官方 skill:{skill_name}') - if not ok and effective_url == url: - # 主 URL 失败,尝试镜像 - for fb_base in _FALLBACK_HUB_BASES: - fb_url = f'{fb_base.rstrip("/")}/{skill_name}/SKILL.md' - print(f' 🔄 尝试镜像: {fb_url}') - ok = add_remote(agent_id, skill_name, fb_url, f'官方 skill:{skill_name}') - if ok: - effective_url = fb_url # 后续 agent 也用这个镜像 - break + ok = add_remote(agent_id, skill_name, url, f'默认 skill:{skill_name}') if ok: success += 1 else: @@ -305,10 +301,10 @@ def import_official_hub(agent_ids: list) -> bool: for f in failed: print(f' - {f}') print(f'\n💡 排查建议:') - print(f' 1. 检查网络: curl -I {OFFICIAL_SKILLS_HUB_BASE}/code_review/SKILL.md') + print(f' 1. 检查网络: curl -I ') print(f' 2. 设置代理: export https_proxy=http://your-proxy:port') - print(f' 3. 使用镜像: export {_HUB_BASE_ENV}=https://ghproxy.com/{OFFICIAL_SKILLS_HUB_BASE}') - print(f' 4. 自定义源: echo "https://your-mirror/skills" > {OCLAW_HOME / "skills-hub-url"}') + print(f' 3. 自定义 Hub: export {_HUB_BASE_ENV}=https://your-hub/raw-base') + print(f' 4. 自定义源: echo "https://your-hub/raw-base" > {OCLAW_HOME / "skills-hub-url"}') print(f' 5. 单独重试: python3 scripts/skill_manager.py add-remote --agent --name --source ') return success == total @@ -339,7 +335,7 @@ def main(): remove_parser.add_argument('--name', required=True, help='Skill 名称') # import-official-hub - import_parser = subparsers.add_parser('import-official-hub', help='从官方库导入 skills') + import_parser = subparsers.add_parser('import-official-hub', help='从默认 Skills 源或自定义 Hub 导入 skills') import_parser.add_argument('--agents', default='', help='逗号分隔的 Agent IDs(可选)') # check-updates diff --git a/tests/test_skill_manager.py b/tests/test_skill_manager.py new file mode 100644 index 0000000..0b1a52c --- /dev/null +++ b/tests/test_skill_manager.py @@ -0,0 +1,92 @@ +import importlib.util +import os +import tempfile +import unittest +from pathlib import Path +from unittest import mock + + +def _load_skill_manager(openclaw_home, hub_base=None): + root = Path(__file__).resolve().parents[1] + script_path = root / "scripts" / "skill_manager.py" + + env = {"OPENCLAW_HOME": str(openclaw_home)} + if hub_base is not None: + env["OPENCLAW_SKILLS_HUB_BASE"] = hub_base + + spec = importlib.util.spec_from_file_location("skill_manager_under_test", script_path) + module = importlib.util.module_from_spec(spec) + with mock.patch.dict(os.environ, env, clear=False): + if hub_base is None: + os.environ.pop("OPENCLAW_SKILLS_HUB_BASE", None) + spec.loader.exec_module(module) + return module + + +class SkillManagerTests(unittest.TestCase): + def test_default_skills_do_not_use_removed_openclaw_hub(self): + with tempfile.TemporaryDirectory() as tmp: + skill_manager = _load_skill_manager(Path(tmp) / ".openclaw") + + self.assertIn("mmx_cli", skill_manager.OFFICIAL_SKILLS_HUB) + self.assertTrue( + all( + "openclaw-ai/skills-hub" not in url + for url in skill_manager.OFFICIAL_SKILLS_HUB.values() + ) + ) + + def test_custom_hub_base_restores_hub_skill_urls(self): + with tempfile.TemporaryDirectory() as tmp: + skill_manager = _load_skill_manager( + Path(tmp) / ".openclaw", + hub_base="https://example.com/openclaw-skills", + ) + + self.assertEqual( + skill_manager.OFFICIAL_SKILLS_HUB["code_review"], + "https://example.com/openclaw-skills/code_review/SKILL.md", + ) + self.assertEqual( + skill_manager.OFFICIAL_SKILLS_HUB["test_framework"], + "https://example.com/openclaw-skills/test_framework/SKILL.md", + ) + self.assertEqual( + skill_manager.OFFICIAL_SKILLS_HUB["mmx_cli"], + "https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md", + ) + + def test_import_official_hub_uses_per_skill_recommended_agents(self): + with tempfile.TemporaryDirectory() as tmp: + skill_manager = _load_skill_manager(Path(tmp) / ".openclaw") + + calls = [] + + def fake_add_remote(agent_id, skill_name, source_url, description=""): + calls.append((agent_id, skill_name, source_url, description)) + return True + + with mock.patch.object(skill_manager, "add_remote", fake_add_remote): + self.assertTrue(skill_manager.import_official_hub([])) + + self.assertEqual( + calls, + [ + ( + "menxia", + "mmx_cli", + "https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md", + "默认 skill:mmx_cli", + ), + ( + "shangshu", + "mmx_cli", + "https://raw.githubusercontent.com/MiniMax-AI/cli/main/skill/SKILL.md", + "默认 skill:mmx_cli", + ), + ], + ) + + +if __name__ == "__main__": + unittest.main()