huaweicloud-devkit 0.1.17 → 0.1.21-dev.0
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.
- package/README.md +2 -2
- package/package.json +1 -1
- package/plugins/huaweicloud-core/.claude-plugin/plugin.json +1 -1
- package/plugins/huaweicloud-core/.codex-plugin/plugin.json +1 -1
- package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +1 -1
- package/plugins/huaweicloud-core/skills/huawei-ecs/references/create-instance.md +12 -8
- package/plugins/huaweicloud-core/skills/huawei-vpc/SKILL.md +2 -1
- package/plugins/huaweicloud-core/skills/huawei-vpc/references/network.md +25 -1
- package/plugins/huaweicloud-core/skills/huaweicloud-cli-and-auth/SKILL.md +6 -4
- package/plugins/huaweicloud-core/src/setup-cli.mjs +61 -17
package/README.md
CHANGED
|
@@ -27,10 +27,10 @@ npx --yes huaweicloud-devkit uninstall # 卸载
|
|
|
27
27
|
### Codex
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
npx --yes huaweicloud-devkit install --target codex
|
|
30
|
+
npx --yes huaweicloud-devkit install --target codex
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
>
|
|
33
|
+
> 需要先安装 Codex CLI。`--target all` 会在 Codex CLI 缺失时跳过 Codex。
|
|
34
34
|
|
|
35
35
|
### Claude Code
|
|
36
36
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "huaweicloud-devkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21-dev.0",
|
|
4
4
|
"description": "Agent toolkit that helps coding agents use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities safely and accurately.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"mcpServers": "./.mcp.json",
|
|
21
21
|
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
22
22
|
"skills": "./skills/",
|
|
23
|
-
"version": "0.1.
|
|
23
|
+
"version": "0.1.19",
|
|
24
24
|
"author": {
|
|
25
25
|
"name": "HuaweiCloud Mate",
|
|
26
26
|
"url": "https://github.com/huaweicloud-mate"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "huaweicloud-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
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",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"mcpServers": "./.mcp.json",
|
|
21
21
|
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
22
22
|
"skills": "./skills/",
|
|
23
|
-
"version": "0.1.
|
|
23
|
+
"version": "0.1.19",
|
|
24
24
|
"author": {
|
|
25
25
|
"name": "HuaweiCloud Mate",
|
|
26
26
|
"url": "https://github.com/huaweicloud-mate"
|
|
@@ -9,16 +9,20 @@ hcloud ECS ListFlavors --cli-region=<region> --cli-output=json
|
|
|
9
9
|
hcloud ECS NovaListAvailabilityZones --cli-region=<region>
|
|
10
10
|
|
|
11
11
|
## 3. Find image
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Broad search — specific names may return empty in some regions
|
|
12
15
|
hcloud IMS ListImages --cli-region=<region> --__imagetype=gold --__isregistered=true --limit=20
|
|
16
|
+
```
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
| Image | ID |
|
|
16
|
-
|-------|----|
|
|
17
|
-
| Ubuntu 22.04 | Query live via ListImages |
|
|
18
|
-
| CentOS 8.2 64bit | Query live via ListImages |
|
|
19
|
-
| EulerOS 2.9 64bit | Query live via ListImages |
|
|
18
|
+
If searching by name (e.g. --name="Ubuntu") returns empty: use broad search without name filter, pick from results. Some regions only offer Huawei Cloud EulerOS (HCE).
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
Common images (verify live per region):
|
|
21
|
+
| Image | Region | ID |
|
|
22
|
+
|-------|--------|----|
|
|
23
|
+
| HCE 2.0 Standard | cn-north-4 | 7d940784-ac0a-425f-b3fa-8478f1a1df70 |
|
|
24
|
+
| Ubuntu 22.04 | Query live | Query live |
|
|
25
|
+
| CentOS 8.2 | Query live | Query live |
|
|
22
26
|
|
|
23
27
|
## 4. Verify or create VPC/subnet
|
|
24
28
|
hcloud VPC ListVpcs --cli-region=<region>
|
|
@@ -26,7 +30,7 @@ hcloud VPC ListSubnets --vpc_id=<vpc-id> --cli-region=<region>
|
|
|
26
30
|
If no VPC/subnet exists: load `huawei-vpc` skill → create VPC → create subnet (with DNS) → create security group → return here.
|
|
27
31
|
|
|
28
32
|
## 5. Create keypair (recommended over adminPass)
|
|
29
|
-
hcloud ECS NovaCreateKeypair --
|
|
33
|
+
hcloud ECS NovaCreateKeypair --keypair_name=<name>
|
|
30
34
|
Save the returned private key to a local file. The public key is auto-injected.
|
|
31
35
|
|
|
32
36
|
Password alternative:
|
|
@@ -38,7 +38,8 @@ Domain expertise for Huawei Cloud Virtual Private Cloud (VPC). Covers VPC/subnet
|
|
|
38
38
|
| SG rule | hcloud VPC CreateSecurityGroupRule --security_group_rule.security_group_id=<id> --security_group_rule.direction=<direction> --security_group_rule.protocol=<protocol> --security_group_rule.multiport=<port> --security_group_rule.remote_ip_prefix=<cidr> | references/security-group.md |
|
|
39
39
|
| Create EIP | hcloud EIP CreatePublicip --publicip.type=<type> --bandwidth.size=<size> --bandwidth.share_type=<share-type> --bandwidth.name=<name> | Run `hcloud EIP CreatePublicip --help` to confirm valid type values per region |
|
|
40
40
|
| Bind EIP to ECS | hcloud EIP AssociatePublicips --publicip_id=<id> --publicip.associate_instance_id=<port-id> --publicip.associate_instance_type=PORT | Get port ID from `hcloud ECS ListServersDetails --server_id=<id>` → `OS-EXT-IPS:port_id` |
|
|
41
|
-
| Unbind EIP | hcloud EIP
|
|
41
|
+
| Unbind EIP | hcloud EIP DisassociatePublicip --publicip_id=<id> | references/eip.md |
|
|
42
|
+
| Delete EIP | hcloud EIP DeletePublicip --publicip_id=<id> | references/eip.md |
|
|
42
43
|
| List EIPs | hcloud EIP ListPublicips | |
|
|
43
44
|
| NAT gateway | hcloud NAT CreateNatGateway --nat.name=<name> --nat.spec=<spec> --router_id=<vpc-id> --internal_network_id=<subnet-id> | Run `hcloud NAT CreateNatGateway --help` for available spec values |
|
|
44
45
|
|
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# VPC Network Management Reference
|
|
2
2
|
|
|
3
|
+
## DNS Addresses by Region
|
|
4
|
+
|
|
5
|
+
Subnets without DNS configuration will fail cloud-init. Use these DNS addresses:
|
|
6
|
+
|
|
7
|
+
| Region | Primary DNS | Secondary DNS |
|
|
8
|
+
|--------|------------|---------------|
|
|
9
|
+
| cn-north-1 | 100.125.1.250 | 100.125.129.250 |
|
|
10
|
+
| cn-north-4 | 100.125.1.250 | 100.125.129.250 |
|
|
11
|
+
| cn-east-3 | 100.125.1.250 | 100.125.129.250 |
|
|
12
|
+
| cn-south-1 | 100.125.1.250 | 100.125.129.250 |
|
|
13
|
+
| ap-southeast-3 | 100.125.1.250 | 100.125.129.250 |
|
|
14
|
+
|
|
15
|
+
**Subnet create with DNS**:
|
|
16
|
+
```bash
|
|
17
|
+
hcloud VPC CreateSubnet \
|
|
18
|
+
--subnet.name=<name> \
|
|
19
|
+
--subnet.vpc_id=<id> \
|
|
20
|
+
--subnet.cidr=10.50.1.0/24 \
|
|
21
|
+
--subnet.gateway_ip=10.50.1.1 \
|
|
22
|
+
--subnet.availability_zone=<az> \
|
|
23
|
+
--subnet.dnsList.1=100.125.1.250 \
|
|
24
|
+
--subnet.dnsList.2=100.125.129.250
|
|
25
|
+
```
|
|
26
|
+
|
|
3
27
|
## Nested Prefix Summary
|
|
4
28
|
|
|
5
29
|
KooCLI 7.x VPC API requires nested prefixes:
|
|
@@ -23,7 +47,7 @@ hcloud EIP AssociatePublicips --publicip_id=<id> \
|
|
|
23
47
|
--publicip.associate_instance_id=<port-id> --publicip.associate_instance_type=PORT
|
|
24
48
|
|
|
25
49
|
# Unbind
|
|
26
|
-
hcloud EIP
|
|
50
|
+
hcloud EIP DisassociatePublicip --publicip_id=<id>
|
|
27
51
|
|
|
28
52
|
# List
|
|
29
53
|
hcloud EIP ListPublicips
|
|
@@ -57,12 +57,14 @@ Agent processes find executables through `PATH`. If OpenCode/Codex cannot find `
|
|
|
57
57
|
|
|
58
58
|
## Configure Credentials Outside Chat
|
|
59
59
|
|
|
60
|
+
**NEVER let AK/SK enter shell history. This is the #1 credential leak vector.**
|
|
61
|
+
|
|
60
62
|
- Create AK/SK in the Huawei Cloud console under `My Credentials -> Access Keys`.
|
|
61
|
-
- **Interactive** (preferred): `hcloud configure init` — prompts
|
|
62
|
-
- **Non-interactive** (
|
|
63
|
-
-
|
|
63
|
+
- **Interactive** (preferred, SAFE): `hcloud configure init` — prompts for AK/SK via terminal input. Values do NOT enter shell history.
|
|
64
|
+
- **Non-interactive** (DANGEROUS — AK/SK in shell history): `hcloud configure set --cli-access-key=<AK> --cli-secret-key=<SK> --cli-region=<region>`. Only use in ephemeral CI/CD shells. User must execute outside agent chat.
|
|
65
|
+
- If MCP is available, use `huaweicloud_show_profile_redacted` to check status without ever seeing credentials.
|
|
64
66
|
- Never paste AK/SK, passwords, tokens, or profile files into the agent conversation.
|
|
65
|
-
- KooCLI stores credentials in `~/.hcloud/config.json`, NOT environment variables. `HCLOUD_ACCESS_KEY` / `HCLOUD_SECRET_KEY` / `HCLOUD_REGION` env vars are NOT read by KooCLI 7.x.
|
|
67
|
+
- KooCLI stores credentials in `~/.hcloud/config.json`, NOT environment variables. `HCLOUD_ACCESS_KEY` / `HCLOUD_SECRET_KEY` / `HCLOUD_REGION` env vars are NOT read by KooCLI 7.x.
|
|
66
68
|
|
|
67
69
|
## Safe Flow
|
|
68
70
|
|
|
@@ -323,19 +323,24 @@ async function cmdInstall() {
|
|
|
323
323
|
if (target === 'codex' || target === 'all') {
|
|
324
324
|
console.log('\n[Codex]');
|
|
325
325
|
if (!hasCodexCLI()) {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
326
|
+
if (target === 'codex') {
|
|
327
|
+
console.log(` \x1b[31mCodex CLI not found. Install Codex first: https://github.com/openai/codex-cli\x1b[0m`);
|
|
328
|
+
console.log(` Then re-run: npx huaweicloud-devkit install --target codex`);
|
|
329
|
+
process.exit(1);
|
|
330
|
+
}
|
|
331
|
+
console.log(` \x1b[33mCodex CLI not found. Skipping Codex.\x1b[0m`);
|
|
332
|
+
console.log(' Install Codex CLI to enable: npx huaweicloud-devkit install --target codex');
|
|
329
333
|
} else {
|
|
330
334
|
installCodex();
|
|
331
335
|
}
|
|
332
336
|
}
|
|
333
337
|
|
|
334
338
|
console.log(`\n\x1b[32mInstallation complete!\x1b[0m`);
|
|
335
|
-
console.log(`\n\x1b[1m\x1b[33m
|
|
336
|
-
console.log(
|
|
337
|
-
console.log(
|
|
338
|
-
console.log(
|
|
339
|
+
console.log(`\n\x1b[1m\x1b[33m╔══════════════════════════════════════════════════════╗`);
|
|
340
|
+
console.log(`\x1b[1m\x1b[33m║ MCP 工具在重启 OpenCode 会话后才生效 ║`);
|
|
341
|
+
console.log(`\x1b[1m\x1b[33m║ 关闭当前会话 → 重新打开,直接描述华为云任务即可 ║`);
|
|
342
|
+
console.log(`\x1b[1m\x1b[33m║ 重启前请勿执行 hcloud 命令,避免 AK/SK 泄露 ║`);
|
|
343
|
+
console.log(`\x1b[1m\x1b[33m╚══════════════════════════════════════════════════════╝\x1b[0m`);
|
|
339
344
|
|
|
340
345
|
const hcloudOk = checkHcloud();
|
|
341
346
|
if (!hcloudOk) {
|
|
@@ -346,8 +351,11 @@ async function cmdInstall() {
|
|
|
346
351
|
}
|
|
347
352
|
|
|
348
353
|
console.log(`\nAfter restart + hcloud setup, run: npx huaweicloud-devkit doctor`);
|
|
354
|
+
|
|
355
|
+
// Write install marker for doctor to detect
|
|
356
|
+
writeFileSync(join(opencodePluginsDir(), '.installed'), new Date().toISOString());
|
|
349
357
|
if (target === 'opencode' || target === 'all') {
|
|
350
|
-
console.log('Or
|
|
358
|
+
console.log('Or describe your Huawei Cloud task in OpenCode');
|
|
351
359
|
}
|
|
352
360
|
if (target === 'codex' || target === 'all') {
|
|
353
361
|
console.log('Or mention @huaweicloud-core in Codex');
|
|
@@ -477,7 +485,16 @@ async function cmdDoctor() {
|
|
|
477
485
|
console.log('\x1b[33mFix failures above, then restart your OpenCode / Codex session.\x1b[0m');
|
|
478
486
|
}
|
|
479
487
|
if (fail === 0 && mcpConfigured) {
|
|
480
|
-
console.log('\n\x1b[32mAll checks passed.\x1b[0m Restart OpenCode
|
|
488
|
+
console.log('\n\x1b[32mAll checks passed.\x1b[0m Restart OpenCode, then describe your Huawei Cloud task');
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Detect "installed but not restarted" scenario
|
|
492
|
+
const installedMarker = join(opencodePluginsDir(), '.installed');
|
|
493
|
+
if (mcpConfigured && existsSync(installedMarker)) {
|
|
494
|
+
console.log(`\n\x1b[1m\x1b[31m╔══════════════════════════════════════════╗`);
|
|
495
|
+
console.log(`\x1b[1m\x1b[31m║ 请重启 OpenCode!MCP 工具尚未激活 ║`);
|
|
496
|
+
console.log(`\x1b[1m\x1b[31m║ 关闭当前会话 → 重新打开即可 ║`);
|
|
497
|
+
console.log(`\x1b[1m\x1b[31m╚══════════════════════════════════════════╝\x1b[0m`);
|
|
481
498
|
}
|
|
482
499
|
}
|
|
483
500
|
|
|
@@ -533,14 +550,38 @@ async function cmdInstallHcloud() {
|
|
|
533
550
|
: join(homedir(), '.local', 'bin');
|
|
534
551
|
|
|
535
552
|
if (os === 'win32') {
|
|
536
|
-
console.log(`[Windows] Download and unzip to ${installDir}`);
|
|
537
553
|
const url = `${baseUrl}/huaweicloud-cli-windows-amd64.zip`;
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
console.log(`
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
554
|
+
const zipPath = join(installDir, 'hcloud.zip');
|
|
555
|
+
|
|
556
|
+
console.log(`[Windows] Auto-installing to ${installDir}...`);
|
|
557
|
+
|
|
558
|
+
try {
|
|
559
|
+
mkdirSync(installDir, { recursive: true });
|
|
560
|
+
|
|
561
|
+
// Download
|
|
562
|
+
console.log(` Downloading ${url}...`);
|
|
563
|
+
const psCmd = `[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '${url}' -OutFile '${zipPath}' -UseBasicParsing`;
|
|
564
|
+
spawnSync('powershell', ['-NoProfile', '-Command', psCmd], { stdio: 'inherit', windowsHide: true });
|
|
565
|
+
|
|
566
|
+
// Extract
|
|
567
|
+
console.log(' Extracting...');
|
|
568
|
+
spawnSync('powershell', ['-NoProfile', '-Command', `Expand-Archive -Path '${zipPath}' -DestinationPath '${installDir}' -Force`], { stdio: 'inherit', windowsHide: true });
|
|
569
|
+
|
|
570
|
+
// Clean up zip
|
|
571
|
+
rmSync(zipPath, { force: true });
|
|
572
|
+
|
|
573
|
+
// Add to PATH
|
|
574
|
+
console.log(' Adding to user PATH...');
|
|
575
|
+
spawnSync('setx', ['PATH', `${process.env.PATH};${installDir}`], { stdio: 'inherit', windowsHide: true });
|
|
576
|
+
|
|
577
|
+
console.log(`\n\x1b[32mInstall complete.\x1b[0m`);
|
|
578
|
+
console.log(` Verify: ${join(installDir, 'hcloud.exe')} version`);
|
|
579
|
+
console.log(' Or restart terminal and: hcloud version');
|
|
580
|
+
} catch (e) {
|
|
581
|
+
console.log(`\n\x1b[33mAuto-install failed: ${e.message}\x1b[0m`);
|
|
582
|
+
console.log(` Manual: download ${url}, unzip to ${installDir}, add to PATH`);
|
|
583
|
+
console.log(` Guide: https://support.huaweicloud.com/qs-hcli/hcli_02_003_01.html`);
|
|
584
|
+
}
|
|
544
585
|
} else if (os === 'linux') {
|
|
545
586
|
console.log('[Linux] One-liner install:');
|
|
546
587
|
console.log(' curl -sSL https://cn-north-4-hdn-koocli.obs.cn-north-4.myhuaweicloud.com/cli/latest/hcloud_install.sh -o ./hcloud_install.sh && bash ./hcloud_install.sh -y');
|
|
@@ -564,7 +605,10 @@ async function cmdInstallHcloud() {
|
|
|
564
605
|
}
|
|
565
606
|
|
|
566
607
|
console.log('\nAfter install, set HCLOUD_BIN if hcloud is not on PATH.');
|
|
567
|
-
console.log('
|
|
608
|
+
console.log('\n\x1b[1m\x1b[33m=== Configure credentials SAFELY ===\x1b[0m');
|
|
609
|
+
console.log(' Interactive (safe): hcloud configure init');
|
|
610
|
+
console.log(' NEVER: hcloud configure set --cli-access-key=xxx (AK/SK in shell history!)');
|
|
611
|
+
console.log('\nThen run: npx huaweicloud-devkit doctor');
|
|
568
612
|
}
|
|
569
613
|
|
|
570
614
|
async function main() {
|