huaweicloud-devkit 1.0.2-next.9 → 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/README.md +85 -51
- package/README.zh-CN.md +85 -49
- package/package.json +11 -5
- package/plugins/huaweicloud-core/.claude-plugin/plugin.json +4 -17
- package/plugins/huaweicloud-core/.codex-plugin/plugin.json +4 -17
- package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +4 -17
- 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 +4 -18
- package/plugins/huaweicloud-core/hooks/huaweicloud-safety.py +32 -9
- 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 +103 -2
- 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 +823 -22
- package/plugins/huaweicloud-core/src/tools.mjs +239 -27
- 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,6 +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
|
+
|
|
63
|
+
function officeaceSkillsRoot() {
|
|
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
|
+
}
|
|
71
|
+
if (process.platform === 'win32') {
|
|
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) {
|
|
75
|
+
if (!base) continue;
|
|
76
|
+
const dir = join(base, 'OfficeAce', '.office-claw', 'skills');
|
|
77
|
+
if (existsSync(dir)) return dir;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
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
|
+
|
|
38
93
|
export function listSkillDirs(root) {
|
|
39
94
|
if (!existsSync(root)) return [];
|
|
40
95
|
try {
|
|
@@ -55,8 +110,15 @@ export function findSkillsRoot(candidates) {
|
|
|
55
110
|
|
|
56
111
|
function resolveSkillsRoot() {
|
|
57
112
|
return (
|
|
58
|
-
findSkillsRoot([
|
|
59
|
-
|
|
113
|
+
findSkillsRoot([
|
|
114
|
+
SKILLS_ROOT_DEV,
|
|
115
|
+
dshSkillsDir(),
|
|
116
|
+
codeartsSkillsDir(),
|
|
117
|
+
opencodeSkillsDir(),
|
|
118
|
+
workbuddySkillsDir(),
|
|
119
|
+
officeaceSkillsRoot(),
|
|
120
|
+
hermesSkillsDir(),
|
|
121
|
+
]) || SKILLS_ROOT_DEV
|
|
60
122
|
);
|
|
61
123
|
}
|
|
62
124
|
const SKILLS_ROOT = resolveSkillsRoot();
|
|
@@ -363,7 +425,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
363
425
|
target: {
|
|
364
426
|
type: 'string',
|
|
365
427
|
description:
|
|
366
|
-
'Agent target to check: opencode, codex, codex-desktop, codearts, workbuddy, dsh, or all (default).',
|
|
428
|
+
'Agent target to check: opencode, codex, codex-desktop, codearts, workbuddy, dsh, officeace, hermes, openclaw, or all (default).',
|
|
367
429
|
},
|
|
368
430
|
},
|
|
369
431
|
},
|
|
@@ -378,23 +440,60 @@ export const TOOL_DEFINITIONS = [
|
|
|
378
440
|
target: {
|
|
379
441
|
type: 'string',
|
|
380
442
|
description:
|
|
381
|
-
'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).',
|
|
382
444
|
},
|
|
383
445
|
},
|
|
384
446
|
},
|
|
385
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
|
+
},
|
|
386
462
|
{
|
|
387
463
|
name: 'huaweicloud_sandbox_exec_with_session',
|
|
388
464
|
description:
|
|
389
|
-
'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.',
|
|
390
466
|
inputSchema: {
|
|
391
467
|
type: 'object',
|
|
392
468
|
required: ['command'],
|
|
393
469
|
properties: {
|
|
394
470
|
command: { type: 'string', description: 'The shell command to execute on the remote workspace' },
|
|
395
|
-
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
|
+
},
|
|
396
476
|
username: { type: 'string', description: 'Login username for the remote terminal (default: root)' },
|
|
397
|
-
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)' },
|
|
398
497
|
},
|
|
399
498
|
},
|
|
400
499
|
},
|
|
@@ -404,7 +503,11 @@ export const TOOL_DEFINITIONS = [
|
|
|
404
503
|
inputSchema: {
|
|
405
504
|
type: 'object',
|
|
406
505
|
properties: {
|
|
407
|
-
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
|
+
},
|
|
408
511
|
username: { type: 'string', description: 'Login username (default: root)' },
|
|
409
512
|
},
|
|
410
513
|
},
|
|
@@ -419,9 +522,46 @@ export const TOOL_DEFINITIONS = [
|
|
|
419
522
|
properties: {
|
|
420
523
|
local_path: { type: 'string', description: 'Absolute path to the local file to upload.' },
|
|
421
524
|
remote_path: { type: 'string', description: 'Target path in the sandbox, e.g. /workspace/<repo>/index.html.' },
|
|
422
|
-
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
|
+
},
|
|
423
530
|
username: { type: 'string', description: 'Login username (default: root)' },
|
|
424
|
-
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)' },
|
|
425
565
|
},
|
|
426
566
|
},
|
|
427
567
|
},
|
|
@@ -534,40 +674,112 @@ export async function callTool(name, args = {}) {
|
|
|
534
674
|
return getAuthStatus(args.target || 'all');
|
|
535
675
|
case 'huaweicloud_auth_sync':
|
|
536
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.' };
|
|
537
687
|
case 'huaweicloud_sandbox_exec_with_session': {
|
|
538
|
-
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
|
+
}
|
|
539
695
|
const sandboxUser2 = args.username || 'root';
|
|
540
|
-
const sandboxTimeout2 = args.timeout_ms ||
|
|
696
|
+
const sandboxTimeout2 = args.timeout_ms || 120000;
|
|
541
697
|
const sandboxResult2 = await execWithSession(sandboxWsId2, args.command, sandboxUser2, sandboxTimeout2);
|
|
542
698
|
return { stdout: sandboxResult2.stdout, exitCode: sandboxResult2.exitCode };
|
|
543
699
|
}
|
|
544
|
-
case '
|
|
545
|
-
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
|
+
}
|
|
546
708
|
const sandboxUser3 = args.username || 'root';
|
|
547
|
-
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);
|
|
548
723
|
return closed ? 'ok' : 'not_connected';
|
|
549
724
|
}
|
|
550
725
|
case 'huaweicloud_sandbox_upload_file': {
|
|
551
726
|
if (!args.local_path || !args.remote_path) {
|
|
552
727
|
throw new Error('local_path and remote_path are required.');
|
|
553
728
|
}
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
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;
|
|
557
738
|
return await uploadFileWithSession(
|
|
558
|
-
|
|
739
|
+
sandboxWsId5,
|
|
559
740
|
args.local_path,
|
|
560
741
|
args.remote_path,
|
|
561
|
-
|
|
562
|
-
|
|
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
|
+
},
|
|
563
769
|
);
|
|
564
770
|
}
|
|
565
771
|
case 'huaweicloud_sandbox_check_user':
|
|
566
772
|
return await hdkitCheckUser();
|
|
567
773
|
case 'huaweicloud_sandbox_sign_agreement':
|
|
568
774
|
return await hdkitSignAgreement();
|
|
569
|
-
case 'huaweicloud_sandbox_connect':
|
|
570
|
-
|
|
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
|
+
}
|
|
571
783
|
case 'huaweicloud_sandbox_credentials':
|
|
572
784
|
return await hdkitCredentials(args.session_id, args.dev_stage_id, args.enable_sts !== false);
|
|
573
785
|
default:
|
|
@@ -753,7 +965,7 @@ async function setupObsConfigFromHcloud(profile) {
|
|
|
753
965
|
const SERVICE_EXAMPLES = {
|
|
754
966
|
ECS: { list: 'ECS ListServersDetails', create: 'ECS CreateServers', show: 'IMS GlanceShowImage' },
|
|
755
967
|
VPC: { list: 'VPC ListVpcs', create: 'VPC CreateVpc', show: 'VPC ShowVpc' },
|
|
756
|
-
|
|
968
|
+
FUNCTIONGRAPH: {
|
|
757
969
|
list: 'FunctionGraph ListFunctions',
|
|
758
970
|
create: 'FunctionGraph CreateFunction',
|
|
759
971
|
show: 'FunctionGraph ShowFunctionConfig',
|
|
@@ -762,7 +974,7 @@ const SERVICE_EXAMPLES = {
|
|
|
762
974
|
OBS: { list: 'OBS ls', create: 'OBS mb obs://<bucket>', show: 'OBS stat obs://<bucket>/<key>' },
|
|
763
975
|
RDS: { list: 'RDS ListInstances', create: 'RDS CreateInstance', show: 'RDS ShowInstance' },
|
|
764
976
|
CES: { list: 'CES ListAlarms', create: 'CES CreateAlarm', show: 'CES ListMetrics' },
|
|
765
|
-
|
|
977
|
+
GAUSSDB: { list: 'GaussDB ListInstances', create: 'GaussDB CreateInstance', show: 'GaussDB ShowInstance' },
|
|
766
978
|
DDS: { list: 'DDS ListInstances', create: 'DDS CreateInstance', show: 'DDS ShowInstance' },
|
|
767
979
|
DCS: { list: 'DCS ListInstances', create: 'DCS CreateInstance', show: 'DCS ShowInstance' },
|
|
768
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';
|