huaweicloud-devkit 1.1.9-next.0 → 1.1.9-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/package.json +2 -2
  2. package/plugins/huaweicloud-core/.claude-plugin/plugin.json +1 -1
  3. package/plugins/huaweicloud-core/.codex-plugin/plugin.json +1 -1
  4. package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +1 -1
  5. package/plugins/huaweicloud-core/.hermes-plugin/plugin.json +1 -1
  6. package/plugins/huaweicloud-core/.workbuddy-plugin/plugin.json +1 -1
  7. package/plugins/huaweicloud-core/openclaw.plugin.json +1 -1
  8. package/plugins/huaweicloud-core/skills/huawei-ecs/SKILL.md +5 -0
  9. package/plugins/huaweicloud-core/skills/huawei-ecs/references/create-instance.md +16 -2
  10. package/plugins/huaweicloud-core/skills/huawei-ecs/references/flavors.md +22 -0
  11. package/plugins/huaweicloud-core/skills/huawei-ecs/references/windows-ssh.md +118 -0
  12. package/plugins/huaweicloud-core/skills/huawei-getting-started/SKILL.md +3 -3
  13. package/plugins/huaweicloud-core/skills/huawei-iac/SKILL.md +36 -36
  14. package/plugins/huaweicloud-core/skills/huawei-obs/SKILL.md +2 -2
  15. package/plugins/huaweicloud-core/skills/huawei-sandbox/SKILL.md +67 -37
  16. package/plugins/huaweicloud-core/skills/huaweicloud-capability-discovery/SKILL.md +2 -2
  17. package/plugins/huaweicloud-core/skills/huaweicloud-cli-and-auth/SKILL.md +6 -6
  18. package/plugins/huaweicloud-core/skills/huaweicloud-core/SKILL.md +16 -9
  19. package/plugins/huaweicloud-core/src/auth/reconcile.mjs +26 -0
  20. package/plugins/huaweicloud-core/src/hcloud-cli.mjs +32 -4
  21. package/plugins/huaweicloud-core/src/sandbox/session-manager.mjs +206 -23
  22. package/plugins/huaweicloud-core/src/setup-cli.mjs +80 -8
  23. package/plugins/huaweicloud-core/src/tools.mjs +21 -2
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
3
  "mcpName": "io.github.huaweicloud/huaweicloud-devkit",
4
- "version": "1.1.9-next.0",
5
- "kooCliVersion": "7.2.12",
4
+ "version": "1.1.9-next.2",
5
+ "kooCliVersion": "7.3.12",
6
6
  "description": "Agent toolkit that helps coding agents use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities safely and accurately.",
7
7
  "type": "module",
8
8
  "files": [
@@ -17,7 +17,7 @@
17
17
  "mcpServers": "./.mcp.json",
18
18
  "description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
19
19
  "skills": "./skills/",
20
- "version": "1.1.9-next.0",
20
+ "version": "1.1.9-next.2",
21
21
  "author": {
22
22
  "name": "HuaweiCloud Mate",
23
23
  "url": "https://github.com/huaweicloud"
@@ -20,7 +20,7 @@
20
20
  "mcpServers": "./.mcp.json",
21
21
  "description": "Agent toolkit that helps coding agents use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities safely and accurately.",
22
22
  "skills": "./skills/",
23
- "version": "1.1.9-next.0",
23
+ "version": "1.1.9-next.2",
24
24
  "author": {
25
25
  "name": "HuaweiCloud Mate",
26
26
  "url": "https://github.com/huaweicloud"
@@ -17,7 +17,7 @@
17
17
  "mcpServers": "./.mcp.json",
18
18
  "description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
19
19
  "skills": "./skills/",
20
- "version": "1.1.9-next.0",
20
+ "version": "1.1.9-next.2",
21
21
  "author": {
22
22
  "name": "HuaweiCloud Mate",
23
23
  "url": "https://github.com/huaweicloud"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
- "version": "1.1.9-next.0",
3
+ "version": "1.1.9-next.2",
4
4
  "description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
5
5
  "author": {
6
6
  "name": "HuaweiCloud Mate",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
- "version": "1.1.9-next.0",
3
+ "version": "1.1.9-next.2",
4
4
  "description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
5
5
  "author": {
6
6
  "name": "HuaweiCloud Mate",
@@ -2,7 +2,7 @@
2
2
  "name": "huaweicloud-devkit",
3
3
  "id": "huaweicloud-devkit",
4
4
  "displayName": "HuaweiCloud DevKit",
5
- "version": "1.1.9-next.0",
5
+ "version": "1.1.9-next.2",
6
6
  "family": "bundle-plugin",
7
7
  "bundleFormat": "codex",
8
8
  "description": "Guide coding agents to use Huawei Cloud safely — KooCLI, APIs, SDKs, 28 MCP tools, skills, and safety guardrails.",
@@ -124,6 +124,10 @@ ssh -o StrictHostKeyChecking=accept-new -i <key> root@<eip> 'dnf install -y ngin
124
124
 
125
125
  > If SCP blocks SSH, use cloud-init `--server.user_data` for full deployment instead. See `references/create-instance.md` §Bootstrap.
126
126
 
127
+ ### Windows Login / Upload (standard paths)
128
+
129
+ Windows has NO working `sshpass` — password automation must go through paramiko; key automation uses the built-in OpenSSH `ssh`/`scp`. The first `Connection refused` on a fresh instance is usually just sshd not ready (retry with backoff before debugging the SG/EIP); a `Permission denied` while the server log shows "accepts key" is the local passphrase trap (`-N '""'` sets a literal `""` passphrase). Full standard paths — sshd-ready retry, paramiko login/upload, and the cloud-init public-key injection path (KooCLI has no `ImportKeypair`): `references/windows-ssh.md`.
130
+
127
131
  ## Deleting Instances
128
132
 
129
133
  - Show the user the exact command and get explicit approval before running
@@ -190,4 +194,5 @@ For Flexus X, use standard ECS CreateServers flow with `x1.*` flavors. For Flexu
190
194
  - ECS Docs: https://support.huaweicloud.com/ecs/
191
195
  - Flavor specs: references/flavors.md
192
196
  - Create instance: references/create-instance.md
197
+ - Windows SSH login/upload: references/windows-ssh.md
193
198
  - HC活动 ECS+Nginx部署: references/hc-activity.md
@@ -39,8 +39,22 @@ If no VPC/subnet exists: load `huawei-vpc` skill → create VPC → create subne
39
39
  **MCP 环境下必须用"本地生成 + 导入"流程**——`NovaCreateKeypair` 返回的 `private_key` 会被 MCP 脱敏管道替换为 `<redacted>`,而私钥仅此一次机会,读不到即作废:
40
40
 
41
41
  ```bash
42
- # 1. 本地生成
43
- ssh-keygen -t rsa -b 2048 -f ./<name> -N '""'
42
+ # 1. 本地生成 — bash / Git Bash / WSL(无 passphrase)
43
+ ssh-keygen -t rsa -b 2048 -f ./<name> -N ''
44
+ ```
45
+
46
+ ```powershell
47
+ # 1. 本地生成 — Windows PowerShell(无 passphrase,实测验证的写法)
48
+ # ⚠️ 引号陷阱:-N '""' 会把字面量 "" 设为私钥 passphrase(实测确认),后续 SSH 症状极具误导性:
49
+ # ECS 已 ACTIVE、22 端口可达、服务端日志显示 "accepts key",签名后仍 Permission denied ——
50
+ # 服务端接受了密钥却拒绝,排查路径反直觉。本地剥掉 passphrase(ssh-keygen -p)立即恢复,服务器侧零改动。
51
+ # 正确写法:--% 停止解析符 + -N ""(PowerShell 会丢弃空字符串参数,-N '' 直接报
52
+ # "option requires an argument -- N";--% 让该行剩余部分按 cmd 规则原样传递,"" 由 CRT 解析为空串)。
53
+ # 注意:--% 之后到行尾全部原样传递 —— 该行不能再跟任何其他命令或注释。
54
+ ssh-keygen --% -t rsa -b 2048 -f .\<name> -N ""
55
+ ```
56
+
57
+ ```bash
44
58
  # 2. 导入公钥
45
59
  hcloud ECS NovaCreateKeypair --keypair.name=<name> --keypair.public_key=<本地 .pub 文件内容>
46
60
  # 3. 使用私钥文件 ./<name> 连接实例
@@ -55,3 +55,25 @@ A flavor can be `normal` globally but `abandon` in specific AZs. Selecting an `a
55
55
 
56
56
  1. Switch to a different AZ: `hcloud ECS NovaListAvailabilityZones --cli-region=<region>`
57
57
  2. Or switch to a different flavor family (e.g., `at7` → `ac7`)
58
+
59
+ ## Conflict rule: `cond:operation:status` vs `cond:operation:az` (#922)
60
+
61
+ The two fields can contradict each other (实测:`kc2.small.2` with `cond:operation:status=abandon` while
62
+ `cond:operation:az=cn-north-4a(normal)`). **The AZ-level field (`cond:operation:az`) WINS for the target AZ**:
63
+
64
+ | Global `status` | Target AZ in `cond:operation:az` | Verdict |
65
+ | ------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
66
+ | `normal` | `<az>(normal)` | Usable in that AZ |
67
+ | `abandon`/`sellout` | `<az>(normal)` | **Usable in that AZ** — the AZ-level field wins; do not refuse to order just because the global status says abandon |
68
+ | `normal` | `<az>(sellout)` / `<az>(abandon)` / AZ absent | NOT usable in that AZ — pick another AZ or flavor |
69
+
70
+ Decision procedure:
71
+
72
+ 1. Find the target AZ entry in `cond:operation:az` (e.g. `cn-north-4a(normal)`).
73
+ 2. If the entry exists for the target AZ, its parenthesized state decides — ignore the global `cond:operation:status`.
74
+ 3. If the target AZ has no entry, fall back to the global `cond:operation:status` (only `normal` is usable).
75
+
76
+ Note: flavor availability is only half of the check — an image TYPE mismatch fails independently with
77
+ **`Ecs.0707 the product does not exist`** (market-type images fail with KunPeng flavors like `kc2.small.2`;
78
+ switch to a gold-type image or a compatible flavor, e.g. `s6.medium.2` + gold). The `huaweicloud_explain_error`
79
+ error map covers `Ecs.0707` with the full combination-troubleshooting procedure.
@@ -0,0 +1,118 @@
1
+ # Windows SSH Login / Upload — Standard Paths
2
+
3
+ Windows has NO working `sshpass` (it is a Linux tool; Windows OpenSSH client does not ship it, and the
4
+ native `ssh` cannot take a password from stdin or env). Use the paths below instead of trial-and-error.
5
+ All facts verified on Windows (2026-10 activity reports: sshpass failures → 8-minute detour → paramiko).
6
+
7
+ ## 0. First connection: `Connection refused` is usually just sshd not ready
8
+
9
+ On a fresh ECS, cloud-init finishes AFTER the instance reports ACTIVE. A first SSH attempt that gets
10
+ `Connection refused` / `timeout` is typically the sshd service not yet listening — do NOT debug the
11
+ security group or EIP on the first refusal. Retry with backoff first:
12
+
13
+ ```bash
14
+ for i in 1 2 3 4 5; do
15
+ ssh -o StrictHostKeyChecking=accept-new -o ConnectTimeout=5 -i <key> root@<eip> 'echo ok' && break
16
+ echo "retry $i: sshd may not be ready yet"; sleep 15
17
+ done
18
+ ```
19
+
20
+ Only after all retries fail, treat it as a network problem (security group port 22 ingress, EIP binding).
21
+
22
+ ## 1. Login from Windows
23
+
24
+ ```powershell
25
+ # Standard OpenSSH login (Windows 10+ ships OpenSSH client)
26
+ ssh -o StrictHostKeyChecking=accept-new -i C:\path\to\<key> root@<eip>
27
+ ```
28
+
29
+ Key file permission note: Windows OpenSSH checks ACLs on the private key. If ssh warns
30
+ `UNPROTECTED PRIVATE KEY FILE`, fix with (PowerShell):
31
+
32
+ ```powershell
33
+ icacls C:\path\to\<key> /inheritance:r /grant:r "$env:USERNAME:R"
34
+ ```
35
+
36
+ Passphrase trap (from `references/create-instance.md` §5): a key generated with `-N '""'` in PowerShell
37
+ carries a LITERAL `""` passphrase — the server accepts the key but SSH still fails `Permission denied`.
38
+ If you hit that, strip the passphrase locally and retry (server side needs zero changes):
39
+
40
+ ```powershell
41
+ ssh-keygen -p -f C:\path\to\<key>
42
+ # enter the old passphrase as "" (two quote characters), leave the new one empty
43
+ ```
44
+
45
+ ## 2. Password auth: sshpass does not exist on Windows — use paramiko
46
+
47
+ `sshpass` is unavailable on Windows OpenSSH; password-based automation must go through Python paramiko
48
+ (pip install paramiko):
49
+
50
+ ```python
51
+ # upload + run commands via paramiko (Windows-safe password auth)
52
+ import paramiko
53
+
54
+ client = paramiko.SSHClient()
55
+ client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
56
+ client.connect('<eip>', username='root', password='<password>', timeout=15)
57
+ # upload
58
+ sftp = client.open_sftp()
59
+ sftp.put(r'C:\local\file.tar.gz', '/root/file.tar.gz')
60
+ sftp.close()
61
+ # run a command
62
+ _, stdout, stderr = client.exec_command('tar -xzf /root/file.tar.gz -C /root && echo OK')
63
+ print(stdout.read().decode(), stderr.read().decode())
64
+ client.close()
65
+ ```
66
+
67
+ - `exec_command` is one-shot per call — chain commands with `&&` inside a single call for state.
68
+ - Never put the password in the conversation or shell history; pass it at runtime.
69
+
70
+ Key-based file upload from Windows (no paramiko needed): `scp` ships with Windows OpenSSH:
71
+
72
+ ```powershell
73
+ scp -o StrictHostKeyChecking=accept-new -i C:\path\to\<key> C:\local\file root@<eip>:/root/
74
+ ```
75
+
76
+ ## 3. No SSH at all: cloud-init public-key injection (standard path)
77
+
78
+ KooCLI has no `ImportKeypair` operation, and `NovaCreateKeypair`'s returned `private_key` is masked
79
+ (redacted) by the tool pipeline — it cannot be recovered. The documented standard path is
80
+ **local keypair generation + cloud-init public-key injection** (no SSH needed at creation time):
81
+
82
+ 1. Generate a keypair locally (per-shell forms and the PowerShell quote trap: `references/create-instance.md` §5)
83
+ 2. Inject the PUBLIC key at creation via `--server.user_data` (base64 cloud-init):
84
+
85
+ ```bash
86
+ # user_data (must be base64-encoded when passed to CreateServers)
87
+ #cloud-config
88
+ ssh_authorized_keys:
89
+ - <content of the local .pub file>
90
+ ```
91
+
92
+ ```bash
93
+ user_data=$(base64 -w0 << 'EOF'
94
+ #cloud-config
95
+ ssh_authorized_keys:
96
+ - <pub key content>
97
+ EOF
98
+ )
99
+ hcloud ECS CreateServers ... --server.user_data=$user_data
100
+ ```
101
+
102
+ 3. After ACTIVE, SSH in with the matching private key (`ssh -i <key> root@<eip>`).
103
+
104
+ This path avoids `NovaCreateKeypair` entirely (no private_key masking problem) and works even when SCP
105
+ policies block SSH at first boot — see `references/create-instance.md` §Bootstrap for the full
106
+ user_data workflow (mirror sources, observability sentinels, first-boot-only semantics).
107
+
108
+ ## 4. Quick reference
109
+
110
+ | Task (Windows) | Path |
111
+ | ------------------------------------------ | ------------------------------------------------------------------- |
112
+ | Login | `ssh -i <key> root@<eip>` (OpenSSH built-in) |
113
+ | First `Connection refused` | Retry 3-5x with 15s backoff — sshd not ready yet |
114
+ | Password automation | paramiko (`sshpass` unavailable on Windows) |
115
+ | File upload (key auth) | `scp -i <key> <local> root@<eip>:<path>` |
116
+ | File upload (password) | paramiko SFTP (`put`) |
117
+ | No keypair yet | local `ssh-keygen` + cloud-init `ssh_authorized_keys` inject |
118
+ | `Permission denied` but server accepts key | literal `""` passphrase from `-N '""'` — strip with `ssh-keygen -p` |
@@ -10,13 +10,13 @@ version: 1
10
10
 
11
11
  ## KooCLI Installation
12
12
 
13
- This plugin is paired with **KooCLI v7.2.12**. Install the pinned version:
13
+ This plugin is paired with **KooCLI v7.3.12**. Install the pinned version:
14
14
 
15
15
  | OS | Command |
16
16
  | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
17
  | Windows (PowerShell) | See https://support.huaweicloud.com/qs-hcli/hcli_02_003.html for MSI download |
18
- | Linux | curl -LO "https://cn-north-4-hdn-koocli.obs.cn-north-4.myhuaweicloud.com/cli/7.2.12/huaweicloud-cli-linux-amd64.tar.gz" && tar -zxvf huaweicloud-cli-linux-amd64.tar.gz |
19
- | macOS | curl -LO "https://cn-north-4-hdn-koocli.obs.cn-north-4.myhuaweicloud.com/cli/7.2.12/huaweicloud-cli-mac-amd64.tar.gz" && tar -zxvf huaweicloud-cli-mac-amd64.tar.gz |
18
+ | Linux | curl -LO "https://cn-north-4-hdn-koocli.obs.cn-north-4.myhuaweicloud.com/cli/7.3.12/huaweicloud-cli-linux-amd64.tar.gz" && tar -zxvf huaweicloud-cli-linux-amd64.tar.gz |
19
+ | macOS | curl -LO "https://cn-north-4-hdn-koocli.obs.cn-north-4.myhuaweicloud.com/cli/7.3.12/huaweicloud-cli-mac-amd64.tar.gz" && tar -zxvf huaweicloud-cli-mac-amd64.tar.gz |
20
20
 
21
21
  > See `huaweicloud-cli-and-auth` skill for arm64 variants and the one-liner (latest) option.
22
22
 
@@ -21,16 +21,16 @@ Always run `hcloud <Service> <Operation> --help` before constructing commands to
21
21
 
22
22
  **Proactive by design**: any deployment intent ("部署一个博客", "搭一套环境", "买个服务器") automatically triggers stages 1-5 BEFORE anything is created. The user NEVER needs to ask for an architecture proposal, cost estimate, or risk warnings - they are built into the flow. Only stages 6-8 (create / verify / manage) wait for explicit user confirmation at the approval gates.
23
23
 
24
- | Stage | What happens | Hard rule |
25
- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
26
- | 1. Scale assessment | **FIRST inspect the project code** (clone remote repos to a temp dir, or read the local path): tech stack, data services (Redis/MySQL/SQLite...), build artifacts, existing Dockerfile/k8s manifests → then classify or ask scale | **NEVER present deployment options (sandbox/ECS/OBS...) before the codebase has been inspected** - options without code analysis are guesses. If scale is not stated or clearly inferable, ASK - present the 3 tiers as options with what each includes and its monthly cost band (see `references/architectures.md`), and let the user choose. Never assume a tier. The scale question and the hosting-target question are SEPARATE questions on separate axes. FunctionGraph filesystem is ephemeral - never recommend SQLite/local files for persistent data |
27
- | 2. Frontend hosting choice | Present BOTH options: (a) OBS+CDN+DNS custom domain, (b) ECS+EIP | For SPA/static frontends (Vue/React dist), **OBS hosting must always appear as an option** with cost comparison against same-host Nginx - do not silently merge the frontend into a compute node. For option (a) three prerequisites: domain ownership verification (CDN requires a DNS record or file upload first - `CDN.00010185` otherwise), ICP filing check, DNS hosting check; domain registration link: https://www.huaweicloud.com/product/domain.html |
28
- | 3. Architecture proposal | ASCII topology tree with dependencies | User confirms before continuing. **Architecture decision points must be surfaced as explicit choices, never silently made**: (a) app depends on Redis/MySQL/Kafka etc. → managed service (DCS/RDS/DMS, billed) vs same-host install (cheap, ops burden) - state the trade-off and ask; (b) repo ships a Dockerfile / SWR image / k8s manifests → offer container path (Docker on ECS or CCE) alongside source-build path; (c) frontend hosting layer (Nginx same-host vs OBS+CDN). Silent defaults here are a correctness failure |
29
- | 4. Parameter discovery | `ListFlavors` / `ListImages` / `huaweicloud_list_regions` | Never hardcode flavor/image names |
30
- | 5. Cost + balance gate | Price every resource via BSS `ListOnDemandResourceRatings`, then query balance | Balance = 0 → the FIRST message must state: "您的余额为 0,按时长计费的资源(ECS/EIP/RDS 等)下单将失败(Ecs.7000),请先充值或使用免费额度"。充值入口:https://account.huaweicloud.com/usercenter/?region=cn-north-4#/userindex/balanceRecharge 。Remedy priority: (1) FIRST claim the one-time incentive voucher (huaweicloud_voucher_status → huaweicloud_voucher_claim) to offset usage fees; (2) then instruct the user to top up balance (via the link above) if pay-per-use orders are needed, otherwise orders fail with `Ecs.7000`; (3) free-tier resources (FunctionGraph, small OBS) proceed without any balance. Balance > 0 → report how long it can sustain (balance ÷ monthly estimate). **权限降级(实测)**:IAM 用户无 `billing:balance:view` 时余额查询报 `CBC.0151` → 不阻塞流程,明确告知"余额无法程序化查询,请自行核对;若下单报 Ecs.7000 即余额不足",领券后继续。定价编码逐服务查证,见 `references/resource-catalog.md` § Pricing |
31
- | 6. Provision | deployment_id, session state, batch approval, ordered creation | See "Provisioning Rules" below |
32
- | 7. Verify | `curl -I` the site / API; expect 200 | DNS CNAME may take minutes to propagate - not an error |
33
- | 8. Manage | Session-scoped status query and destroy | See "Destroy Rules" below |
24
+ | Stage | What happens | Hard rule |
25
+ | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
26
+ | 1. Scale assessment | **FIRST inspect the project code** (clone remote repos to a temp dir, or read the local path): tech stack, data services (Redis/MySQL/SQLite...), build artifacts, existing Dockerfile/k8s manifests → then classify or ask scale | **NEVER present deployment options (sandbox/ECS/OBS...) before the codebase has been inspected** - options without code analysis are guesses. If scale is not stated or clearly inferable, ASK - present the 3 tiers as options with what each includes and its monthly cost band (see `references/architectures.md`), and let the user choose. Never assume a tier. The scale question and the hosting-target question are SEPARATE questions on separate axes. FunctionGraph filesystem is ephemeral - never recommend SQLite/local files for persistent data |
27
+ | 2. Frontend hosting choice | Present BOTH options: (a) OBS+CDN+DNS custom domain, (b) ECS+EIP | For SPA/static frontends (Vue/React dist), **OBS hosting must always appear as an option** with cost comparison against same-host Nginx - do not silently merge the frontend into a compute node. For option (a) three prerequisites: domain ownership verification (CDN requires a DNS record or file upload first - `CDN.00010185` otherwise), ICP filing check, DNS hosting check; domain registration link: https://www.huaweicloud.com/product/domain.html |
28
+ | 3. Architecture proposal | ASCII topology tree with dependencies | User confirms before continuing. **Architecture decision points must be surfaced as explicit choices, never silently made**: (a) app depends on Redis/MySQL/Kafka etc. → managed service (DCS/RDS/DMS, billed) vs same-host install (cheap, ops burden) - state the trade-off and ask; (b) repo ships a Dockerfile / SWR image / k8s manifests → offer container path (Docker on ECS or CCE) alongside source-build path; (c) frontend hosting layer (Nginx same-host vs OBS+CDN). Silent defaults here are a correctness failure |
29
+ | 4. Parameter discovery | `ListFlavors` / `ListImages` / `huaweicloud_list_regions` | Never hardcode flavor/image names |
30
+ | 5. Cost + balance gate | Price every resource via BSS `ListOnDemandResourceRatings`, then query balance | **前置拦截(实测 #922):估算成本 > 余额(含余额为 0)时 STOP — 不要带着一份注定失败的下单继续 stage 6**。第一条消息必须说明:"您的余额不足以覆盖本次部署的按时长计费资源(预计首月 <估算>,当前余额 <余额>),下单将失败(Ecs.7000 Insufficient account balance)——已暂停,请先充值或领券,完成后回复"已充值/继续"即可从本阶段续跑原配置"。充值入口:https://account.huaweicloud.com/usercenter/?region=cn-north-4#/userindex/balanceRecharge 。Remedy priority: (1) FIRST claim the one-time incentive voucher (huaweicloud_voucher_status → huaweicloud_voucher_claim) to offset usage fees; (2) then instruct the user to top up balance (via the link above) — pause the flow and resume from stage 5 with the SAME configuration after the top-up, never walk a known-doomed order; (3) free-tier resources (FunctionGraph, small OBS) proceed without any balance. Balance >= 估算成本 → report how long it can sustain (balance ÷ monthly estimate). **权限降级(实测)**:IAM 用户无 `billing:balance:view` 时余额查询报 `CBC.0151` → 不阻塞流程,明确告知"余额无法程序化查询,请自行核对;若下单报 Ecs.7000 即余额不足",领券后继续。定价编码逐服务查证,见 `references/resource-catalog.md` § Pricing |
31
+ | 6. Provision | deployment_id, session state, batch approval, ordered creation | See "Provisioning Rules" below |
32
+ | 7. Verify | `curl -I` the site / API; expect 200 | DNS CNAME may take minutes to propagate - not an error |
33
+ | 8. Manage | Session-scoped status query and destroy | See "Destroy Rules" below |
34
34
 
35
35
  ## Provisioning Rules (Stage 6)
36
36
 
@@ -52,32 +52,32 @@ Execution: show the to-be-deleted list for final confirmation → delete in **re
52
52
 
53
53
  ## Critical Warnings
54
54
 
55
- | Trap | Why / Rule |
56
- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57
- | Stale `securityToken` poisons every hcloud call | Symptom: every API returns `APIGW.0301 Incorrect IAM authentication information` while OBS/obsutil still works. `configure set` refuses empty values and auth-sync never clears the field. Fix: `hcloud configure delete --cli-profile=default`, then re-run auth init with AK/SK only (no token) |
58
- | OBS writes bypass the REST write-prefix policy | `mb` / `cp` / `rm` / `chattri` are obsutil-style commands. ALWAYS route them through `huaweicloud_plan_cli_command` → approval → `huaweicloud_run_approved_command`. Never treat them as read-only |
59
- | `OBS mb` flag rules differ from cp/rm | `mb` does NOT accept `-f` (flag parse error) and REQUIRES explicit `-location=<region>` even with a regional endpoint (else `IllegalLocationConstraintException`) |
60
- | Duplicate `OBS mb` is idempotent success | Same-account same-name bucket creation returns success, not an error - never treat a second create as failure. OBS deletes are also idempotent (deleting a nonexistent object succeeds) |
61
- | Bucket ACL does not cascade to objects | Every uploaded object needs `-acl=public-read` at upload time (`-f` IS valid on cp/rm) |
62
- | OBS static website bucket name must equal the domain | e.g. bucket `www.example.com` for domain `www.example.com` |
63
- | VPC v3 API differs from older docs | v3 `CreateSecurityGroup` has NO `vpc_id` (account-scoped); `CreateSecurityGroupRule` uses `multiport=80` not `port_range_min/max`; `DeleteSubnet` requires `vpc_id` too. Always `--help` first |
64
- | Public exposure is auto-blocked | Risk rules deny `0.0.0.0/0` port rules at plan time. For test/dev use a narrower `remote_ip_prefix` (e.g. the VPC CIDR) or get user consent for a documented exception |
65
- | ECS CreateServers hidden required params | Besides flavor/image/nics/az it also needs `--server.vpcid` and `--server.root_volume.volumetype` - order submission fails without them |
66
- | FunctionGraph runtime/code enums are strict | runtime must be exact (`Node.js18.15`, `Python3.9`, `Go1.x`, ...); inline code is the PAIR `--package=default --code_type=inline` (`--package=inline` → `FSS.1006`); TIMER triggers use `--event_data.schedule_type=Rate --event_data.schedule=1m` (`@every` style → `FSS.1109`); DeleteFunction takes `--function_urn` WITHOUT `:latest` |
67
- | Keypairs: `NovaCreateKeypair`, not CreateKeypair | `ECS CreateKeypair` does NOT exist - use `hcloud ECS NovaCreateKeypair`; delete takes `--keypair_name` (not `--keypair.name`). The API-generated `private_key` is MASKED in tool output - for SSH access create the keypair in the console or import the user's own public key, then bind with `--server.key_name=<n>` |
68
- | Long inline args break MCP JSON | Values >~2KB inline (e.g. `--server.user_data=<base64 cloud-init>`) fail JSON parsing silently. Write a local JSON file and pass `--cli-jsonInput=<file>` (see `references/resource-catalog.md` header note) |
69
- | EIP quota fails at RUN stage, not at plan | `EIP.7905 Quota exceeded` appears only after plan+approval - pre-check quota during stage 5 (and count precisely: `ListPublicips --limit=50` truncates, a "50/50" read on a 59-EIP account is wrong). Released quotas may lag minutes before `EIP.7905` clears |
70
- | Zero balance blocks order submission | ECS creation fails with `Ecs.7000 Insufficient account balance` when cash + voucher accounts are 0. This is the stage-5 gate materialized: stop, mark `partial`, tell the user pay-by-duration resources need a balance top-up. Free-tier resources (FunctionGraph, small OBS) DO work at 0 balance - the gate applies to order-submission resources only |
71
- | CDN mainland acceleration requires ICP filing | Unregistered domains cannot go live on CDN - check before stage 3. CDN create ALSO requires domain ownership verification first (`CDN.00010185 Verify domain ownership failed` - user must add a DNS record or upload a verification file) |
72
- | CDN is a global service in KooCLI | CDN operations only accept `--cli-region=cn-north-1` or `ap-southeast-1` - never the resource region |
73
- | OBS static website hosting has NO CLI path | `chattri` only sets ACL/storage-class; obsutil has no website command. Options: console setup, or CDN OBS-origin with `--domain.sources.1.enable_obs_web_hosting=1`. Without website hosting, verify via direct object URLs (still public HTTP 200) |
74
- | DNS hosting location | `hcloud DNS ListPublicZones` decides: hosted in Huawei Cloud → auto-create CNAME record set; hosted elsewhere → output the CNAME value for manual setup at the user's DNS provider |
75
- | EIP bills when idle; stopped ECS still bills | Include in cost estimate; destroy unattached EIPs |
76
- | ECS delete defaults leak resources | `--delete_publicip` and `--delete_volume` are false by default - set `true` when tearing down |
77
- | EIP binding type is non-obvious | `--publicip.associate_instance_type=PORT` (not INSTANCE) |
78
- | State is session-only | Temp-dir file, dies with the session. Never promise cross-session deploy management |
79
- | State file must be UTF-8 WITHOUT BOM | PowerShell `Set-Content -Encoding utf8` adds a BOM that breaks JSON parsers - write state with Node or another BOM-less writer |
80
- | HTTPS needs a certificate | CDN serves plain HTTP by default; SSL cert (upload or SCM) required for HTTPS |
55
+ | Trap | Why / Rule |
56
+ | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57
+ | Stale `securityToken` poisons every hcloud call | Symptom: every API returns `APIGW.0301 Incorrect IAM authentication information` while OBS/obsutil still works. `configure set` refuses empty values and auth-sync never clears the field. Fix: `hcloud configure delete --cli-profile=default`, then re-run auth init with AK/SK only (no token) |
58
+ | OBS writes bypass the REST write-prefix policy | `mb` / `cp` / `rm` / `chattri` are obsutil-style commands. ALWAYS route them through `huaweicloud_plan_cli_command` → approval → `huaweicloud_run_approved_command`. Never treat them as read-only |
59
+ | `OBS mb` flag rules differ from cp/rm | `mb` does NOT accept `-f` (flag parse error) and REQUIRES explicit `-location=<region>` even with a regional endpoint (else `IllegalLocationConstraintException`) |
60
+ | Duplicate `OBS mb` is idempotent success | Same-account same-name bucket creation returns success, not an error - never treat a second create as failure. OBS deletes are also idempotent (deleting a nonexistent object succeeds) |
61
+ | Bucket ACL does not cascade to objects | Every uploaded object needs `-acl=public-read` at upload time (`-f` IS valid on cp/rm) |
62
+ | OBS static website bucket name must equal the domain | e.g. bucket `www.example.com` for domain `www.example.com` |
63
+ | VPC v3 API differs from older docs | v3 `CreateSecurityGroup` has NO `vpc_id` (account-scoped); `CreateSecurityGroupRule` uses `multiport=80` not `port_range_min/max`; `DeleteSubnet` requires `vpc_id` too. Always `--help` first |
64
+ | Public exposure is auto-blocked | Risk rules deny `0.0.0.0/0` port rules at plan time. For test/dev use a narrower `remote_ip_prefix` (e.g. the VPC CIDR) or get user consent for a documented exception |
65
+ | ECS CreateServers hidden required params | Besides flavor/image/nics/az it also needs `--server.vpcid` and `--server.root_volume.volumetype` - order submission fails without them |
66
+ | FunctionGraph runtime/code enums are strict | runtime must be exact (`Node.js18.15`, `Python3.9`, `Go1.x`, ...); inline code is the PAIR `--package=default --code_type=inline` (`--package=inline` → `FSS.1006`); TIMER triggers use `--event_data.schedule_type=Rate --event_data.schedule=1m` (`@every` style → `FSS.1109`); DeleteFunction takes `--function_urn` WITHOUT `:latest` |
67
+ | Keypairs: `NovaCreateKeypair`, not CreateKeypair | `ECS CreateKeypair` does NOT exist - use `hcloud ECS NovaCreateKeypair`; delete takes `--keypair_name` (not `--keypair.name`). The API-generated `private_key` is MASKED in tool output - for SSH access create the keypair in the console or import the user's own public key, then bind with `--server.key_name=<n>` |
68
+ | Long inline args break MCP JSON | Values >~2KB inline (e.g. `--server.user_data=<base64 cloud-init>`) fail JSON parsing silently. Write a local JSON file and pass `--cli-jsonInput=<file>` (see `references/resource-catalog.md` header note) |
69
+ | EIP quota fails at RUN stage, not at plan | `EIP.7905 Quota exceeded` appears only after plan+approval - pre-check quota during stage 5 (and count precisely: `ListPublicips --limit=50` truncates, a "50/50" read on a 59-EIP account is wrong). Released quotas may lag minutes before `EIP.7905` clears |
70
+ | Zero balance blocks order submission | ECS creation fails with `Ecs.7000 Insufficient account balance` when cash + voucher accounts are 0. This is the stage-5 gate materialized — and since #922 the gate INTERCEPTS before the order: when the estimate exceeds the balance, STOP at stage 5 (recharge entry + resume after top-up) instead of walking a known-doomed `CreateServers`. Free-tier resources (FunctionGraph, small OBS) DO work at 0 balance - the gate applies to order-submission resources only |
71
+ | CDN mainland acceleration requires ICP filing | Unregistered domains cannot go live on CDN - check before stage 3. CDN create ALSO requires domain ownership verification first (`CDN.00010185 Verify domain ownership failed` - user must add a DNS record or upload a verification file) |
72
+ | CDN is a global service in KooCLI | CDN operations only accept `--cli-region=cn-north-1` or `ap-southeast-1` - never the resource region |
73
+ | OBS static website hosting has NO CLI path | `chattri` only sets ACL/storage-class; obsutil has no website command. Options: console setup, or CDN OBS-origin with `--domain.sources.1.enable_obs_web_hosting=1`. Without website hosting, verify via direct object URLs (still public HTTP 200) |
74
+ | DNS hosting location | `hcloud DNS ListPublicZones` decides: hosted in Huawei Cloud → auto-create CNAME record set; hosted elsewhere → output the CNAME value for manual setup at the user's DNS provider |
75
+ | EIP bills when idle; stopped ECS still bills | Include in cost estimate; destroy unattached EIPs |
76
+ | ECS delete defaults leak resources | `--delete_publicip` and `--delete_volume` are false by default - set `true` when tearing down |
77
+ | EIP binding type is non-obvious | `--publicip.associate_instance_type=PORT` (not INSTANCE) |
78
+ | State is session-only | Temp-dir file, dies with the session. Never promise cross-session deploy management |
79
+ | State file must be UTF-8 WITHOUT BOM | PowerShell `Set-Content -Encoding utf8` adds a BOM that breaks JSON parsers - write state with Node or another BOM-less writer |
80
+ | HTTPS needs a certificate | CDN serves plain HTTP by default; SSL cert (upload or SCM) required for HTTPS |
81
81
 
82
82
  ## MCP Tools
83
83
 
@@ -10,8 +10,8 @@ version: 1
10
10
 
11
11
  ## Routing Guard: Deploy vs Store
12
12
 
13
- - If the developer's goal is to **deploy, host, or preview a web app / static website** (temporary hosting, quick preview), do NOT default to OBS. Present deployment-target options with the sandbox first: ① huawei-sandbox (recommended), ② OBS static hosting, ③ ECS, ④ CCE. Ask: "建议优先部署到沙箱(临时运行环境,可预览访问),也可选 OBS 静态托管/ECS/CCE,你想部署到哪里?"
14
- - Proceed with OBS only when the developer selects OBS, explicitly asks for OBS, or the intent is long-term static hosting / CDN / file storage. **Deployment intent proceeding on OBS is a resource purchase: load `huawei-iac` for orchestration (cost+balance gate, batch approval, state tracking, ordered destroy) - this skill then supplies the bucket/object commands.** Sandbox choice (huawei-sandbox) bypasses iac - no purchase involved.
13
+ - If the developer's goal is to **deploy, host, or preview a web app / static website** (temporary hosting, quick preview), do NOT default to OBS. You MUST present deployment-target options via the `question` tool with the sandbox first: ① huawei-sandbox (recommended), ② OBS static hosting (需提前准备好自定义域名 — the default OBS endpoint does not support HTTPS for static hosting), ③ ECS (需搭配弹性公网IP/EIP 才能公网访问), ④ CCE. Ask: "建议优先部署到沙箱(临时运行环境,可预览访问),也可选 OBS 静态托管(需提前准备好自定义域名)、ECS(需搭配弹性公网IP/EIP)或 CCE,你想部署到哪里?"
14
+ - Proceed with OBS only when the developer explicitly names OBS, or selects OBS through the `question` gate after being asked. Long-term static hosting / CDN / file storage intent alone is NOT a named target and cannot bypass the gate — still present the options via the `question` tool first. **NEVER infer or default the target** when it is unstated. **Deployment intent proceeding on OBS is a resource purchase: load `huawei-iac` for orchestration (cost+balance gate, batch approval, state tracking, ordered destroy) - this skill then supplies the bucket/object commands.** Sandbox choice (huawei-sandbox) bypasses iac - no purchase involved.
15
15
  - OBS is a storage service; it is not a general web-hosting default.
16
16
 
17
17
  ## Critical: OBS Command Syntax