wattetheria 0.3.2 → 0.3.4
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/.env.release +1 -1
- package/README.md +11 -7
- package/lib/cli.js +334 -5
- package/package.json +1 -1
package/.env.release
CHANGED
package/README.md
CHANGED
|
@@ -556,9 +556,11 @@ Agent commands such as `identity`, `wallet`, and `servicenet` are forwarded to t
|
|
|
556
556
|
native `wattetheria-client-cli`; installed release packages should not require Rust on the user's
|
|
557
557
|
machine. The JS wrapper resolves `WATTETHERIA_CLI_BIN` first, then the matching optional native
|
|
558
558
|
package such as `@wattetheria/cli-win32-x64`, then `bin/native/<platform>-<arch>/`, then `PATH`.
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
559
|
+
`identity` and `wallet` are lightweight local setup commands for ServiceNet publishing and wallet
|
|
560
|
+
binding when no local Wattetheria node identity or wallet exists. If a local node already has
|
|
561
|
+
identity or wallet state, the wrapper refuses to create a separate local identity or wallet through
|
|
562
|
+
those setup commands. ServiceNet commands can still run through an installed node when no host
|
|
563
|
+
native CLI is available.
|
|
562
564
|
|
|
563
565
|
NPM publish flow:
|
|
564
566
|
|
|
@@ -583,14 +585,16 @@ CLI saves the provider/card context locally:
|
|
|
583
585
|
```bash
|
|
584
586
|
npx wattetheria servicenet agent-card init
|
|
585
587
|
# or write the template into a specific directory:
|
|
586
|
-
npx wattetheria servicenet agent-card init --out
|
|
588
|
+
npx wattetheria servicenet agent-card init --out <output-directory>
|
|
587
589
|
|
|
588
|
-
npx wattetheria servicenet
|
|
590
|
+
npx wattetheria servicenet register
|
|
591
|
+
# If the card is not in the current directory:
|
|
592
|
+
npx wattetheria servicenet register --card <path-to-agent-card.json>
|
|
589
593
|
```
|
|
590
594
|
|
|
591
595
|
Then publish through the ServiceNet business command with the returned agent id. The publish
|
|
592
|
-
command reads the saved provider id,
|
|
593
|
-
|
|
596
|
+
command reads the saved provider id, endpoint URL, and card path from local context instead of
|
|
597
|
+
asking for repeated flags:
|
|
594
598
|
|
|
595
599
|
```bash
|
|
596
600
|
npx wattetheria servicenet publish <agent-id>
|
package/lib/cli.js
CHANGED
|
@@ -73,10 +73,25 @@ Commands:
|
|
|
73
73
|
doctor Check local prerequisites
|
|
74
74
|
help Show this help
|
|
75
75
|
|
|
76
|
-
Agent subcommands
|
|
77
|
-
identity
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
Agent subcommands:
|
|
77
|
+
identity
|
|
78
|
+
init Initialize a lightweight local identity for ServiceNet publishing or wallet binding
|
|
79
|
+
show Show the local identity public DID and public key
|
|
80
|
+
export-seed Export the local identity seed; treat it like a password
|
|
81
|
+
|
|
82
|
+
wallet
|
|
83
|
+
create-payment-account Create a local payment account for ServiceNet payment binding
|
|
84
|
+
import-payment-account Import a local payment account for ServiceNet payment binding
|
|
85
|
+
watch-payment-account Track a payment address without importing its private key
|
|
86
|
+
list-payment-accounts List local payment accounts
|
|
87
|
+
bind-payment-account Select the active local payment account
|
|
88
|
+
active-payment-account Show the active local payment account
|
|
89
|
+
|
|
90
|
+
servicenet
|
|
91
|
+
agent-card init Generate an editable agent-card.json template in the current directory
|
|
92
|
+
register --card <path-to-agent-card.json>
|
|
93
|
+
Register the agent card and local identity with ServiceNet; returns agent_id and provider_id
|
|
94
|
+
publish <agent-id> Publish a registered ServiceNet agent using the agent_id returned by register
|
|
80
95
|
|
|
81
96
|
Options:
|
|
82
97
|
--version, -v Alias for \`version\`
|
|
@@ -94,6 +109,15 @@ Options:
|
|
|
94
109
|
`);
|
|
95
110
|
}
|
|
96
111
|
|
|
112
|
+
function throwCommandSuggestion(argv) {
|
|
113
|
+
if (argv[0] === "provider" && argv[1] === "register") {
|
|
114
|
+
throw new Error("Unknown command: provider register. Use `wattetheria servicenet register`.");
|
|
115
|
+
}
|
|
116
|
+
if (argv[0] === "register") {
|
|
117
|
+
throw new Error("Unknown command: register. Use `wattetheria servicenet register`.");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
97
121
|
function parseArgs(argv) {
|
|
98
122
|
let command = DEFAULT_COMMAND;
|
|
99
123
|
let index = 0;
|
|
@@ -1291,11 +1315,25 @@ function bundledRustBinaryPath() {
|
|
|
1291
1315
|
|
|
1292
1316
|
function missingNativeCliError(commandName) {
|
|
1293
1317
|
const platformKey = nativePlatformKey() || `${process.platform}-${process.arch}`;
|
|
1318
|
+
if (commandName === "identity" || commandName === "wallet") {
|
|
1319
|
+
return new Error(
|
|
1320
|
+
[
|
|
1321
|
+
`Cannot run '${commandName}' because the Wattetheria native CLI for ${platformKey} was not found.`,
|
|
1322
|
+
"",
|
|
1323
|
+
"`wattetheria identity` and `wattetheria wallet` are lightweight local setup commands",
|
|
1324
|
+
"for ServiceNet publishing and wallet binding. They do not require a local Wattetheria",
|
|
1325
|
+
"node, but they do require the native CLI package for this system.",
|
|
1326
|
+
"",
|
|
1327
|
+
"Install the matching Wattetheria native CLI package, then retry."
|
|
1328
|
+
].join("\n")
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1294
1332
|
const deployment = deploymentState();
|
|
1295
1333
|
if (deployment.installed) {
|
|
1296
1334
|
return new Error(
|
|
1297
1335
|
`Wattetheria node deployment was found at ${deployment.dir}, but this npm package does not include ` +
|
|
1298
|
-
`the native
|
|
1336
|
+
`the native CLI for ${platformKey}. ` +
|
|
1299
1337
|
`Run 'npx wattetheria status' to check the installed node, or update the local node image.`
|
|
1300
1338
|
);
|
|
1301
1339
|
}
|
|
@@ -1306,6 +1344,103 @@ function missingNativeCliError(commandName) {
|
|
|
1306
1344
|
);
|
|
1307
1345
|
}
|
|
1308
1346
|
|
|
1347
|
+
function forwardedSubcommand(rawArgv) {
|
|
1348
|
+
for (let index = 1; index < rawArgv.length; index += 1) {
|
|
1349
|
+
const arg = rawArgv[index];
|
|
1350
|
+
if (arg.startsWith("-")) {
|
|
1351
|
+
if (!arg.includes("=")) {
|
|
1352
|
+
index += 1;
|
|
1353
|
+
}
|
|
1354
|
+
continue;
|
|
1355
|
+
}
|
|
1356
|
+
return arg;
|
|
1357
|
+
}
|
|
1358
|
+
return "";
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
function isIdentityWriteCommand(commandName, rawArgv) {
|
|
1362
|
+
return commandName === "identity" && forwardedSubcommand(rawArgv) === "init";
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
function isWalletWriteCommand(commandName, rawArgv) {
|
|
1366
|
+
if (commandName !== "wallet") {
|
|
1367
|
+
return false;
|
|
1368
|
+
}
|
|
1369
|
+
return new Set([
|
|
1370
|
+
"create-payment-account",
|
|
1371
|
+
"import-payment-account",
|
|
1372
|
+
"watch-payment-account",
|
|
1373
|
+
"bind-payment-account"
|
|
1374
|
+
]).has(forwardedSubcommand(rawArgv));
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
function installedNodeArtifacts(deployment = deploymentState()) {
|
|
1378
|
+
return {
|
|
1379
|
+
identityPath: path.join(deployment.stateDir, "identity.json"),
|
|
1380
|
+
walletMetadataPath: path.join(deployment.stateDir, ".watt-wallet", "metadata.json"),
|
|
1381
|
+
walletKeystorePath: path.join(deployment.stateDir, ".watt-wallet", "keystore.json")
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
function explicitDataDir(rawArgv) {
|
|
1386
|
+
const option = parsePathOption(rawArgv, "--data-dir", 1);
|
|
1387
|
+
if (!option) {
|
|
1388
|
+
return "";
|
|
1389
|
+
}
|
|
1390
|
+
if (!option.value) {
|
|
1391
|
+
throw new Error("Missing value for --data-dir");
|
|
1392
|
+
}
|
|
1393
|
+
return path.resolve(option.value);
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
function usesSeparateDataDir(rawArgv, deployment) {
|
|
1397
|
+
const dataDir = explicitDataDir(rawArgv);
|
|
1398
|
+
return Boolean(dataDir) && dataDir !== path.resolve(deployment.stateDir);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
function ensureLightweightCommandAllowed(commandName, rawArgv) {
|
|
1402
|
+
if (!(isIdentityWriteCommand(commandName, rawArgv) || isWalletWriteCommand(commandName, rawArgv))) {
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
const deployment = deploymentState();
|
|
1406
|
+
if (!deployment.installed || usesSeparateDataDir(rawArgv, deployment)) {
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1409
|
+
const artifacts = installedNodeArtifacts(deployment);
|
|
1410
|
+
if (isIdentityWriteCommand(commandName, rawArgv) && fs.existsSync(artifacts.identityPath)) {
|
|
1411
|
+
throw new Error(
|
|
1412
|
+
[
|
|
1413
|
+
"Refusing to initialize a separate local identity.",
|
|
1414
|
+
"",
|
|
1415
|
+
"A local Wattetheria node is already installed and has an identity at:",
|
|
1416
|
+
deployment.stateDir,
|
|
1417
|
+
"",
|
|
1418
|
+
"`wattetheria identity init` is only for lightweight local setup when no Wattetheria",
|
|
1419
|
+
"node identity exists. Use the installed node's identity instead, or choose a separate",
|
|
1420
|
+
"data directory only for isolated testing."
|
|
1421
|
+
].join("\n")
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
if (
|
|
1425
|
+
isWalletWriteCommand(commandName, rawArgv)
|
|
1426
|
+
&& fs.existsSync(artifacts.walletMetadataPath)
|
|
1427
|
+
&& fs.existsSync(artifacts.walletKeystorePath)
|
|
1428
|
+
) {
|
|
1429
|
+
throw new Error(
|
|
1430
|
+
[
|
|
1431
|
+
"Refusing to modify a separate local wallet.",
|
|
1432
|
+
"",
|
|
1433
|
+
"A local Wattetheria node is already installed and has wallet state at:",
|
|
1434
|
+
deployment.stateDir,
|
|
1435
|
+
"",
|
|
1436
|
+
"`wattetheria wallet` setup commands are only for lightweight local setup when no",
|
|
1437
|
+
"Wattetheria node wallet exists. Use the installed node's wallet instead, or choose a",
|
|
1438
|
+
"separate data directory only for isolated testing."
|
|
1439
|
+
].join("\n")
|
|
1440
|
+
);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1309
1444
|
function forwardedArgsForInstalledNode(commandName, rawArgv) {
|
|
1310
1445
|
const args = [commandName];
|
|
1311
1446
|
if (!rawArgv.some((arg) => arg === "--data-dir" || arg.startsWith("--data-dir="))) {
|
|
@@ -1315,6 +1450,158 @@ function forwardedArgsForInstalledNode(commandName, rawArgv) {
|
|
|
1315
1450
|
return args;
|
|
1316
1451
|
}
|
|
1317
1452
|
|
|
1453
|
+
function isServicenetAgentCardInit(commandName, rawArgv) {
|
|
1454
|
+
return commandName === "servicenet"
|
|
1455
|
+
&& rawArgv[1] === "agent-card"
|
|
1456
|
+
&& rawArgv[2] === "init";
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
function isServicenetRegister(commandName, rawArgv) {
|
|
1460
|
+
return commandName === "servicenet"
|
|
1461
|
+
&& rawArgv[1] === "register";
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
function isServicenetPublish(commandName, rawArgv) {
|
|
1465
|
+
return commandName === "servicenet"
|
|
1466
|
+
&& rawArgv[1] === "publish";
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
function usesWorkspaceMount(commandName, rawArgv) {
|
|
1470
|
+
return isServicenetAgentCardInit(commandName, rawArgv)
|
|
1471
|
+
|| isServicenetRegister(commandName, rawArgv)
|
|
1472
|
+
|| isServicenetPublish(commandName, rawArgv);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
function findExistingAncestor(targetPath) {
|
|
1476
|
+
let cursor = path.resolve(targetPath);
|
|
1477
|
+
while (!fs.existsSync(cursor)) {
|
|
1478
|
+
const parent = path.dirname(cursor);
|
|
1479
|
+
if (parent === cursor) {
|
|
1480
|
+
throw new Error(`No existing parent directory found for ${targetPath}`);
|
|
1481
|
+
}
|
|
1482
|
+
cursor = parent;
|
|
1483
|
+
}
|
|
1484
|
+
return cursor;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
function toContainerPath(relativePath) {
|
|
1488
|
+
if (!relativePath || relativePath === ".") {
|
|
1489
|
+
return "/workspace";
|
|
1490
|
+
}
|
|
1491
|
+
return `/workspace/${relativePath.split(path.sep).join("/")}`;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
function parsePathOption(rawArgv, optionName, startIndex) {
|
|
1495
|
+
const equalsPrefix = `${optionName}=`;
|
|
1496
|
+
for (let index = startIndex; index < rawArgv.length; index += 1) {
|
|
1497
|
+
const arg = rawArgv[index];
|
|
1498
|
+
if (arg === optionName) {
|
|
1499
|
+
return { index, value: rawArgv[index + 1], style: "separate" };
|
|
1500
|
+
}
|
|
1501
|
+
if (arg.startsWith(equalsPrefix)) {
|
|
1502
|
+
return { index, value: arg.slice(equalsPrefix.length), style: "equals" };
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
return null;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
function pathMountFor(targetPath) {
|
|
1509
|
+
const requestedPath = path.resolve(targetPath);
|
|
1510
|
+
const existingPath = fs.existsSync(requestedPath) ? requestedPath : "";
|
|
1511
|
+
const mountSource = existingPath
|
|
1512
|
+
? (
|
|
1513
|
+
fs.statSync(existingPath).isDirectory()
|
|
1514
|
+
? existingPath
|
|
1515
|
+
: path.dirname(existingPath)
|
|
1516
|
+
)
|
|
1517
|
+
: findExistingAncestor(requestedPath);
|
|
1518
|
+
return {
|
|
1519
|
+
mountSource,
|
|
1520
|
+
containerPath: toContainerPath(path.relative(mountSource, requestedPath))
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
function rewritePathOption(rawArgv, parsedOption, containerPath) {
|
|
1525
|
+
const rewrittenArgv = [...rawArgv];
|
|
1526
|
+
if (parsedOption.style === "separate") {
|
|
1527
|
+
rewrittenArgv[parsedOption.index + 1] = containerPath;
|
|
1528
|
+
} else {
|
|
1529
|
+
rewrittenArgv[parsedOption.index] = `${rewrittenArgv[parsedOption.index].split("=")[0]}=${containerPath}`;
|
|
1530
|
+
}
|
|
1531
|
+
return rewrittenArgv;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
function dockerWorkspaceInvocation(commandName, rawArgv) {
|
|
1535
|
+
if (isServicenetAgentCardInit(commandName, rawArgv)) {
|
|
1536
|
+
const outputArg = parsePathOption(rawArgv, "--out", 3);
|
|
1537
|
+
const outputPath = outputArg?.value || process.cwd();
|
|
1538
|
+
if (outputArg && !outputArg.value) {
|
|
1539
|
+
throw new Error("Missing value for --out");
|
|
1540
|
+
}
|
|
1541
|
+
const outputMount = pathMountFor(outputPath);
|
|
1542
|
+
const rewrittenArgv = outputArg
|
|
1543
|
+
? rewritePathOption(rawArgv, outputArg, outputMount.containerPath)
|
|
1544
|
+
: rawArgv;
|
|
1545
|
+
return {
|
|
1546
|
+
args: outputArg
|
|
1547
|
+
? forwardedArgsForInstalledNode(commandName, rewrittenArgv)
|
|
1548
|
+
: [...forwardedArgsForInstalledNode(commandName, rawArgv), "--out", outputMount.containerPath],
|
|
1549
|
+
mountSource: outputMount.mountSource
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
if (isServicenetRegister(commandName, rawArgv)) {
|
|
1554
|
+
const cardArg = parsePathOption(rawArgv, "--card", 2);
|
|
1555
|
+
if (!cardArg) {
|
|
1556
|
+
return {
|
|
1557
|
+
args: forwardedArgsForInstalledNode(commandName, rawArgv),
|
|
1558
|
+
mountSource: process.cwd()
|
|
1559
|
+
};
|
|
1560
|
+
}
|
|
1561
|
+
if (!cardArg.value) {
|
|
1562
|
+
throw new Error("Missing value for --card");
|
|
1563
|
+
}
|
|
1564
|
+
const cardMount = pathMountFor(cardArg.value);
|
|
1565
|
+
return {
|
|
1566
|
+
args: forwardedArgsForInstalledNode(
|
|
1567
|
+
commandName,
|
|
1568
|
+
rewritePathOption(rawArgv, cardArg, cardMount.containerPath)
|
|
1569
|
+
),
|
|
1570
|
+
mountSource: cardMount.mountSource
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
return {
|
|
1575
|
+
args: forwardedArgsForInstalledNode(commandName, rawArgv),
|
|
1576
|
+
mountSource: process.cwd()
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
function hostPathFromWorkspace(containerPath, mountSource) {
|
|
1581
|
+
if (containerPath === "/workspace") {
|
|
1582
|
+
return mountSource;
|
|
1583
|
+
}
|
|
1584
|
+
if (!containerPath.startsWith("/workspace/")) {
|
|
1585
|
+
return containerPath;
|
|
1586
|
+
}
|
|
1587
|
+
return path.join(mountSource, containerPath.slice("/workspace/".length));
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
function rewriteWorkspaceJsonStdout(stdout, mountSource) {
|
|
1591
|
+
if (!stdout.trim()) {
|
|
1592
|
+
return stdout;
|
|
1593
|
+
}
|
|
1594
|
+
try {
|
|
1595
|
+
const payload = JSON.parse(stdout);
|
|
1596
|
+
if (typeof payload.card === "string") {
|
|
1597
|
+
payload.card = hostPathFromWorkspace(payload.card, mountSource);
|
|
1598
|
+
}
|
|
1599
|
+
return `${JSON.stringify(payload, null, 2)}\n`;
|
|
1600
|
+
} catch (_error) {
|
|
1601
|
+
return stdout;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1318
1605
|
function runInstalledNodeCli(commandName, rawArgv, deployment) {
|
|
1319
1606
|
const dockerCommand = resolveDockerCommand();
|
|
1320
1607
|
if (!dockerCommand) {
|
|
@@ -1323,6 +1610,41 @@ function runInstalledNodeCli(commandName, rawArgv, deployment) {
|
|
|
1323
1610
|
`to run '${commandName}' inside the installed node. Start Docker Desktop and retry.`
|
|
1324
1611
|
);
|
|
1325
1612
|
}
|
|
1613
|
+
if (usesWorkspaceMount(commandName, rawArgv)) {
|
|
1614
|
+
const invocation = dockerWorkspaceInvocation(commandName, rawArgv);
|
|
1615
|
+
const result = spawnSync(
|
|
1616
|
+
dockerCommand,
|
|
1617
|
+
[
|
|
1618
|
+
"compose",
|
|
1619
|
+
"--project-name",
|
|
1620
|
+
DEFAULT_PROJECT_NAME,
|
|
1621
|
+
"--env-file",
|
|
1622
|
+
deployment.envPath,
|
|
1623
|
+
"-f",
|
|
1624
|
+
deployment.composePath,
|
|
1625
|
+
"run",
|
|
1626
|
+
"--rm",
|
|
1627
|
+
"--no-deps",
|
|
1628
|
+
"-T",
|
|
1629
|
+
"--entrypoint",
|
|
1630
|
+
"/app/target/release/wattetheria-client-cli",
|
|
1631
|
+
"-v",
|
|
1632
|
+
`${invocation.mountSource}:/workspace`,
|
|
1633
|
+
"-w",
|
|
1634
|
+
"/workspace",
|
|
1635
|
+
"kernel",
|
|
1636
|
+
...invocation.args
|
|
1637
|
+
],
|
|
1638
|
+
{ stdio: ["inherit", "pipe", "inherit"], encoding: "utf8" }
|
|
1639
|
+
);
|
|
1640
|
+
if (result.stdout) {
|
|
1641
|
+
process.stdout.write(rewriteWorkspaceJsonStdout(result.stdout, invocation.mountSource));
|
|
1642
|
+
}
|
|
1643
|
+
if (typeof result.status === "number") {
|
|
1644
|
+
process.exit(result.status);
|
|
1645
|
+
}
|
|
1646
|
+
throw result.error ?? new Error(`Failed to run '${commandName}' inside the installed node`);
|
|
1647
|
+
}
|
|
1326
1648
|
const result = spawnSync(
|
|
1327
1649
|
dockerCommand,
|
|
1328
1650
|
[
|
|
@@ -1348,6 +1670,8 @@ function runInstalledNodeCli(commandName, rawArgv, deployment) {
|
|
|
1348
1670
|
}
|
|
1349
1671
|
|
|
1350
1672
|
function forwardToRustBinary(commandName, rawArgv) {
|
|
1673
|
+
ensureLightweightCommandAllowed(commandName, rawArgv);
|
|
1674
|
+
|
|
1351
1675
|
// Only the Rust binary name is allowed here. The bare `wattetheria` name
|
|
1352
1676
|
// resolves to this JS shim on most user PATHs (via the npm bin link), so
|
|
1353
1677
|
// including it would create an infinite spawn loop.
|
|
@@ -1374,6 +1698,9 @@ function forwardToRustBinary(commandName, rawArgv) {
|
|
|
1374
1698
|
}
|
|
1375
1699
|
|
|
1376
1700
|
const deployment = deploymentState();
|
|
1701
|
+
if (commandName === "identity" || commandName === "wallet") {
|
|
1702
|
+
throw missingNativeCliError(commandName);
|
|
1703
|
+
}
|
|
1377
1704
|
if (deployment.runnable) {
|
|
1378
1705
|
runInstalledNodeCli(commandName, rawArgv, deployment);
|
|
1379
1706
|
return;
|
|
@@ -1383,6 +1710,8 @@ function forwardToRustBinary(commandName, rawArgv) {
|
|
|
1383
1710
|
}
|
|
1384
1711
|
|
|
1385
1712
|
async function run(argv) {
|
|
1713
|
+
throwCommandSuggestion(argv);
|
|
1714
|
+
|
|
1386
1715
|
if (argv[0] && FORWARDED_SUBCOMMANDS.has(argv[0])) {
|
|
1387
1716
|
forwardToRustBinary(argv[0], argv);
|
|
1388
1717
|
return;
|