huaweicloud-devkit 0.1.21-dev.0 → 0.1.23
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 +22 -1
- package/package.json +42 -42
- package/plugins/huaweicloud-core/.claude-plugin/plugin.json +43 -43
- package/plugins/huaweicloud-core/.codex-plugin/plugin.json +42 -42
- package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +43 -43
- package/plugins/huaweicloud-core/src/setup-cli.mjs +214 -12
- package/plugins/huaweicloud-core/src/tools.mjs +5 -0
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
帮助 AI 编码助手安全、准确地使用华为云——技能引导、KooCLI 工具、安全策略一站式集成。
|
|
7
7
|
|
|
8
|
-
HuaweiCloud DevKit 为 AI 编码助手提供操作华为云所需的知识、工具和安全护栏,支持 OpenCode、Codex、Claude Code、Cursor
|
|
8
|
+
HuaweiCloud DevKit 为 AI 编码助手提供操作华为云所需的知识、工具和安全护栏,支持 OpenCode、Codex、Claude Code、Cursor、码道(CodeArts Agent)等主流 Agent。
|
|
9
9
|
|
|
10
10
|
## 快速开始
|
|
11
11
|
|
|
@@ -42,6 +42,27 @@ npx --yes huaweicloud-devkit install --target codex
|
|
|
42
42
|
/plugin install huaweicloud-core@huaweicloud-devkit
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
### CodeArts Agent(码道)
|
|
46
|
+
|
|
47
|
+
码道没有插件市场,通过技能 + MCP 机制适配:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx --yes huaweicloud-devkit install --target codearts
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
自动安装 27 个技能到 `~/.codeartsdoer/skills/` 与项目级 `.codeartsdoer/skills/`,MCP 服务器注册到用户级与项目级 `.codeartsdoer/mcp/mcp_settings.json`。若本机已存在 KooCLI(`~/hcloud/hcloud.exe`),会自动将 `HCLOUD_BIN` 注入 MCP 配置。安装后**重启会话**使 MCP 工具生效。
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx --yes huaweicloud-devkit install-hcloud # 安装 KooCLI(自动接受隐私协议)
|
|
57
|
+
npx --yes huaweicloud-devkit doctor # 自检:hcloud、MCP、技能、沙箱模式
|
|
58
|
+
npx --yes huaweicloud-devkit status --target codearts # 查看码道安装状态
|
|
59
|
+
npx --yes huaweicloud-devkit uninstall --target codearts # 卸载
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> **沙箱模式**:码道默认 `bash_mode: sandbox` 会阻止 KooCLI 写入配置目录(如 `~/.hcloud/root`),导致隐私协议无法持久化、KooCLI 无法运行。`install-hcloud` 会自动检测沙箱模式并给出明确指引——请在**码道外终端**安装使用 KooCLI,或在码道设置中关闭沙箱模式(设置 → 权限 → Bash 模式)后重试。
|
|
63
|
+
>
|
|
64
|
+
> **认证**:KooCLI 就绪后,还需在码道外终端执行 `hcloud configure init` 配置 AK/SK 与区域,然后即可在码道中描述你的华为云任务。
|
|
65
|
+
|
|
45
66
|
### Cursor
|
|
46
67
|
|
|
47
68
|
通过 **设置 → 插件 → 团队市场 → 添加市场 → 从仓库导入**,指向 `huaweicloud-mate/huaweicloud-devkit`。
|
package/package.json
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
2
|
+
"name": "huaweicloud-devkit",
|
|
3
|
+
"version": "0.1.23",
|
|
4
|
+
"description": "Agent toolkit that helps coding agents use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities safely and accurately.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"bin",
|
|
8
|
+
".agents",
|
|
9
|
+
"plugins/huaweicloud-core",
|
|
10
|
+
"integrations/opencode"
|
|
11
|
+
],
|
|
12
|
+
"bin": {
|
|
13
|
+
"huaweicloud-devkit": "./bin/setup.cjs"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/huaweicloud-mate/huaweicloud-devkit.git"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "node --test",
|
|
21
|
+
"lint:md": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#.git\" \"#test/**\" \"#docs/**\"",
|
|
22
|
+
"lint": "npm run lint:md",
|
|
23
|
+
"validate": "node ./scripts/validate-package.mjs",
|
|
24
|
+
"postinstall": "node -e \"console.log(\u0027\\nHuaweiCloud DevKit installed. Run: npx huaweicloud-devkit install\\n\u0027)\""
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"markdownlint-cli2": "^0.23.2"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"huaweicloud",
|
|
31
|
+
"huawei-cloud",
|
|
32
|
+
"agent",
|
|
33
|
+
"codex",
|
|
34
|
+
"opencode",
|
|
35
|
+
"mcp",
|
|
36
|
+
"koocli",
|
|
37
|
+
"hcloud"
|
|
38
|
+
],
|
|
39
|
+
"license": "Apache-2.0",
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": "\u003e=20"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
2
|
+
"interface": {
|
|
3
|
+
"displayName": "HuaweiCloud Devkit",
|
|
4
|
+
"shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
|
|
5
|
+
"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.",
|
|
6
|
+
"developerName": "HuaweiCloud Mate",
|
|
7
|
+
"category": "Cloud",
|
|
8
|
+
"capabilities": [
|
|
9
|
+
"Read",
|
|
10
|
+
"Interactive"
|
|
11
|
+
],
|
|
12
|
+
"websiteURL": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
13
|
+
"brandColor": "#C7000B",
|
|
14
|
+
"defaultPrompt": [
|
|
15
|
+
"Help me choose the right Huawei Cloud capability.",
|
|
16
|
+
"Check my Huawei Cloud CLI setup safely.",
|
|
17
|
+
"Plan this Huawei Cloud API or SDK task."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"mcpServers": "./.mcp.json",
|
|
21
|
+
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
22
|
+
"skills": "./skills/",
|
|
23
|
+
"version": "0.1.23",
|
|
24
|
+
"author": {
|
|
25
|
+
"name": "HuaweiCloud Mate",
|
|
26
|
+
"url": "https://github.com/huaweicloud-mate"
|
|
27
|
+
},
|
|
28
|
+
"hooks": "./hooks/",
|
|
29
|
+
"name": "huaweicloud-core",
|
|
30
|
+
"homepage": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
31
|
+
"repository": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
32
|
+
"license": "Apache-2.0",
|
|
33
|
+
"keywords": [
|
|
34
|
+
"huaweicloud",
|
|
35
|
+
"huawei-cloud",
|
|
36
|
+
"koocli",
|
|
37
|
+
"hcloud",
|
|
38
|
+
"agent",
|
|
39
|
+
"mcp",
|
|
40
|
+
"api",
|
|
41
|
+
"sdk",
|
|
42
|
+
"skills"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
2
|
+
"name": "huaweicloud-core",
|
|
3
|
+
"version": "0.1.23",
|
|
4
|
+
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "HuaweiCloud Mate",
|
|
7
|
+
"url": "https://github.com/huaweicloud-mate"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
10
|
+
"repository": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
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
|
+
],
|
|
23
|
+
"skills": "./skills/",
|
|
24
|
+
"mcpServers": "./.mcp.json",
|
|
25
|
+
"interface": {
|
|
26
|
+
"displayName": "HuaweiCloud Devkit",
|
|
27
|
+
"shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
|
|
28
|
+
"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.",
|
|
29
|
+
"developerName": "HuaweiCloud Mate",
|
|
30
|
+
"category": "Cloud",
|
|
31
|
+
"capabilities": [
|
|
32
|
+
"Read",
|
|
33
|
+
"Interactive"
|
|
34
|
+
],
|
|
35
|
+
"websiteURL": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
36
|
+
"brandColor": "#C7000B",
|
|
37
|
+
"defaultPrompt": [
|
|
38
|
+
"Help me choose the right Huawei Cloud capability.",
|
|
39
|
+
"Check my Huawei Cloud CLI setup safely.",
|
|
40
|
+
"Plan this Huawei Cloud API or SDK task."
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
2
|
+
"interface": {
|
|
3
|
+
"displayName": "HuaweiCloud Devkit",
|
|
4
|
+
"shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
|
|
5
|
+
"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.",
|
|
6
|
+
"developerName": "HuaweiCloud Mate",
|
|
7
|
+
"category": "Cloud",
|
|
8
|
+
"capabilities": [
|
|
9
|
+
"Read",
|
|
10
|
+
"Interactive"
|
|
11
|
+
],
|
|
12
|
+
"websiteURL": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
13
|
+
"brandColor": "#C7000B",
|
|
14
|
+
"defaultPrompt": [
|
|
15
|
+
"Help me choose the right Huawei Cloud capability.",
|
|
16
|
+
"Check my Huawei Cloud CLI setup safely.",
|
|
17
|
+
"Plan this Huawei Cloud API or SDK task."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"mcpServers": "./.mcp.json",
|
|
21
|
+
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
22
|
+
"skills": "./skills/",
|
|
23
|
+
"version": "0.1.23",
|
|
24
|
+
"author": {
|
|
25
|
+
"name": "HuaweiCloud Mate",
|
|
26
|
+
"url": "https://github.com/huaweicloud-mate"
|
|
27
|
+
},
|
|
28
|
+
"hooks": "./hooks/",
|
|
29
|
+
"name": "huaweicloud-core",
|
|
30
|
+
"homepage": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
31
|
+
"repository": "https://github.com/huaweicloud-mate/huaweicloud-devkit",
|
|
32
|
+
"license": "Apache-2.0",
|
|
33
|
+
"keywords": [
|
|
34
|
+
"huaweicloud",
|
|
35
|
+
"huawei-cloud",
|
|
36
|
+
"koocli",
|
|
37
|
+
"hcloud",
|
|
38
|
+
"agent",
|
|
39
|
+
"mcp",
|
|
40
|
+
"api",
|
|
41
|
+
"sdk",
|
|
42
|
+
"skills"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -37,6 +37,63 @@ function codexDesktopCommandsDir() { return join(homedir(), '.agents', 'commands
|
|
|
37
37
|
function codexDesktopPluginsDir() { return join(homedir(), '.agents', 'huaweicloud-plugins'); }
|
|
38
38
|
function codexDesktopConfigFile() { return join(homedir(), '.agents', 'opencode.json'); }
|
|
39
39
|
|
|
40
|
+
function codeartsSkillsDir() { return join(homedir(), '.codeartsdoer', 'skills'); }
|
|
41
|
+
function codeartsMcpSettingsDir() { return join(homedir(), '.codeartsdoer', 'mcp'); }
|
|
42
|
+
function codeartsMcpSettingsFile() { return join(codeartsMcpSettingsDir(), 'mcp_settings.json'); }
|
|
43
|
+
function codeartsProjectDir() { return join(process.cwd(), '.codeartsdoer'); }
|
|
44
|
+
function codeartsProjectSkillsDir() { return join(codeartsProjectDir(), 'skills'); }
|
|
45
|
+
function codeartsProjectMcpSettingsFile() { return join(codeartsProjectDir(), 'mcp', 'mcp_settings.json'); }
|
|
46
|
+
function codeartsPluginsDir() { return join(homedir(), '.codeartsdoer', 'huaweicloud-plugins'); }
|
|
47
|
+
|
|
48
|
+
// Detect CodeArts sandbox mode (bash_mode in permission config).
|
|
49
|
+
function detectCodeartsSandbox() {
|
|
50
|
+
try {
|
|
51
|
+
const configPath = join(homedir(), '.codeartsdoer', 'codearts-data', 'storage', 'permission', 'config.json');
|
|
52
|
+
if (!existsSync(configPath)) return null;
|
|
53
|
+
const config = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
54
|
+
return typeof config.bash_mode === 'string' ? config.bash_mode : null;
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Locate an existing hcloud executable (HCLOUD_BIN, ~/hcloud on Windows, ~/.local/bin elsewhere).
|
|
61
|
+
function findHcloudBin() {
|
|
62
|
+
if (process.env.HCLOUD_BIN && existsSync(process.env.HCLOUD_BIN)) return process.env.HCLOUD_BIN;
|
|
63
|
+
const isWin = platform() === 'win32';
|
|
64
|
+
const candidates = isWin
|
|
65
|
+
? [join(homedir(), 'hcloud', 'hcloud.exe')]
|
|
66
|
+
: [join(homedir(), '.local', 'bin', 'hcloud'), join(homedir(), 'hcloud', 'hcloud'), join(homedir(), 'hcloud', 'hcloud.exe')];
|
|
67
|
+
for (const c of candidates) {
|
|
68
|
+
if (existsSync(c)) return c;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function printSandboxWarning(reason) {
|
|
74
|
+
console.log(`\n\x1b[1m\x1b[31m⚠ 检测到码道沙箱模式 (bash_mode: sandbox)\x1b[0m`);
|
|
75
|
+
console.log(`\x1b[31m ${reason}\x1b[0m`);
|
|
76
|
+
console.log(`\x1b[31m 请任选其一继续:\x1b[0m`);
|
|
77
|
+
console.log(`\x1b[31m A. 在码道外的终端安装并使用 KooCLI (推荐):`);
|
|
78
|
+
console.log(`\x1b[31m https://support.huaweicloud.com/qs-hcli/hcli_02_003.html`);
|
|
79
|
+
console.log(`\x1b[31m B. 在码道设置中关闭沙箱模式后重试 (设置 → 权限 → Bash 模式)`);
|
|
80
|
+
console.log(`\x1b[31m 关闭沙箱后重新运行: npx huaweicloud-devkit install-hcloud\x1b[0m`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Try to auto-accept the KooCLI privacy agreement by answering 'y' on stdin.
|
|
84
|
+
// Returns true when hcloud runs without re-prompting for the agreement.
|
|
85
|
+
function acceptKooCliPrivacy(hcloudBin) {
|
|
86
|
+
const run = () => spawnSync(hcloudBin, ['version'], {
|
|
87
|
+
encoding: 'utf8', timeout: 10000, windowsHide: true, input: 'y\n',
|
|
88
|
+
});
|
|
89
|
+
const first = run();
|
|
90
|
+
const out = (first.stdout || '') + (first.stderr || '');
|
|
91
|
+
if (!/同意并继续使用|agree/i.test(out)) return first.status === 0;
|
|
92
|
+
const second = run();
|
|
93
|
+
const out2 = (second.stdout || '') + (second.stderr || '');
|
|
94
|
+
return second.status === 0 && !/同意并继续使用/.test(out2);
|
|
95
|
+
}
|
|
96
|
+
|
|
40
97
|
function checkNode() {
|
|
41
98
|
const v = process.versions.node.split('.').map(Number);
|
|
42
99
|
if (v[0] < 20) {
|
|
@@ -103,8 +160,10 @@ function hasCodexCLI() {
|
|
|
103
160
|
}
|
|
104
161
|
|
|
105
162
|
function checkHcloud() {
|
|
106
|
-
const
|
|
107
|
-
|
|
163
|
+
const bin = findHcloudBin() || (process.env.HCLOUD_BIN || 'hcloud');
|
|
164
|
+
const r = spawnSync(`"${bin}" version`, [], { shell: true, windowsHide: true, stdio: 'pipe', timeout: 5000, input: 'y\n' });
|
|
165
|
+
const out = (r.stdout ? r.stdout.toString() : '') + (r.stderr ? r.stderr.toString() : '');
|
|
166
|
+
return r.status === 0 && /KooCLI|Current.*version|当前KooCLI/i.test(out);
|
|
108
167
|
}
|
|
109
168
|
|
|
110
169
|
function getMarketplaceName() {
|
|
@@ -274,6 +333,96 @@ function uninstallCodexDesktop() {
|
|
|
274
333
|
}
|
|
275
334
|
}
|
|
276
335
|
|
|
336
|
+
function registerCodeartsMcp(configPath) {
|
|
337
|
+
const mcpPath = join(codeartsPluginsDir(), 'src', 'mcp-server.mjs').replace(/\\/g, '/');
|
|
338
|
+
let config = {};
|
|
339
|
+
if (existsSync(configPath)) {
|
|
340
|
+
try { config = JSON.parse(readFileSync(configPath, 'utf8')); } catch {}
|
|
341
|
+
}
|
|
342
|
+
config.mcpServers = config.mcpServers || {};
|
|
343
|
+
const env = { HUAWEICLOUD_AGENT_TOOLKIT_MODE: 'local' };
|
|
344
|
+
const hcloudBin = findHcloudBin();
|
|
345
|
+
if (hcloudBin) env.HCLOUD_BIN = hcloudBin.replace(/\\/g, '/');
|
|
346
|
+
config.mcpServers.huaweicloud = {
|
|
347
|
+
command: 'node',
|
|
348
|
+
args: [mcpPath],
|
|
349
|
+
env,
|
|
350
|
+
enabled: true,
|
|
351
|
+
};
|
|
352
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
353
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
354
|
+
console.log(` MCP config updated: ${configPath}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
async function installCodeArts() {
|
|
358
|
+
const skillsSrc = join(PLUGIN_ROOT, 'skills');
|
|
359
|
+
const srcDir = join(PLUGIN_ROOT, 'src');
|
|
360
|
+
const safetyDir = join(PLUGIN_ROOT, 'safety');
|
|
361
|
+
|
|
362
|
+
copyDir(skillsSrc, codeartsSkillsDir());
|
|
363
|
+
console.log(` Skills -> ${codeartsSkillsDir()}`);
|
|
364
|
+
copyDir(skillsSrc, codeartsProjectSkillsDir());
|
|
365
|
+
console.log(` Skills -> ${codeartsProjectSkillsDir()}`);
|
|
366
|
+
|
|
367
|
+
const pluginDest = codeartsPluginsDir();
|
|
368
|
+
copyDir(srcDir, join(pluginDest, 'src'));
|
|
369
|
+
console.log(` MCP Server -> ${join(pluginDest, 'src')}`);
|
|
370
|
+
copyDir(safetyDir, join(pluginDest, 'safety'));
|
|
371
|
+
console.log(` Safety Policy -> ${join(pluginDest, 'safety')}`);
|
|
372
|
+
|
|
373
|
+
registerCodeartsMcp(codeartsMcpSettingsFile());
|
|
374
|
+
registerCodeartsMcp(codeartsProjectMcpSettingsFile());
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function uninstallCodeArts() {
|
|
378
|
+
let removed = 0;
|
|
379
|
+
for (const skillsDir of [codeartsSkillsDir(), codeartsProjectSkillsDir()]) {
|
|
380
|
+
if (!existsSync(skillsDir)) continue;
|
|
381
|
+
for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
|
|
382
|
+
if (entry.name.startsWith('huawei')) {
|
|
383
|
+
removeIfExists(join(skillsDir, entry.name));
|
|
384
|
+
removed++;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (removed > 0) console.log(` Removed ${removed} skills`);
|
|
389
|
+
|
|
390
|
+
if (removeIfExists(codeartsPluginsDir())) {
|
|
391
|
+
console.log(' Removed MCP server and safety policy');
|
|
392
|
+
}
|
|
393
|
+
for (const configPath of [codeartsMcpSettingsFile(), codeartsProjectMcpSettingsFile()]) {
|
|
394
|
+
if (!existsSync(configPath)) continue;
|
|
395
|
+
let config = {};
|
|
396
|
+
try { config = JSON.parse(readFileSync(configPath, 'utf8')); } catch {}
|
|
397
|
+
if (config.mcpServers?.huaweicloud) {
|
|
398
|
+
delete config.mcpServers.huaweicloud;
|
|
399
|
+
if (Object.keys(config.mcpServers).length === 0) delete config.mcpServers;
|
|
400
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
401
|
+
console.log(` Config cleaned: ${configPath}`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function codeartsStatus() {
|
|
407
|
+
const pluginDir = codeartsPluginsDir();
|
|
408
|
+
console.log(` MCP Server: ${existsSync(join(pluginDir, 'src', 'mcp-server.mjs')) ? '\x1b[32mInstalled\x1b[0m' : '\x1b[31mNot installed\x1b[0m'}`);
|
|
409
|
+
console.log(` Safety Policy: ${existsSync(join(pluginDir, 'safety', 'policy.json')) ? '\x1b[32mInstalled\x1b[0m' : '\x1b[31mNot installed\x1b[0m'}`);
|
|
410
|
+
let skillCount = 0;
|
|
411
|
+
if (existsSync(codeartsSkillsDir())) {
|
|
412
|
+
skillCount = readdirSync(codeartsSkillsDir(), { withFileTypes: true })
|
|
413
|
+
.filter((d) => d.isDirectory() && d.name.startsWith('huawei')).length;
|
|
414
|
+
}
|
|
415
|
+
console.log(` Skills: ${skillCount > 0 ? `\x1b[32m${skillCount} installed\x1b[0m` : '\x1b[31mNot installed\x1b[0m'}`);
|
|
416
|
+
if (existsSync(codeartsMcpSettingsFile())) {
|
|
417
|
+
try {
|
|
418
|
+
const config = JSON.parse(readFileSync(codeartsMcpSettingsFile(), 'utf8'));
|
|
419
|
+
console.log(` MCP config: ${config.mcpServers?.huaweicloud ? '\x1b[32mConfigured\x1b[0m' : '\x1b[31mNot configured\x1b[0m'}`);
|
|
420
|
+
} catch {
|
|
421
|
+
console.log(` MCP config: \x1b[31mInvalid\x1b[0m`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
277
426
|
function opencodeStatus() {
|
|
278
427
|
const pluginDir = opencodePluginsDir();
|
|
279
428
|
const skillsDir = opencodeSkillsDir();
|
|
@@ -302,6 +451,7 @@ function parseTarget() {
|
|
|
302
451
|
const val = (process.argv[idx + 1] || '').toLowerCase();
|
|
303
452
|
if (val === 'codex') return 'codex';
|
|
304
453
|
if (val === 'codex-desktop') return 'codex-desktop';
|
|
454
|
+
if (val === 'codearts') return 'codearts';
|
|
305
455
|
if (val === 'all') return 'all';
|
|
306
456
|
return 'opencode';
|
|
307
457
|
}
|
|
@@ -320,6 +470,10 @@ async function cmdInstall() {
|
|
|
320
470
|
console.log('\n[Codex Desktop]');
|
|
321
471
|
await installCodexDesktop();
|
|
322
472
|
}
|
|
473
|
+
if (target === 'codearts' || target === 'all') {
|
|
474
|
+
console.log('\n[CodeArts]');
|
|
475
|
+
await installCodeArts();
|
|
476
|
+
}
|
|
323
477
|
if (target === 'codex' || target === 'all') {
|
|
324
478
|
console.log('\n[Codex]');
|
|
325
479
|
if (!hasCodexCLI()) {
|
|
@@ -336,8 +490,12 @@ async function cmdInstall() {
|
|
|
336
490
|
}
|
|
337
491
|
|
|
338
492
|
console.log(`\n\x1b[32mInstallation complete!\x1b[0m`);
|
|
493
|
+
const appName = target === 'codearts' ? 'CodeArts'
|
|
494
|
+
: target === 'codex-desktop' ? 'Codex Desktop'
|
|
495
|
+
: target === 'codex' ? 'Codex' : 'OpenCode';
|
|
496
|
+
const pad = ' '.repeat(24 - appName.length);
|
|
339
497
|
console.log(`\n\x1b[1m\x1b[33m╔══════════════════════════════════════════════════════╗`);
|
|
340
|
-
console.log(`\x1b[1m\x1b[33m║ MCP 工具在重启
|
|
498
|
+
console.log(`\x1b[1m\x1b[33m║ MCP 工具在重启 ${appName} 会话后才生效${pad}║`);
|
|
341
499
|
console.log(`\x1b[1m\x1b[33m║ 关闭当前会话 → 重新打开,直接描述华为云任务即可 ║`);
|
|
342
500
|
console.log(`\x1b[1m\x1b[33m║ 重启前请勿执行 hcloud 命令,避免 AK/SK 泄露 ║`);
|
|
343
501
|
console.log(`\x1b[1m\x1b[33m╚══════════════════════════════════════════════════════╝\x1b[0m`);
|
|
@@ -353,10 +511,14 @@ async function cmdInstall() {
|
|
|
353
511
|
console.log(`\nAfter restart + hcloud setup, run: npx huaweicloud-devkit doctor`);
|
|
354
512
|
|
|
355
513
|
// Write install marker for doctor to detect
|
|
356
|
-
|
|
514
|
+
const markerDir = target === 'codearts' ? codeartsPluginsDir() : opencodePluginsDir();
|
|
515
|
+
writeFileSync(join(markerDir, '.installed'), new Date().toISOString());
|
|
357
516
|
if (target === 'opencode' || target === 'all') {
|
|
358
517
|
console.log('Or describe your Huawei Cloud task in OpenCode');
|
|
359
518
|
}
|
|
519
|
+
if (target === 'codearts' || target === 'all') {
|
|
520
|
+
console.log('Or describe your Huawei Cloud task in CodeArts');
|
|
521
|
+
}
|
|
360
522
|
if (target === 'codex' || target === 'all') {
|
|
361
523
|
console.log('Or mention @huaweicloud-core in Codex');
|
|
362
524
|
}
|
|
@@ -371,6 +533,10 @@ async function cmdUninstall() {
|
|
|
371
533
|
console.log('[OpenCode]');
|
|
372
534
|
await uninstallOpenCode();
|
|
373
535
|
}
|
|
536
|
+
if (target === 'codearts' || target === 'all') {
|
|
537
|
+
console.log('\n[CodeArts]');
|
|
538
|
+
uninstallCodeArts();
|
|
539
|
+
}
|
|
374
540
|
if (target === 'codex' || target === 'all') {
|
|
375
541
|
console.log('\n[Codex]');
|
|
376
542
|
uninstallCodexDesktop();
|
|
@@ -392,6 +558,10 @@ async function cmdStatus() {
|
|
|
392
558
|
console.log('[OpenCode]');
|
|
393
559
|
opencodeStatus();
|
|
394
560
|
}
|
|
561
|
+
if (target === 'codearts' || target === 'all') {
|
|
562
|
+
console.log('\n[CodeArts]');
|
|
563
|
+
codeartsStatus();
|
|
564
|
+
}
|
|
395
565
|
if (target === 'codex' || target === 'all') {
|
|
396
566
|
console.log('\n[Codex]');
|
|
397
567
|
if (!hasCodexCLI()) {
|
|
@@ -449,11 +619,21 @@ async function cmdDoctor() {
|
|
|
449
619
|
check('OpenCode MCP configured', mcpConfigured, `Add MCP to ${opencodeCfg} — run: npx huaweicloud-devkit-test install`);
|
|
450
620
|
|
|
451
621
|
// hcloud CLI
|
|
452
|
-
const hcloudBin = process.env.HCLOUD_BIN || 'hcloud';
|
|
453
|
-
const hcloudCheck = spawnSync(`"${hcloudBin}" version`, [], { shell: true, windowsHide: true, stdio: 'pipe', timeout: 5000 });
|
|
454
|
-
const
|
|
622
|
+
const hcloudBin = findHcloudBin() || (process.env.HCLOUD_BIN || 'hcloud');
|
|
623
|
+
const hcloudCheck = spawnSync(`"${hcloudBin}" version`, [], { shell: true, windowsHide: true, stdio: 'pipe', timeout: 5000, input: 'y\n' });
|
|
624
|
+
const hcloudOut = (hcloudCheck.stdout || '').toString() + (hcloudCheck.stderr || '').toString();
|
|
625
|
+
const hcloudOk = hcloudCheck.status === 0 && /KooCLI|Current.*version|当前KooCLI/i.test(hcloudOut);
|
|
455
626
|
check('hcloud CLI installed', hcloudOk, 'Run: npx huaweicloud-devkit install-hcloud');
|
|
456
627
|
|
|
628
|
+
// CodeArts sandbox mode warning
|
|
629
|
+
const sandboxMode = detectCodeartsSandbox();
|
|
630
|
+
if (sandboxMode === 'sandbox') {
|
|
631
|
+
console.log(` \x1b[33m[WARN]\x1b[0m CodeArts sandbox mode active (bash_mode: sandbox)`);
|
|
632
|
+
console.log(` KooCLI may fail to write config in ~/.hcloud/ and hang on the privacy agreement.`);
|
|
633
|
+
console.log(` Fix: disable sandbox (Settings → Permissions) or use a terminal outside CodeArts.`);
|
|
634
|
+
warn++;
|
|
635
|
+
}
|
|
636
|
+
|
|
457
637
|
if (hcloudOk) {
|
|
458
638
|
const ver = (hcloudCheck.stdout.toString().match(/(\d+\.\d+\.\d+)/) || [])[1] || 'unknown';
|
|
459
639
|
console.log(` Version: ${ver}`);
|
|
@@ -465,7 +645,7 @@ async function cmdDoctor() {
|
|
|
465
645
|
}
|
|
466
646
|
|
|
467
647
|
// Skills
|
|
468
|
-
const skillsOptions = [opencodeSkillsDir(), codexDesktopSkillsDir()];
|
|
648
|
+
const skillsOptions = [opencodeSkillsDir(), codexDesktopSkillsDir(), codeartsSkillsDir()];
|
|
469
649
|
let skillCount = 0, skillsDir = '';
|
|
470
650
|
for (const dir of skillsOptions) {
|
|
471
651
|
if (!existsSync(dir)) continue;
|
|
@@ -561,11 +741,14 @@ async function cmdInstallHcloud() {
|
|
|
561
741
|
// Download
|
|
562
742
|
console.log(` Downloading ${url}...`);
|
|
563
743
|
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 });
|
|
744
|
+
const dl = spawnSync('powershell', ['-NoProfile', '-Command', psCmd], { stdio: 'inherit', windowsHide: true, timeout: 180000 });
|
|
745
|
+
if (dl.status !== 0) throw new Error(`下载失败 (PowerShell exit ${dl.status})`);
|
|
565
746
|
|
|
566
747
|
// Extract
|
|
567
748
|
console.log(' Extracting...');
|
|
568
|
-
spawnSync('powershell', ['-NoProfile', '-Command', `Expand-Archive -Path '${zipPath}' -DestinationPath '${installDir}' -Force`], { stdio: 'inherit', windowsHide: true });
|
|
749
|
+
const ex = spawnSync('powershell', ['-NoProfile', '-Command', `Expand-Archive -Path '${zipPath}' -DestinationPath '${installDir}' -Force`], { stdio: 'inherit', windowsHide: true, timeout: 60000 });
|
|
750
|
+
if (ex.status !== 0) throw new Error(`解压失败 (PowerShell exit ${ex.status})`);
|
|
751
|
+
if (!existsSync(join(installDir, 'hcloud.exe'))) throw new Error('hcloud.exe 未生成,可能已被安全软件拦截');
|
|
569
752
|
|
|
570
753
|
// Clean up zip
|
|
571
754
|
rmSync(zipPath, { force: true });
|
|
@@ -576,11 +759,29 @@ async function cmdInstallHcloud() {
|
|
|
576
759
|
|
|
577
760
|
console.log(`\n\x1b[32mInstall complete.\x1b[0m`);
|
|
578
761
|
console.log(` Verify: ${join(installDir, 'hcloud.exe')} version`);
|
|
762
|
+
|
|
763
|
+
// Auto-accept the KooCLI privacy agreement so first run does not hang
|
|
764
|
+
console.log('\n Accepting KooCLI privacy agreement...');
|
|
765
|
+
const hcloudBin = join(installDir, 'hcloud.exe');
|
|
766
|
+
if (acceptKooCliPrivacy(hcloudBin)) {
|
|
767
|
+
console.log(' \x1b[32mPrivacy agreement accepted. KooCLI ready.\x1b[0m');
|
|
768
|
+
} else {
|
|
769
|
+
console.log(' \x1b[33m无法自动接受隐私协议(可能因沙箱阻止写入配置目录)。\x1b[0m');
|
|
770
|
+
if (detectCodeartsSandbox() === 'sandbox') {
|
|
771
|
+
printSandboxWarning('KooCLI 需要写入配置目录 (如 ~/.hcloud/root) 以保存隐私协议同意状态,但沙箱模式阻止了写入。');
|
|
772
|
+
} else {
|
|
773
|
+
console.log(' 请在码道外终端运行一次: hcloud version 并按提示输入 y');
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
579
777
|
console.log(' Or restart terminal and: hcloud version');
|
|
580
778
|
} catch (e) {
|
|
581
779
|
console.log(`\n\x1b[33mAuto-install failed: ${e.message}\x1b[0m`);
|
|
582
780
|
console.log(` Manual: download ${url}, unzip to ${installDir}, add to PATH`);
|
|
583
781
|
console.log(` Guide: https://support.huaweicloud.com/qs-hcli/hcli_02_003_01.html`);
|
|
782
|
+
if (detectCodeartsSandbox() === 'sandbox') {
|
|
783
|
+
printSandboxWarning('沙箱模式拦截了 KooCLI 自动安装(无法创建/写入安装目录)。');
|
|
784
|
+
}
|
|
584
785
|
}
|
|
585
786
|
} else if (os === 'linux') {
|
|
586
787
|
console.log('[Linux] One-liner install:');
|
|
@@ -646,7 +847,7 @@ async function main() {
|
|
|
646
847
|
case '-h':
|
|
647
848
|
default:
|
|
648
849
|
console.log(BANNER);
|
|
649
|
-
console.log('Usage: npx huaweicloud-devkit <command> [--target <opencode|codex|all>]\n');
|
|
850
|
+
console.log('Usage: npx huaweicloud-devkit <command> [--target <opencode|codex|codearts|all>]\n');
|
|
650
851
|
console.log('Commands:');
|
|
651
852
|
console.log(' install Install skills, MCP server, safety policy');
|
|
652
853
|
console.log(' uninstall Remove installed files');
|
|
@@ -657,10 +858,11 @@ async function main() {
|
|
|
657
858
|
console.log(' install-hcloud Show KooCLI install commands for your OS');
|
|
658
859
|
console.log(' help Show this help');
|
|
659
860
|
console.log('\nOptions:');
|
|
660
|
-
console.log(' --target Target agent: opencode (default), codex, all');
|
|
861
|
+
console.log(' --target Target agent: opencode (default), codex, codearts, all');
|
|
661
862
|
console.log('\nExamples:');
|
|
662
863
|
console.log(' npx huaweicloud-devkit install');
|
|
663
864
|
console.log(' npx huaweicloud-devkit install --target codex');
|
|
865
|
+
console.log(' npx huaweicloud-devkit install --target codearts');
|
|
664
866
|
console.log(' npx huaweicloud-devkit install --target all');
|
|
665
867
|
break;
|
|
666
868
|
}
|
|
@@ -12,8 +12,13 @@ function opencodeSkillsDir() {
|
|
|
12
12
|
const home = homedir();
|
|
13
13
|
return join(home, '.config', 'opencode', 'skills');
|
|
14
14
|
}
|
|
15
|
+
function codeartsSkillsDir() {
|
|
16
|
+
const home = homedir();
|
|
17
|
+
return join(home, '.codeartsdoer', 'skills');
|
|
18
|
+
}
|
|
15
19
|
function resolveSkillsRoot() {
|
|
16
20
|
if (existsSync(SKILLS_ROOT_DEV)) return SKILLS_ROOT_DEV;
|
|
21
|
+
if (existsSync(codeartsSkillsDir())) return codeartsSkillsDir();
|
|
17
22
|
if (existsSync(opencodeSkillsDir())) return opencodeSkillsDir();
|
|
18
23
|
return SKILLS_ROOT_DEV;
|
|
19
24
|
}
|