huaweicloud-devkit 1.1.3-next.1 → 1.1.3-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
3
  "interface": {
4
- "displayName": "HuaweiCloud Devkit"
4
+ "displayName": "HuaweiCloud DevKit"
5
5
  },
6
6
  "plugins": [
7
7
  {
package/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
5
5
  [![CI](https://github.com/huaweicloud/huaweicloud-devkit/actions/workflows/ci.yml/badge.svg)](https://github.com/huaweicloud/huaweicloud-devkit/actions/workflows/ci.yml)
6
6
  [![npm version](https://img.shields.io/npm/v/huaweicloud-devkit)](https://www.npmjs.com/package/huaweicloud-devkit)
7
+ [![Beta](https://img.shields.io/badge/beta-v1.1.3-orange)](https://github.com/huaweicloud/huaweicloud-devkit)
7
8
 
8
9
  **[中文](README.zh-CN.md) | English**
9
10
 
@@ -31,7 +32,18 @@ Supports OpenCode, Codex, CodeArts Agent, WorkBuddy, DeepSeek Harness (DSH), Off
31
32
 
32
33
  ## Quick Start
33
34
 
34
- > If `--target` is omitted, the installer auto-detects agents on your machine. When multiple agents are detected, **all of them** will be installed. Specify `--target` to control which agent receives the install.
35
+ > If `--target` is omitted, the installer auto-detects agents on your machine:
36
+ >
37
+ > - **None detected**: interactive terminals ask what you want (install to one
38
+ > explicit target / install to all / wire up a generic MCP agent);
39
+ > non-interactive shells error out with the supported target list.
40
+ > - **One detected**: installs directly to it.
41
+ > - **Multiple detected**: interactive terminals show a multi-select chooser;
42
+ > non-interactive shells error and point at `--target <agent>` / `--target all`.
43
+ > For a one-shot full setup, run `npx --yes huaweicloud-devkit install --target all`
44
+ > (Codex is skipped when its CLI is missing).
45
+
46
+ The commands below are global (they act on every agent):
35
47
 
36
48
  ```bash
37
49
  npx --yes huaweicloud-devkit version # print CLI version and installed plugin versions per agent
@@ -51,7 +63,7 @@ npx --yes huaweicloud-devkit doctor --target opencode
51
63
  npx --yes huaweicloud-devkit status --target opencode
52
64
  npx --yes huaweicloud-devkit update --target opencode
53
65
  npx --yes huaweicloud-devkit uninstall --target opencode
54
- rm -rf ~/.npm/_npx/ # Linux/macOS only; Windows path TBD
66
+ rm -rf ~/.npm/_npx/ # Linux/macOS; Windows: rmdir /s /q %LOCALAPPDATA%\npm-cache\_npx
55
67
  ```
56
68
 
57
69
  ### Codex
@@ -211,7 +223,7 @@ npx --yes huaweicloud-devkit install --target openclaw
211
223
  npx --yes huaweicloud-devkit status --target openclaw
212
224
  npx --yes huaweicloud-devkit update --target openclaw
213
225
  npx --yes huaweicloud-devkit uninstall --target openclaw
214
- rm -rf ~/.npm/_npx/ # Linux/macOS only; Windows path TBD
226
+ rm -rf ~/.npm/_npx/ # Linux/macOS; Windows: rmdir /s /q %LOCALAPPDATA%\npm-cache\_npx
215
227
  ```
216
228
 
217
229
  ### AtomCode
@@ -256,7 +268,7 @@ If your agent supports `type: "remote"` (Streamable HTTP) instead of stdio, star
256
268
  npx --yes huaweicloud-devkit-mcp --transport remote
257
269
  ```
258
270
 
259
- It listens on `127.0.0.1:9528` by default (no conflict with the IACMCPServer port 9527). Then connect with a remote config (opencode example):
271
+ It listens on `127.0.0.1:9528` by default. Then connect with a remote config (opencode example):
260
272
 
261
273
  ```jsonc
262
274
  {
@@ -312,7 +324,7 @@ npx --yes huaweicloud-devkit install --target all
312
324
  ### Update All Agents
313
325
 
314
326
  ```bash
315
- npx huaweicloud-devkit version
327
+ npx --yes huaweicloud-devkit@latest version
316
328
  npx --yes huaweicloud-devkit@latest update --target all
317
329
  ```
318
330
 
@@ -322,7 +334,7 @@ locally cached older one.
322
334
 
323
335
  ## What It Does
324
336
 
325
- - **Guided cloud operations** — agents get step-by-step guidance for 20+ Huawei Cloud services (ECS, OBS, VPC, RDS, GaussDB, FunctionGraph, APIG, CCE, and more)
337
+ - **Guided cloud operations** — agents get step-by-step guidance for 20+ commonly used Huawei Cloud services (ECS, OBS, VPC, RDS, GaussDB, FunctionGraph, APIG, CCE, and more)
326
338
  - **Safety-first execution** — all write operations require explicit user approval; credentials and secrets are automatically redacted from output
327
339
  - **Pre-execution risk checks** — public exposure, credential leaks, and destructive operations are caught before they run
328
340
  - **Regional awareness** — auto-discovers available regions and checks service availability before creating resources
@@ -332,6 +344,10 @@ locally cached older one.
332
344
 
333
345
  ECS, OBS, VPC, IAM, RDS, GaussDB, FunctionGraph, APIG, CCE, SMN/DMS, ModelArts, Cloud Eye, CTS, DEW, Billing, CBR, WAF/AAD, DDS/DCS, Deployment, and Getting Started guides.
334
346
 
347
+ > Above is the pre-wired guidance list; the remaining 200+ Huawei Cloud services
348
+ > are still reachable via KooCLI / API / SDK routing (see capability-discovery
349
+ > and cli-and-auth meta-skills).
350
+
335
351
  ## Documentation
336
352
 
337
353
  - [Architecture](docs/architecture.md)
package/README.zh-CN.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # HuaweiCloud DevKit
2
2
 
3
- [![参与讨论](https://img.shields.io/badge/参与讨论-Join%20the%20discussion-blue)](https://github.com/huaweicloud/huaweicloud-devkit/discussions)
3
+ [![Discussions](https://img.shields.io/badge/Discussions-Join%20the%20discussion-blue)](https://github.com/huaweicloud/huaweicloud-devkit/discussions)
4
4
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
5
5
  [![CI](https://github.com/huaweicloud/huaweicloud-devkit/actions/workflows/ci.yml/badge.svg)](https://github.com/huaweicloud/huaweicloud-devkit/actions/workflows/ci.yml)
6
6
  [![npm version](https://img.shields.io/npm/v/huaweicloud-devkit)](https://www.npmjs.com/package/huaweicloud-devkit)
7
+ [![Beta](https://img.shields.io/badge/beta-v1.1.3-orange)](https://github.com/huaweicloud/huaweicloud-devkit)
7
8
 
8
9
  **中文 | [English](README.md)**
9
10
 
@@ -31,7 +32,14 @@
31
32
 
32
33
  ## 快速开始
33
34
 
34
- > 省略 `--target` 时,安装器会自动检测机器上的 agent,检测到多个时**全部安装**。建议始终指定 `--target` 以明确安装目标。
35
+ > 省略 `--target` 时,安装器会自动检测机器上的 agent:
36
+ >
37
+ > - **未检测到**:交互终端会询问你如何继续(指定 target 安装 / 全部安装 / 接入通用 MCP agent);非交互终端报错并列出支持列表。
38
+ > - **检测到单个**:直接安装到该 agent。
39
+ > - **检测到多个**:交互终端弹出多选;非交互终端报错并提示 `--target <agent>` 或 `--target all`。
40
+ > 需要一步全量安装时执行 `npx --yes huaweicloud-devkit install --target all`(Codex 缺少 CLI 时跳过)。
41
+
42
+ 以下为全局命令(一次性作用于所有 agent):
35
43
 
36
44
  ```bash
37
45
  npx --yes huaweicloud-devkit version # 查看 CLI 版本和各 agent 已安装的插件版本
@@ -51,7 +59,7 @@ npx --yes huaweicloud-devkit doctor --target opencode
51
59
  npx --yes huaweicloud-devkit status --target opencode
52
60
  npx --yes huaweicloud-devkit update --target opencode
53
61
  npx --yes huaweicloud-devkit uninstall --target opencode
54
- rm -rf ~/.npm/_npx/ # 仅 Linux/macOS;Windows 路径待确认
62
+ rm -rf ~/.npm/_npx/ # 仅 Linux/macOS;Windows:rmdir /s /q %LOCALAPPDATA%\npm-cache\_npx
55
63
  ```
56
64
 
57
65
  ### Codex
@@ -211,7 +219,7 @@ npx --yes huaweicloud-devkit install --target openclaw
211
219
  npx --yes huaweicloud-devkit status --target openclaw
212
220
  npx --yes huaweicloud-devkit update --target openclaw
213
221
  npx --yes huaweicloud-devkit uninstall --target openclaw
214
- rm -rf ~/.npm/_npx/ # 仅 Linux/macOS;Windows 路径待确认
222
+ rm -rf ~/.npm/_npx/ # 仅 Linux/macOS;Windows:rmdir /s /q %LOCALAPPDATA%\npm-cache\_npx
215
223
  ```
216
224
 
217
225
  ### AtomCode
@@ -256,7 +264,7 @@ npx --yes huaweicloud-devkit uninstall --target atomcode
256
264
  npx --yes huaweicloud-devkit-mcp --transport remote
257
265
  ```
258
266
 
259
- 默认监听 `127.0.0.1:9528`(与预置的 IACMCPServer 端口 9527 不冲突)。随后以远程方式连接(以 opencode 为例):
267
+ 默认监听 `127.0.0.1:9528`。随后以远程方式连接(以 opencode 为例):
260
268
 
261
269
  ```jsonc
262
270
  {
@@ -312,7 +320,7 @@ npx --yes huaweicloud-devkit install --target all
312
320
  ### 更新所有 Agent
313
321
 
314
322
  ```bash
315
- npx huaweicloud-devkit version
323
+ npx --yes huaweicloud-devkit@latest version
316
324
  npx --yes huaweicloud-devkit@latest update --target all
317
325
  ```
318
326
 
@@ -320,7 +328,7 @@ npx --yes huaweicloud-devkit@latest update --target all
320
328
 
321
329
  ## 功能特性
322
330
 
323
- - **引导式云操作** — Agent 获得 20+ 华为云服务的分步操作指引(ECS、OBS、VPC、RDS、GaussDB、FunctionGraph、APIG、CCE 等)
331
+ - **引导式云操作** — Agent 获得 20+ 常用华为云服务的分步操作指引(ECS、OBS、VPC、RDS、GaussDB、FunctionGraph、APIG、CCE 等)
324
332
  - **安全优先执行** — 所有写操作需用户明确批准;凭证和密钥自动脱敏
325
333
  - **执行前风险检查** — 公网暴露、凭证泄露、破坏性操作在执行前即被拦截
326
334
  - **区域感知** — 自动发现可用区域,创建资源前检查服务可用性
@@ -330,6 +338,8 @@ npx --yes huaweicloud-devkit@latest update --target all
330
338
 
331
339
  ECS、OBS、VPC、IAM、RDS、GaussDB、FunctionGraph、APIG、CCE、SMN/DMS、ModelArts、Cloud Eye、CTS、DEW、Billing、CBR、WAF/AAD、DDS/DCS、Deployment,以及入门指南。
332
340
 
341
+ > 以上为预置指引的服务列表;其余 200+ 华为云服务仍可通过 KooCLI / API / SDK 路由调用(见 capability-discovery 与 cli-and-auth 元技能)。
342
+
333
343
  ## 文档
334
344
 
335
345
  - [架构](docs/architecture.md)
@@ -2,7 +2,7 @@
2
2
  description: Self-check Huawei Cloud DevKit readiness — hcloud, MCP, skills, auth.
3
3
  ---
4
4
 
5
- Use HuaweiCloud Devkit tools and skills to perform a comprehensive readiness check:
5
+ Use HuaweiCloud DevKit tools and skills to perform a comprehensive readiness check:
6
6
 
7
7
  1. Check if KooCLI `hcloud` is installed: `huaweicloud_check_cli`. If not, guide user to install.
8
8
  2. Check if hcloud has active credentials: `hcloud configure list` (redacted).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: huaweicloud-core
3
- description: OpenCode entry skill for HuaweiCloud Devkit. Use when a developer asks OpenCode to use Huawei Cloud Skills, KooCLI, APIs, SDKs, future MCP tools, or low-priority Terraform guidance.
3
+ description: OpenCode entry skill for HuaweiCloud DevKit. Use when a developer asks OpenCode to use Huawei Cloud Skills, KooCLI, APIs, SDKs, future MCP tools, or low-priority Terraform guidance.
4
4
  ---
5
5
 
6
6
  # Huawei Cloud Core For OpenCode
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
3
  "mcpName": "io.github.huaweicloud/huaweicloud-devkit",
4
- "version": "1.1.3-next.1",
4
+ "version": "1.1.3-next.2",
5
5
  "kooCliVersion": "7.2.12",
6
6
  "description": "Agent toolkit that helps coding agents use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities safely and accurately.",
7
7
  "type": "module",
@@ -33,10 +33,11 @@
33
33
  "test": "node --test \"test/*.test.mjs\"",
34
34
  "format": "prettier --write .",
35
35
  "format:check": "prettier --check .",
36
- "lint:md": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#.git\" \"#test/**\" \"#docs/**\"",
36
+ "lint:md": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#.git\" \"#test/**\" \"#docs/**\" \"#.superpowers/**\"",
37
37
  "lint:js": "eslint .",
38
38
  "lint": "npm run lint:md && npm run lint:js",
39
- "validate": "node ./scripts/validate-package.mjs",
39
+ "validate": "node ./scripts/validate-package.mjs && node ./scripts/sync-readme-badge.mjs",
40
+ "badge:sync": "node ./scripts/sync-readme-badge.mjs --write",
40
41
  "pack:verify": "node ./scripts/pack-verify.mjs",
41
42
  "postinstall": "node ./bin/dsh-postinstall.cjs"
42
43
  },
@@ -1,8 +1,8 @@
1
1
  {
2
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.",
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
6
  "developerName": "HuaweiCloud Mate",
7
7
  "category": "Cloud",
8
8
  "capabilities": ["Read", "Interactive"],
@@ -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.3-next.1",
20
+ "version": "1.1.3-next.2",
21
21
  "author": {
22
22
  "name": "HuaweiCloud Mate",
23
23
  "url": "https://github.com/huaweicloud"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "interface": {
3
- "shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
3
+ "shortDescription": "HuaweiCloud DevKit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
4
4
  "developerName": "HuaweiCloud Mate",
5
5
  "capabilities": ["Read", "Interactive"],
6
6
  "brandColor": "#C7000B",
@@ -13,14 +13,14 @@
13
13
  "Check my Huawei Cloud CLI setup safely.",
14
14
  "Plan this Huawei Cloud API or SDK task."
15
15
  ],
16
- "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.",
16
+ "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.",
17
17
  "websiteURL": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
18
- "displayName": "HuaweiCloud Devkit"
18
+ "displayName": "HuaweiCloud DevKit"
19
19
  },
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.3-next.1",
23
+ "version": "1.1.3-next.2",
24
24
  "author": {
25
25
  "name": "HuaweiCloud Mate",
26
26
  "url": "https://github.com/huaweicloud"
@@ -1,8 +1,8 @@
1
1
  {
2
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.",
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
6
  "developerName": "HuaweiCloud Mate",
7
7
  "category": "Cloud",
8
8
  "capabilities": ["Read", "Interactive"],
@@ -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.3-next.1",
20
+ "version": "1.1.3-next.2",
21
21
  "author": {
22
22
  "name": "HuaweiCloud Mate",
23
23
  "url": "https://github.com/huaweicloud"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
- "version": "1.1.3-next.1",
3
+ "version": "1.1.3-next.2",
4
4
  "description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
5
5
  "author": {
6
6
  "name": "HuaweiCloud Mate",
@@ -13,9 +13,9 @@
13
13
  "skills": "./skills/",
14
14
  "mcpServers": "./.mcp.json",
15
15
  "interface": {
16
- "displayName": "HuaweiCloud Devkit",
17
- "shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
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.",
16
+ "displayName": "HuaweiCloud DevKit",
17
+ "shortDescription": "HuaweiCloud DevKit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
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.",
19
19
  "developerName": "HuaweiCloud Mate",
20
20
  "category": "Cloud",
21
21
  "capabilities": ["Read", "Interactive"],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
- "version": "1.1.3-next.1",
3
+ "version": "1.1.3-next.2",
4
4
  "description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
5
5
  "author": {
6
6
  "name": "HuaweiCloud Mate",
@@ -13,9 +13,9 @@
13
13
  "skills": "./skills/",
14
14
  "mcpServers": "./.mcp.json",
15
15
  "interface": {
16
- "displayName": "HuaweiCloud Devkit",
17
- "shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
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.",
16
+ "displayName": "HuaweiCloud DevKit",
17
+ "shortDescription": "HuaweiCloud DevKit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
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.",
19
19
  "developerName": "HuaweiCloud Mate",
20
20
  "category": "Cloud",
21
21
  "capabilities": ["Read", "Interactive"],
@@ -2,7 +2,7 @@
2
2
  "name": "huaweicloud-devkit",
3
3
  "id": "huaweicloud-devkit",
4
4
  "displayName": "HuaweiCloud DevKit",
5
- "version": "1.1.3-next.1",
5
+ "version": "1.1.3-next.2",
6
6
  "family": "bundle-plugin",
7
7
  "bundleFormat": "codex",
8
8
  "description": "Guide coding agents to use Huawei Cloud safely — KooCLI, APIs, SDKs, 28 MCP tools, skills, and safety guardrails.",
@@ -1047,7 +1047,7 @@ async function installCodexDesktop() {
1047
1047
 
1048
1048
  // Register in personal marketplace (Codex discovers plugins from ~/.agents/plugins/marketplace.json)
1049
1049
  ensureCodexMarketplaceEntry();
1050
- console.log(' \x1b[33m请到插件 → 个人 → HuaweiCloud Devkit → 安装\x1b[0m');
1050
+ console.log(' \x1b[33m请到插件 → 个人 → HuaweiCloud DevKit → 安装\x1b[0m');
1051
1051
 
1052
1052
  // Clean up old install locations from pre-marketplace era
1053
1053
  removeIfExists(join(homedir(), '.agents', 'skills'));
@@ -3009,7 +3009,7 @@ function opencodeStatus() {
3009
3009
  }
3010
3010
  }
3011
3011
 
3012
- function autoDetectTarget() {
3012
+ function detectAgents() {
3013
3013
  const checks = [
3014
3014
  ['opencode', () => existsSync(join(homedir(), '.config', 'opencode'))],
3015
3015
  ['codex-desktop', () => existsSync(join(homedir(), '.codex'))],
@@ -3028,7 +3028,11 @@ function autoDetectTarget() {
3028
3028
  ['openclaw', () => existsSync(join(homedir(), '.openclaw'))],
3029
3029
  ['atomcode', () => existsSync(atomcodeHome())],
3030
3030
  ];
3031
- const detected = checks.filter(([, check]) => check()).map(([name]) => name);
3031
+ return checks.filter(([, check]) => check()).map(([name]) => name);
3032
+ }
3033
+
3034
+ function autoDetectTarget() {
3035
+ const detected = detectAgents();
3032
3036
  if (detected.length === 0) {
3033
3037
  console.error('No supported agent detected.');
3034
3038
  console.error(`Supported: ${SUPPORTED_AGENT_TARGETS.join(', ')} (or "all")`);
@@ -3039,6 +3043,208 @@ function autoDetectTarget() {
3039
3043
  return 'all';
3040
3044
  }
3041
3045
 
3046
+ const AGENT_LABELS = {
3047
+ opencode: 'OpenCode',
3048
+ 'codex-desktop': 'Codex Desktop',
3049
+ codearts: 'CodeArts',
3050
+ 'codearts-work': 'CodeArts Work',
3051
+ workbuddy: 'WorkBuddy',
3052
+ dsh: 'DSH',
3053
+ officeace: 'OfficeAce',
3054
+ hermes: 'Hermes',
3055
+ openclaw: 'OpenClaw',
3056
+ atomcode: 'AtomCode',
3057
+ };
3058
+
3059
+ function promptSelectAgents(detected) {
3060
+ if (!process.stdin.isTTY) {
3061
+ console.error(
3062
+ `Multiple agents detected (${detected.join(', ')}). Cannot prompt in a non-interactive shell — ` +
3063
+ 'specify `--target <agent>` or `--target all`.',
3064
+ );
3065
+ return Promise.resolve(null);
3066
+ }
3067
+ const question = [
3068
+ 'Multiple agents detected. Select which to install (multi-select):',
3069
+ ...detected.map((name, i) => ` ${i + 1}) ${AGENT_LABELS[name] || name}`),
3070
+ 'Enter numbers separated by commas/spaces, "all" for every detected, Enter to install all detected, or "0" to cancel: ',
3071
+ ].join('\n');
3072
+ return new Promise((resolve) => {
3073
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
3074
+ rl.question(question, (a) => {
3075
+ rl.close();
3076
+ const answer = (a || '').trim().toLowerCase();
3077
+ if (answer === '0' || answer === 'n' || answer === 'no' || answer === 'q') {
3078
+ resolve(null);
3079
+ return;
3080
+ }
3081
+ if (answer === '' || answer === 'all') {
3082
+ resolve(detected.slice());
3083
+ return;
3084
+ }
3085
+ const parts = answer.split(/[\s,,]+/).filter(Boolean);
3086
+ const indices = new Set();
3087
+ for (const part of parts) {
3088
+ const n = Number(part);
3089
+ if (Number.isSafeInteger(n) && n >= 1 && n <= detected.length) {
3090
+ indices.add(n - 1);
3091
+ } else {
3092
+ console.error(`Invalid selection: "${part}". Installing all detected.`);
3093
+ resolve(detected.slice());
3094
+ return;
3095
+ }
3096
+ }
3097
+ resolve([...indices].map((i) => detected[i]));
3098
+ });
3099
+ });
3100
+ }
3101
+
3102
+ const MCP_ENTRY = {
3103
+ command: 'npx',
3104
+ args: ['-y', '-p', 'huaweicloud-devkit', 'huaweicloud-devkit-mcp'],
3105
+ };
3106
+
3107
+ function promptZeroDetect() {
3108
+ if (!process.stdin.isTTY) {
3109
+ console.error('No supported agent detected.');
3110
+ console.error(`Supported: ${SUPPORTED_AGENT_TARGETS.join(', ')} (or "all")`);
3111
+ console.error('Use --target <agent> to specify.');
3112
+ return Promise.resolve({ abort: true });
3113
+ }
3114
+ const question = [
3115
+ 'No supported agent detected.',
3116
+ 'What would you like to do?',
3117
+ ' 1) Install to a specific agent (e.g. codex)',
3118
+ ' 2) Install to all supported agents (--target all)',
3119
+ ' 3) Wire up a generic MCP agent (Claude Code / Cursor / custom MCP client)',
3120
+ ' 0) Exit',
3121
+ 'Enter choice: ',
3122
+ ].join('\n');
3123
+ return new Promise((resolve) => {
3124
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
3125
+ const ask = () => {
3126
+ rl.question(question, (a) => {
3127
+ const answer = (a || '').trim().toLowerCase();
3128
+ if (answer === '1') {
3129
+ rl.question('Enter agent target (e.g. codex): ', (t) => {
3130
+ const val = (t || '').trim().toLowerCase();
3131
+ rl.close();
3132
+ if (val === 'all' || SUPPORTED_AGENT_TARGETS.includes(val)) {
3133
+ resolve({ explicit: true, target: val });
3134
+ } else {
3135
+ console.error(`Unknown target: ${val}`);
3136
+ console.error(`Supported: ${SUPPORTED_AGENT_TARGETS.join(', ')} (or "all")`);
3137
+ resolve({ abort: true });
3138
+ }
3139
+ });
3140
+ return;
3141
+ }
3142
+ if (answer === '2') {
3143
+ rl.close();
3144
+ resolve({ explicit: true, target: 'all' });
3145
+ return;
3146
+ }
3147
+ if (answer === '3') {
3148
+ rl.close();
3149
+ resolve({ mcp: true });
3150
+ return;
3151
+ }
3152
+ if (answer === '' || answer === '0' || answer === 'n' || answer === 'no' || answer === 'q') {
3153
+ rl.close();
3154
+ resolve({ abort: true });
3155
+ return;
3156
+ }
3157
+ console.error(`Invalid choice: "${answer}"`);
3158
+ ask();
3159
+ });
3160
+ };
3161
+ ask();
3162
+ });
3163
+ }
3164
+
3165
+ function printMCPConfigSnippet(reason) {
3166
+ console.log(` ${reason}`);
3167
+ console.log(' Add this to your agent MCP config (stdio):');
3168
+ const snippet = JSON.stringify({ mcpServers: { 'huaweicloud-devkit': MCP_ENTRY } }, null, 2)
3169
+ .split('\n')
3170
+ .map((line) => ` ${line}`)
3171
+ .join('\n');
3172
+ console.log(snippet);
3173
+ console.log(' Or run the remote server and use a remote (Streamable HTTP) config:');
3174
+ console.log(' npx --yes huaweicloud-devkit-mcp --transport remote # listens on 127.0.0.1:9528');
3175
+ console.log(' See README → "Other Agents" for details.');
3176
+ }
3177
+
3178
+ function configureMCPAgent(targetFile, agentLabel) {
3179
+ let config = {};
3180
+ let existed = false;
3181
+ if (existsSync(targetFile)) {
3182
+ existed = true;
3183
+ try {
3184
+ config = JSON.parse(readFileSync(targetFile, 'utf8'));
3185
+ } catch {
3186
+ console.error(` [${agentLabel}] ${targetFile} is not valid JSON; leaving it untouched.`);
3187
+ return false;
3188
+ }
3189
+ }
3190
+ config.mcpServers = config.mcpServers || {};
3191
+ if (config.mcpServers['huaweicloud-devkit']) {
3192
+ console.log(` [${agentLabel}] mcpServers.huaweicloud-devkit already configured; skipping.`);
3193
+ return true;
3194
+ }
3195
+ if (existed) copyFileSync(targetFile, `${targetFile}.bak`);
3196
+ config.mcpServers['huaweicloud-devkit'] = { ...MCP_ENTRY };
3197
+ mkdirSync(dirname(targetFile), { recursive: true });
3198
+ writeFileSync(targetFile, JSON.stringify(config, null, 2), 'utf8');
3199
+ console.log(` [${agentLabel}] MCP server configured in ${targetFile}. Restart the session to apply.`);
3200
+ return true;
3201
+ }
3202
+
3203
+ function configureGenericMCP() {
3204
+ console.log('Configuring a generic MCP agent (MCP tools only; skills/hooks are not installed)...');
3205
+ const targets = [];
3206
+ const claudeFile = process.env.CLAUDE_CONFIG_DIR
3207
+ ? join(process.env.CLAUDE_CONFIG_DIR, '.claude.json')
3208
+ : join(homedir(), '.claude.json');
3209
+ if (existsSync(claudeFile)) targets.push(['Claude Code', claudeFile]);
3210
+ const cursorFile = join(homedir(), '.cursor', 'mcp.json');
3211
+ if (existsSync(cursorFile) || existsSync(join(homedir(), '.cursor'))) {
3212
+ targets.push(['Cursor', cursorFile]);
3213
+ }
3214
+
3215
+ if (targets.length === 0) {
3216
+ printMCPConfigSnippet('No known MCP agent detected; here is a config snippet you can paste:');
3217
+ return false;
3218
+ }
3219
+ let anyConfigured = false;
3220
+ for (const [label, file] of targets) {
3221
+ if (configureMCPAgent(file, label)) anyConfigured = true;
3222
+ }
3223
+ if (!anyConfigured) {
3224
+ console.log(' Nothing to configure for the detected MCP agents.');
3225
+ }
3226
+ return anyConfigured;
3227
+ }
3228
+
3229
+ async function resolveInstallTarget() {
3230
+ const idx = process.argv.indexOf('--target');
3231
+ if (idx >= 0) {
3232
+ const val = (process.argv[idx + 1] || '').toLowerCase();
3233
+ if (val === 'all' || SUPPORTED_AGENT_TARGETS.includes(val)) {
3234
+ return { explicit: true, target: val };
3235
+ }
3236
+ console.error(`Unknown target: ${val}`);
3237
+ console.error(`Supported: ${SUPPORTED_AGENT_TARGETS.join(', ')} (or "all")`);
3238
+ process.exit(1);
3239
+ }
3240
+ const detected = detectAgents();
3241
+ if (detected.length === 1) return { explicit: true, target: detected[0] };
3242
+ if (detected.length === 0) return promptZeroDetect();
3243
+ const chosen = await promptSelectAgents(detected);
3244
+ if (!chosen) return { abort: true };
3245
+ return { explicit: false, subset: chosen };
3246
+ }
3247
+
3042
3248
  function parseTarget() {
3043
3249
  const idx = process.argv.indexOf('--target');
3044
3250
  if (idx < 0) return autoDetectTarget();
@@ -3084,13 +3290,37 @@ function writeInstallMarker(target) {
3084
3290
  }
3085
3291
 
3086
3292
  async function cmdInstall() {
3087
- const target = parseTarget();
3088
3293
  console.log(BANNER);
3089
- console.log(`Installing HuaweiCloud DevKit${target !== 'opencode' ? ` for ${target}` : ''}...\n`);
3294
+ const plan = await resolveInstallTarget();
3295
+ if (plan.abort) {
3296
+ process.exitCode = 1;
3297
+ return;
3298
+ }
3299
+ if (plan.mcp) {
3300
+ const ok = configureGenericMCP();
3301
+ process.exitCode = ok ? 0 : 1;
3302
+ return;
3303
+ }
3304
+ const hasExplicitTarget = plan.explicit;
3305
+ const target = plan.explicit ? plan.target : null;
3306
+ const selected = new Set(plan.explicit ? [] : plan.subset);
3307
+
3308
+ if (hasExplicitTarget) {
3309
+ console.log(`Installing HuaweiCloud DevKit for ${target}...\n`);
3310
+ } else {
3311
+ console.log(`Installing HuaweiCloud DevKit to ${[...selected].join(', ')}...\n`);
3312
+ }
3313
+
3090
3314
  checkNode();
3091
3315
  checkForUpdate();
3092
3316
  const installFailures = [];
3093
3317
 
3318
+ function shouldInstall(name) {
3319
+ if (name === 'codex') return hasExplicitTarget && (target === 'codex' || target === 'all');
3320
+ if (hasExplicitTarget) return target === name || target === 'all';
3321
+ return selected.has(name);
3322
+ }
3323
+
3094
3324
  async function runInstallStep(stepTarget, title, fn) {
3095
3325
  console.log(title);
3096
3326
  try {
@@ -3108,37 +3338,37 @@ async function cmdInstall() {
3108
3338
  }
3109
3339
  }
3110
3340
 
3111
- if (target === 'opencode' || target === 'all') {
3341
+ if (shouldInstall('opencode')) {
3112
3342
  await runInstallStep('opencode', '[OpenCode]', installOpenCode);
3113
3343
  }
3114
- if (target === 'codex-desktop' || target === 'all') {
3344
+ if (shouldInstall('codex-desktop')) {
3115
3345
  await runInstallStep('codex-desktop', '\n[Codex Desktop]', installCodexDesktop);
3116
3346
  }
3117
- if (target === 'codearts' || target === 'all') {
3347
+ if (shouldInstall('codearts')) {
3118
3348
  await runInstallStep('codearts', '\n[CodeArts]', installCodeArts);
3119
3349
  }
3120
- if (target === 'codearts-work' || target === 'all') {
3350
+ if (shouldInstall('codearts-work')) {
3121
3351
  await runInstallStep('codearts-work', '\n[CodeArts Work]', installCodeArtsWork);
3122
3352
  }
3123
- if (target === 'workbuddy' || target === 'all') {
3353
+ if (shouldInstall('workbuddy')) {
3124
3354
  await runInstallStep('workbuddy', '\n[WorkBuddy]', installWorkBuddy);
3125
3355
  }
3126
- if (target === 'dsh' || target === 'all') {
3356
+ if (shouldInstall('dsh')) {
3127
3357
  await runInstallStep('dsh', '\n[DSH]', installDsh);
3128
3358
  }
3129
- if (target === 'officeace' || target === 'all') {
3359
+ if (shouldInstall('officeace')) {
3130
3360
  await runInstallStep('officeace', '\n[OfficeAce]', installOfficeAce);
3131
3361
  }
3132
- if (target === 'hermes' || target === 'all') {
3362
+ if (shouldInstall('hermes')) {
3133
3363
  await runInstallStep('hermes', '\n[Hermes Agent]', installHermes);
3134
3364
  }
3135
- if (target === 'openclaw' || target === 'all') {
3365
+ if (shouldInstall('openclaw')) {
3136
3366
  await runInstallStep('openclaw', '\n[OpenClaw]', installOpenClaw);
3137
3367
  }
3138
- if (target === 'atomcode' || target === 'all') {
3368
+ if (shouldInstall('atomcode')) {
3139
3369
  await runInstallStep('atomcode', '\n[AtomCode]', installAtomCode);
3140
3370
  }
3141
- if (target === 'codex' || target === 'all') {
3371
+ if (shouldInstall('codex')) {
3142
3372
  await runInstallStep('codex', '\n[Codex]', () => {
3143
3373
  if (!hasCodexCLI()) {
3144
3374
  if (target === 'codex') {
@@ -4068,6 +4298,10 @@ async function cmdReinstall() {
4068
4298
  let confirmed = false;
4069
4299
  async function confirm(msg) {
4070
4300
  if (confirmed) return true;
4301
+ if (!process.stdin.isTTY) {
4302
+ console.log('Non-interactive shell: skipping confirmation (declined).');
4303
+ return false;
4304
+ }
4071
4305
  const rl = createInterface({ input: process.stdin, output: process.stdout });
4072
4306
  return new Promise((ok) => {
4073
4307
  rl.question(`${msg} [y/N] `, (a) => {