huaweicloud-devkit 1.1.9 → 1.1.10-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/package.json +1 -1
  4. package/plugins/huaweicloud-core/.claude-plugin/plugin.json +1 -1
  5. package/plugins/huaweicloud-core/.codex-plugin/plugin.json +1 -1
  6. package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +1 -1
  7. package/plugins/huaweicloud-core/.hermes-plugin/plugin.json +1 -1
  8. package/plugins/huaweicloud-core/.workbuddy-plugin/plugin.json +1 -1
  9. package/plugins/huaweicloud-core/openclaw.plugin.json +1 -1
  10. package/plugins/huaweicloud-core/safety/rules/cloud-risk-rules.json +1 -1
  11. package/plugins/huaweicloud-core/skills/huawei-ecs/references/create-instance.md +26 -0
  12. package/plugins/huaweicloud-core/skills/huawei-ecs/references/hc-activity.md +16 -0
  13. package/plugins/huaweicloud-core/skills/huawei-ecs/references/troubleshooting.md +51 -0
  14. package/plugins/huaweicloud-core/skills/huawei-ecs/references/windows-ssh.md +24 -0
  15. package/plugins/huaweicloud-core/skills/huawei-iac/SKILL.md +38 -36
  16. package/plugins/huaweicloud-core/skills/huawei-iam/SKILL.md +35 -16
  17. package/plugins/huaweicloud-core/skills/huawei-iam/references/quick-ref.md +35 -0
  18. package/plugins/huaweicloud-core/skills/huawei-sandbox/SKILL.md +8 -1
  19. package/plugins/huaweicloud-core/src/account-type.mjs +135 -0
  20. package/plugins/huaweicloud-core/src/hcloud-cli.mjs +15 -1
  21. package/plugins/huaweicloud-core/src/safety-policy.mjs +36 -5
  22. package/plugins/huaweicloud-core/src/sandbox/session-manager.mjs +172 -21
  23. package/plugins/huaweicloud-core/src/tools.mjs +55 -5
@@ -9,6 +9,7 @@ import { createHmac, createHash } from 'node:crypto';
9
9
  import { evaluateArtifacts, evaluateCommandRisk, evaluateDeployPlan } from './risk-rule-engine.mjs';
10
10
  import { classifyTextCommand, redactSecrets } from './safety-policy.mjs';
11
11
  import { planHcloudCommand, runHcloud, consumeApprovalToken, inspectApprovalToken, hashArgs } from './hcloud-cli.mjs';
12
+ import { checkAccountType } from './account-type.mjs';
12
13
  import { searchMarketplace } from './search-market.mjs';
13
14
  import { getServiceIcon } from './icon-library.mjs';
14
15
  import { detectFramework } from './detect-framework.mjs';
@@ -420,6 +421,21 @@ export const TOOL_DEFINITIONS = [
420
421
  properties: {},
421
422
  },
422
423
  },
424
+ {
425
+ name: 'huaweicloud_check_account_type',
426
+ description:
427
+ 'Check whether the current credentials belong to the primary account or an IAM sub-user. Runs STS GetCallerIdentity + IAM KeystoneListAuthDomains (both read-only, no identity-policy permission required) and applies the validated rule: username == domainName -> primary account, otherwise IAM sub-user. Use before sandbox deployment (primary-account prechecks), account confirmation, or any task that needs to know who the current AK/SK belongs to. Returns isPrimaryAccount, applicable, domainId, domainName, userId, username, principalUrn, and an evidence string. Agency-session credentials are detected and reported as applicable:false.',
428
+ inputSchema: {
429
+ type: 'object',
430
+ properties: {
431
+ region: {
432
+ type: 'string',
433
+ description:
434
+ 'Optional region ID for the region-level GetCallerIdentity endpoint (e.g., cn-north-4). Defaults to the configured cli-region.',
435
+ },
436
+ },
437
+ },
438
+ },
423
439
  {
424
440
  name: 'huaweicloud_get_regional_availability',
425
441
  description:
@@ -621,12 +637,16 @@ export const TOOL_DEFINITIONS = [
621
637
  {
622
638
  name: 'huaweicloud_sandbox_upload_file',
623
639
  description:
624
- 'Upload a local file into the sandbox workspace. Base64-encodes the file, writes it in small chunks through the terminal session (the exec channel is fragile for large single commands), then decodes and verifies the md5 checksum. Use this instead of embedding large file content directly in a command.',
640
+ 'Upload a local file into the sandbox workspace. Base64-encodes the file, writes it in small chunks through the terminal session (the exec channel is fragile for large single commands), then decodes and verifies the md5 checksum. The remote parent directory is created automatically if absent. Use this instead of embedding large file content directly in a command. local_path must be readable from the machine running the DevKit MCP server — if the file lives elsewhere, copy it to the local temp directory first.',
625
641
  inputSchema: {
626
642
  type: 'object',
627
643
  required: ['local_path', 'remote_path'],
628
644
  properties: {
629
- local_path: { type: 'string', description: 'Absolute path to the local file to upload.' },
645
+ local_path: {
646
+ type: 'string',
647
+ description:
648
+ 'Absolute path to the local file, readable from the machine running the DevKit MCP server (copy to the local temp dir first if not).',
649
+ },
630
650
  remote_path: { type: 'string', description: 'Target path in the sandbox, e.g. /workspace/<repo>/index.html.' },
631
651
  workspace_id: {
632
652
  type: 'string',
@@ -641,12 +661,16 @@ export const TOOL_DEFINITIONS = [
641
661
  {
642
662
  name: 'huaweicloud_sandbox_upload_project',
643
663
  description:
644
- 'Package a local project directory and upload it to a sandbox workspace via HTTP tunnel. Falls back to base64 chunking if tunnel fails. Creates a tar.gz archive, uploads it, and extracts it on the sandbox by default.',
664
+ 'Package a local project directory and upload it to a sandbox workspace via HTTP tunnel. Falls back to base64 chunking if tunnel fails. Creates a tar.gz archive, uploads it, and extracts it on the sandbox by default. local_dir must be readable from the machine running the DevKit MCP server — if the project lives elsewhere, copy it to the local temp directory first.',
645
665
  inputSchema: {
646
666
  type: 'object',
647
667
  required: ['local_dir'],
648
668
  properties: {
649
- local_dir: { type: 'string', description: 'Local project directory to upload.' },
669
+ local_dir: {
670
+ type: 'string',
671
+ description:
672
+ 'Local project directory, readable from the machine running the DevKit MCP server (copy to the local temp dir first if not).',
673
+ },
650
674
  remote_dir: {
651
675
  type: 'string',
652
676
  description:
@@ -1186,6 +1210,8 @@ export async function callTool(name, rawArgs = {}, opts = {}) {
1186
1210
  return retrieveSkill(args.name || '');
1187
1211
  case 'huaweicloud_list_regions':
1188
1212
  return listRegions();
1213
+ case 'huaweicloud_check_account_type':
1214
+ return checkAccountType(args);
1189
1215
  case 'huaweicloud_get_regional_availability':
1190
1216
  return getRegionalAvailability(args.service || '', args.region || '');
1191
1217
  case 'huaweicloud_explain_error':
@@ -2279,8 +2305,18 @@ function explainError({ service = 'unknown', errorCode = '', message = '', reque
2279
2305
  fgs: 'FSS',
2280
2306
  ecs: 'Ecs',
2281
2307
  ECS: 'Ecs',
2308
+ kps: 'Kps',
2309
+ KPS: 'Kps',
2282
2310
  };
2283
- const patternKey = SERVICE_ALIASES[svc] || service;
2311
+ // #935 E2E-B1: real MCP calls pass only errorCode (e.g. Ecs.0019, KPS.9004)
2312
+ // with no service — derive the service key from the dotted-code prefix so the
2313
+ // service-keyed mapping table is hit. Explicit service behavior is unchanged.
2314
+ let resolvedService = service;
2315
+ if ((!service || svc === 'unknown') && /^[A-Za-z]+\.\w+/.test(errorCode)) {
2316
+ const prefix = errorCode.split('.')[0].toLowerCase();
2317
+ resolvedService = SERVICE_ALIASES[prefix] || errorCode.split('.')[0].toUpperCase();
2318
+ }
2319
+ const patternKey = SERVICE_ALIASES[svc] || resolvedService;
2284
2320
 
2285
2321
  const hwErrorPatterns = {
2286
2322
  OBS: {
@@ -2309,6 +2345,14 @@ function explainError({ service = 'unknown', errorCode = '', message = '', reque
2309
2345
  Ecs: {
2310
2346
  'Ecs.0707':
2311
2347
  'The flavor + image-type combination does not exist ("the product does not exist") — the error does not say which side is wrong, so check BOTH (#922): (1) the flavor is abandoned/sellout in this region/AZ (check os_extra_specs.cond:operation:status and cond:operation:az; see the huawei-ecs skill references/flavors.md for the AZ-vs-global-status conflict rule); (2) the image TYPE is incompatible with the flavor — market-type images fail with KunPeng flavors (kc1/kc2 etc.). Fix: switch the image to a gold-type image or switch to a compatible general-purpose flavor (verified: kc2.small.2 + market Ubuntu → Ecs.0707; s6.medium.2 + gold Ubuntu works), re-listing with hcloud ECS ListFlavors / hcloud IMS ListImages --__imagetype=gold first.',
2348
+ // #935 (report 4 problem 1 / report 1 坑5): real-world ECS order failures
2349
+ // with no mapping — flavor offline, AZ capacity, balance, keypair restriction.
2350
+ 'Ecs.0019':
2351
+ 'The flavor has been taken offline (Ecs.0019). Run `hcloud ECS ListFlavors --cli-region=<region>` to query currently on-sale flavors and switch to a replacement flavor (see the huawei-ecs skill references/flavors.md for the cond:operation:status field rules — a flavor marked 卖光/下线 keeps failing until you pick an on-sale one), then recreate.',
2352
+ 'Ecs.0319':
2353
+ 'The requested flavor has insufficient capacity in the selected availability zone (Ecs.0319). Fix: retry in a different availability zone, or switch to a replacement flavor (list on-sale flavors with `hcloud ECS ListFlavors --cli-region=<region>`), then recreate.',
2354
+ 'Ecs.0067':
2355
+ 'Order submission rejected for balance reasons (Ecs.0067). Check the cash balance with `hcloud BSS ShowCustomerAccountBalances --cli-region=cn-north-1` and top up if needed — pay-per-use order risk control checks the CASH balance only (代金券/vouchers do NOT participate in order risk control; they only offset the bill at settlement). Also settle any historical arrears, however small, before retrying.',
2312
2356
  },
2313
2357
  APIGW: {
2314
2358
  'APIGW.0301':
@@ -2316,6 +2360,12 @@ function explainError({ service = 'unknown', errorCode = '', message = '', reque
2316
2360
  'APIGW.0802':
2317
2361
  'The current IAM user has no permissions in the requested region. Go to IAM console → Users → Permissions → add the target region, or switch to a different region.',
2318
2362
  },
2363
+ // #935 (report 1 坑5): KPS keypair creation has its own restriction code —
2364
+ // the Kps service had no entry at all, so the error fell through to generic advice.
2365
+ Kps: {
2366
+ 'KPS.9004':
2367
+ 'Keypair creation rejected for account restrictions (KPS.9004). Check the cash balance with `hcloud BSS ShowCustomerAccountBalances --cli-region=cn-north-1` and top up if needed, and settle any historical arrears (even a small unpaid amount triggers this) — then retry `hcloud ECS NovaCreateKeypair` or create the keypair in the console.',
2368
+ },
2319
2369
  };
2320
2370
  if (hwErrorPatterns[patternKey] && hwErrorPatterns[patternKey][errorCode]) {
2321
2371
  suggestions.push(hwErrorPatterns[patternKey][errorCode]);