[!IMPORTANT] When the user wants to search, discover, or install a Huawei Cloud (华为云) agent skill: 1. Search — use this skill ( ) to find the relevant Skill. 2. Install — install the matched Skill (see Step 3). 3. Execute — follow the installed Skill's instructions to fulfill the request. This skill handles skill discovery and installation only — it does not perform Huawei Cloud resource management/query tasks itself; those are handled by the skills it installs. Overview This skill enables users to efficiently search, discover, and install Huawei Cloud skills. Dependency : Python 3.6+ and net…

*|*'`'*|*';'*|*'|'*|*'&'*|*'\u003c'*|*'>'*)\n return 1 ;;\n esac\n return 0\n}\nif ! _validate_install_dir; then\n echo \"警告: SKILL_QUALITY_INSTALL_DIR 非法(需为安全的绝对路径), 跳过安装\" >&2\n exit 0\nfi\n\n# 固定版本 (维护者升级时同步更新 SHA256 白名单与发布包)。\nPINNED_VERSION=\"${PINNED_VERSION:-${SQCLI_PINNED_VERSION:-1.1.8}}\"\n\nusage() {\n cat \u003c\u003c'EOF' >&2\n用法: bash scripts/ensure_cli.sh [选项]\n -h, --help 显示本帮助\n -v, --version VERSION 指定固定版本 (默认: SQCLI_PINNED_VERSION 或 1.1.8)\n -a, --arch ARCH 指定目标架构 (x86_64|arm64, 默认: uname -m)\n -s, --sha256 HASH 指定 tar.gz 的 SHA256 校验和 (白名单外时显式提供)\nEOF\n}\n\n# 0. 解析命名参数 (getopt: 支持长选项; 未传参时保持默认行为)\nPARSED=$(getopt -o hv:a:s: --long help,version:,arch:,sha256: -n \"$(basename \"$0\")\" -- \"$@\") || { usage; exit 1; }\neval set -- \"$PARSED\"\n\nwhile true; do\n case \"$1\" in\n -h|--help) usage; exit 0 ;;\n -v|--version) PINNED_VERSION=\"$2\"; shift 2 ;;\n -a|--arch) ARCH_OVERRIDE=\"$2\"; shift 2 ;;\n -s|--sha256) SHA256_OVERRIDE=\"$2\"; shift 2 ;;\n --) shift; break ;;\n *) usage; exit 1 ;;\n esac\ndone\n\n# PATH 修复: 保证 skill-quality-cli 可通过裸命令调用。\n# 若能通过裸命令成功运行 version 则立即返回; 否则在 PATH 中第一个可写目录\n# 创建 shim(真实解析到 ~/.local/bin); 全部不可写时打印一次性 export 指引。\nensure_on_path() {\n if command -v skill-quality-cli >/dev/null 2>&1 \\\n && skill-quality-cli version >/dev/null 2>&1; then\n return 0\n fi\n local src=\"${INSTALL_DIR}/skill-quality-cli\"\n [ -x \"$src\" ] || return 0\n local dir target\n for dir in $(printf '%s' \"$PATH\" | tr ':' '\\n'); do\n [ -n \"$dir\" ] || continue\n [ -w \"$dir\" ] || continue\n target=\"$dir/skill-quality-cli\"\n # 用 shim 脚本而非 symlink: 原始 wrapper 依 dirname \"$0\" 定位\n # skill-quality-cli.bin / skill-quality-cli.d/, symlink 会使 $0\n # 指向链接目录而找不到 cli_entry.py, 报\"找不到 cli_entry.py\"。\n rm -f \"$target\" 2>/dev/null\n if printf '#!/bin/sh\\nexec \"%s\" \"$@\"\\n' \"$src\" > \"$target\" 2>/dev/null; then\n chmod +x \"$target\" 2>/dev/null\n echo \"提示: 已在 $target 创建 shim, 保证 skill-quality-cli 可被直接调用\" >&2\n return 0\n fi\n done\n echo \"提示: skill-quality-cli 已安装到 $src, 但不在 PATH 中。\" >&2\n echo \" 请执行: export PATH=\\\"${INSTALL_DIR}:\\$PATH\\\"\" >&2\n return 0\n}\n\n# 写入安装版本元数据(与 cli_entry.py 的 ~/.skill-quality/version.json 一致),\n# 否则 `skill-quality-cli version` 显示 (installed unknown), upgrade 报\"尚未安装\"。\nensure_version_meta() {\n local vf=\"$HOME/.skill-quality/version.json\"\n [ -f \"$vf\" ] && return 0\n mkdir -p \"$HOME/.skill-quality\"\n printf '{\"version\": \"%s\", \"installed_at\": %s, \"path\": \"%s\"}\\n' \\\n \"$PINNED_VERSION\" \"$(date +%s)\" \"${INSTALL_DIR}/skill-quality-cli\" > \"$vf\"\n}\n\n# 1. 已安装且可用 → 退出(PATH 可能不含 ~/.local/bin, 同时检查绝对路径)\nCLI_BIN=\"\"\nif command -v skill-quality-cli >/dev/null 2>&1; then\n CLI_BIN=\"skill-quality-cli\"\nelif [ -x \"${INSTALL_DIR}/skill-quality-cli\" ]; then\n CLI_BIN=\"${INSTALL_DIR}/skill-quality-cli\"\nfi\nif [ -n \"$CLI_BIN\" ] && \"$CLI_BIN\" version >/dev/null 2>&1; then\n ensure_version_meta\n ensure_on_path\n exit 0\nfi\n\n# 2. SHA256 白名单(可信发布渠道 = OBS 官方桶 + 本文件声明的哈希)。\n# VERSION 升级时, 由维护者同步更新 PINNED_VERSION 与对应架构的 SHA256,\n# 并发布到可信渠道, 禁止绕过校验安装。\n# 官方发布通道当前仅提供 linux-arm64 构建 (OBS 桶中无 x86_64 包 → 403)。\n# x86_64 用户可通过 --sha256 显式提供可信校验和后自行托管安装包走本脚本安装。\nPINNED_SHA256_ARM64=\"1a73773831c0f52542f5591cd9e5126b0c160b8dd36b67f9f833edb0c06a03d5\"\n\nARCH=\"${ARCH_OVERRIDE:-$(uname -m)}\"\ncase \"$ARCH\" in\n x86_64|amd64)\n LINUX_ARCH=\"x86_64\"\n if [ -n \"${SHA256_OVERRIDE:-}\" ]; then\n EXPECTED_SHA256=\"$SHA256_OVERRIDE\"\n elif [ -n \"${SQCLI_SHA256_X86_64:-}\" ]; then\n EXPECTED_SHA256=\"$SQCLI_SHA256_X86_64\"\n else\n echo \"警告: skill-quality-cli 官方发布通道当前仅提供 linux-arm64 构建\" >&2\n echo \" x86_64 平台暂无法自动安装; 如已有可信安装包与校验和,\" >&2\n echo \" 请使用 --sha256 \u003cHASH> 显式提供后重试\" >&2\n exit 0\n fi\n ;;\n aarch64|arm64)\n LINUX_ARCH=\"arm64\"\n EXPECTED_SHA256=\"${SHA256_OVERRIDE:-${SQCLI_SHA256_ARM64:-$PINNED_SHA256_ARM64}}\"\n ;;\n *)\n echo \"警告: 不支持的架构 ${ARCH}, 跳过安装\" >&2\n exit 0\n ;;\nesac\n\nTMPDIR=$(mktemp -d)\ntrap 'rm -rf \"$TMPDIR\"' EXIT\n\nPKG_URL=\"${OBS_BASE}/v${PINNED_VERSION}/skill-quality-cli-v${PINNED_VERSION}-linux-${LINUX_ARCH}.tar.gz\"\nif ! curl -fsSL --max-time 30 --connect-timeout 5 -o \"${TMPDIR}/sqc.tar.gz\" \"$PKG_URL\"; then\n echo \"警告: 下载 skill-quality-cli 失败(${LINUX_ARCH}), 跳过安装\" >&2\n exit 0\nfi\n\n# 3. SHA256 校验(不通过 → 拒装, 防供应链投毒)\nGOT_SHA256=$(sha256sum \"${TMPDIR}/sqc.tar.gz\" | awk '{print $1}')\nif [ \"$GOT_SHA256\" != \"$EXPECTED_SHA256\" ]; then\n echo \"警告: skill-quality-cli 校验和不匹配(期望 ${EXPECTED_SHA256}, 实际 ${GOT_SHA256}), 拒绝安装\" >&2\n exit 0\nfi\n\ntar xzf \"${TMPDIR}/sqc.tar.gz\" -C \"${TMPDIR}\" --no-same-owner\n\nmkdir -p \"${INSTALL_DIR}/skill-quality-cli.d\"\n\n# 关键文件(主程序/.bin/.d 模块)必须全部复制成功并赋可执行权限; 任一失败即\n# 清理半成品并警告退出(不阻塞业务), 避免留下残缺 CLI 却仍提示\"已就绪\"。\nif ! cp \"${TMPDIR}/skill-quality-cli\" \"${INSTALL_DIR}/\" \\\n || ! cp \"${TMPDIR}/skill-quality-cli.bin\" \"${INSTALL_DIR}/\" \\\n || ! cp \"${TMPDIR}/skill-quality-cli.d/cli_entry.py\" \"${INSTALL_DIR}/skill-quality-cli.d/\" \\\n || ! cp \"${TMPDIR}/skill-quality-cli.d/cli_reporting.py\" \"${INSTALL_DIR}/skill-quality-cli.d/\" \\\n || ! chmod +x \"${INSTALL_DIR}/skill-quality-cli\" \"${INSTALL_DIR}/skill-quality-cli.bin\"; then\n echo \"警告: 安装 skill-quality-cli 失败(复制或赋权出错), 跳过安装\" >&2\n # 精确回滚本次安装落盘的固定文件(白名单), 避免递归强制删除的滥用风险\n rollback_bin=\"${INSTALL_DIR}/skill-quality-cli\"\n rollback_raw=\"${INSTALL_DIR}/skill-quality-cli.bin\"\n rollback_entry=\"${INSTALL_DIR}/skill-quality-cli.d/cli_entry.py\"\n rollback_report=\"${INSTALL_DIR}/skill-quality-cli.d/cli_reporting.py\"\n rm -f \"$rollback_bin\" \"$rollback_raw\" \"$rollback_entry\" \"$rollback_report\"\n rmdir \"${INSTALL_DIR}/skill-quality-cli.d\" 2>/dev/null || true\n exit 0\nfi\n\necho \"skill-quality-cli v${PINNED_VERSION} 已就绪\"\nensure_version_meta\nensure_on_path\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":8713,"content_sha256":"3f080e618c23dd424de03df4c6fcb821abd368387e8769b33e68e2cdc7d88564"},{"filename":"scripts/install_cli.sh","content":"#!/bin/bash\n# install_cli.sh — 手动安装 skill-quality-cli(不含自动升级)。\n# 合规: 本脚本由用户/agent 主动执行(见 SKILL.md Step 0 / references 指引);\n# 业务脚本不调用本文件。\n# 安全(供应链): 固定版本 + SHA256 白名单校验, 未命中白名单一律拒绝安装。\n# 用法:\n# bash scripts/install_cli.sh [--version V] [--arch ARCH] [--sha256 HASH] [--help]\nset -euo pipefail\n\nOBS_BASE=\"https://obs-skills-repository.obs.cn-north-4.myhuaweicloud.com/skill-quality-cli\"\n\nusage() {\n cat \u003c\u003c'EOF' >&2\n用法: bash scripts/install_cli.sh [选项]\n -h, --help 显示本帮助\n -v, --version VERSION 指定固定版本 (默认: SQCLI_PINNED_VERSION 或 1.1.8)\n -a, --arch ARCH 指定目标架构 (x86_64|arm64, 默认: uname -m)\n -s, --sha256 HASH 指定 tar.gz 的 SHA256 校验和 (白名单外时显式提供)\nEOF\n}\n\n# 解析命名参数 (getopt: 支持长选项; 未传参时保持默认行为)\nPARSED=$(getopt -o hv:a:s: --long help,version:,arch:,sha256: -n \"$(basename \"$0\")\" -- \"$@\") || { usage; exit 1; }\neval set -- \"$PARSED\"\n\nwhile true; do\n case \"$1\" in\n -h|--help) usage; exit 0 ;;\n -v|--version) PINNED_VERSION=\"$2\"; shift 2 ;;\n -a|--arch) ARCH_OVERRIDE=\"$2\"; shift 2 ;;\n -s|--sha256) SHA256_OVERRIDE=\"$2\"; shift 2 ;;\n --) shift; break ;;\n *) usage; exit 1 ;;\n esac\ndone\n\n# 固定版本 + SHA256 白名单(可信发布渠道 = OBS 官方桶 + 本文件声明的哈希)。\n# VERSION 升级时, 由维护者同步更新 PINNED_VERSION 与对应架构的 SHA256。\nPINNED_VERSION=\"${PINNED_VERSION:-${SQCLI_PINNED_VERSION:-1.1.8}}\"\n# 官方发布通道当前仅提供 linux-arm64 构建 (OBS 桶中无 x86_64 包 → 403)。\n# x86_64 用户可通过 --sha256 显式提供可信校验和后自行托管安装包走本脚本安装。\nPINNED_SHA256_ARM64=\"1a73773831c0f52542f5591cd9e5126b0c160b8dd36b67f9f833edb0c06a03d5\"\n\nARCH=\"${ARCH_OVERRIDE:-$(uname -m)}\"\ncase \"$ARCH\" in\n x86_64|amd64)\n LINUX_ARCH=\"x86_64\"\n if [ -n \"${SHA256_OVERRIDE:-}\" ]; then\n EXPECTED_SHA256=\"$SHA256_OVERRIDE\"\n elif [ -n \"${SQCLI_SHA256_X86_64:-}\" ]; then\n EXPECTED_SHA256=\"$SQCLI_SHA256_X86_64\"\n else\n echo \"错误: skill-quality-cli 官方发布通道当前仅提供 linux-arm64 构建\" >&2\n echo \" x86_64 平台暂无法自动安装; 如已有可信安装包与校验和,\" >&2\n echo \" 请使用 --sha256 \u003cHASH> 显式提供后重试\" >&2\n exit 1\n fi\n ;;\n aarch64|arm64)\n LINUX_ARCH=\"arm64\"\n EXPECTED_SHA256=\"${SHA256_OVERRIDE:-${SQCLI_SHA256_ARM64:-$PINNED_SHA256_ARM64}}\"\n ;;\n *)\n echo \"错误: 不支持的架构 ${ARCH}\" >&2\n exit 1\n ;;\nesac\n\nTMPDIR=$(mktemp -d)\ntrap 'rm -rf \"$TMPDIR\"' EXIT\n\nPKG_URL=\"${OBS_BASE}/v${PINNED_VERSION}/skill-quality-cli-v${PINNED_VERSION}-linux-${LINUX_ARCH}.tar.gz\"\nif ! curl -fsSL --max-time 30 --connect-timeout 5 -o \"${TMPDIR}/sqc.tar.gz\" \"$PKG_URL\"; then\n echo \"错误: 下载 skill-quality-cli 失败(${LINUX_ARCH}), 请检查网络或稍后重试\" >&2\n exit 1\nfi\n\n# SHA256 校验(不通过 → 拒装, 防供应链投毒)\nGOT_SHA256=$(sha256sum \"${TMPDIR}/sqc.tar.gz\" | awk '{print $1}')\nif [ \"$GOT_SHA256\" != \"$EXPECTED_SHA256\" ]; then\n echo \"错误: skill-quality-cli 校验和不匹配(期望 ${EXPECTED_SHA256}, 实际 ${GOT_SHA256}), 可能被篡改, 已拒绝安装\" >&2\n exit 1\nfi\n\ntar xzf \"${TMPDIR}/sqc.tar.gz\" -C \"${TMPDIR}\" --no-same-owner\n\nmkdir -p ~/.local/bin/skill-quality-cli.d\ncp \"${TMPDIR}/skill-quality-cli\" ~/.local/bin/ || true\ncp \"${TMPDIR}/skill-quality-cli.bin\" ~/.local/bin/ || true\ncp \"${TMPDIR}/skill-quality-cli.d/cli_entry.py\" ~/.local/bin/skill-quality-cli.d/ || true\ncp \"${TMPDIR}/skill-quality-cli.d/cli_reporting.py\" ~/.local/bin/skill-quality-cli.d/ || true\nchmod +x ~/.local/bin/skill-quality-cli ~/.local/bin/skill-quality-cli.bin || true\n\necho \"skill-quality-cli v${PINNED_VERSION} 安装完成(手动触发)\"","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4107,"content_sha256":"6e559e83d1bbb2526f12b52402382e2d8a9554b89015924c04bd940aabd21e7a"},{"filename":"scripts/search-skills.py","content":"#!/usr/bin/env python3\n\"\"\"Search Huawei Cloud agent skills by keyword/category.\n\nOnly the top-3 (score-descending) search results are reported to the\ninstall-count API (exposure impression, fire-and-forget, non-blocking).\nSet SKILL_QUALITY_REPORT=0 to disable this reporting.\nThis script has no other telemetry and no external CLI dependency.\n\nIndex loading uses dual-source fallback: GitCode API v5 (primary) → Gitee raw\n(backup). On GitCode 429 (Too Many Requests) or network failure, the script\nautomatically switches to the Gitee raw source, which has an independent IP\nand WAF, unaffected by GitCode rate limits. A local cache (TTL 1h) avoids\nrepeated network calls within the same session.\n\"\"\"\n\nimport argparse\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport sys\nimport threading\nimport time\nfrom urllib.request import urlopen, Request\nfrom urllib.error import URLError, HTTPError\n\n\n# ---------------------------------------------------------------------------\n# Index source configuration — dual-source with automatic failover\n# ---------------------------------------------------------------------------\n\n# 索引分支可通过环境变量注入(默认指向当前生产使用的 test-for-index 分支,\n# 由索引仓库维护方发布正式数据后切换),避免把分支名硬编码散落在各处。\nINDEX_BRANCH = os.environ.get(\"FIND_SKILLS_INDEX_BRANCH\", \"test-for-index\")\n\n# GitCode API v5 (primary) — returns base64-encoded JSON via contents API\nGITCODE_BASE = \"https://gitcode.com/api/v5/repos/developer-skill/skills-group-contribution/contents/skills-index\"\n\n# Gitee raw (backup) — independent IP/WAF, unaffected by GitCode rate limits\nGITEE_BASE = \"https://gitee.com/csimon666/skills-group-contribution/raw/{}/skills-index\".format(INDEX_BRANCH)\n\nSOURCES = [\n {\n \"name\": \"gitcode\",\n \"is_api\": True, # GitCode contents API returns base64-encoded content\n },\n {\n \"name\": \"gitee\",\n \"is_api\": False, # Gitee raw returns plain JSON\n },\n]\n\nHTTP_TIMEOUT = 15\nMAX_RETRIES = 3\n\n# Local cache — avoids repeated network calls within TTL window\nCACHE_DIR = os.path.expanduser(\"~/.cache/huawei-cloud-find-skills\")\nCACHE_TTL = int(os.environ.get(\"FIND_SKILLS_CACHE_TTL\", \"3600\")) # default 1h\n\n# Install-count API (same endpoint as Step 3 install counting). Used to report\n# every search-result skill name as an exposure impression - fire-and-forget,\n# never blocks or fails the search.\nINSTALL_COUNT_URL = \"https://devdata2.huaweicloud.com/rest/developer/fwdo/rest/developer/servlet/hdskillservice/v1/obs/findcounts/increment\"\nINSTALL_COUNT_TIMEOUT = HTTP_TIMEOUT\n\nGENERIC_KEYWORDS = {\n \"华为云\", \"huawei\", \"huawei cloud\", \"云\", \"cloud\",\n \"技能\", \"skill\", \"skills\", \"所有\", \"all\", \"全部\",\n \"有什么\", \"有哪些\", \"相关\", \"列表\", \"list\",\n \"查找\", \"搜索\", \"发现\", \"浏览\", \"find\", \"search\",\n \"discover\", \"browse\", \"show\", \"explore\",\n \"agent\", \"市场\", \"market\", \"类目\", \"category\",\n \"安装\", \"install\",\n}\n\n\n# ---------------------------------------------------------------------------\n# Network fetch with 429 retry + exponential backoff\n# ---------------------------------------------------------------------------\n\ndef _fetch_from_network(url, label, is_api):\n \"\"\"Fetch JSON from a single URL with 429 retry.\n\n Returns (parsed_data, retry_after_remaining) or raises on non-429 errors.\n On exhausted 429 retries, returns (None, 0) so caller can fall back.\n \"\"\"\n for attempt in range(MAX_RETRIES):\n try:\n req = Request(url, headers={\"User-Agent\": \"huawei-cloud-find-skills/1.0\"})\n with urlopen(req, timeout=HTTP_TIMEOUT) as resp:\n raw = resp.read().decode(\"utf-8\")\n parsed = json.loads(raw)\n if is_api and isinstance(parsed, dict) and parsed.get(\"encoding\") == \"base64\" and \"content\" in parsed:\n decoded = base64.b64decode(parsed[\"content\"]).decode(\"utf-8\")\n return json.loads(decoded), 0\n return parsed, 0\n except HTTPError as e:\n if e.code == 429:\n # Respect Retry-After header if present\n retry_after = e.headers.get(\"Retry-After\")\n if retry_after:\n try:\n wait = min(int(retry_after), 10)\n except ValueError:\n wait = 2 ** attempt\n else:\n wait = 2 ** attempt\n if attempt \u003c MAX_RETRIES - 1:\n time.sleep(wait)\n continue\n # Exhausted retries for this source — return None to trigger fallback\n return None, 0\n raise RuntimeError(f\"N02: Failed to fetch {label}: {e}\") from e\n except (URLError, OSError, ValueError, UnicodeDecodeError, binascii.Error) as e:\n raise RuntimeError(f\"N02: Failed to fetch {label}: {e}\") from e\n return None, 0\n\n\n# ---------------------------------------------------------------------------\n# Local cache\n# ---------------------------------------------------------------------------\n\ndef _cache_path(key):\n h = hashlib.sha256(key.encode(\"utf-8\")).hexdigest()[:16]\n return os.path.join(CACHE_DIR, f\"{h}.json\")\n\n\ndef _cache_get(key):\n path = _cache_path(key)\n if not os.path.exists(path):\n return None\n age = time.time() - os.path.getmtime(path)\n if age > CACHE_TTL:\n return None\n try:\n with open(path, \"r\", encoding=\"utf-8\") as f:\n return json.load(f)\n except (OSError, ValueError):\n return None\n\n\ndef _cache_put(key, data):\n try:\n os.makedirs(CACHE_DIR, exist_ok=True)\n with open(_cache_path(key), \"w\", encoding=\"utf-8\") as f:\n json.dump(data, f)\n except (OSError, ValueError):\n pass # cache write failure is non-fatal\n\n\n# ---------------------------------------------------------------------------\n# Dual-source loader: GitCode → GitHub → cache\n# ---------------------------------------------------------------------------\n\ndef load_json_dual_source(filename, label):\n \"\"\"Load a JSON index file with dual-source fallback and local cache.\n\n Tries each source in order (GitCode first, GitHub second). On 429 or\n network error, falls back to the next source. Results are cached locally.\n Returns (data, source_name) or raises if all sources fail.\n \"\"\"\n cache_key = f\"{INDEX_BRANCH}:{filename}\"\n\n # 1. Try cache\n cached = _cache_get(cache_key)\n if cached is not None:\n return cached, \"cache\"\n\n # 2. Try each network source\n errors = []\n for source in SOURCES:\n sname = source[\"name\"]\n if sname == \"gitcode\":\n url = f\"{GITCODE_BASE}/{filename}?ref={INDEX_BRANCH}\"\n else:\n url = f\"{GITEE_BASE}/{filename}\"\n\n try:\n data, _ = _fetch_from_network(url, f\"{label} ({sname})\", source[\"is_api\"])\n if data is not None:\n _cache_put(cache_key, data)\n return data, sname\n # 429 exhausted — try next source\n errors.append(f\"{sname}: 429 after retries\")\n except RuntimeError as e:\n errors.append(f\"{sname}: {e}\")\n continue # try next source\n\n raise RuntimeError(f\"N02: Failed to fetch {label} from all sources ({', '.join(errors)})\")\n\n\ndef load_index():\n data, _ = load_json_dual_source(\"index.json\", \"index.json\")\n return data\n\n\ndef load_cn_en_map():\n data, _ = load_json_dual_source(\"cn-en-map.json\", \"cn-en-map.json\")\n return data\n\n\n# ---------------------------------------------------------------------------\n# Search logic (unchanged)\n# ---------------------------------------------------------------------------\n\ndef is_generic(kw):\n k = kw.lower().strip()\n return k in GENERIC_KEYWORDS or any(g in k for g in (\"华为云\", \"huawei\"))\n\n\n# 上游 cn-en-map.json 部分 key 是脏数据(如 's: 弹性云服务器'、'or \"CCE 告警\".',\n# 'cloud operations (中文触发词:L实例执行脚本)'), 反向映射时仅使用干净的 CN key,\n# 避免 expanded/matched 输出混入乱码(ISSUE-002)。全角冒号/反斜杠同样视为脏标记。\nDIRTY_KEY_CHARS = (\":\", \":\", '\"', \"'\", \"{\", \"}\", \"[\", \"]\", \"\\\\\")\nMAX_MAP_KEY_LEN = 40\n\n\ndef is_clean_map_key(k):\n if not isinstance(k, str):\n return False\n if k != k.strip() or len(k) > MAX_MAP_KEY_LEN:\n return False\n return not any(ch in k for ch in DIRTY_KEY_CHARS)\n\n\ndef expand_keywords(raw_keyword, cn_en_map):\n if not raw_keyword:\n return [], []\n parts = [p for p in raw_keyword.replace(\",\", \" \").replace(\";\", \" \").split() if p]\n expanded = list(parts)\n for p in parts:\n p_lower = p.lower()\n if p in cn_en_map and is_clean_map_key(p):\n expanded.append(cn_en_map[p])\n for cn, en in cn_en_map.items():\n if en == p_lower and is_clean_map_key(cn):\n expanded.append(cn)\n all_kws = sorted(set(expanded))\n specific = [kw for kw in all_kws if not is_generic(kw)]\n generic = [kw for kw in all_kws if is_generic(kw)]\n return specific, generic\n\n\ndef extract_skill_fields(skill):\n \"\"\"批量提取 skill 字段(一次性字典访问, 后续循环内只做本地匹配)。\"\"\"\n name = skill.get(\"name\", \"\")\n category = skill.get(\"category\", \"\")\n service = skill.get(\"service\", \"\")\n description = skill.get(\"description\", \"\")\n raw_triggers = skill.get(\"triggers\") or []\n triggers = [t for t in raw_triggers if t]\n return {\n \"name\": name,\n \"category\": category,\n \"service\": service,\n \"description\": description,\n \"triggers\": triggers,\n }\n\n\ndef score_skill(fields, specific_kws, generic_kws):\n if not specific_kws and not generic_kws:\n return 1, []\n name_l = fields[\"name\"].lower()\n desc_l = fields[\"description\"].lower()\n service_l = fields[\"service\"].lower()\n trig_l = [t.lower() for t in fields[\"triggers\"]]\n total = 0\n matched = []\n for kw in specific_kws:\n k = kw.lower()\n s = 0\n if k in name_l:\n s += 10\n if any(k in t for t in trig_l):\n s += 8\n if k in desc_l:\n s += 5\n if k in service_l:\n s += 3\n if s > 0:\n total += s\n matched.append(kw)\n for kw in generic_kws:\n k = kw.lower()\n s = 0\n if k in name_l:\n s += 10\n if any(k in t for t in trig_l):\n s += 4\n if k in desc_l:\n s += 2\n if k in service_l:\n s += 1\n if s > 0:\n total += s\n matched.append(kw)\n if not specific_kws and total == 0:\n total = 1\n if len(desc_l) > 20:\n total += 1\n if trig_l:\n total += 1\n return total, matched\n\n\ndef truncate(desc, limit=150):\n if desc and len(desc) > limit:\n return desc[:limit] + \"...\"\n return desc\n\n\n# ---------------------------------------------------------------------------\n# Telemetry: install-count impression (unchanged from master)\n# ---------------------------------------------------------------------------\n\ndef _post_impression(skill_id):\n \"\"\"Single-instance POST to the install-count API (best-effort).\"\"\"\n body = json.dumps({\"skill_id\": skill_id}).encode(\"utf-8\")\n req = Request(\n INSTALL_COUNT_URL,\n data=body,\n headers={\n \"Content-Type\": \"application/json\",\n \"Accept\": \"application/json, text/plain, */*\",\n \"Origin\": \"https://skills.huaweicloud.com\",\n \"Referer\": \"https://skills.huaweicloud.com/\",\n \"User-Agent\": \"huawei-cloud-find-skills/1.0\",\n },\n )\n try:\n with urlopen(req, timeout=INSTALL_COUNT_TIMEOUT) as resp:\n resp.read()\n return True\n except (URLError, HTTPError, OSError, ValueError):\n return False\n\n\ndef report_search_results_impressions(results):\n \"\"\"Report only the top-3 search results via the install-count API.\n\n Only the first three results (already sorted by score descending) are reported —\n each skill_id (`skills/\u003ccategory>/\u003cservice>/\u003cname>`) is POSTed to the same\n endpoint Step 3 uses for install counting, so search-result exposures are\n counted too. Fire-and-forget: reporting runs in a daemon background thread and\n returns immediately, so it never blocks or delays the search output.\n \"\"\"\n if not results:\n return 0\n if os.environ.get(\"SKILL_QUALITY_REPORT\") == \"0\":\n return 0\n reported = {\"n\": 0}\n\n def _worker():\n for r in results[:3]:\n if _post_impression(\"skills/{}/{}/{}\".format(r[\"category\"], r[\"service\"], r[\"name\"])):\n reported[\"n\"] += 1\n\n threading.Thread(target=_worker, daemon=True).start()\n return reported[\"n\"]\n\n\n# ---------------------------------------------------------------------------\n# Main\n# ---------------------------------------------------------------------------\n\ndef main():\n parser = argparse.ArgumentParser(description=\"Search Huawei Cloud skills\")\n parser.add_argument(\"-k\", \"--keyword\", default=\"\", help=\"Search keyword(s), space/comma/semicolon separated\")\n parser.add_argument(\"-c\", \"--category\", default=\"\", help=\"Filter by category\")\n args = parser.parse_args()\n\n if not args.keyword and not args.category:\n print(\"Usage: python search-skills.py -k \u003ckeyword> [-c \u003ccategory>]\")\n print(\"ERROR: missing keyword and category (U02)\", file=sys.stderr)\n return 1\n\n idx, idx_source = load_json_dual_source(\"index.json\", \"index.json\")\n raw_skills = idx.get(\"skills\", [])\n skills = [extract_skill_fields(s) for s in raw_skills]\n\n if args.keyword:\n cn_en_map, map_source = load_json_dual_source(\"cn-en-map.json\", \"cn-en-map.json\")\n specific_kws, generic_kws = expand_keywords(args.keyword, cn_en_map)\n else:\n specific_kws, generic_kws = [], []\n map_source = \"n/a\"\n has_specific = bool(specific_kws)\n\n results = []\n\n for skill in skills:\n category = skill[\"category\"]\n if args.category and category != args.category:\n continue\n sc, matched = score_skill(skill, specific_kws, generic_kws)\n if has_specific and sc == 0:\n continue\n desc = truncate(skill[\"description\"])\n trig_preview = skill[\"triggers\"][:5]\n results.append({\n \"score\": sc,\n \"name\": skill[\"name\"],\n \"category\": category,\n \"service\": skill[\"service\"],\n \"description\": desc,\n \"triggers\": trig_preview,\n \"matched\": matched,\n })\n\n results.sort(key=lambda r: r[\"score\"], reverse=True)\n\n impressions = report_search_results_impressions(results)\n\n if not results:\n print(f\"No results for keyword='{args.keyword}' category='{args.category}'\")\n print()\n print(\"Fallback suggestions:\")\n print(\" 1. Try broader or alternative keywords\")\n print(\" 2. Remove category filter\")\n print(\" 3. Switch CN\u003c->EN (e.g., 'obs' \u003c-> 'object storage')\")\n print(\" 4. List all: python search-skills.py -c 'computing'\")\n return 0\n\n all_kws = specific_kws + generic_kws\n print(f\"Found {len(results)} skill(s) for keyword='{args.keyword}' category='{args.category}':\")\n if len(all_kws) > 1 or (len(all_kws) == 1 and all_kws[0] != args.keyword):\n print(f\" (expanded: {', '.join(all_kws)})\")\n print()\n for r in results:\n match_info = f\" matched: {','.join(r['matched'])}\" if r[\"matched\"] else \"\"\n print(f\" [{r['score']}pts] {r['name']} ({r['category']}/{r['service']}){match_info}\")\n print(f\" {r['description']}\")\n if r[\"triggers\"]:\n print(f\" triggers: {', '.join(r['triggers'])}\")\n print()\n\n print(f\" [data source: index: {idx_source}, map: {map_source}]\")\n return 0\n\n\nif __name__ == \"__main__\":\n try:\n rc = main()\n except Exception as e: # noqa: BLE001\n print(f\"ERROR: {e}\", file=sys.stderr)\n sys.exit(1)\n sys.exit(rc)\n","content_type":"text/x-python; charset=utf-8","language":"python","size":16192,"content_sha256":"b94a2f7f37a9e938dc7821db8adaf23c6f75c82ac8d1d279b339f4700c1fae5a"}],"content_json":{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"[!IMPORTANT] ","type":"text"},{"text":"When the user wants to search, discover, or install a Huawei Cloud (华为云) agent skill:","type":"text","marks":[{"type":"strong"}]}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Search","type":"text","marks":[{"type":"strong"}]},{"text":" — use this skill (","type":"text"},{"text":"huawei-cloud-find-skills","type":"text","marks":[{"type":"code_inline"}]},{"text":") to find the relevant Skill.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Install","type":"text","marks":[{"type":"strong"}]},{"text":" — install the matched Skill (see ","type":"text"},{"text":"Step 3","type":"text","marks":[{"type":"link","attrs":{"href":"#step-3-install-skill","title":null}}]},{"text":").","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Execute","type":"text","marks":[{"type":"strong"}]},{"text":" — follow the installed Skill's instructions to fulfill the request.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"This skill handles ","type":"text"},{"text":"skill discovery and installation only","type":"text","marks":[{"type":"strong"}]},{"text":" — it does not perform Huawei Cloud resource management/query tasks itself; those are handled by the skills it installs.","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill enables users to efficiently search, discover, and install Huawei Cloud skills.","type":"text"}]},{"type":"paragraph","content":[{"text":"Dependency","type":"text","marks":[{"type":"strong"}]},{"text":": Python 3.6+ and network access to ","type":"text"},{"text":"gitcode.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" (API v5 for the skill index), ","type":"text"},{"text":"gitee.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" (backup index), and ","type":"text"},{"text":"github.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"raw.githubusercontent.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" (for skill details). Quality telemetry is collected automatically via ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" (installed by ","type":"text"},{"text":"scripts/ensure_cli.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" if absent) — no other CLI or credential is required.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Privacy & Telemetry","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"透明披露","type":"text","marks":[{"type":"strong"}]},{"text":": 本 skill 在搜索与安装过程中会产生以下对外遥测上报。均为","type":"text"},{"text":"匿名聚合数据","type":"text","marks":[{"type":"strong"}]},{"text":"(技能名/类目/服务等元信息), ","type":"text"},{"text":"不包含","type":"text","marks":[{"type":"strong"}]},{"text":"用户输入内容、凭证、云资源数据或个人身份信息。","type":"text"},{"text":"质量上报默认开启","type":"text","marks":[{"type":"strong"}]},{"text":"(opt-out): 如需关闭, 设置环境变量 ","type":"text"},{"text":"export SKILL_QUALITY_REPORT=0","type":"text","marks":[{"type":"code_inline"}]},{"text":" 即可整体关闭。","type":"text"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"上报内容","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"触发点","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"目的地","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"是否含敏感数据","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"搜索 top-3 曝光计数","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/search-skills.py","type":"text","marks":[{"type":"code_inline"}]},{"text":"(每次搜索)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"devdata2.huaweicloud.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" install-count API","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"否(仅技能名/类目/服务)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"安装计数","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Step 3.1 ","type":"text"},{"text":"curl","type":"text","marks":[{"type":"code_inline"}]},{"text":"(每次安装前)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"devdata2.huaweicloud.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" install-count API","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"否(仅 ","type":"text"},{"text":"skill_id","type":"text","marks":[{"type":"code_inline"}]},{"text":",即 ","type":"text"},{"text":"skills/\u003ccategory>/\u003cservice>/\u003cname>","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"质量上报","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"skill-quality-cli run","type":"text","marks":[{"type":"code_inline"}]},{"text":" 包装执行","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"quality 上报 APIG(测试环境)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"否(执行状态/耗时/技能名)","type":"text"}]}]}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"默认开启 / 关闭方式","type":"text","marks":[{"type":"strong"}]},{"text":": 以上三类上报","type":"text"},{"text":"默认开启","type":"text","marks":[{"type":"strong"}]},{"text":"(未设置该环境变量即会上报);如需关闭, 执行 ","type":"text"},{"text":"export SKILL_QUALITY_REPORT=0","type":"text","marks":[{"type":"code_inline"}]},{"text":"(","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" 与 ","type":"text"},{"text":"search-skills.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" 均遵循该开关)。","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"上报均为 ","type":"text"},{"text":"fire-and-forget","type":"text","marks":[{"type":"strong"}]},{"text":",永不阻塞搜索/安装主流程。","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Scenario Description","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill enables users to:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Search Skills","type":"text","marks":[{"type":"strong"}]},{"text":": Find skills by keyword, category, or both (matched against name, description, and triggers)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Browse Categories","type":"text","marks":[{"type":"strong"}]},{"text":": Explore available skill categories","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"View Skill Details","type":"text","marks":[{"type":"strong"}]},{"text":": Fetch full SKILL.md content from GitHub for specific skills","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Install Skills","type":"text","marks":[{"type":"strong"}]},{"text":": Guide users through skill installation via ","type":"text"},{"text":"npx skills add","type":"text","marks":[{"type":"code_inline"}]},{"text":" (GitCode default), ","type":"text"},{"text":"npx skills add https://clawhub.ai/huaweicloudskill/skills/\u003cskill-name>","type":"text","marks":[{"type":"code_inline"}]},{"text":" (ClawHub), or fallback GitHub method","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Architecture","type":"text","marks":[{"type":"strong"}]},{"text":": Dual-source fallback (local cache → GitCode API v5 → Gitee raw) → In-memory search → GitHub raw fetch for details → Install","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Use Cases","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Find a skill for managing ECS instances\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"What Huawei Cloud skills are available for OBS?\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"华为云有哪些 VPC 相关的 skill?\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Browse all available Huawei Cloud skills\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Install a skill for RDS management\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"帮我找一个华为云网络相关的skill\"","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Prerequisites","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Python 3.6+","type":"text","marks":[{"type":"strong"}]},{"text":" must be installed and available as ","type":"text"},{"text":"python","type":"text","marks":[{"type":"code_inline"}]},{"text":" (or ","type":"text"},{"text":"python3","type":"text","marks":[{"type":"code_inline"}]},{"text":") in ","type":"text"},{"text":"PATH","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Network access","type":"text","marks":[{"type":"strong"}]},{"text":" to ","type":"text"},{"text":"gitcode.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" (API v5 for index), ","type":"text"},{"text":"gitee.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" (backup index), and ","type":"text"},{"text":"github.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"raw.githubusercontent.com","type":"text","marks":[{"type":"code_inline"}]},{"text":" (for skill details)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — ","type":"text"},{"text":"MANDATORY (Step 0.1)","type":"text","marks":[{"type":"strong"}]},{"text":": ensured by ","type":"text"},{"text":"bash scripts/ensure_cli.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" (idempotent, skips if already present). ","type":"text"},{"text":"MUST be triggered on EVERY execution of this skill","type":"text","marks":[{"type":"strong"}]},{"text":" before running any search/install command.","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Upgrade: run ","type":"text"},{"text":"skill-quality-cli upgrade","type":"text","marks":[{"type":"code_inline"}]},{"text":" manually (no auto-upgrade)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"质量上报","type":"text","marks":[{"type":"strong"}]},{"text":": 每次搜索(Step 1)与安装(Step 3)命令都必须用 ","type":"text"},{"text":"skill-quality-cli run --skill-name huawei-cloud-find-skills -- ","type":"text","marks":[{"type":"code_inline"}]},{"text":" 包装执行, 保证每次执行都触发质量上报","type":"text"}]}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 0: Check Python Environment","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"MANDATORY","type":"text","marks":[{"type":"strong"}]},{"text":": Before running any script command, verify Python is available.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ Mandatory: every ","type":"text","marks":[{"type":"strong"}]},{"text":"hcloud","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" command in this skill MUST be wrapped with ","type":"text","marks":[{"type":"strong"}]},{"text":"skill-quality-cli run --skill-name huawei-cloud-find-skills -- ","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — bare ","type":"text","marks":[{"type":"strong"}]},{"text":"hcloud","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" calls are strictly forbidden.","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check Python availability\npython --version # or: python3 --version","type":"text"}]},{"type":"paragraph","content":[{"text":"If the command fails or returns Python 2.x:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Install Python 3","type":"text","marks":[{"type":"strong"}]},{"text":": Download from ","type":"text"},{"text":"python.org","type":"text","marks":[{"type":"link","attrs":{"href":"https://www.python.org/downloads/","title":null}}]},{"text":" or use a package manager:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# macOS\nbrew install python3\n# Ubuntu/Debian\nsudo apt-get install python3\n# Windows — download installer from python.org, check \"Add Python to PATH\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify after install","type":"text","marks":[{"type":"strong"}]},{"text":": Run ","type":"text"},{"text":"python --version","type":"text","marks":[{"type":"code_inline"}]},{"text":" again to confirm Python 3.6+ is available","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If ","type":"text","marks":[{"type":"strong"}]},{"text":"python","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" points to Python 2","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"python3","type":"text","marks":[{"type":"code_inline"}]},{"text":" instead of ","type":"text"},{"text":"python","type":"text","marks":[{"type":"code_inline"}]},{"text":" in all commands below","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 0.1: Ensure ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" (MANDATORY)","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"MANDATORY","type":"text","marks":[{"type":"strong"}]},{"text":": Before running any search/install command, ensure ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" is installed and available. ","type":"text"},{"text":"This step MUST be triggered on EVERY execution of this skill","type":"text","marks":[{"type":"strong"}]},{"text":", immediately after Step 0. It is at the same mandatory level as ","type":"text"},{"text":"Step 0: Check Python Environment","type":"text","marks":[{"type":"strong"}]},{"text":" — do not skip it even if you believe the CLI is already present (","type":"text"},{"text":"ensure_cli.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" is idempotent and exits silently when everything is ready).","type":"text"}]},{"type":"paragraph","content":[{"text":"披露","type":"text","marks":[{"type":"strong"}]},{"text":": 该 CLI 仅用于本 skill 的","type":"text"},{"text":"匿名质量遥测上报","type":"text","marks":[{"type":"strong"}]},{"text":"(执行状态/耗时, 见 ","type":"text"},{"text":"Privacy & Telemetry","type":"text","marks":[{"type":"link","attrs":{"href":"#privacy--telemetry","title":null}}]},{"text":"); 安装位置 ","type":"text"},{"text":"~/.local/bin","type":"text","marks":[{"type":"code_inline"}]},{"text":", 不修改系统 服务或全局配置; 关闭方式见 ","type":"text"},{"text":"Privacy & Telemetry","type":"text","marks":[{"type":"link","attrs":{"href":"#privacy--telemetry","title":null}}]},{"text":"。","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Ensure ~/.local/bin is on PATH (where skill-quality-cli is installed)\nexport PATH=\"$HOME/.local/bin:$PATH\"\n\n# Ensure skill-quality-cli is ready (idempotent: installs only if absent;\n# also auto-links the CLI into a writable PATH dir so the bare command works)\nbash scripts/ensure_cli.sh\n\n# Verify availability\ncommand -v skill-quality-cli && skill-quality-cli version","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Outcome","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Behavior","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CLI already installed & usable","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Silent pass","type":"text","marks":[{"type":"strong"}]},{"text":" — script exits immediately","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CLI missing","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Installs the latest release into ","type":"text"},{"text":"~/.local/bin/","type":"text","marks":[{"type":"code_inline"}]},{"text":" (prints ","type":"text"},{"text":"skill-quality-cli vX.Y.Z 已就绪","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Install fails (no network, etc.)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Prints a warning; ","type":"text"},{"text":"never blocks the flow","type":"text","marks":[{"type":"strong"}]}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"ensure_cli.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" 会自动把 ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" 软链到 ","type":"text"},{"text":"PATH","type":"text","marks":[{"type":"code_inline"}]},{"text":" 中第一个可写目录 (如 ","type":"text"},{"text":"/usr/local/bin","type":"text","marks":[{"type":"code_inline"}]},{"text":"),因此 ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" 通常可直接调用。若仍不可用 (没有任何可写的 PATH 目录),请在当前 shell 执行:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"export PATH=\"$HOME/.local/bin:$PATH\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Manual one-off install fallback: ","type":"text"},{"text":"bash scripts/install_cli.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 0.5: Check KooCLI Version (NON-BLOCKING)","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"OPTIONAL","type":"text","marks":[{"type":"strong"}]},{"text":": A KooCLI (","type":"text"},{"text":"hcloud","type":"text","marks":[{"type":"code_inline"}]},{"text":") availability/version check that ","type":"text"},{"text":"never blocks the flow","type":"text","marks":[{"type":"strong"}]},{"text":". Skills installed later may depend on KooCLI; this step warns early, then ","type":"text"},{"text":"always continues to Step 1","type":"text","marks":[{"type":"strong"}]},{"text":" regardless of the outcome.","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check KooCLI availability & version (non-blocking)\npython scripts/check-koocli.py","type":"text"}]},{"type":"paragraph","content":[{"text":"→ ","type":"text"},{"text":"scripts/check-koocli.py","type":"text","marks":[{"type":"link","attrs":{"href":"scripts/check-koocli.py","title":null}}]},{"text":" (Python — cross-platform)","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Outcome","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Behavior","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"hcloud","type":"text","marks":[{"type":"code_inline"}]},{"text":" installed and version OK (≥ 3.0.0)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Silent pass","type":"text","marks":[{"type":"strong"}]},{"text":" — no output","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"hcloud","type":"text","marks":[{"type":"code_inline"}]},{"text":" installed but too old","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Prints an upgrade reminder (","type":"text"},{"text":"hcloud update -y","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"hcloud","type":"text","marks":[{"type":"code_inline"}]},{"text":" not installed","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Prints an install reminder (official KooCLI guide link)","type":"text"}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"The script always exits ","type":"text"},{"text":"0","type":"text","marks":[{"type":"code_inline"}]},{"text":" — it is informational only and never interrupts search or installation.","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Repository Info","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"INDEX_REPO=developer-skill/skills-group-contribution\nINDEX_BRANCH=test-for-index\nSKILLS_REPO=huaweicloud/huaweicloud-skills\nSKILLS_BRANCH=master\nRAW_BASE=https://raw.githubusercontent.com/$SKILLS_REPO/$SKILLS_BRANCH","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Index Source","type":"text"}]},{"type":"paragraph","content":[{"text":"The search script uses a ","type":"text"},{"text":"dual-source fallback","type":"text","marks":[{"type":"strong"}]},{"text":" for resilient data loading:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"1. Local cache (~/.cache/huawei-cloud-find-skills/, TTL 1h) — fastest, no network\n2. GitCode API v5 (primary) — WAF rate-limited, no X-RateLimit headers\n3. Gitee raw (backup) — independent IP/WAF, switched on 429","type":"text"}]},{"type":"paragraph","content":[{"text":"Primary source (GitCode API v5):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"SKILLS_INDEX_URL=https://gitcode.com/api/v5/repos/developer-skill/skills-group-contribution/contents/skills-index/index.json?ref=test-for-index\nSKILLS_CN_EN_MAP_URL=https://gitcode.com/api/v5/repos/developer-skill/skills-group-contribution/contents/skills-index/cn-en-map.json?ref=test-for-index","type":"text"}]},{"type":"paragraph","content":[{"text":"Backup source (Gitee raw):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"BACKUP_INDEX_URL=https://gitee.com/csimon666/skills-group-contribution/raw/test-for-index/skills-index/index.json\nBACKUP_MAP_URL=https://gitee.com/csimon666/skills-group-contribution/raw/test-for-index/skills-index/cn-en-map.json","type":"text"}]},{"type":"paragraph","content":[{"text":"On 429 (Too Many Requests), the script automatically retries with exponential backoff, then falls through to Gitee raw — a different IP/WAF unaffected by GitCode rate limits.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Core Workflow and Core Commands","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Search Skills","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"MANDATORY","type":"text","marks":[{"type":"strong"}]},{"text":": The agent MUST execute the search script to search the skill index. Do NOT read the JSON file directly — always use the script.","type":"text"}]}]},{"type":"paragraph","content":[{"text":"Given ","type":"text"},{"text":"keyword","type":"text","marks":[{"type":"code_inline"}]},{"text":" (from AI-understood user intent) and optional ","type":"text"},{"text":"category","type":"text","marks":[{"type":"code_inline"}]},{"text":", run the search script:","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ MANDATORY (质量上报)","type":"text","marks":[{"type":"strong"}]},{"text":": 搜索命令必须用 ","type":"text"},{"text":"skill-quality-cli run --skill-name huawei-cloud-find-skills -- ","type":"text","marks":[{"type":"code_inline"}]},{"text":" 包装, 保证每次搜索都触发质量上报。严禁裸调 ","type":"text"},{"text":"python scripts/search-skills.py","type":"text","marks":[{"type":"code_inline"}]},{"text":"。","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"powershell"},"content":[{"text":"# PowerShell\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- python scripts/search-skills.py -k \"\u003ckeyword>\"\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- python scripts/search-skills.py -k \"\u003ckeyword>\" -c \"\u003ccategory>\"\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- python scripts/search-skills.py -c \"\u003ccategory>\"","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Bash\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- python scripts/search-skills.py -k \"\u003ckeyword>\"\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- python scripts/search-skills.py -k \"\u003ckeyword>\" -c \"\u003ccategory>\"\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- python scripts/search-skills.py -c \"\u003ccategory>\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ 安全(命令注入防护)","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"keyword","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"category","type":"text","marks":[{"type":"code_inline"}]},{"text":" 来自用户输入,严禁未转义直接拼接到 shell 命令字符串中。若输入包含 ","type":"text"},{"text":"$()","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"$(...)","type":"text","marks":[{"type":"code_inline"}]},{"text":", 反引号 ","type":"text"},{"text":" ","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":", ","type":"text","marks":[{"type":"code_inline"}]},{"text":";","type":"text"},{"text":", ","type":"text","marks":[{"type":"code_inline"}]},{"text":"|` 等 shell 元字符,在 Bash/PowerShell 双引号字符串中会触发命令注入。必须按以下方式调用,避免将外部输入拼入 shell 字符串:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"首选(推荐)","type":"text","marks":[{"type":"strong"}]},{"text":": 用 Python ","type":"text"},{"text":"subprocess","type":"text","marks":[{"type":"code_inline"}]},{"text":" 参数数组方式调用,不经 shell:","type":"text"},{"text":"subprocess.run([sys.executable, \"scripts/search-skills.py\", \"-k\", keyword, \"-c\", category])","type":"text","marks":[{"type":"code_inline"}]},{"text":";","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"必须在 shell 中执行时,用","type":"text"},{"text":"单引号","type":"text","marks":[{"type":"strong"}]},{"text":"包裹用户输入(","type":"text"},{"text":"'\u003ckeyword>'","type":"text","marks":[{"type":"code_inline"}]},{"text":"),并先做转义(将输入中的 ","type":"text"},{"text":"'","type":"text","marks":[{"type":"code_inline"}]},{"text":" 替换为 ","type":"text"},{"text":"'\\''","type":"text","marks":[{"type":"code_inline"}]},{"text":")或使用 shell 转义工具(","type":"text"},{"text":"shlex.quote","type":"text","marks":[{"type":"code_inline"}]},{"text":");","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"遇到包含 ","type":"text"},{"text":"$()","type":"text","marks":[{"type":"code_inline"}]},{"text":", 反引号, ","type":"text"},{"text":";","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"|","type":"text","marks":[{"type":"code_inline"}]},{"text":" 等元字符的输入时,优先改为参数数组方式,或在展示给用户前对输入做脱敏处理。","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"→ ","type":"text"},{"text":"scripts/search-skills.py","type":"text","marks":[{"type":"link","attrs":{"href":"scripts/search-skills.py","title":null}}]},{"text":" (Python — cross-platform)","type":"text"}]},{"type":"paragraph","content":[{"text":"What the script does","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Fetches ","type":"text"},{"text":"index.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"cn-en-map.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" via HTTP GET from GitCode API v5 (auto-decodes base64 content)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Expands keywords via ","type":"text"},{"text":"cn-en-map.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" (bidirectional CN↔EN, e.g., \"ECS\" → \"ECS, 弹性云服务器, 云服务器\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Scores each skill: name match ","type":"text"},{"text":"+10","type":"text","marks":[{"type":"strong"}]},{"text":", trigger match ","type":"text"},{"text":"+8","type":"text","marks":[{"type":"strong"}]},{"text":", description match ","type":"text"},{"text":"+5","type":"text","marks":[{"type":"strong"}]},{"text":", service match ","type":"text"},{"text":"+3","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Sorts by score descending, outputs formatted results with matched keywords","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Reports only the top-3 results' skill names to the install-count API (","type":"text"},{"text":"skills/\u003ccategory>/\u003cservice>/\u003cname>","type":"text","marks":[{"type":"code_inline"}]},{"text":") as exposure impressions — fire-and-forget, never blocks or fails the search","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Fallback iteration","type":"text","marks":[{"type":"strong"}]},{"text":" (if no results): 1) Switch CN↔EN keywords 2) Expand keywords 3) Remove category filter 4) Try synonyms 5) List all skills","type":"text"}]},{"type":"paragraph","content":[{"text":"The process should persist until the skill is found or its absence is confirmed. In the event of total failure, notify the user of the specific steps that were attempted.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: View Skill Details (optional)","type":"text"}]},{"type":"paragraph","content":[{"text":"Fetch the full SKILL.md content from GitHub for intent validation. Skip this step if the search results from Step 1 are sufficiently informative.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# URL pattern — use the skill's category, service, and name from index\nDETAIL_URL=\"https://raw.githubusercontent.com/huaweicloud/huaweicloud-skills/master/skills/${category}/${service}/${name}/SKILL.md\"","type":"text"}]},{"type":"paragraph","content":[{"text":"The agent can fetch this URL using ","type":"text"},{"text":"curl","type":"text","marks":[{"type":"code_inline"}]},{"text":" or its web-fetch tool, then present the skill's full documentation to the user.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Install Skill","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"MANDATORY","type":"text","marks":[{"type":"strong"}]},{"text":": Before installing, the agent MUST call the install-count API to record the installation. Then use one of the install commands below. Option A is the default; Option C is a fallback when Option A is unavailable.","type":"text"}]}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Step 3.1: Record Install Count","type":"text"}]},{"type":"paragraph","content":[{"text":"Before executing the install command, call the install-count API. The ","type":"text"},{"text":"skill_id","type":"text","marks":[{"type":"code_inline"}]},{"text":" is constructed from the search results in Step 1: ","type":"text"},{"text":"skills/\u003ccategory>/\u003cservice>/\u003cskill-name>","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"IMPORTANT","type":"text","marks":[{"type":"strong"}]},{"text":": The ","type":"text"},{"text":"category","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"service","type":"text","marks":[{"type":"code_inline"}]},{"text":" values MUST be taken directly from the Step 1 search output (format: ","type":"text"},{"text":"name (category/service)","type":"text","marks":[{"type":"code_inline"}]},{"text":"). Do NOT guess or hardcode them.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ MANDATORY (质量上报)","type":"text","marks":[{"type":"strong"}]},{"text":": 安装计数请求同样用 ","type":"text"},{"text":"run","type":"text","marks":[{"type":"code_inline"}]},{"text":" 包装, 保证安装流程触发质量上报。","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"skill-quality-cli run --skill-name huawei-cloud-find-skills -- curl -s -X POST \"https://devdata2.huaweicloud.com/rest/developer/fwdo/rest/developer/servlet/hdskillservice/v1/obs/findcounts/increment\" -H \"Accept: application/json, text/plain, */*\" -H \"Content-Type: application/json\" -H \"Origin: https://skills.huaweicloud.com\" -H \"Referer: https://skills.huaweicloud.com/\" -d \"{\\\"skill_id\\\":\\\"skills/\u003ccategory>/\u003cservice>/\u003cskill-name>\\\"}\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"This is a fire-and-forget request. Do NOT block the install flow on its success or failure.","type":"text"}]}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Step 3.2: Execute Install Command","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ MANDATORY (质量上报)","type":"text","marks":[{"type":"strong"}]},{"text":": 安装命令必须用 ","type":"text"},{"text":"skill-quality-cli run --skill-name huawei-cloud-find-skills -- sh -c '...'","type":"text","marks":[{"type":"code_inline"}]},{"text":" 包装, 保证每次安装都触发质量上报。","type":"text"},{"text":"sh -c","type":"text","marks":[{"type":"code_inline"}]},{"text":" 内的 ","type":"text"},{"text":"printf \"\\n\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" 用于自动确认 ","type":"text"},{"text":"npx skills add","type":"text","marks":[{"type":"code_inline"}]},{"text":" 的 scope 交互提示。","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Option A: npx skills add from GitCode (default)\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- sh -c 'printf \"\\n\" | npx skills add https://gitcode.com/huaweicloud/huaweicloud-skills.git#master --skill \u003cskill-name> -y'\n\n# Option B: npx skills add from ClawHub\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- sh -c 'printf \"\\n\" | npx skills add https://clawhub.ai/huaweicloudskill/skills/\u003cskill-name> -y'\n\n# Option C (fallback): npx skills add from GitHub\nskill-quality-cli run --skill-name huawei-cloud-find-skills -- sh -c 'printf \"\\n\" | npx skills add huaweicloud/huaweicloud-skills --skill \u003cskill-name> -y'","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ 安全","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"\u003cskill-name>","type":"text","marks":[{"type":"code_inline"}]},{"text":" 必须来自 Step 1 搜索结果的规范技能名(","type":"text"},{"text":"name","type":"text","marks":[{"type":"code_inline"}]},{"text":" 字段),禁止拼接未经校验的用户输入到 ","type":"text"},{"text":"sh -c '...'","type":"text","marks":[{"type":"code_inline"}]},{"text":" 内;若技能名含 ","type":"text"},{"text":"'","type":"text","marks":[{"type":"code_inline"}]},{"text":" 等 shell 元字符,须先转义(","type":"text"},{"text":"'","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"'\\''","type":"text","marks":[{"type":"code_inline"}]},{"text":")或改用 ","type":"text"},{"text":"npx skills add ... -y","type":"text","marks":[{"type":"code_inline"}]},{"text":" 裸调用(此时质量上报改为安装完成后手动 ","type":"text"},{"text":"skill-quality-cli report --skill-name huawei-cloud-find-skills","type":"text","marks":[{"type":"code_inline"}]},{"text":")。","type":"text"}]}]},{"type":"paragraph","content":[{"text":"If all installation attempts fail, report the error message to the user. Do NOT attempt any method outside the commands above.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Parameter Confirmation","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameter","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Required/Optional","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Keyword","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Optional","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Search keyword (matched against name, description, triggers, service)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Category","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Optional","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Category code for filtering (e.g., \"computing\", \"storage\", \"network\")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"skill-name","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Required (Step 3)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Exact skill name for installing","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Document","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"GitCode API v5 ","type":"text"},{"text":"index.json","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skill index fetched via HTTP GET (base64 decoded)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"GitCode API v5 ","type":"text"},{"text":"cn-en-map.json","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Chinese-English keyword mapping fetched via HTTP GET (base64 decoded)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/search-skills.py","type":"text","marks":[{"type":"link","attrs":{"href":"scripts/search-skills.py","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Search script (Python) — fetches from GitCode API v5, expands keywords, scores, sorts, reports top-3 search-result exposures","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/check-koocli.py","type":"text","marks":[{"type":"link","attrs":{"href":"scripts/check-koocli.py","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Step 0.5 non-blocking KooCLI (","type":"text"},{"text":"hcloud","type":"text","marks":[{"type":"code_inline"}]},{"text":") availability/version check","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/ensure_cli.sh","type":"text","marks":[{"type":"link","attrs":{"href":"scripts/ensure_cli.sh","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MANDATORY (Step 0.1)","type":"text","marks":[{"type":"strong"}]},{"text":" idempotent installer for ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" (installs only if absent, no auto-upgrade)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/install_cli.sh","type":"text","marks":[{"type":"link","attrs":{"href":"scripts/install_cli.sh","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Manual one-off installer for ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" (user-triggered only)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/iam-policies.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/iam-policies.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"IAM 权限说明 — 本 Skill 仅访问公开接口,无需任何 IAM 凭证/策略","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/verification-method.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/verification-method.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"验证方法 — 各场景的验证步骤与预期结果","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/acceptance-criteria.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/acceptance-criteria.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"验收标准 — 功能/数据/安全/文件规范验收项","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/cli-installation-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/cli-installation-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CLI 安装/升级/遥测关闭说明","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Search Heuristics","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Optional reference for keyword-to-category hints. The agent can infer categories from ","type":"text"},{"text":"index.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" without these.","type":"text"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cloud infrastructure keywords (ecs, bms, vpc, obs, rds, ...) → likely ","type":"text"},{"text":"computing","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"network","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"storage","type":"text","marks":[{"type":"code_inline"}]},{"text":", etc.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tool keywords (cli, terraform, koo) → likely ","type":"text"},{"text":"devtools","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Management keywords (monitoring, alarm, log) → likely ","type":"text"},{"text":"monitoring","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Troubleshooting","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Issue: ","type":"text"},{"text":"python","type":"text","marks":[{"type":"code_inline"}]},{"text":" is not recognized as a command","type":"text"}]},{"type":"paragraph","content":[{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": Python 3 is not installed or not in ","type":"text"},{"text":"PATH","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Install Python 3.6+ and ensure it is added to ","type":"text"},{"text":"PATH","type":"text","marks":[{"type":"code_inline"}]},{"text":". On Windows, re-run the installer and check \"Add Python to PATH\". Alternatively, use ","type":"text"},{"text":"python3","type":"text","marks":[{"type":"code_inline"}]},{"text":" if available.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Issue: ","type":"text"},{"text":"skill-quality-cli: command not found","type":"text","marks":[{"type":"code_inline"}]},{"text":" (exit 127)","type":"text"}]},{"type":"paragraph","content":[{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"skill-quality-cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" is installed into ","type":"text"},{"text":"~/.local/bin/","type":"text","marks":[{"type":"code_inline"}]},{"text":", which is usually NOT on the default ","type":"text"},{"text":"PATH","type":"text","marks":[{"type":"code_inline"}]},{"text":". ","type":"text"},{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Re-run ","type":"text"},{"text":"bash scripts/ensure_cli.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" — it now auto-links the CLI into the first writable directory on ","type":"text"},{"text":"PATH","type":"text","marks":[{"type":"code_inline"}]},{"text":" (e.g. ","type":"text"},{"text":"/usr/local/bin","type":"text","marks":[{"type":"code_inline"}]},{"text":"), so the bare command works. As a manual fallback, run ","type":"text"},{"text":"export PATH=\"$HOME/.local/bin:$PATH\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" in the current shell. If the CLI is missing entirely, ","type":"text"},{"text":"ensure_cli.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" installs it idempotently (skips if already present) and never blocks the business flow.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Issue: Script fails with ","type":"text"},{"text":"SyntaxError: invalid syntax","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": System ","type":"text"},{"text":"python","type":"text","marks":[{"type":"code_inline"}]},{"text":" points to Python 2.x (the script requires Python 3.6+) ","type":"text"},{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Run with ","type":"text"},{"text":"python3","type":"text","marks":[{"type":"code_inline"}]},{"text":" explicitly: ","type":"text"},{"text":"python3 scripts/search-skills.py -k \"\u003ckeyword>\"","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Issue: Script fails with \"Failed to fetch index.json\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": GitCode API v5 URL unreachable ","type":"text"},{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Verify network connectivity to ","type":"text"},{"text":"gitcode.com","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Issue: GitCode API v5 returns 404","type":"text"}]},{"type":"paragraph","content":[{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": File path incorrect or the branch is not ","type":"text"},{"text":"test-for-index","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Verify the skill's ","type":"text"},{"text":"category","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"service","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"name","type":"text","marks":[{"type":"code_inline"}]},{"text":" from search results","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Issue: Search returns no results","type":"text"}]},{"type":"paragraph","content":[{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": Keywords don't match any skill ","type":"text"},{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Try broader keywords","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Switch between Chinese and English keywords (e.g., \"对象存储\" → \"obs\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"List all skills: ","type":"text"},{"text":"python scripts/search-skills.py -c \"computing\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Notes","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"This skill is ","type":"text"},{"text":"read-only","type":"text","marks":[{"type":"strong"}]},{"text":" and does not create any cloud resources","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Dual-source with caching","type":"text","marks":[{"type":"strong"}]},{"text":" — local cache (TTL 1h) → GitCode API v5 → Gitee raw (on 429)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cache location","type":"text","marks":[{"type":"strong"}]},{"text":" — ","type":"text"},{"text":"~/.cache/huawei-cloud-find-skills/","type":"text","marks":[{"type":"code_inline"}]},{"text":", TTL configurable via ","type":"text"},{"text":"FIND_SKILLS_CACHE_TTL","type":"text","marks":[{"type":"code_inline"}]},{"text":" env var (default 3600s)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MUST use script to search","type":"text","marks":[{"type":"strong"}]},{"text":" — do not read index.json directly","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Index repo: ","type":"text"},{"text":"https://gitcode.com/developer-skill/skills-group-contribution","type":"text","marks":[{"type":"code_inline"}]},{"text":" (branch: ","type":"text"},{"text":"test-for-index","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Skills repo: ","type":"text"},{"text":"https://github.com/huaweicloud/huaweicloud-skills","type":"text","marks":[{"type":"code_inline"}]},{"text":" (branch: ","type":"text"},{"text":"master","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"KooCLI","type":"text","marks":[{"type":"strong"}]},{"text":": the search/install flow itself is pure Python + HTTP (no service-level hcloud commands, no ","type":"text"},{"text":"--cli-region","type":"text","marks":[{"type":"code_inline"}]},{"text":"). Step 0.5 performs only a non-blocking KooCLI availability/version check (","type":"text"},{"text":"hcloud version","type":"text","marks":[{"type":"code_inline"}]},{"text":" via ","type":"text"},{"text":"scripts/check-koocli.py","type":"text","marks":[{"type":"code_inline"}]},{"text":") to warn about a missing/outdated CLI before installing skills that depend on it.","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"huawei-cloud-find-skills","author":"@skillopedia","source":{"stars":59,"repo_name":"huaweicloud-skills","origin_url":"https://github.com/huaweicloud/huaweicloud-skills/blob/HEAD/skills/devtools/common/huawei-cloud-find-skills/SKILL.md","repo_owner":"huaweicloud","body_sha256":"1b7d58d5dc6e6d66c322fd4a68bc3e36fb52f16ca86391a9bed49204eab8b06f","cluster_key":"a8245ba0c007f9f6914b792d904e63e29aef9afbcebd239ee8bf6581bcb40ee9","clean_bundle":{"format":"clean-skill-bundle-v1","source":"huaweicloud/huaweicloud-skills/skills/devtools/common/huawei-cloud-find-skills/SKILL.md","text_bytes":38866,"source_commit":"bad25df61c331db250f0cc79f1fa7acee08b3fc8","skills_sh_rank":1573,"attachment_count":8,"text_attachments":8,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/devtools/common/huawei-cloud-find-skills/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"integrations-apis","category_label":"Integrations"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"integrations-apis","import_tag":"skills-sh-top20k-2026-11","description":"Invoke this skill to search, list, query, discover, browse, find and install any Huawei Cloud (华为云) agent skill. Triggers include: \"华为云\", \"华为云有什么skill\", \"华为云相关skill\", \"华为云agent skill 市场\", \"华为云skill类目\", \"explore Huawei Cloud skills\", \"show Huawei Cloud skill categories\", \"does a Huawei Cloud skill exist for...\", \"which Huawei Cloud skills exist\", \"搜索华为云技能\", \"查询华为云skill列表\", \"有没有管理ECS/OBS/RDS的skill\", \"帮我找 XX 华为云skill\", \"介绍 XX Skill 内容\", \"华为云 XX Skill 具体做什么\", \"安装华为云Skill\".\n"}},"renderedAt":1793666599815}

[!IMPORTANT] When the user wants to search, discover, or install a Huawei Cloud (华为云) agent skill: 1. Search — use this skill ( ) to find the relevant Skill. 2. Install — install the matched Skill (see Step 3). 3. Execute — follow the installed Skill's instructions to fulfill the request. This skill handles skill discovery and installation only — it does not perform Huawei Cloud resource management/query tasks itself; those are handled by the skills it installs. Overview This skill enables users to efficiently search, discover, and install Huawei Cloud skills. Dependency : Python 3.6+ and net…