huaweicloud-devkit 1.0.2-next.9 → 1.0.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 (36) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/README.md +85 -51
  3. package/README.zh-CN.md +85 -49
  4. package/package.json +11 -5
  5. package/plugins/huaweicloud-core/.claude-plugin/plugin.json +4 -17
  6. package/plugins/huaweicloud-core/.codex-plugin/plugin.json +4 -17
  7. package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +4 -17
  8. package/plugins/huaweicloud-core/.hermes-plugin/plugin.json +30 -0
  9. package/plugins/huaweicloud-core/.mcp.json +1 -2
  10. package/plugins/huaweicloud-core/.workbuddy-plugin/plugin.json +4 -18
  11. package/plugins/huaweicloud-core/hooks/huaweicloud-safety.py +32 -9
  12. package/plugins/huaweicloud-core/openclaw.plugin.json +20 -0
  13. package/plugins/huaweicloud-core/skills/huawei-cloud-find-skills/SKILL.md +1 -1
  14. package/plugins/huaweicloud-core/skills/huawei-sandbox/SKILL.md +67 -20
  15. package/plugins/huaweicloud-core/skills/huaweicloud-capability-discovery/SKILL.md +11 -0
  16. package/plugins/huaweicloud-core/skills/huaweicloud-cli-and-auth/SKILL.md +16 -0
  17. package/plugins/huaweicloud-core/skills/huaweicloud-core/SKILL.md +27 -24
  18. package/plugins/huaweicloud-core/skills/huaweicloud-core/references/select.md +12 -0
  19. package/plugins/huaweicloud-core/src/auth/agent-registration.mjs +103 -2
  20. package/plugins/huaweicloud-core/src/auth/credentials.mjs +65 -0
  21. package/plugins/huaweicloud-core/src/mcp-server.mjs +31 -4
  22. package/plugins/huaweicloud-core/src/proxy/proxy-agent.mjs +6 -1
  23. package/plugins/huaweicloud-core/src/sandbox/hdkitservice-api.mjs +7 -2
  24. package/plugins/huaweicloud-core/src/sandbox/hwlink-api.mjs +14 -4
  25. package/plugins/huaweicloud-core/src/sandbox/sandbox-file-server.py +45 -0
  26. package/plugins/huaweicloud-core/src/sandbox/session-manager.mjs +432 -10
  27. package/plugins/huaweicloud-core/src/setup-cli.mjs +823 -22
  28. package/plugins/huaweicloud-core/src/tools.mjs +239 -27
  29. package/plugins/huaweicloud-core/src/ws-exec/hwlink-exec-client.js +18 -4
  30. package/plugins/huaweicloud-core/src/ws-exec/hwlink-fair-queue.js +9 -0
  31. package/plugins/huaweicloud-core/src/ws-exec/hwlink-multiplexer.js +9 -0
  32. package/plugins/huaweicloud-core/src/ws-exec/hwlink-packet.js +9 -0
  33. package/plugins/huaweicloud-core/src/ws-exec/hwlink-terminal-channel.js +9 -0
  34. package/plugins/huaweicloud-core/src/ws-exec/hwlink-tunnel-channel.mjs +267 -0
  35. package/plugins/huaweicloud-core/src/ws-exec/index.js +3 -0
  36. package/plugins/huaweicloud-core/src/ws-exec/ws-exec-client.js +9 -5
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "huaweicloud-core",
3
- "version": "1.0.2-next.9",
2
+ "name": "huaweicloud-devkit",
3
+ "version": "1.0.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",
@@ -9,30 +9,16 @@
9
9
  "homepage": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
10
10
  "repository": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
11
11
  "license": "Apache-2.0",
12
- "keywords": [
13
- "huaweicloud",
14
- "huawei-cloud",
15
- "koocli",
16
- "hcloud",
17
- "agent",
18
- "mcp",
19
- "api",
20
- "sdk",
21
- "skills"
22
- ],
12
+ "keywords": ["huaweicloud", "huawei-cloud", "koocli", "hcloud", "agent", "mcp", "api", "sdk", "skills"],
23
13
  "skills": "./skills/",
24
14
  "mcpServers": "./.mcp.json",
25
- "hooks": "./hooks/",
26
15
  "interface": {
27
16
  "displayName": "HuaweiCloud Devkit",
28
17
  "shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
29
18
  "longDescription": "HuaweiCloud Devkit helps coding agents choose and use Huawei Cloud Skills, KooCLI, APIs, SDKs, and MCP tools with less context, safer command execution, and more accurate cloud implementation decisions.",
30
19
  "developerName": "HuaweiCloud Mate",
31
20
  "category": "Cloud",
32
- "capabilities": [
33
- "Read",
34
- "Interactive"
35
- ],
21
+ "capabilities": ["Read", "Interactive"],
36
22
  "websiteURL": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
37
23
  "brandColor": "#C7000B",
38
24
  "defaultPrompt": [
@@ -18,15 +18,38 @@ from pathlib import Path
18
18
 
19
19
  DENY_PREFIX = "Huawei Cloud safety hook blocked this action: "
20
20
  RULES_PATH = Path(__file__).resolve().parents[1] / "safety" / "rules" / "cloud-risk-rules.json"
21
+ POLICY_PATH = Path(__file__).resolve().parents[1] / "safety" / "policy.json"
21
22
 
22
- CONFIG_FILE_RE = re.compile(r"(\.hcloud|\.huaweicloud|hcloud[/\\](config|credentials)|huaweicloud[/\\](config|credentials))", re.I)
23
- ENV_DUMP_RE = re.compile(r"(env|printenv|Get-ChildItem\s+Env:|gci\s+Env:|dir\s+Env:).*(HUAWEICLOUD|HWC_|HCLOUD|OS_)", re.I)
24
- SECRET_READ_RE = re.compile(r"(ShowSecretVersion|GetSecretValue|secret_string|secret_binary)", re.I)
25
- HCLOUD_RE = re.compile(r"(^|\s)hcloud(\.exe)?\s+", re.I)
26
- WRITE_OPERATION_RE = re.compile(
27
- r"\b(BatchCreate|BatchDelete|Create|Delete|Update|Modify|Resize|Reboot|Stop|Start|Restart|Authorize|Revoke|Add|Remove|Associate|Disassociate|Attach|Detach|Enable|Disable)\w*",
28
- re.I,
23
+ CONFIG_FILE_RE = None
24
+ SECRET_READ_RE = None
25
+ WRITE_OPERATION_RE = None
26
+
27
+
28
+ def load_policy():
29
+ global CONFIG_FILE_RE, SECRET_READ_RE, WRITE_OPERATION_RE
30
+ try:
31
+ with POLICY_PATH.open("r", encoding="utf-8") as file_obj:
32
+ policy = json.load(file_obj)
33
+ cred_patterns = policy.get("credentialFilePatterns", [])
34
+ if cred_patterns:
35
+ CONFIG_FILE_RE = re.compile("|".join(cred_patterns), re.I)
36
+ blocked_secrets = policy.get("blockedSecretOperations", [])
37
+ if blocked_secrets:
38
+ SECRET_READ_RE = re.compile("|".join(re.escape(op) for op in blocked_secrets), re.I)
39
+ write_prefixes = policy.get("writeOperationPrefixes", [])
40
+ if write_prefixes:
41
+ WRITE_OPERATION_RE = re.compile(r"\b(" + "|".join(write_prefixes) + r")\w*", re.I)
42
+ except Exception:
43
+ pass
44
+
45
+
46
+ load_policy()
47
+
48
+ ENV_DUMP_RE = re.compile(
49
+ r"(env|printenv|Get-ChildItem\s+Env:|gci\s+Env:|dir\s+Env:).*(HUAWEICLOUD|HWC_|HCLOUD|OS_)", re.I,
29
50
  )
51
+ HCLOUD_RE = re.compile(r"(^|\s)hcloud(\.exe)?\s+", re.I)
52
+ READ_OPERATION_RE = re.compile(r"\b(List|Show|Get|Describe|NovaList|NovaShow)\w*", re.I)
30
53
  READ_OPERATION_RE = re.compile(r"\b(List|Show|Get|Describe|NovaList|NovaShow)\w*", re.I)
31
54
 
32
55
 
@@ -117,11 +140,11 @@ def main():
117
140
  tool_name = data.get("tool_name", "")
118
141
  text = command_text(data.get("tool_input", {}))
119
142
 
120
- if CONFIG_FILE_RE.search(text):
143
+ if CONFIG_FILE_RE and CONFIG_FILE_RE.search(text):
121
144
  deny("reading Huawei Cloud credential/profile files can expose AK/SK or tokens. Use redacted toolkit tools.")
122
145
  if ENV_DUMP_RE.search(text):
123
146
  deny("dumping cloud credential environment variables is not allowed.")
124
- if SECRET_READ_RE.search(text):
147
+ if SECRET_READ_RE and SECRET_READ_RE.search(text):
125
148
  deny("direct secret value retrieval would put plaintext secrets into the agent context.")
126
149
  denied_rule = first_denied_command_rule(text)
127
150
  if denied_rule:
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "huaweicloud-devkit",
3
+ "id": "huaweicloud-devkit",
4
+ "displayName": "HuaweiCloud DevKit",
5
+ "version": "1.0.2",
6
+ "family": "bundle-plugin",
7
+ "bundleFormat": "codex",
8
+ "description": "Guide coding agents to use Huawei Cloud safely — KooCLI, APIs, SDKs, 28 MCP tools, skills, and safety guardrails.",
9
+ "author": {
10
+ "name": "HuaweiCloud Mate",
11
+ "url": "https://github.com/huaweicloud"
12
+ },
13
+ "homepage": "https://github.com/huaweicloud/huaweicloud-devkit",
14
+ "repository": "https://github.com/huaweicloud/huaweicloud-devkit",
15
+ "license": "Apache-2.0",
16
+ "keywords": ["huaweicloud", "huawei-cloud", "koocli", "hcloud", "agent", "mcp", "api", "sdk", "skills", "cloud"],
17
+ "category": "Cloud",
18
+ "capabilities": ["Read", "Interactive"],
19
+ "brandColor": "#C7000B"
20
+ }
@@ -37,7 +37,7 @@ This skill enables users to:
37
37
 
38
38
  ## Prerequisites
39
39
 
40
- - **Node.js >= 20** must be installed
40
+ - **Node.js >= 22** must be installed
41
41
  - **Network access** to `gitcode.com` (API v5 for index) and `github.com` / `raw.githubusercontent.com` (for skill details)
42
42
 
43
43
  ### Step 0: Check Python Environment
@@ -40,11 +40,31 @@ Domain expertise for Huawei Cloud Sandbox (DevStation) instances and workspace t
40
40
 
41
41
  ### Terminal Execution
42
42
 
43
- | Tool | Purpose |
44
- | --------------------------------------- | ------------------------------------------------------------------------ |
45
- | `huaweicloud_sandbox_exec_with_session` | Session-based execution (state persists) |
46
- | `huaweicloud_sandbox_upload_file` | Upload a local file into the sandbox (chunked base64 write + md5 verify) |
47
- | `huaweicloud_sandbox_close_session` | Close a persistent terminal session |
43
+ | Tool | Purpose |
44
+ | --------------------------------------- | --------------------------------------------------------------------------- |
45
+ | `huaweicloud_sandbox_exec_with_session` | Session-based execution (state persists; best for interactive work) |
46
+ | `huaweicloud_sandbox_exec_one_shot` | One-shot execution (fresh connection; best for long/heavy commands) |
47
+ | `huaweicloud_sandbox_upload_file` | Upload a local file into the sandbox (chunked base64 write + md5 verify) |
48
+ | `huaweicloud_sandbox_upload_project` | Upload a local project directory to sandbox (HTTP tunnel, tar.gz + extract) |
49
+ | `huaweicloud_sandbox_close_session` | Close a persistent terminal session |
50
+
51
+ ### Tool Selection Guide
52
+
53
+ | Scenario | Use | Why |
54
+ | ---------------------------------- | ---------------------------------- | ------------------------------------------------------------ |
55
+ | `cd`, env setup, command chains | `exec_with_session` | Needs shared shell state across calls |
56
+ | `npm install`, `apt-get`, builds | `exec_one_shot` | Long-running (>30s), no state needed, more stable |
57
+ | `curl`, health checks, quick tests | Either — `exec_one_shot` preferred | Stateless, fast |
58
+ | Server startup (background) | `exec_with_session` | Need to `nohup ... &` then check output in same session |
59
+ | Deployment scripts | `exec_one_shot+shot` | Long script, fresh connection avoids session timeouts |
60
+ | Single file upload (<1MB) | `upload_file` | Base64 chunked, reliable for small files |
61
+ | Project directory upload (>1MB) | `upload_project` | HTTP tunnel, much faster than base64 for multi-file projects |
62
+
63
+ **Timeout tuning**: default is 120s. For commands expected to run longer (e.g. large builds), pass `timeout_ms` explicitly:
64
+
65
+ ```json
66
+ { "timeout_ms": 300000 }
67
+ ```
48
68
 
49
69
  ## Workflow
50
70
 
@@ -59,20 +79,40 @@ Setup is a **plugin-side preflight** — the developer should be asked a questio
59
79
  4. **Both missing** (`HDKIT_NOT_REALNAME_AND_AGREEMENT`): present **both** requirements together in one message — the real-name verification steps (console, step 2) **and** the agreement-signing request (step 3, wait for explicit consent) — so the developer can complete both at once
60
80
  5. **Connect**: `huaweicloud_sandbox_connect` — returns `session_id`, `dev_stage_id`, `connection_id`, `connection_address`
61
81
  6. **Inject credentials** (optional): `huaweicloud_sandbox_credentials` — enables cloud API access from sandbox
62
- 7. **Execute commands**: `huaweicloud_sandbox_exec_with_session` for interactive work
63
- 8. **Expose the deployed app and return the public URL**: set up a public access link for the app port and give the URL to the developer as the final result (see "Expose the deployed app (public URL)") this step uses an internal tunnel mechanism that must never be mentioned to the developer
82
+ 7. **Execute commands**: use `huaweicloud_sandbox_exec_with_session` for interactive work (cd, env setup), or `huaweicloud_sandbox_exec_one_shot` for long-running builds/installs. See [Tool Selection Guide](#tool-selection-guide).
83
+ 8. **Upload project** (if deploying local code): `huaweicloud_sandbox_upload_project` to transfer a local project directory into `/workspace/<name>`uses HTTP tunnel, much faster than base64 for multi-file projects. Use `huaweicloud_sandbox_upload_file` for single files.
84
+ 9. **Expose the deployed app and return the public URL**: set up a public access link for the app port and give the URL to the developer as the final result (see "Expose the deployed app (public URL)") — this step uses an internal tunnel mechanism that must never be mentioned to the developer
64
85
 
65
86
  ## File Transfer (local → sandbox)
66
87
 
67
- There is no general file-upload primitive on the sandbox service itself. Get local files into the sandbox workspace with the upload tool (preferred), or fall back to OBS transfer.
88
+ ### upload_project (preferred for directories)
89
+
90
+ `huaweicloud_sandbox_upload_project` packages a local directory as tar.gz, uploads it to the sandbox via HTTP tunnel, and extracts it. This is the fastest way to transfer multi-file projects.
91
+
92
+ **Prerequisites**: sandbox must already be connected (`sandbox_connect` called first). The tool handles everything internally — no manual setup needed.
93
+
94
+ ```json
95
+ {
96
+ "local_dir": "/path/to/local/project",
97
+ "remote_dir": "/workspace",
98
+ "extract": true,
99
+ "exclude": ["node_modules", ".git", "__pycache__"]
100
+ }
101
+ ```
102
+
103
+ - `local_dir` (required): local project directory
104
+ - `remote_dir` (optional, default `/workspace`): parent directory on sandbox
105
+ - `extract` (optional, default `true`): extract tar.gz after upload
106
+ - `exclude` (optional): patterns to exclude from archive
107
+ - Result includes `md5` and `md5Verified` for integrity check
68
108
 
69
- ### Upload tool (preferred)
109
+ ### upload_file (for single files)
70
110
 
71
- `huaweicloud_sandbox_upload_file` (local_path → remote_path) uploads a local file by base64-encoding it and writing it in small chunks through the terminal session, then decoding and verifying the md5 checksum. Use it for any file too large to inline into a single command.
111
+ `huaweicloud_sandbox_upload_file` (local_path → remote_path) uploads a local file by base64-encoding it and writing it in small chunks through the terminal session, then decoding and verifying the md5 checksum. Use it for individual files, especially small ones (<1MB).
72
112
 
73
113
  ### Exec channel size limit
74
114
 
75
- `huaweicloud_sandbox_exec_with_session` is fragile for long commands and large inline content. Do NOT paste a file's base64 directly into a single command:
115
+ `huaweicloud_sandbox_exec_with_session` and `huaweicloud_sandbox_exec_one_shot` are fragile for long commands and large inline content. Do NOT paste a file's base64 directly into a single command:
76
116
 
77
117
  | Payload | Result |
78
118
  | --------------------------- | -------------------------------------- |
@@ -104,7 +144,11 @@ Expose a deployed web app to a public URL and return that URL to the developer.
104
144
  **Install** (internal tooling; skip if `devbridge version` already works):
105
145
 
106
146
  ```bash
107
- curl -fsSL https://res-hd.hc-cdn.cn/sharedata/hdspace/devbridge/install.sh | bash
147
+ if command -v devbridge >/dev/null 2>&1; then
148
+ echo "devbridge already installed"
149
+ else
150
+ curl -fsSL https://res-hd.hc-cdn.cn/sharedata/hdspace/devbridge/install.sh | bash
151
+ fi
108
152
  export PATH=$PATH:$HOME/.huawei/bin # installer only writes ~/.bashrc; session shells do not re-source it
109
153
  ```
110
154
 
@@ -143,9 +187,12 @@ sleep 10 && cat /tmp/host.log
143
187
  | Never install tunnel tooling locally | If the sandbox cannot install it, report a generic error and stop — installing on the developer's machine defeats sandbox deployment |
144
188
  | Return the deployment URL | Always hand the public URL from the host log to the developer as the final result |
145
189
  | Session state persists | `exec_with_session` preserves `cd`, env vars, aliases between calls |
190
+ | Long commands prefer one-shot | `exec_one_shot` creates a fresh connection per call — more stable for builds, installs, and scripts >30s. See [Tool Selection Guide](#tool-selection-guide). |
146
191
  | Destructive commands blocked | `rm -rf /`, `mkfs`, `dd if=`, fork bombs are denied by safety policy |
147
192
  | Workspace ID = dev_stage_id | Use `dev_stage_id` from `sandbox_connect` as `workspace_id` for terminal exec |
148
193
  | Projects live in `/workspace` | Clone/install project code under `/workspace/<repo-name>` (filesystem-root workspace mount, not `$HOME/workspace`), never in `/tmp` — ephemeral locations lose the project when the sandbox session restarts |
194
+ | Upload project for local code | Use `sandbox_upload_project` to transfer local projects — packages as tar.gz, uploads via HTTP tunnel, extracts on sandbox. Much faster than base64 for multi-file projects |
195
+ | Upload file for single files | Use `sandbox_upload_file` for individual files — base64 chunked, reliable for small files (<1MB) |
149
196
  | Node.js >= 22 required | Sandbox terminal uses built-in WebSocket (globalThis.WebSocket); if Node.js is missing, install it from the Huawei Cloud mirror (see "Node.js in the sandbox") |
150
197
 
151
198
  ## Node.js in the sandbox
@@ -163,11 +210,11 @@ node --version
163
210
 
164
211
  ## Environment Variables
165
212
 
166
- | Variable | Required | Description |
167
- | ----------------------- | -------- | ------------------------- |
168
- | `HW_ACCESS_KEY` | Yes | Huawei Cloud AK |
169
- | `HW_SECRET_KEY` | Yes | Huawei Cloud SK |
170
- | `HW_SECURITY_TOKEN` | No | STS security token |
171
- | `HW_WORKSPACE_ID` | No | Default workspace ID |
172
- | `HDKITSERVICE_ENDPOINT` | No | hdkitservice API endpoint |
173
- | `HWLINK_ENDPOINT` | No | DevStation API endpoint |
213
+ | Variable | Required | Description |
214
+ | ----------------------- | -------- | --------------------------------------------------------------- |
215
+ | `HW_ACCESS_KEY` | Yes | Huawei Cloud AK |
216
+ | `HW_SECRET_KEY` | Yes | Huawei Cloud SK |
217
+ | `HW_SECURITY_TOKEN` | No | STS security token |
218
+ | `HW_WORKSPACE_ID` | No | Default workspace ID |
219
+ | `HDKITSERVICE_ENDPOINT` | No | hdkitservice API endpoint (default: devkit.huaweicloud.com) |
220
+ | `HWLINK_ENDPOINT` | No | DevStation API endpoint (default: devstation.myhuaweicloud.com) |
@@ -22,6 +22,17 @@ Use this skill to turn vague developer intent into a precise Huawei Cloud capabi
22
22
  9. When no built-in devkit skill matches, browse the community skill marketplace at https://github.com/huaweicloud/huaweicloud-skills. Fetch the index from https://raw.githubusercontent.com/huaweicloud/huaweicloud-skills/master/skills-index/index.json.
23
23
  10. When the deliverable is a PPT, architecture diagram (draw.io), or frontend page that needs official Huawei Cloud service logos, use the `huaweicloud_get_service_icon` MCP tool to get logo URLs from the official Icons library instead of guessing or hotlinking unofficial images.
24
24
 
25
+ ## Scenario Routing
26
+
27
+ Match the scenario before picking a service. For "deploy a web app" requests, layer the recommendation instead of defaulting to a production service:
28
+
29
+ | Scenario | Recommended path |
30
+ | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
31
+ | hello world / prototype / demo / temporary preview (free, quick try) | `huawei-sandbox` first — temporary runtime + public URL, ~8h validity, zero billed resources |
32
+ | production / long-term / custom domain / high availability | `huawei-functiongraph` / `huawei-ecs` (or `huawei-cce` for containers) |
33
+
34
+ Route to the sandbox when the developer signals free/quick preview intent ("免费", "快速", "预览", "hello world", "原型", "演示"); route to production services only when production-grade hosting is explicitly required.
35
+
25
36
  ## Official Service Logos
26
37
 
27
38
  - Use `huaweicloud_get_service_icon` with the service name, alias, or Chinese name (e.g. `ecs`, `obs`, `modelarts`, `对象存储`). It returns the official CDN logo URL (`logo.source_url`), category, and product page link from https://open.huaweicloud.com/openplatform/icons.html.
@@ -121,8 +121,24 @@ hcloud <Service> <ListOp> --cli-output=json --cli-query "items[?status=='ACTIVE'
121
121
  hcloud <Service> <Op> --cli-debug=true
122
122
  ```
123
123
 
124
+ ## Credential Resolution Priority
125
+
126
+ Credentials are resolved in this order (highest priority first):
127
+
128
+ | Priority | Source | Mechanism | Persistence |
129
+ | -------- | ----------------------- | ---------------------------------------------------------- | ------------------------------- |
130
+ | 1 | Runtime credentials | `huaweicloud_auth_init` tool | Memory (cleared on MCP restart) |
131
+ | 2 | Environment variables | `HW_ACCESS_KEY` / `HW_SECRET_KEY` | MCP process lifetime |
132
+ | 3 | CodeArts project config | `.codeartsdoer/mcp/mcp_settings.json` (project, then user) | File |
133
+ | 4 | Global config file | `~/.config/huaweicloud/credentials.json` | Permanent |
134
+ | 5 | KooCLI profile | `~/.hcloud/config.json` (KooCLI only) | Permanent |
135
+
136
+ When switching accounts within the same Agent session, use `huaweicloud_auth_init` to set runtime credentials. This overrides all other sources for the current MCP process.
137
+
124
138
  ## Preferred Toolkit Tools
125
139
 
140
+ - `huaweicloud_auth_init`
141
+ - `huaweicloud_auth_status`
126
142
  - `huaweicloud_check_cli`
127
143
  - `huaweicloud_show_profile_redacted`
128
144
  - `huaweicloud_plan_cli_command`
@@ -46,30 +46,32 @@ Do not rely on training data for facts. Huawei Cloud services, pricing, quotas,
46
46
 
47
47
  ## Service Map
48
48
 
49
- | Workload | Primary Service | Skill |
50
- | ------------------------------------- | -------------------- | ------------------------ |
51
- | Web application hosting | ECS | huawei-ecs |
52
- | Containerized microservices | CCE | huawei-cce |
53
- | Static file storage / CDN (long-term) | OBS | huawei-obs |
54
- | Relational database (MySQL/PG) | RDS | huawei-rds |
55
- | Distributed SQL database | GaussDB | huawei-gaussdb |
56
- | Document database (MongoDB API) | DDS | huawei-dds-dcs |
57
- | In-memory cache | DCS (Redis) | huawei-dds-dcs |
58
- | Serverless functions | FunctionGraph | huawei-functiongraph |
59
- | API management | APIG | huawei-apig |
60
- | AI model training/inference | ModelArts | huawei-modelarts |
61
- | Message queuing | DMS (Kafka/RabbitMQ) | huawei-smn-dms |
62
- | Push notifications | SMN | huawei-smn-dms |
63
- | Secret management | DEW (CSMS) | huawei-dew |
64
- | Key management | DEW (KMS) | huawei-dew |
65
- | DDoS protection | AAD | huawei-waf-aad |
66
- | Web firewall | WAF | huawei-waf-aad |
67
- | Monitoring dashboards | Cloud Eye (CES) | huawei-cloud-eye |
68
- | Audit trails | CTS | huawei-cts |
69
- | Backup / disaster recovery | CBR | huawei-cbr |
70
- | CI/CD pipeline | CloudDeploy | huawei-deployment |
71
- | Temporary runtime / web app preview | Sandbox (DevStation) | huawei-sandbox |
72
- | Getting started | Account setup | huaweicloud-cli-and-auth |
49
+ | Workload | Primary Service | Skill |
50
+ | ------------------------------------------------ | -------------------- | ------------------------ |
51
+ | Web application hosting (production / long-term) | ECS | huawei-ecs |
52
+ | Containerized microservices | CCE | huawei-cce |
53
+ | Static file storage / CDN (long-term) | OBS | huawei-obs |
54
+ | Relational database (MySQL/PG) | RDS | huawei-rds |
55
+ | Distributed SQL database | GaussDB | huawei-gaussdb |
56
+ | Document database (MongoDB API) | DDS | huawei-dds-dcs |
57
+ | In-memory cache | DCS (Redis) | huawei-dds-dcs |
58
+ | Serverless functions | FunctionGraph | huawei-functiongraph |
59
+ | API management | APIG | huawei-apig |
60
+ | AI model training/inference | ModelArts | huawei-modelarts |
61
+ | Message queuing | DMS (Kafka/RabbitMQ) | huawei-smn-dms |
62
+ | Push notifications | SMN | huawei-smn-dms |
63
+ | Secret management | DEW (CSMS) | huawei-dew |
64
+ | Key management | DEW (KMS) | huawei-dew |
65
+ | DDoS protection | AAD | huawei-waf-aad |
66
+ | Web firewall | WAF | huawei-waf-aad |
67
+ | Monitoring dashboards | Cloud Eye (CES) | huawei-cloud-eye |
68
+ | Audit trails | CTS | huawei-cts |
69
+ | Backup / disaster recovery | CBR | huawei-cbr |
70
+ | CI/CD pipeline | CloudDeploy | huawei-deployment |
71
+ | Temporary runtime / web app preview | Sandbox (DevStation) | huawei-sandbox |
72
+ | Getting started | Account setup | huaweicloud-cli-and-auth |
73
+
74
+ **Web app scenario layering**: for "deploy a web app", prefer `huawei-sandbox` for free/quick try (hello world, prototype, demo, temporary preview — temporary runtime + public URL, ~8h validity, zero billed resources); route to `huawei-functiongraph` / `huawei-ecs` (or `huawei-cce`) for production / long-term / custom-domain / high-availability hosting.
73
75
 
74
76
  ## Deployment Target Options
75
77
 
@@ -100,6 +102,7 @@ When the intent is to **deploy, host, or preview a web app or static website** (
100
102
 
101
103
  - Use huaweicloud_search_docs to discover skills covering a topic
102
104
  - Use huaweicloud_retrieve_skill to load a full SKILL.md after routing
105
+ - Use huaweicloud_auth_init to switch credentials at runtime when different accounts co-exist in the same session
103
106
  - If no built-in skill matches, consult huaweicloud-capability-discovery for external marketplace options
104
107
  - Use huaweicloud_list_regions before creating regional resources
105
108
  - Use huaweicloud_get_regional_availability when unsure about service-region pairs
@@ -28,3 +28,15 @@ Route based on answers:
28
28
  - SQL + massive scale / distributed -> huawei-gaussdb
29
29
  - Document model (MongoDB-compatible) -> huawei-dds-dcs
30
30
  - Cache / key-value -> huawei-dds-dcs (DCS)
31
+
32
+ ## Example: I need to deploy a web app
33
+
34
+ Ask:
35
+
36
+ - Is this a quick try / prototype / demo / temporary preview (free)?
37
+ - Or production (long-term, custom domain, high availability)?
38
+
39
+ Route by scenario:
40
+
41
+ - Free / quick try / prototype / demo / temporary preview -> huawei-sandbox (temporary runtime + public URL, ~8h validity, zero billed resources)
42
+ - Production / long-term / custom domain / high availability -> huawei-functiongraph / huawei-ecs (or huawei-cce for containers)
@@ -1,9 +1,20 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
2
+ import { join, resolve } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  import { spawnSync } from 'node:child_process';
5
+ import { createRequire } from 'node:module';
5
6
 
6
- export const SUPPORTED_AGENT_TARGETS = ['opencode', 'codex', 'codex-desktop', 'codearts', 'workbuddy', 'dsh'];
7
+ export const SUPPORTED_AGENT_TARGETS = [
8
+ 'opencode',
9
+ 'codex',
10
+ 'codex-desktop',
11
+ 'codearts',
12
+ 'workbuddy',
13
+ 'dsh',
14
+ 'officeace',
15
+ 'hermes',
16
+ 'openclaw',
17
+ ];
7
18
 
8
19
  function baseHome() {
9
20
  return process.env.HUAWEICLOUD_HOME || homedir();
@@ -90,6 +101,94 @@ function dshRegistered() {
90
101
  }
91
102
  }
92
103
 
104
+ function readOfficeaceRegistryInstallDir() {
105
+ if (process.platform !== 'win32') return null;
106
+ try {
107
+ const r = spawnSync('reg', ['query', 'HKCU\\SOFTWARE\\OfficeAce\\OfficeAce', '/v', 'InstallDir'], {
108
+ encoding: 'utf8',
109
+ windowsHide: true,
110
+ timeout: 5000,
111
+ });
112
+ if (r.status === 0) {
113
+ const m = r.stdout.match(/InstallDir\s+REG_SZ\s+(.+)/);
114
+ if (m) return m[1].trim();
115
+ }
116
+ } catch {}
117
+ return null;
118
+ }
119
+
120
+ function officeaceCapabilitiesDir() {
121
+ const configRoot = process.env.OFFICE_CLAW_CONFIG_ROOT;
122
+ if (configRoot && existsSync(join(configRoot, 'capabilities.json'))) return configRoot;
123
+ const regDir = readOfficeaceRegistryInstallDir();
124
+ if (regDir) {
125
+ const dir = join(regDir, '.office-claw');
126
+ if (existsSync(join(dir, 'capabilities.json'))) return dir;
127
+ }
128
+ if (process.platform === 'win32') {
129
+ const bases = [process.env.ProgramFiles, 'C:\\Program Files', 'D:\\Program Files'];
130
+ if (process.env.LOCALAPPDATA) bases.push(join(process.env.LOCALAPPDATA, 'Programs'));
131
+ for (const base of bases) {
132
+ if (!base) continue;
133
+ const dir = join(base, 'OfficeAce', '.office-claw');
134
+ if (existsSync(join(dir, 'capabilities.json'))) return dir;
135
+ }
136
+ }
137
+ return null;
138
+ }
139
+
140
+ function officeaceCapabilitiesDirSafe() {
141
+ return officeaceCapabilitiesDir() || join(baseHome(), '.office-claw');
142
+ }
143
+
144
+ function officeaceSqlitePath() {
145
+ const capDir = officeaceCapabilitiesDirSafe();
146
+ return join(resolve(capDir, '..'), 'data', 'mcp-connectors.sqlite');
147
+ }
148
+
149
+ function officeaceRegistered() {
150
+ let hasMcp = false;
151
+ const dbPath = officeaceSqlitePath();
152
+ if (existsSync(dbPath)) {
153
+ const nodeMajor = Number(process.versions.node.split('.')[0]);
154
+ if (nodeMajor >= 22) {
155
+ try {
156
+ const { DatabaseSync } = createRequire(import.meta.url)('node:sqlite');
157
+ const db = new DatabaseSync(dbPath, { readonly: true });
158
+ const row = db.prepare("SELECT enabled FROM mcp_connectors WHERE name = 'huaweicloud-devkit'").get();
159
+ db.close();
160
+ hasMcp = Boolean(row?.enabled);
161
+ } catch {}
162
+ }
163
+ }
164
+
165
+ const capFile = join(officeaceCapabilitiesDirSafe(), 'capabilities.json');
166
+ const cfg = readJsonSafe(capFile);
167
+ const hasSkills = cfg?.capabilities?.some((c) => c.id === 'huaweicloud-core' && c.type === 'skill') ?? false;
168
+
169
+ return hasMcp || hasSkills;
170
+ }
171
+
172
+ function hermesHome() {
173
+ if (process.env.HERMES_HOME) return process.env.HERMES_HOME;
174
+ // Hermes on Windows stores under LOCALAPPDATA, not ~/.hermes
175
+ if (process.platform === 'win32' && process.env.LOCALAPPDATA) {
176
+ return join(process.env.LOCALAPPDATA, 'hermes');
177
+ }
178
+ return join(baseHome(), '.hermes');
179
+ }
180
+
181
+ function hermesRegistered() {
182
+ const configPath = join(hermesHome(), 'config.yaml');
183
+ if (!existsSync(configPath)) return false;
184
+ try {
185
+ const content = readFileSync(configPath, 'utf8');
186
+ return content.includes('mcp_servers:') && content.includes('huaweicloud-devkit');
187
+ } catch {
188
+ return false;
189
+ }
190
+ }
191
+
93
192
  export function getAgentRegistrationStatuses(target = 'all') {
94
193
  const requested = target === 'all' ? SUPPORTED_AGENT_TARGETS : [target];
95
194
  const result = { target, agents: {} };
@@ -101,6 +200,8 @@ export function getAgentRegistrationStatuses(target = 'all') {
101
200
  if (agent === 'codearts') configured = codeartsRegistered();
102
201
  if (agent === 'workbuddy') configured = workbuddyRegistered();
103
202
  if (agent === 'dsh') configured = dshRegistered();
203
+ if (agent === 'officeace') configured = officeaceRegistered();
204
+ if (agent === 'hermes') configured = hermesRegistered();
104
205
  result.agents[agent] = { configured };
105
206
  }
106
207
  return result;
@@ -84,6 +84,13 @@ export function resolveCredentials(options = {}) {
84
84
  let securityToken = process.env.HW_SECURITY_TOKEN;
85
85
  let region = process.env.HW_REGION || process.env.HUAWEICLOUD_REGION || '';
86
86
 
87
+ const codeartsCreds = isCodeArtsContext() ? readCodeArtsCredentials() : null;
88
+ if (codeartsCreds) {
89
+ if (!ak && codeartsCreds.ak) ak = codeartsCreds.ak;
90
+ if (!sk && codeartsCreds.sk) sk = codeartsCreds.sk;
91
+ if (!region && codeartsCreds.region) region = codeartsCreds.region;
92
+ }
93
+
87
94
  const stored = readGlobalCredentials();
88
95
  if (stored) {
89
96
  if (!ak && stored.ak) ak = stored.ak;
@@ -101,3 +108,61 @@ export function resolveCredentials(options = {}) {
101
108
 
102
109
  return { ak, sk, securityToken, region };
103
110
  }
111
+
112
+ function isCodeArtsContext() {
113
+ return existsSync(join(process.cwd(), '.codeartsdoer')) || existsSync(join(homedir(), '.codeartsdoer'));
114
+ }
115
+
116
+ function readCodeArtsCredentials() {
117
+ const searchPaths = [
118
+ join(process.cwd(), '.codeartsdoer', 'mcp', 'mcp_settings.json'),
119
+ join(homedir(), '.codeartsdoer', 'mcp', 'mcp_settings.json'),
120
+ ];
121
+
122
+ for (const path of searchPaths) {
123
+ try {
124
+ if (!existsSync(path)) continue;
125
+ const config = JSON.parse(readFileSync(path, 'utf8'));
126
+ const server = config?.mcpServers?.['huaweicloud-devkit'];
127
+ if (!server?.env) continue;
128
+
129
+ const ak = server.env.HW_ACCESS_KEY;
130
+ const sk = server.env.HW_SECRET_KEY;
131
+ if (ak && sk) {
132
+ return {
133
+ ak,
134
+ sk,
135
+ securityToken: server.env.HW_SECURITY_TOKEN || '',
136
+ region: server.env.HW_REGION || server.env.HUAWEICLOUD_REGION || '',
137
+ };
138
+ }
139
+ } catch {
140
+ // mcp_settings.json missing or invalid — skip
141
+ }
142
+ }
143
+
144
+ return null;
145
+ }
146
+
147
+ let runtimeCredentials = null;
148
+
149
+ export function setRuntimeCredentials(ak, sk, securityToken, region) {
150
+ runtimeCredentials = { ak, sk, securityToken: securityToken || '', region: region || '' };
151
+ }
152
+
153
+ export function clearRuntimeCredentials() {
154
+ runtimeCredentials = null;
155
+ }
156
+
157
+ export function resolveCredentialsWithRuntime(options = {}) {
158
+ if (runtimeCredentials) {
159
+ return {
160
+ ak: runtimeCredentials.ak,
161
+ sk: runtimeCredentials.sk,
162
+ securityToken: runtimeCredentials.securityToken,
163
+ region: runtimeCredentials.region,
164
+ };
165
+ }
166
+
167
+ return resolveCredentials(options);
168
+ }