huaweicloud-devkit 1.0.2-next.8 → 1.0.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.
- package/.agents/plugins/marketplace.json +1 -1
- package/LICENSE +201 -201
- package/README.md +71 -52
- package/README.zh-CN.md +71 -50
- package/bin/setup.cjs +0 -0
- package/package.json +9 -5
- package/plugins/huaweicloud-core/.claude-plugin/plugin.json +2 -2
- package/plugins/huaweicloud-core/.codex-plugin/plugin.json +2 -2
- package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +2 -2
- package/plugins/huaweicloud-core/.hermes-plugin/plugin.json +30 -0
- package/plugins/huaweicloud-core/.mcp.json +1 -2
- package/plugins/huaweicloud-core/.workbuddy-plugin/plugin.json +2 -3
- package/plugins/huaweicloud-core/hooks/huaweicloud-safety.py +159 -136
- package/plugins/huaweicloud-core/openclaw.plugin.json +20 -0
- package/plugins/huaweicloud-core/skills/huawei-cloud-find-skills/SKILL.md +1 -1
- package/plugins/huaweicloud-core/skills/huawei-sandbox/SKILL.md +67 -20
- package/plugins/huaweicloud-core/skills/huaweicloud-capability-discovery/SKILL.md +11 -0
- package/plugins/huaweicloud-core/skills/huaweicloud-cli-and-auth/SKILL.md +16 -0
- package/plugins/huaweicloud-core/skills/huaweicloud-core/SKILL.md +27 -24
- package/plugins/huaweicloud-core/skills/huaweicloud-core/references/select.md +12 -0
- package/plugins/huaweicloud-core/src/auth/agent-registration.mjs +79 -11
- package/plugins/huaweicloud-core/src/auth/credentials.mjs +65 -0
- package/plugins/huaweicloud-core/src/mcp-server.mjs +31 -4
- package/plugins/huaweicloud-core/src/proxy/proxy-agent.mjs +6 -1
- package/plugins/huaweicloud-core/src/sandbox/hdkitservice-api.mjs +7 -2
- package/plugins/huaweicloud-core/src/sandbox/hwlink-api.mjs +14 -4
- package/plugins/huaweicloud-core/src/sandbox/sandbox-file-server.py +45 -0
- package/plugins/huaweicloud-core/src/sandbox/session-manager.mjs +432 -10
- package/plugins/huaweicloud-core/src/setup-cli.mjs +581 -87
- package/plugins/huaweicloud-core/src/tools.mjs +225 -33
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-exec-client.js +18 -4
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-fair-queue.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-multiplexer.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-packet.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-terminal-channel.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-tunnel-channel.mjs +267 -0
- package/plugins/huaweicloud-core/src/ws-exec/index.js +3 -0
- package/plugins/huaweicloud-core/src/ws-exec/ws-exec-client.js +9 -5
|
@@ -5,17 +5,26 @@ import { readFileSync, readdirSync, existsSync, writeFileSync } from 'node:fs';
|
|
|
5
5
|
import { join, dirname } from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
|
+
import { spawnSync } from 'node:child_process';
|
|
8
9
|
import { searchMarketplace } from './search-market.mjs';
|
|
9
10
|
import { getServiceIcon } from './icon-library.mjs';
|
|
10
11
|
import {
|
|
11
12
|
execWithSession,
|
|
13
|
+
execOneShot,
|
|
12
14
|
closeSession,
|
|
13
15
|
uploadFileWithSession,
|
|
14
|
-
|
|
16
|
+
uploadProjectWithSession,
|
|
17
|
+
currentWorkspaceId,
|
|
18
|
+
setWorkspaceId,
|
|
15
19
|
} from './sandbox/session-manager.mjs';
|
|
16
20
|
import { hdkitCheckUser, hdkitSignAgreement, hdkitConnect, hdkitCredentials } from './sandbox/hdkitservice-api.mjs';
|
|
17
21
|
import { getAuthStatus, syncAuth } from './auth/service.mjs';
|
|
18
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
readGlobalCredentials,
|
|
24
|
+
writeObsConfig as writeObsConfigFile,
|
|
25
|
+
setRuntimeCredentials,
|
|
26
|
+
clearRuntimeCredentials,
|
|
27
|
+
} from './auth/credentials.mjs';
|
|
19
28
|
|
|
20
29
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
30
|
const SKILLS_ROOT_DEV = join(__dirname, '..', 'skills');
|
|
@@ -35,20 +44,52 @@ function dshSkillsDir() {
|
|
|
35
44
|
const home = process.env.DSH_HOME || join(homedir(), '.dsh');
|
|
36
45
|
return join(home, 'skills');
|
|
37
46
|
}
|
|
47
|
+
function readOfficeaceRegistryInstallDir() {
|
|
48
|
+
if (process.platform !== 'win32') return null;
|
|
49
|
+
try {
|
|
50
|
+
const r = spawnSync('reg', ['query', 'HKCU\\SOFTWARE\\OfficeAce\\OfficeAce', '/v', 'InstallDir'], {
|
|
51
|
+
encoding: 'utf8',
|
|
52
|
+
windowsHide: true,
|
|
53
|
+
timeout: 5000,
|
|
54
|
+
});
|
|
55
|
+
if (r.status === 0) {
|
|
56
|
+
const m = r.stdout.match(/InstallDir\s+REG_SZ\s+(.+)/);
|
|
57
|
+
if (m) return m[1].trim();
|
|
58
|
+
}
|
|
59
|
+
} catch {}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
function officeaceSkillsRoot() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
64
|
+
const configRoot = process.env.OFFICE_CLAW_CONFIG_ROOT;
|
|
65
|
+
if (configRoot && existsSync(join(configRoot, 'capabilities.json'))) return join(configRoot, 'skills');
|
|
66
|
+
const regDir = readOfficeaceRegistryInstallDir();
|
|
67
|
+
if (regDir) {
|
|
68
|
+
const dir = join(regDir, '.office-claw', 'skills');
|
|
69
|
+
if (existsSync(dir)) return dir;
|
|
70
|
+
}
|
|
43
71
|
if (process.platform === 'win32') {
|
|
44
|
-
|
|
72
|
+
const bases = [process.env.ProgramFiles, 'C:\\Program Files', 'D:\\Program Files'];
|
|
73
|
+
if (process.env.LOCALAPPDATA) bases.push(join(process.env.LOCALAPPDATA, 'Programs'));
|
|
74
|
+
for (const base of bases) {
|
|
45
75
|
if (!base) continue;
|
|
46
|
-
const dir = join(base, 'OfficeAce', '.office-claw');
|
|
47
|
-
if (existsSync(
|
|
76
|
+
const dir = join(base, 'OfficeAce', '.office-claw', 'skills');
|
|
77
|
+
if (existsSync(dir)) return dir;
|
|
48
78
|
}
|
|
49
79
|
}
|
|
50
|
-
return
|
|
80
|
+
return null;
|
|
51
81
|
}
|
|
82
|
+
|
|
83
|
+
function hermesSkillsDir() {
|
|
84
|
+
if (process.env.HERMES_HOME) return join(process.env.HERMES_HOME, 'skills');
|
|
85
|
+
// Hermes on Windows stores under LOCALAPPDATA, not ~/.hermes
|
|
86
|
+
if (process.platform === 'win32' && process.env.LOCALAPPDATA) {
|
|
87
|
+
return join(process.env.LOCALAPPDATA, 'hermes', 'skills');
|
|
88
|
+
}
|
|
89
|
+
const home = homedir();
|
|
90
|
+
return join(home, '.hermes', 'skills');
|
|
91
|
+
}
|
|
92
|
+
|
|
52
93
|
export function listSkillDirs(root) {
|
|
53
94
|
if (!existsSync(root)) return [];
|
|
54
95
|
try {
|
|
@@ -76,6 +117,7 @@ function resolveSkillsRoot() {
|
|
|
76
117
|
opencodeSkillsDir(),
|
|
77
118
|
workbuddySkillsDir(),
|
|
78
119
|
officeaceSkillsRoot(),
|
|
120
|
+
hermesSkillsDir(),
|
|
79
121
|
]) || SKILLS_ROOT_DEV
|
|
80
122
|
);
|
|
81
123
|
}
|
|
@@ -383,7 +425,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
383
425
|
target: {
|
|
384
426
|
type: 'string',
|
|
385
427
|
description:
|
|
386
|
-
'Agent target to check: opencode, codex, codex-desktop, codearts, workbuddy, dsh, officeace, or all (default).',
|
|
428
|
+
'Agent target to check: opencode, codex, codex-desktop, codearts, workbuddy, dsh, officeace, hermes, openclaw, or all (default).',
|
|
387
429
|
},
|
|
388
430
|
},
|
|
389
431
|
},
|
|
@@ -398,23 +440,60 @@ export const TOOL_DEFINITIONS = [
|
|
|
398
440
|
target: {
|
|
399
441
|
type: 'string',
|
|
400
442
|
description:
|
|
401
|
-
'Agent target to report after sync: opencode, codex, codex-desktop, codearts, workbuddy, dsh, or all (default).',
|
|
443
|
+
'Agent target to report after sync: opencode, codex, codex-desktop, codearts, workbuddy, dsh, officeace, hermes, or all (default).',
|
|
402
444
|
},
|
|
403
445
|
},
|
|
404
446
|
},
|
|
405
447
|
},
|
|
448
|
+
{
|
|
449
|
+
name: 'huaweicloud_auth_init',
|
|
450
|
+
description:
|
|
451
|
+
'Set or clear runtime Huawei Cloud credentials (AK/SK) for this MCP session. Runtime credentials take highest priority over environment variables and config files for all subsequent API calls. Use when switching accounts within the same Agent session — call with AK/SK to switch, or with clear=true to fall back to env/file credentials.',
|
|
452
|
+
inputSchema: {
|
|
453
|
+
type: 'object',
|
|
454
|
+
properties: {
|
|
455
|
+
ak: { type: 'string', description: 'Huawei Cloud Access Key (required unless clear=true)' },
|
|
456
|
+
sk: { type: 'string', description: 'Huawei Cloud Secret Key (required unless clear=true)' },
|
|
457
|
+
region: { type: 'string', description: 'Default region (optional)' },
|
|
458
|
+
clear: { type: 'boolean', description: 'Set to true to clear runtime credentials and revert to env/file' },
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
},
|
|
406
462
|
{
|
|
407
463
|
name: 'huaweicloud_sandbox_exec_with_session',
|
|
408
464
|
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.',
|
|
465
|
+
'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
466
|
inputSchema: {
|
|
411
467
|
type: 'object',
|
|
412
468
|
required: ['command'],
|
|
413
469
|
properties: {
|
|
414
470
|
command: { type: 'string', description: 'The shell command to execute on the remote workspace' },
|
|
415
|
-
workspace_id: {
|
|
471
|
+
workspace_id: {
|
|
472
|
+
type: 'string',
|
|
473
|
+
description:
|
|
474
|
+
'Workspace ID from huaweicloud_sandbox_connect return value. Required - must be passed explicitly when HW_WORKSPACE_ID is not set.',
|
|
475
|
+
},
|
|
416
476
|
username: { type: 'string', description: 'Login username for the remote terminal (default: root)' },
|
|
417
|
-
timeout_ms: { type: 'number', description: 'Execution timeout in milliseconds (default:
|
|
477
|
+
timeout_ms: { type: 'number', description: 'Execution timeout in milliseconds (default: 120000)' },
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
name: 'huaweicloud_sandbox_exec_one_shot',
|
|
483
|
+
description:
|
|
484
|
+
'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.',
|
|
485
|
+
inputSchema: {
|
|
486
|
+
type: 'object',
|
|
487
|
+
required: ['command'],
|
|
488
|
+
properties: {
|
|
489
|
+
command: { type: 'string', description: 'The shell command to execute on the remote workspace' },
|
|
490
|
+
workspace_id: {
|
|
491
|
+
type: 'string',
|
|
492
|
+
description:
|
|
493
|
+
'Workspace ID from huaweicloud_sandbox_connect return value. Required - must be passed explicitly when HW_WORKSPACE_ID is not set.',
|
|
494
|
+
},
|
|
495
|
+
username: { type: 'string', description: 'Login username for the remote terminal (default: root)' },
|
|
496
|
+
timeout_ms: { type: 'number', description: 'Execution timeout in milliseconds (default: 120000)' },
|
|
418
497
|
},
|
|
419
498
|
},
|
|
420
499
|
},
|
|
@@ -424,7 +503,11 @@ export const TOOL_DEFINITIONS = [
|
|
|
424
503
|
inputSchema: {
|
|
425
504
|
type: 'object',
|
|
426
505
|
properties: {
|
|
427
|
-
workspace_id: {
|
|
506
|
+
workspace_id: {
|
|
507
|
+
type: 'string',
|
|
508
|
+
description:
|
|
509
|
+
'Workspace ID from huaweicloud_sandbox_connect return value. Required - must be passed explicitly when HW_WORKSPACE_ID is not set.',
|
|
510
|
+
},
|
|
428
511
|
username: { type: 'string', description: 'Login username (default: root)' },
|
|
429
512
|
},
|
|
430
513
|
},
|
|
@@ -439,9 +522,46 @@ export const TOOL_DEFINITIONS = [
|
|
|
439
522
|
properties: {
|
|
440
523
|
local_path: { type: 'string', description: 'Absolute path to the local file to upload.' },
|
|
441
524
|
remote_path: { type: 'string', description: 'Target path in the sandbox, e.g. /workspace/<repo>/index.html.' },
|
|
442
|
-
workspace_id: {
|
|
525
|
+
workspace_id: {
|
|
526
|
+
type: 'string',
|
|
527
|
+
description:
|
|
528
|
+
'Workspace ID from huaweicloud_sandbox_connect return value. Required - must be passed explicitly when HW_WORKSPACE_ID is not set.',
|
|
529
|
+
},
|
|
443
530
|
username: { type: 'string', description: 'Login username (default: root)' },
|
|
444
|
-
timeout_ms: { type: 'number', description: 'Per-command execution timeout in milliseconds (default:
|
|
531
|
+
timeout_ms: { type: 'number', description: 'Per-command execution timeout in milliseconds (default: 120000)' },
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
name: 'huaweicloud_sandbox_upload_project',
|
|
537
|
+
description:
|
|
538
|
+
'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.',
|
|
539
|
+
inputSchema: {
|
|
540
|
+
type: 'object',
|
|
541
|
+
required: ['local_dir'],
|
|
542
|
+
properties: {
|
|
543
|
+
local_dir: { type: 'string', description: 'Local project directory to upload.' },
|
|
544
|
+
remote_dir: {
|
|
545
|
+
type: 'string',
|
|
546
|
+
description:
|
|
547
|
+
'Remote parent directory where project will be extracted (default: /workspace). Final layout: <remote_dir>/<dirname>/',
|
|
548
|
+
},
|
|
549
|
+
workspace_id: {
|
|
550
|
+
type: 'string',
|
|
551
|
+
description:
|
|
552
|
+
'Workspace ID from huaweicloud_sandbox_connect return value. Required - must be passed explicitly when HW_WORKSPACE_ID is not set.',
|
|
553
|
+
},
|
|
554
|
+
username: { type: 'string', description: 'Login username (default: root)' },
|
|
555
|
+
exclude: {
|
|
556
|
+
type: 'array',
|
|
557
|
+
items: { type: 'string' },
|
|
558
|
+
description: 'Patterns to exclude from archive (default: .git, node_modules, __pycache__, .venv)',
|
|
559
|
+
},
|
|
560
|
+
extract: {
|
|
561
|
+
type: 'boolean',
|
|
562
|
+
description: 'Extract tar.gz on sandbox after upload (default: true)',
|
|
563
|
+
},
|
|
564
|
+
timeout_ms: { type: 'number', description: 'Execution timeout in milliseconds (default: 300000)' },
|
|
445
565
|
},
|
|
446
566
|
},
|
|
447
567
|
},
|
|
@@ -554,40 +674,112 @@ export async function callTool(name, args = {}) {
|
|
|
554
674
|
return getAuthStatus(args.target || 'all');
|
|
555
675
|
case 'huaweicloud_auth_sync':
|
|
556
676
|
return syncAuth(args.target || 'all');
|
|
677
|
+
case 'huaweicloud_auth_init':
|
|
678
|
+
if (args.clear) {
|
|
679
|
+
clearRuntimeCredentials();
|
|
680
|
+
return { status: 'cleared', message: 'Runtime credentials cleared. Fallback to env/file.' };
|
|
681
|
+
}
|
|
682
|
+
if (!args.ak || !args.sk) {
|
|
683
|
+
throw new Error('ak and sk are required. Set clear=true to clear runtime credentials.');
|
|
684
|
+
}
|
|
685
|
+
setRuntimeCredentials(args.ak, args.sk, undefined, args.region);
|
|
686
|
+
return { status: 'ok', message: 'Runtime credentials set for this MCP session.' };
|
|
557
687
|
case 'huaweicloud_sandbox_exec_with_session': {
|
|
558
|
-
const sandboxWsId2 = args.workspace_id ||
|
|
688
|
+
const sandboxWsId2 = args.workspace_id || currentWorkspaceId;
|
|
689
|
+
if (!sandboxWsId2) {
|
|
690
|
+
throw new Error(
|
|
691
|
+
'workspace_id is required. No sandbox connected — call huaweicloud_sandbox_connect first, ' +
|
|
692
|
+
'or set HW_WORKSPACE_ID environment variable before starting the agent.',
|
|
693
|
+
);
|
|
694
|
+
}
|
|
559
695
|
const sandboxUser2 = args.username || 'root';
|
|
560
|
-
const sandboxTimeout2 = args.timeout_ms ||
|
|
696
|
+
const sandboxTimeout2 = args.timeout_ms || 120000;
|
|
561
697
|
const sandboxResult2 = await execWithSession(sandboxWsId2, args.command, sandboxUser2, sandboxTimeout2);
|
|
562
698
|
return { stdout: sandboxResult2.stdout, exitCode: sandboxResult2.exitCode };
|
|
563
699
|
}
|
|
564
|
-
case '
|
|
565
|
-
const sandboxWsId3 = args.workspace_id ||
|
|
700
|
+
case 'huaweicloud_sandbox_exec_one_shot': {
|
|
701
|
+
const sandboxWsId3 = args.workspace_id || currentWorkspaceId;
|
|
702
|
+
if (!sandboxWsId3) {
|
|
703
|
+
throw new Error(
|
|
704
|
+
'workspace_id is required. No sandbox connected — call huaweicloud_sandbox_connect first, ' +
|
|
705
|
+
'or set HW_WORKSPACE_ID environment variable before starting the agent.',
|
|
706
|
+
);
|
|
707
|
+
}
|
|
566
708
|
const sandboxUser3 = args.username || 'root';
|
|
567
|
-
const
|
|
709
|
+
const sandboxTimeout3 = args.timeout_ms || 120000;
|
|
710
|
+
const sandboxResult3 = await execOneShot(sandboxWsId3, args.command, sandboxUser3, sandboxTimeout3);
|
|
711
|
+
return { stdout: sandboxResult3.stdout, exitCode: sandboxResult3.exitCode };
|
|
712
|
+
}
|
|
713
|
+
case 'huaweicloud_sandbox_close_session': {
|
|
714
|
+
const sandboxWsId4 = args.workspace_id || currentWorkspaceId;
|
|
715
|
+
if (!sandboxWsId4) {
|
|
716
|
+
throw new Error(
|
|
717
|
+
'workspace_id is required. No sandbox connected — call huaweicloud_sandbox_connect first, ' +
|
|
718
|
+
'or set HW_WORKSPACE_ID environment variable before starting the agent.',
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
const sandboxUser4 = args.username || 'root';
|
|
722
|
+
const closed = await closeSession(sandboxWsId4, sandboxUser4);
|
|
568
723
|
return closed ? 'ok' : 'not_connected';
|
|
569
724
|
}
|
|
570
725
|
case 'huaweicloud_sandbox_upload_file': {
|
|
571
726
|
if (!args.local_path || !args.remote_path) {
|
|
572
727
|
throw new Error('local_path and remote_path are required.');
|
|
573
728
|
}
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
729
|
+
const sandboxWsId5 = args.workspace_id || currentWorkspaceId;
|
|
730
|
+
if (!sandboxWsId5) {
|
|
731
|
+
throw new Error(
|
|
732
|
+
'workspace_id is required. No sandbox connected — call huaweicloud_sandbox_connect first, ' +
|
|
733
|
+
'or set HW_WORKSPACE_ID environment variable before starting the agent.',
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
const sandboxUser5 = args.username || 'root';
|
|
737
|
+
const sandboxTimeout5 = args.timeout_ms || 120000;
|
|
577
738
|
return await uploadFileWithSession(
|
|
578
|
-
|
|
739
|
+
sandboxWsId5,
|
|
579
740
|
args.local_path,
|
|
580
741
|
args.remote_path,
|
|
581
|
-
|
|
582
|
-
|
|
742
|
+
sandboxUser5,
|
|
743
|
+
sandboxTimeout5,
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
case 'huaweicloud_sandbox_upload_project': {
|
|
747
|
+
if (!args.local_dir) {
|
|
748
|
+
throw new Error('local_dir is required.');
|
|
749
|
+
}
|
|
750
|
+
const sandboxWsId6 = args.workspace_id || currentWorkspaceId;
|
|
751
|
+
if (!sandboxWsId6) {
|
|
752
|
+
throw new Error(
|
|
753
|
+
'workspace_id is required. No sandbox connected — call huaweicloud_sandbox_connect first, ' +
|
|
754
|
+
'or set HW_WORKSPACE_ID environment variable before starting the agent.',
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
const sandboxUser6 = args.username || 'root';
|
|
758
|
+
const sandboxTimeout6 = args.timeout_ms || 120000;
|
|
759
|
+
return await uploadProjectWithSession(
|
|
760
|
+
sandboxWsId6,
|
|
761
|
+
args.local_dir,
|
|
762
|
+
args.remote_dir,
|
|
763
|
+
sandboxUser6,
|
|
764
|
+
sandboxTimeout6,
|
|
765
|
+
{
|
|
766
|
+
exclude: args.exclude,
|
|
767
|
+
extract: args.extract,
|
|
768
|
+
},
|
|
583
769
|
);
|
|
584
770
|
}
|
|
585
771
|
case 'huaweicloud_sandbox_check_user':
|
|
586
772
|
return await hdkitCheckUser();
|
|
587
773
|
case 'huaweicloud_sandbox_sign_agreement':
|
|
588
774
|
return await hdkitSignAgreement();
|
|
589
|
-
case 'huaweicloud_sandbox_connect':
|
|
590
|
-
|
|
775
|
+
case 'huaweicloud_sandbox_connect': {
|
|
776
|
+
const connectResult = await hdkitConnect(args);
|
|
777
|
+
const devStageId = connectResult?.dev_stage_id || connectResult?.devStageId;
|
|
778
|
+
if (devStageId) {
|
|
779
|
+
setWorkspaceId(devStageId);
|
|
780
|
+
}
|
|
781
|
+
return connectResult;
|
|
782
|
+
}
|
|
591
783
|
case 'huaweicloud_sandbox_credentials':
|
|
592
784
|
return await hdkitCredentials(args.session_id, args.dev_stage_id, args.enable_sts !== false);
|
|
593
785
|
default:
|
|
@@ -773,7 +965,7 @@ async function setupObsConfigFromHcloud(profile) {
|
|
|
773
965
|
const SERVICE_EXAMPLES = {
|
|
774
966
|
ECS: { list: 'ECS ListServersDetails', create: 'ECS CreateServers', show: 'IMS GlanceShowImage' },
|
|
775
967
|
VPC: { list: 'VPC ListVpcs', create: 'VPC CreateVpc', show: 'VPC ShowVpc' },
|
|
776
|
-
|
|
968
|
+
FUNCTIONGRAPH: {
|
|
777
969
|
list: 'FunctionGraph ListFunctions',
|
|
778
970
|
create: 'FunctionGraph CreateFunction',
|
|
779
971
|
show: 'FunctionGraph ShowFunctionConfig',
|
|
@@ -782,7 +974,7 @@ const SERVICE_EXAMPLES = {
|
|
|
782
974
|
OBS: { list: 'OBS ls', create: 'OBS mb obs://<bucket>', show: 'OBS stat obs://<bucket>/<key>' },
|
|
783
975
|
RDS: { list: 'RDS ListInstances', create: 'RDS CreateInstance', show: 'RDS ShowInstance' },
|
|
784
976
|
CES: { list: 'CES ListAlarms', create: 'CES CreateAlarm', show: 'CES ListMetrics' },
|
|
785
|
-
|
|
977
|
+
GAUSSDB: { list: 'GaussDB ListInstances', create: 'GaussDB CreateInstance', show: 'GaussDB ShowInstance' },
|
|
786
978
|
DDS: { list: 'DDS ListInstances', create: 'DDS CreateInstance', show: 'DDS ShowInstance' },
|
|
787
979
|
DCS: { list: 'DCS ListInstances', create: 'DCS CreateInstance', show: 'DCS ShowInstance' },
|
|
788
980
|
};
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file contains code derived from hwlink.
|
|
3
|
+
*
|
|
4
|
+
* Source:
|
|
5
|
+
* https://gitcode.com/huawei-developers/hwlink
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the ISC License.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
import {
|
|
2
11
|
DEFAULT_TIMEOUT_MS,
|
|
3
12
|
WebSocketExecError,
|
|
@@ -383,10 +392,15 @@ class HwlinkTerminalExecSession {
|
|
|
383
392
|
const pending = this.pending;
|
|
384
393
|
if (!pending) return;
|
|
385
394
|
|
|
386
|
-
const
|
|
387
|
-
|
|
395
|
+
const doneMarker = pending.markers.doneMarker;
|
|
396
|
+
const markerIndex = pending.buffer.lastIndexOf(doneMarker);
|
|
397
|
+
if (markerIndex === -1) return;
|
|
398
|
+
|
|
399
|
+
const afterMarker = pending.buffer.slice(markerIndex + doneMarker.length);
|
|
400
|
+
const exitMatch = afterMarker.match(/^(\d+)/);
|
|
401
|
+
if (!exitMatch) return;
|
|
388
402
|
|
|
389
|
-
const rawOutput = pending.buffer.slice(0,
|
|
403
|
+
const rawOutput = pending.buffer.slice(0, markerIndex);
|
|
390
404
|
const stdout = cleanCommandOutput(rawOutput, {
|
|
391
405
|
inputEchoed: this.inputEchoed,
|
|
392
406
|
command: pending.command,
|
|
@@ -397,7 +411,7 @@ class HwlinkTerminalExecSession {
|
|
|
397
411
|
this.pending = null;
|
|
398
412
|
pending.resolve({
|
|
399
413
|
stdout,
|
|
400
|
-
exitCode: Number(
|
|
414
|
+
exitCode: Number(exitMatch[1]),
|
|
401
415
|
url: this.url,
|
|
402
416
|
source: this.source,
|
|
403
417
|
username: this.username,
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file contains code derived from hwlink.
|
|
3
|
+
*
|
|
4
|
+
* Source:
|
|
5
|
+
* https://gitcode.com/huawei-developers/hwlink
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the ISC License.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
const DEFAULT_HIGH_WATERMARK = 8 * 1024 * 1024;
|
|
2
11
|
const DEFAULT_LOW_WATERMARK = 2 * 1024 * 1024;
|
|
3
12
|
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file contains code derived from hwlink.
|
|
3
|
+
*
|
|
4
|
+
* Source:
|
|
5
|
+
* https://gitcode.com/huawei-developers/hwlink
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the ISC License.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
import { Buffer } from 'node:buffer';
|
|
2
11
|
|
|
3
12
|
import { FairQueue } from './hwlink-fair-queue.js';
|