huaweicloud-devkit 1.1.0-next.17 → 1.1.0-next.18
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/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/.hermes-plugin/plugin.json +1 -1
- package/plugins/huaweicloud-core/.workbuddy-plugin/plugin.json +1 -1
- package/plugins/huaweicloud-core/openclaw.plugin.json +1 -1
- package/plugins/huaweicloud-core/safety/rules/cloud-risk-rules.json +1 -1
- package/plugins/huaweicloud-core/skills/huawei-sandbox/SKILL.md +4 -4
- package/plugins/huaweicloud-core/src/hcloud-cli.mjs +5 -4
- package/plugins/huaweicloud-core/src/sandbox/session-manager.mjs +4 -1
- package/plugins/huaweicloud-core/src/setup-cli.mjs +9 -1
- package/plugins/huaweicloud-core/src/tools.mjs +9 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "huaweicloud-devkit",
|
|
3
|
-
"version": "1.1.0-next.
|
|
3
|
+
"version": "1.1.0-next.18",
|
|
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": [
|
|
@@ -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.0-next.
|
|
20
|
+
"version": "1.1.0-next.18",
|
|
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.0-next.
|
|
23
|
+
"version": "1.1.0-next.18",
|
|
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.0-next.
|
|
20
|
+
"version": "1.1.0-next.18",
|
|
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.0-next.
|
|
3
|
+
"version": "1.1.0-next.18",
|
|
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.0-next.
|
|
3
|
+
"version": "1.1.0-next.18",
|
|
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.0-next.
|
|
5
|
+
"version": "1.1.0-next.18",
|
|
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.",
|
|
@@ -157,7 +157,7 @@
|
|
|
157
157
|
"match": {
|
|
158
158
|
"all": [
|
|
159
159
|
{ "field": "text", "regex": "(Delete|BatchDelete|Remove|\\brm\\b|delete)" },
|
|
160
|
-
{ "field": "text", "regex": "(--force
|
|
160
|
+
{ "field": "text", "regex": "(\\s--force|\\s-f\\s|\\s--recursive|\\s-r\\s|delete_publicip\\s*[=:]\\s*true)" }
|
|
161
161
|
]
|
|
162
162
|
},
|
|
163
163
|
"message": "The command combines deletion with force, recursive, or cascading deletion behavior.",
|
|
@@ -95,7 +95,7 @@ Setup is a **plugin-side preflight** — the developer should be asked a questio
|
|
|
95
95
|
2. **Real-name verification only** (`HDKIT_NOT_REALNAME`): tell the developer once, "Huawei Cloud requires real-name verification before using the sandbox — please complete it in the Huawei Cloud console (实名认证)." and stop — do not retry `connect` in a loop
|
|
96
96
|
3. **Sign agreement only** (`HDKIT_NOT_AGREEMENT`): **STOP and do NOT sign on your own.** Ask the developer: "Huawei Cloud sandbox requires signing the latest developer service agreement. May I sign it for you?" Then **wait for the developer to explicitly agree** (e.g. "签署" / "确认" / "sign it"). Only after explicit consent call `huaweicloud_sandbox_sign_agreement` and return its result (`signed`/`signedCount`) to the developer. **Never sign a legal agreement on the developer's behalf without their explicit, unambiguous consent.** Do not expose the underlying sandbox/DevBridge service as a separate entity the developer must understand or sign up for
|
|
97
97
|
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
|
|
98
|
-
5. **Connect**: `huaweicloud_sandbox_connect` — returns `session_id`, `dev_stage_id`, `connection_id`, `connection_address`. The `source` parameter identifies the calling agent (valid values: `
|
|
98
|
+
5. **Connect**: `huaweicloud_sandbox_connect` — returns `session_id`, `dev_stage_id`, `connection_id`, `connection_address`. The `source` parameter identifies the calling agent (valid values: `CLI`, `WEB`, `VSCODE`, `WEBVNC`, `WEBPTY`, `WEBIDE`, `CURSOR`, etc. — case-sensitive, all uppercase). The `git` parameter (with `repo_url`, `repo_name`, `target_path`) is accepted but does NOT auto-clone the repository — always clone manually.
|
|
99
99
|
6. **Cleanup previous deployments** (after first connect to a sandbox): nginx configs, DevBridge tunnels, and stale web processes from previous deployments can cause port conflicts and quota errors. Run cleanup immediately after connect:
|
|
100
100
|
|
|
101
101
|
```bash
|
|
@@ -357,13 +357,13 @@ Use the detected `PKG_MGR` for all package installations below.
|
|
|
357
357
|
|
|
358
358
|
**Architecture awareness**: the sandbox runs Linux aarch64 (ARM64). Native binaries built on x64 (Windows/macOS Intel) will not execute. Always install dependencies and build inside the sandbox. For projects with native addons (Taro `@swc/core`, Prisma, `esbuild`, `node-gyp`), local x64 pre-build + upload of `dist/` output is a viable alternative when sandbox builds fail.
|
|
359
359
|
|
|
360
|
-
**GitCode SSL**: if `git clone` from GitCode fails with SSL certificate errors:
|
|
360
|
+
**GitCode SSL**: if `git clone` from GitCode fails with SSL certificate errors, use a one-shot override (do NOT set it globally — that would disable cert verification for every repo):
|
|
361
361
|
|
|
362
362
|
```bash
|
|
363
|
-
git
|
|
363
|
+
git -c http.sslVerify=false clone <repo-url>
|
|
364
364
|
```
|
|
365
365
|
|
|
366
|
-
Then retry the clone. This
|
|
366
|
+
Then retry the clone. This bypasses SSL verification only for this single clone.
|
|
367
367
|
|
|
368
368
|
#### 3b: Install nginx (before project upload)
|
|
369
369
|
|
|
@@ -71,6 +71,7 @@ function runHcloudOnce(plan, options) {
|
|
|
71
71
|
const executable = options.executable || options.env?.HCLOUD_BIN || discoverHcloudPath() || 'hcloud';
|
|
72
72
|
const executableArgs = Array.isArray(options.executableArgs) ? options.executableArgs.map(String) : [];
|
|
73
73
|
const cwd = options.cwd || undefined;
|
|
74
|
+
const stdin = options.stdin ?? 'y\n';
|
|
74
75
|
|
|
75
76
|
return new Promise((resolve) => {
|
|
76
77
|
const proxySettings = getProxySettings();
|
|
@@ -90,11 +91,11 @@ function runHcloudOnce(plan, options) {
|
|
|
90
91
|
...options.env,
|
|
91
92
|
},
|
|
92
93
|
});
|
|
93
|
-
if (
|
|
94
|
-
if (typeof
|
|
95
|
-
|
|
94
|
+
if (stdin) {
|
|
95
|
+
if (typeof stdin === 'function') {
|
|
96
|
+
stdin(child.stdin);
|
|
96
97
|
} else {
|
|
97
|
-
child.stdin.write(String(
|
|
98
|
+
child.stdin.write(String(stdin));
|
|
98
99
|
child.stdin.end();
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -948,6 +948,7 @@ fi
|
|
|
948
948
|
: ''
|
|
949
949
|
}`,
|
|
950
950
|
`echo "SCORE:\${PASS}/\${TOTAL}"`,
|
|
951
|
+
`echo "TUNNEL_URL:\${TUNNEL_URL:-}"`,
|
|
951
952
|
`[ "\${PASS}" = "\${TOTAL}" ] && echo "VERDICT:COMPLETE" || echo "VERDICT:INCOMPLETE"`,
|
|
952
953
|
]
|
|
953
954
|
.filter(Boolean)
|
|
@@ -958,10 +959,11 @@ fi
|
|
|
958
959
|
const checks = {};
|
|
959
960
|
const lines = stdout.split('\n');
|
|
960
961
|
for (const line of lines) {
|
|
961
|
-
const m = line.match(/^(\w+):(
|
|
962
|
+
const m = line.match(/^(\w+):(\w+)\b(.*)/);
|
|
962
963
|
if (m) checks[m[1]] = { status: m[2], detail: (m[3] || '').trim() };
|
|
963
964
|
}
|
|
964
965
|
const scoreMatch = stdout.match(/SCORE:(\d+)\/(\d+)/);
|
|
966
|
+
const tunnelMatch = stdout.match(/TUNNEL_URL:(https:\/\/[^\s]+)/);
|
|
965
967
|
const complete = /VERDICT:COMPLETE/.test(stdout);
|
|
966
968
|
|
|
967
969
|
const missing = [];
|
|
@@ -977,6 +979,7 @@ fi
|
|
|
977
979
|
checkType: isCrossPlatform ? 'cross-platform' : 'standard',
|
|
978
980
|
checks,
|
|
979
981
|
score: scoreMatch ? { pass: parseInt(scoreMatch[1], 10), total: parseInt(scoreMatch[2], 10) } : null,
|
|
982
|
+
publicUrl: tunnelMatch ? tunnelMatch[1] : undefined,
|
|
980
983
|
missingSteps: missing.length > 0 ? missing.join(', ') : undefined,
|
|
981
984
|
nextStep: !complete
|
|
982
985
|
? missing.includes('devbridge_tunnel') || missing.includes('tunnel_url_accessible')
|
|
@@ -474,6 +474,7 @@ function installRuntimeDeps(pluginsDir) {
|
|
|
474
474
|
};
|
|
475
475
|
let r = spawnSync('npm', ['install', '--omit=dev'], spawnOpts);
|
|
476
476
|
const isRetryable = (res) => {
|
|
477
|
+
if (res.status === 0) return false;
|
|
477
478
|
const stderr = (res.stderr || '').toString();
|
|
478
479
|
return res.error?.code === 'EPERM' || res.error?.code === 'EBUSY' || /EPERM|EBUSY/.test(stderr);
|
|
479
480
|
};
|
|
@@ -482,6 +483,11 @@ function installRuntimeDeps(pluginsDir) {
|
|
|
482
483
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 2000);
|
|
483
484
|
r = spawnSync('npm', ['install', '--omit=dev'], spawnOpts);
|
|
484
485
|
}
|
|
486
|
+
if (r.status !== 0 && !isRetryable(r)) {
|
|
487
|
+
console.log(` \x1b[33m[RETRY]\x1b[0m npm install failed (exit ${r.status}), retrying in 3s...`);
|
|
488
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 3000);
|
|
489
|
+
r = spawnSync('npm', ['install', '--omit=dev'], spawnOpts);
|
|
490
|
+
}
|
|
485
491
|
const undiciDir = join(pluginsDir, 'node_modules', 'undici');
|
|
486
492
|
if (r.status === 0 && existsSync(undiciDir)) {
|
|
487
493
|
console.log(` Runtime deps installed -> ${join(pluginsDir, 'node_modules')}`);
|
|
@@ -489,12 +495,14 @@ function installRuntimeDeps(pluginsDir) {
|
|
|
489
495
|
const errCode = r.error?.code;
|
|
490
496
|
const err = (r.stderr || '').toString().trim().split(/\r?\n/).slice(-2).join(' ');
|
|
491
497
|
const hint = errCode === 'ENOENT' ? ' (npm not found — ensure Node.js/npm is in PATH)' : '';
|
|
492
|
-
|
|
498
|
+
const msg = `npm install failed in ${pluginsDir}${err ? `: ${err}` : ''}${hint}`;
|
|
499
|
+
console.log(` \x1b[31m[ERROR]\x1b[0m ${msg}`);
|
|
493
500
|
console.log(' Manual fix: cd %s && npm install', pluginsDir);
|
|
494
501
|
if (!existsSync(undiciDir)) {
|
|
495
502
|
console.log(` \x1b[31m[ERROR]\x1b[0m undici is NOT installed. MCP server will fail to start.`);
|
|
496
503
|
console.log(` Run manually: cd "${pluginsDir}" && npm install undici@^8.10.0`);
|
|
497
504
|
}
|
|
505
|
+
throw new Error(msg);
|
|
498
506
|
}
|
|
499
507
|
}
|
|
500
508
|
|
|
@@ -106,6 +106,10 @@ function hermesSkillsDir() {
|
|
|
106
106
|
return join(home, '.hermes', 'skills');
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
function codexDesktopSkillsDir() {
|
|
110
|
+
return join(homedir(), '.agents', 'skills');
|
|
111
|
+
}
|
|
112
|
+
|
|
109
113
|
export function listSkillDirs(root) {
|
|
110
114
|
if (!existsSync(root)) return [];
|
|
111
115
|
try {
|
|
@@ -135,6 +139,7 @@ function resolveSkillsRoot() {
|
|
|
135
139
|
workbuddySkillsDir(),
|
|
136
140
|
officeaceSkillsRoot(),
|
|
137
141
|
hermesSkillsDir(),
|
|
142
|
+
codexDesktopSkillsDir(),
|
|
138
143
|
]) || SKILLS_ROOT_DEV
|
|
139
144
|
);
|
|
140
145
|
}
|
|
@@ -1228,7 +1233,10 @@ async function runApprovedCommand(args = {}) {
|
|
|
1228
1233
|
}
|
|
1229
1234
|
const strictPlan = planHcloudCommand(args.args || [], { allowWrites: false });
|
|
1230
1235
|
const plan = planHcloudCommand(args.args || [], { allowWrites: true });
|
|
1231
|
-
|
|
1236
|
+
const approved = String(args.approvedCommand || '');
|
|
1237
|
+
const planned = String(plan.command || '');
|
|
1238
|
+
const normalized = (s) => s.replace(/--\S+[= ]<redacted>/g, '--<placeholder>');
|
|
1239
|
+
if (normalized(approved) !== normalized(planned)) {
|
|
1232
1240
|
throw new Error('approvedCommand must exactly match the planned hcloud command.');
|
|
1233
1241
|
}
|
|
1234
1242
|
const result = await runHcloud(args.args || [], {
|