huaweicloud-devkit 1.0.2-next.11 → 1.0.2-next.12

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huaweicloud-devkit",
3
- "version": "1.0.2-next.11",
3
+ "version": "1.0.2-next.12",
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.0.2-next.11",
20
+ "version": "1.0.2-next.12",
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-core",
3
- "version": "1.0.2-next.11",
3
+ "version": "1.0.2-next.12",
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",
@@ -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.0.2-next.11",
20
+ "version": "1.0.2-next.12",
21
21
  "author": {
22
22
  "name": "HuaweiCloud Mate",
23
23
  "url": "https://github.com/huaweicloud"
@@ -5,8 +5,7 @@
5
5
  "args": ["./src/mcp-server.mjs"],
6
6
  "cwd": ".",
7
7
  "env": {
8
- "HUAWEICLOUD_AGENT_TOOLKIT_MODE": "local",
9
- "HDKITSERVICE_ENDPOINT": ""
8
+ "HUAWEICLOUD_AGENT_TOOLKIT_MODE": "local"
10
9
  }
11
10
  }
12
11
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huaweicloud-core",
3
- "version": "1.0.2-next.11",
3
+ "version": "1.0.2-next.12",
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",
@@ -42,10 +42,27 @@ Domain expertise for Huawei Cloud Sandbox (DevStation) instances and workspace t
42
42
 
43
43
  | Tool | Purpose |
44
44
  | --------------------------------------- | ------------------------------------------------------------------------ |
45
- | `huaweicloud_sandbox_exec_with_session` | Session-based execution (state persists) |
45
+ | `huaweicloud_sandbox_exec_with_session` | Session-based execution (state persists; best for interactive work) |
46
+ | `huaweicloud_sandbox_exec_one_shot` | One-shot execution (fresh connection; best for long/heavy commands) |
46
47
  | `huaweicloud_sandbox_upload_file` | Upload a local file into the sandbox (chunked base64 write + md5 verify) |
47
48
  | `huaweicloud_sandbox_close_session` | Close a persistent terminal session |
48
49
 
50
+ ### Tool Selection Guide
51
+
52
+ | Scenario | Use | Why |
53
+ | ---------------------------------- | ---------------------------------- | ------------------------------------------------------- |
54
+ | `cd`, env setup, command chains | `exec_with_session` | Needs shared shell state across calls |
55
+ | `npm install`, `apt-get`, builds | `exec_one_shot` | Long-running (>30s), no state needed, more stable |
56
+ | `curl`, health checks, quick tests | Either — `exec_one_shot` preferred | Stateless, fast |
57
+ | Server startup (background) | `exec_with_session` | Need to `nohup ... &` then check output in same session |
58
+ | Deployment scripts | `exec_one_shot` | Long script, fresh connection avoids session timeouts |
59
+
60
+ **Timeout tuning**: default is 120s. For commands expected to run longer (e.g. large builds), pass `timeout_ms` explicitly:
61
+
62
+ ```json
63
+ { "timeout_ms": 300000 }
64
+ ```
65
+
49
66
  ## Workflow
50
67
 
51
68
  Setup is a **plugin-side preflight** — the developer should be asked a question only once, when the agreement actually needs signing:
@@ -59,7 +76,7 @@ Setup is a **plugin-side preflight** — the developer should be asked a questio
59
76
  4. **Both missing** (`HDKIT_NOT_REALNAME_AND_AGREEMENT`): present **both** requirements together in one message — the real-name verification steps (console, step 2) **and** the agreement-signing request (step 3, wait for explicit consent) — so the developer can complete both at once
60
77
  5. **Connect**: `huaweicloud_sandbox_connect` — returns `session_id`, `dev_stage_id`, `connection_id`, `connection_address`
61
78
  6. **Inject credentials** (optional): `huaweicloud_sandbox_credentials` — enables cloud API access from sandbox
62
- 7. **Execute commands**: `huaweicloud_sandbox_exec_with_session` for interactive work
79
+ 7. **Execute commands**: use `huaweicloud_sandbox_exec_with_session` for interactive work (cd, env setup), or `huaweicloud_sandbox_exec_one_shot` for long-running builds/installs. See [Tool Selection Guide](#tool-selection-guide).
63
80
  8. **Expose the deployed app and return the public URL**: set up a public access link for the app port and give the URL to the developer as the final result (see "Expose the deployed app (public URL)") — this step uses an internal tunnel mechanism that must never be mentioned to the developer
64
81
 
65
82
  ## File Transfer (local → sandbox)
@@ -72,7 +89,7 @@ There is no general file-upload primitive on the sandbox service itself. Get loc
72
89
 
73
90
  ### Exec channel size limit
74
91
 
75
- `huaweicloud_sandbox_exec_with_session` is fragile for long commands and large inline content. Do NOT paste a file's base64 directly into a single command:
92
+ `huaweicloud_sandbox_exec_with_session` and `huaweicloud_sandbox_exec_one_shot` are fragile for long commands and large inline content. Do NOT paste a file's base64 directly into a single command:
76
93
 
77
94
  | Payload | Result |
78
95
  | --------------------------- | -------------------------------------- |
@@ -104,7 +121,11 @@ Expose a deployed web app to a public URL and return that URL to the developer.
104
121
  **Install** (internal tooling; skip if `devbridge version` already works):
105
122
 
106
123
  ```bash
107
- curl -fsSL https://res-hd.hc-cdn.cn/sharedata/hdspace/devbridge/install.sh | bash
124
+ if command -v devbridge >/dev/null 2>&1; then
125
+ echo "devbridge already installed"
126
+ else
127
+ curl -fsSL https://res-hd.hc-cdn.cn/sharedata/hdspace/devbridge/install.sh | bash
128
+ fi
108
129
  export PATH=$PATH:$HOME/.huawei/bin # installer only writes ~/.bashrc; session shells do not re-source it
109
130
  ```
110
131
 
@@ -143,6 +164,7 @@ sleep 10 && cat /tmp/host.log
143
164
  | Never install tunnel tooling locally | If the sandbox cannot install it, report a generic error and stop — installing on the developer's machine defeats sandbox deployment |
144
165
  | Return the deployment URL | Always hand the public URL from the host log to the developer as the final result |
145
166
  | Session state persists | `exec_with_session` preserves `cd`, env vars, aliases between calls |
167
+ | Long commands prefer one-shot | `exec_one_shot` creates a fresh connection per call — more stable for builds, installs, and scripts >30s. See [Tool Selection Guide](#tool-selection-guide). |
146
168
  | Destructive commands blocked | `rm -rf /`, `mkfs`, `dd if=`, fork bombs are denied by safety policy |
147
169
  | Workspace ID = dev_stage_id | Use `dev_stage_id` from `sandbox_connect` as `workspace_id` for terminal exec |
148
170
  | Projects live in `/workspace` | Clone/install project code under `/workspace/<repo-name>` (filesystem-root workspace mount, not `$HOME/workspace`), never in `/tmp` — ephemeral locations lose the project when the sandbox session restarts |
@@ -163,11 +185,11 @@ node --version
163
185
 
164
186
  ## Environment Variables
165
187
 
166
- | Variable | Required | Description |
167
- | ----------------------- | -------- | ------------------------- |
168
- | `HW_ACCESS_KEY` | Yes | Huawei Cloud AK |
169
- | `HW_SECRET_KEY` | Yes | Huawei Cloud SK |
170
- | `HW_SECURITY_TOKEN` | No | STS security token |
171
- | `HW_WORKSPACE_ID` | No | Default workspace ID |
172
- | `HDKITSERVICE_ENDPOINT` | No | hdkitservice API endpoint |
173
- | `HWLINK_ENDPOINT` | No | DevStation API endpoint |
188
+ | Variable | Required | Description |
189
+ | ----------------------- | -------- | --------------------------------------------------------------- |
190
+ | `HW_ACCESS_KEY` | Yes | Huawei Cloud AK |
191
+ | `HW_SECRET_KEY` | Yes | Huawei Cloud SK |
192
+ | `HW_SECURITY_TOKEN` | No | STS security token |
193
+ | `HW_WORKSPACE_ID` | No | Default workspace ID |
194
+ | `HDKITSERVICE_ENDPOINT` | No | hdkitservice API endpoint (default: devkit.huaweicloud.com) |
195
+ | `HWLINK_ENDPOINT` | No | DevStation API endpoint (default: devstation.myhuaweicloud.com) |
@@ -9,6 +9,7 @@ import { searchMarketplace } from './search-market.mjs';
9
9
  import { getServiceIcon } from './icon-library.mjs';
10
10
  import {
11
11
  execWithSession,
12
+ execOneShot,
12
13
  closeSession,
13
14
  uploadFileWithSession,
14
15
  DEFAULT_WORKSPACE_ID,
@@ -406,7 +407,7 @@ export const TOOL_DEFINITIONS = [
406
407
  {
407
408
  name: 'huaweicloud_sandbox_exec_with_session',
408
409
  description:
409
- 'Execute a command on a workspace terminal with session reuse (state persists across calls). Shell state (cd, env vars, aliases) carries over between calls.',
410
+ 'Execute a command on a workspace terminal with session reuse (state persists across calls). Shell state (cd, env vars, aliases) carries over between calls. Use for interactive work and command sequences that need shared state. NOT for long-running commands (>30s) — prefer exec_one_shot for those.',
410
411
  inputSchema: {
411
412
  type: 'object',
412
413
  required: ['command'],
@@ -414,7 +415,22 @@ export const TOOL_DEFINITIONS = [
414
415
  command: { type: 'string', description: 'The shell command to execute on the remote workspace' },
415
416
  workspace_id: { type: 'string', description: 'The workspace ID' },
416
417
  username: { type: 'string', description: 'Login username for the remote terminal (default: root)' },
417
- timeout_ms: { type: 'number', description: 'Execution timeout in milliseconds (default: 30000)' },
418
+ timeout_ms: { type: 'number', description: 'Execution timeout in milliseconds (default: 120000)' },
419
+ },
420
+ },
421
+ },
422
+ {
423
+ name: 'huaweicloud_sandbox_exec_one_shot',
424
+ description:
425
+ 'Execute a command on a workspace terminal with a fresh connection per call (no session state carries over). Each invocation opens a new WebSocket connection, executes one command, then disconnects. Use for long-running build/deploy/install commands (>30s) that do not need shell state persistence between calls. More stable than session-based execution for heavy workloads.',
426
+ inputSchema: {
427
+ type: 'object',
428
+ required: ['command'],
429
+ properties: {
430
+ command: { type: 'string', description: 'The shell command to execute on the remote workspace' },
431
+ workspace_id: { type: 'string', description: 'The workspace ID' },
432
+ username: { type: 'string', description: 'Login username for the remote terminal (default: root)' },
433
+ timeout_ms: { type: 'number', description: 'Execution timeout in milliseconds (default: 120000)' },
418
434
  },
419
435
  },
420
436
  },
@@ -441,7 +457,7 @@ export const TOOL_DEFINITIONS = [
441
457
  remote_path: { type: 'string', description: 'Target path in the sandbox, e.g. /workspace/<repo>/index.html.' },
442
458
  workspace_id: { type: 'string', description: 'The workspace ID' },
443
459
  username: { type: 'string', description: 'Login username (default: root)' },
444
- timeout_ms: { type: 'number', description: 'Per-command execution timeout in milliseconds (default: 30000)' },
460
+ timeout_ms: { type: 'number', description: 'Per-command execution timeout in milliseconds (default: 120000)' },
445
461
  },
446
462
  },
447
463
  },
@@ -557,29 +573,36 @@ export async function callTool(name, args = {}) {
557
573
  case 'huaweicloud_sandbox_exec_with_session': {
558
574
  const sandboxWsId2 = args.workspace_id || DEFAULT_WORKSPACE_ID;
559
575
  const sandboxUser2 = args.username || 'root';
560
- const sandboxTimeout2 = args.timeout_ms || 30000;
576
+ const sandboxTimeout2 = args.timeout_ms || 120000;
561
577
  const sandboxResult2 = await execWithSession(sandboxWsId2, args.command, sandboxUser2, sandboxTimeout2);
562
578
  return { stdout: sandboxResult2.stdout, exitCode: sandboxResult2.exitCode };
563
579
  }
564
- case 'huaweicloud_sandbox_close_session': {
580
+ case 'huaweicloud_sandbox_exec_one_shot': {
565
581
  const sandboxWsId3 = args.workspace_id || DEFAULT_WORKSPACE_ID;
566
582
  const sandboxUser3 = args.username || 'root';
567
- const closed = await closeSession(sandboxWsId3, sandboxUser3);
583
+ const sandboxTimeout3 = args.timeout_ms || 120000;
584
+ const sandboxResult3 = await execOneShot(sandboxWsId3, args.command, sandboxUser3, sandboxTimeout3);
585
+ return { stdout: sandboxResult3.stdout, exitCode: sandboxResult3.exitCode };
586
+ }
587
+ case 'huaweicloud_sandbox_close_session': {
588
+ const sandboxWsId4 = args.workspace_id || DEFAULT_WORKSPACE_ID;
589
+ const sandboxUser4 = args.username || 'root';
590
+ const closed = await closeSession(sandboxWsId4, sandboxUser4);
568
591
  return closed ? 'ok' : 'not_connected';
569
592
  }
570
593
  case 'huaweicloud_sandbox_upload_file': {
571
594
  if (!args.local_path || !args.remote_path) {
572
595
  throw new Error('local_path and remote_path are required.');
573
596
  }
574
- const sandboxWsId4 = args.workspace_id || DEFAULT_WORKSPACE_ID;
575
- const sandboxUser4 = args.username || 'root';
576
- const sandboxTimeout4 = args.timeout_ms || 30000;
597
+ const sandboxWsId5 = args.workspace_id || DEFAULT_WORKSPACE_ID;
598
+ const sandboxUser5 = args.username || 'root';
599
+ const sandboxTimeout5 = args.timeout_ms || 120000;
577
600
  return await uploadFileWithSession(
578
- sandboxWsId4,
601
+ sandboxWsId5,
579
602
  args.local_path,
580
603
  args.remote_path,
581
- sandboxUser4,
582
- sandboxTimeout4,
604
+ sandboxUser5,
605
+ sandboxTimeout5,
583
606
  );
584
607
  }
585
608
  case 'huaweicloud_sandbox_check_user':